Deprecate normalize_presentation_timestamp

Force earliest_presentation_timestamp to start from 0 by default for
single segment segmenter.

Change-Id: Icfc14e27051c6edfb7a86559045c50a0ce51a62e
This commit is contained in:
KongQun Yang 2014-07-16 16:41:54 -07:00 committed by Gerrit Code Review
parent 66f155502d
commit 3e6190ec2b
15 changed files with 24 additions and 66 deletions

View File

@ -30,7 +30,7 @@ This document provides the information needed to create a DASH packager that is
```Shell ```Shell
ninja -C out/Debug # build all modules in Debug mode ninja -C out/Debug # build all modules in Debug mode
ninja -C out/Release # build all modules in Release mode ninja -C out/Release # build all modules in Release mode
ninja -C out/Release mp4 # build mp4 module in Debug mode ninja -C out/Release mp4 # build mp4 module in Release mode
``` ```
Refer to ninja manual for details. Refer to ninja manual for details.
@ -177,9 +177,6 @@ muxer_options.segment_sap_aligned = true;
// segment_sap_aligned. // segment_sap_aligned.
muxer_options.fragment_sap_aligned = true; muxer_options.fragment_sap_aligned = true;
// Set to true to normalize the presentation timestamps to start from zero.
muxer_options.normalize_presentation_timestamp = true;
// For ISO BMFF only. // For ISO BMFF only.
// Set the number of subsegments in each SIDX box. If 0, a single SIDX box // Set the number of subsegments in each SIDX box. If 0, a single SIDX box
// is used per segment. If -1, no SIDX box is used. Otherwise, the Muxer // is used per segment. If -1, no SIDX box is used. Otherwise, the Muxer

View File

@ -38,10 +38,6 @@ DEFINE_bool(fragment_sap_aligned,
true, true,
"Force fragments to begin with stream access points. This flag " "Force fragments to begin with stream access points. This flag "
"implies segment_sap_aligned."); "implies segment_sap_aligned.");
DEFINE_bool(normalize_presentation_timestamp,
true,
"Set to true to normalize the presentation timestamps to start"
"from zero.");
DEFINE_int32(num_subsegments_per_sidx, DEFINE_int32(num_subsegments_per_sidx,
1, 1,
"For ISO BMFF only. Set the number of subsegments in each " "For ISO BMFF only. Set the number of subsegments in each "

View File

@ -18,7 +18,6 @@ DECLARE_double(segment_duration);
DECLARE_bool(segment_sap_aligned); DECLARE_bool(segment_sap_aligned);
DECLARE_double(fragment_duration); DECLARE_double(fragment_duration);
DECLARE_bool(fragment_sap_aligned); DECLARE_bool(fragment_sap_aligned);
DECLARE_bool(normalize_presentation_timestamp);
DECLARE_int32(num_subsegments_per_sidx); DECLARE_int32(num_subsegments_per_sidx);
DECLARE_string(temp_dir); DECLARE_string(temp_dir);

View File

@ -91,12 +91,10 @@ scoped_ptr<EncryptionKeySource> CreateEncryptionKeySource() {
bool AssignFlagsFromProfile() { bool AssignFlagsFromProfile() {
bool single_segment = FLAGS_single_segment; bool single_segment = FLAGS_single_segment;
bool normalize_pts = FLAGS_normalize_presentation_timestamp;
if (FLAGS_profile == "on-demand") { if (FLAGS_profile == "on-demand") {
single_segment = true; single_segment = true;
} else if (FLAGS_profile == "live") { } else if (FLAGS_profile == "live") {
single_segment = false; single_segment = false;
normalize_pts = false;
} else if (FLAGS_profile != "") { } else if (FLAGS_profile != "") {
fprintf(stderr, "ERROR: --profile '%s' is not supported.\n", fprintf(stderr, "ERROR: --profile '%s' is not supported.\n",
FLAGS_profile.c_str()); FLAGS_profile.c_str());
@ -108,12 +106,6 @@ bool AssignFlagsFromProfile() {
fprintf(stdout, "Profile %s: set --single_segment to %s.\n", fprintf(stdout, "Profile %s: set --single_segment to %s.\n",
FLAGS_profile.c_str(), single_segment ? "true" : "false"); FLAGS_profile.c_str(), single_segment ? "true" : "false");
} }
if (FLAGS_normalize_presentation_timestamp != normalize_pts) {
FLAGS_normalize_presentation_timestamp = normalize_pts;
fprintf(stdout,
"Profile %s: set --normalize_presentation_timestamp to %s.\n",
FLAGS_profile.c_str(), normalize_pts ? "true" : "false");
}
return true; return true;
} }
@ -125,8 +117,6 @@ bool GetMuxerOptions(MuxerOptions* muxer_options) {
muxer_options->fragment_duration = FLAGS_fragment_duration; muxer_options->fragment_duration = FLAGS_fragment_duration;
muxer_options->segment_sap_aligned = FLAGS_segment_sap_aligned; muxer_options->segment_sap_aligned = FLAGS_segment_sap_aligned;
muxer_options->fragment_sap_aligned = FLAGS_fragment_sap_aligned; muxer_options->fragment_sap_aligned = FLAGS_fragment_sap_aligned;
muxer_options->normalize_presentation_timestamp =
FLAGS_normalize_presentation_timestamp;
muxer_options->num_subsegments_per_sidx = FLAGS_num_subsegments_per_sidx; muxer_options->num_subsegments_per_sidx = FLAGS_num_subsegments_per_sidx;
muxer_options->temp_dir = FLAGS_temp_dir; muxer_options->temp_dir = FLAGS_temp_dir;
return true; return true;

View File

@ -14,7 +14,6 @@ MuxerOptions::MuxerOptions()
fragment_duration(0), fragment_duration(0),
segment_sap_aligned(false), segment_sap_aligned(false),
fragment_sap_aligned(false), fragment_sap_aligned(false),
normalize_presentation_timestamp(false),
num_subsegments_per_sidx(0), num_subsegments_per_sidx(0),
bandwidth(0) {} bandwidth(0) {}
MuxerOptions::~MuxerOptions() {} MuxerOptions::~MuxerOptions() {}

View File

@ -43,9 +43,6 @@ struct MuxerOptions {
/// implies that segment_sap_aligned is true as well. /// implies that segment_sap_aligned is true as well.
bool fragment_sap_aligned; bool fragment_sap_aligned;
/// Set to true to normalize the presentation timestamp to start from zero.
bool normalize_presentation_timestamp;
/// For ISO BMFF only. /// For ISO BMFF only.
/// Set the number of subsegments in each SIDX box. If 0, a single SIDX box /// Set the number of subsegments in each SIDX box. If 0, a single SIDX box
/// is used per segment. If -1, no SIDX box is used. Otherwise, the Muxer /// is used per segment. If -1, no SIDX box is used. Otherwise, the Muxer

View File

@ -23,11 +23,10 @@ namespace mp4 {
EncryptingFragmenter::EncryptingFragmenter( EncryptingFragmenter::EncryptingFragmenter(
TrackFragment* traf, TrackFragment* traf,
bool normalize_presentation_timestamp,
scoped_ptr<EncryptionKey> encryption_key, scoped_ptr<EncryptionKey> encryption_key,
int64 clear_time, int64 clear_time,
uint8 nalu_length_size) uint8 nalu_length_size)
: Fragmenter(traf, normalize_presentation_timestamp), : Fragmenter(traf),
encryption_key_(encryption_key.Pass()), encryption_key_(encryption_key.Pass()),
nalu_length_size_(nalu_length_size), nalu_length_size_(nalu_length_size),
clear_time_(clear_time) { clear_time_(clear_time) {

View File

@ -20,15 +20,12 @@ namespace mp4 {
class EncryptingFragmenter : public Fragmenter { class EncryptingFragmenter : public Fragmenter {
public: public:
/// @param traf points to a TrackFragment box. /// @param traf points to a TrackFragment box.
/// @param normalize_presentation_timestamp defines whether PTS should be
/// normalized to start from zero.
/// @param encryption_key contains the encryption parameters. /// @param encryption_key contains the encryption parameters.
/// @param clear_time specifies clear lead duration in units of the current /// @param clear_time specifies clear lead duration in units of the current
/// track's timescale. /// track's timescale.
/// @param nalu_length_size specifies the size of NAL unit length, in bytes, /// @param nalu_length_size specifies the size of NAL unit length, in bytes,
/// for subsample encryption. /// for subsample encryption.
EncryptingFragmenter(TrackFragment* traf, EncryptingFragmenter(TrackFragment* traf,
bool normalize_presentation_timestamp,
scoped_ptr<EncryptionKey> encryption_key, scoped_ptr<EncryptionKey> encryption_key,
int64 clear_time, int64 clear_time,
uint8 nalu_length_size); uint8 nalu_length_size);

View File

@ -17,13 +17,11 @@ namespace {
const int64 kInvalidTime = kint64max; const int64 kInvalidTime = kint64max;
} // namespace } // namespace
Fragmenter::Fragmenter(TrackFragment* traf, Fragmenter::Fragmenter(TrackFragment* traf)
bool normalize_presentation_timestamp)
: traf_(traf), : traf_(traf),
fragment_initialized_(false), fragment_initialized_(false),
fragment_finalized_(false), fragment_finalized_(false),
fragment_duration_(0), fragment_duration_(0),
normalize_presentation_timestamp_(normalize_presentation_timestamp),
presentation_start_time_(kInvalidTime), presentation_start_time_(kInvalidTime),
earliest_presentation_time_(kInvalidTime), earliest_presentation_time_(kInvalidTime),
first_sap_time_(kInvalidTime) { first_sap_time_(kInvalidTime) {
@ -52,21 +50,6 @@ Status Fragmenter::AddSample(scoped_refptr<MediaSample> sample) {
fragment_duration_ += sample->duration(); fragment_duration_ += sample->duration();
int64 pts = sample->pts(); int64 pts = sample->pts();
if (normalize_presentation_timestamp_) {
// Normalize PTS to start from 0. Some players do not like non-zero
// presentation starting time.
// NOTE: The timeline of the remuxed video may not be exactly the same as
// the original video. An EditList box may be useful to solve this.
if (presentation_start_time_ == kInvalidTime) {
presentation_start_time_ = pts;
pts = 0;
} else {
// Is it safe to assume the first sample in the media has the earliest
// presentation timestamp?
DCHECK_GE(pts, presentation_start_time_);
pts -= presentation_start_time_;
}
}
// Set |earliest_presentation_time_| to |pts| if |pts| is smaller or if it is // Set |earliest_presentation_time_| to |pts| if |pts| is smaller or if it is
// not yet initialized (kInvalidTime > pts is always true). // not yet initialized (kInvalidTime > pts is always true).

View File

@ -28,9 +28,7 @@ struct TrackFragment;
class Fragmenter { class Fragmenter {
public: public:
/// @param traf points to a TrackFragment box. /// @param traf points to a TrackFragment box.
/// @param normalize_presentation_timestamp defines whether PTS should be Fragmenter(TrackFragment* traf);
/// normalized to start from zero.
Fragmenter(TrackFragment* traf, bool normalize_presentation_timestamp);
virtual ~Fragmenter(); virtual ~Fragmenter();
@ -78,7 +76,6 @@ class Fragmenter {
bool fragment_initialized_; bool fragment_initialized_;
bool fragment_finalized_; bool fragment_finalized_;
uint64 fragment_duration_; uint64 fragment_duration_;
bool normalize_presentation_timestamp_;
int64 presentation_start_time_; int64 presentation_start_time_;
int64 earliest_presentation_time_; int64 earliest_presentation_time_;
int64 first_sap_time_; int64 first_sap_time_;

View File

@ -15,14 +15,12 @@ namespace mp4 {
KeyRotationFragmenter::KeyRotationFragmenter( KeyRotationFragmenter::KeyRotationFragmenter(
MovieFragment* moof, MovieFragment* moof,
TrackFragment* traf, TrackFragment* traf,
bool normalize_presentation_timestamp,
EncryptionKeySource* encryption_key_source, EncryptionKeySource* encryption_key_source,
EncryptionKeySource::TrackType track_type, EncryptionKeySource::TrackType track_type,
int64 crypto_period_duration, int64 crypto_period_duration,
int64 clear_time, int64 clear_time,
uint8 nalu_length_size) uint8 nalu_length_size)
: EncryptingFragmenter(traf, : EncryptingFragmenter(traf,
normalize_presentation_timestamp,
scoped_ptr<EncryptionKey>(new EncryptionKey()), scoped_ptr<EncryptionKey>(new EncryptionKey()),
clear_time, clear_time,
nalu_length_size), nalu_length_size),

View File

@ -21,8 +21,6 @@ class KeyRotationFragmenter : public EncryptingFragmenter {
public: public:
/// @param moof points to a MovieFragment box. /// @param moof points to a MovieFragment box.
/// @param traf points to a TrackFragment box. /// @param traf points to a TrackFragment box.
/// @param normalize_presentation_timestamp defines whether PTS should be
/// normalized to start from zero.
/// @param encryption_key_source points to the source which generates /// @param encryption_key_source points to the source which generates
/// encryption keys. /// encryption keys.
/// @param track_type indicates whether SD key or HD key should be used to /// @param track_type indicates whether SD key or HD key should be used to
@ -35,7 +33,6 @@ class KeyRotationFragmenter : public EncryptingFragmenter {
/// encryption. /// encryption.
KeyRotationFragmenter(MovieFragment* moof, KeyRotationFragmenter(MovieFragment* moof,
TrackFragment* traf, TrackFragment* traf,
bool normalize_presentation_timestamp,
EncryptionKeySource* encryption_key_source, EncryptionKeySource* encryption_key_source,
EncryptionKeySource::TrackType track_type, EncryptionKeySource::TrackType track_type,
int64 crypto_period_duration, int64 crypto_period_duration,

View File

@ -146,8 +146,7 @@ Status Segmenter::Initialize(const std::vector<MediaStream*>& streams,
sidx_->reference_id = i + 1; sidx_->reference_id = i + 1;
} }
if (!encryption_key_source) { if (!encryption_key_source) {
fragmenters_[i] = new Fragmenter( fragmenters_[i] = new Fragmenter(&moof_->tracks[i]);
&moof_->tracks[i], options_.normalize_presentation_timestamp);
continue; continue;
} }
@ -165,7 +164,6 @@ Status Segmenter::Initialize(const std::vector<MediaStream*>& streams,
fragmenters_[i] = new KeyRotationFragmenter( fragmenters_[i] = new KeyRotationFragmenter(
moof_.get(), moof_.get(),
&moof_->tracks[i], &moof_->tracks[i],
options_.normalize_presentation_timestamp,
encryption_key_source, encryption_key_source,
track_type, track_type,
crypto_period_duration_in_seconds * streams[i]->info()->time_scale(), crypto_period_duration_in_seconds * streams[i]->info()->time_scale(),
@ -191,7 +189,6 @@ Status Segmenter::Initialize(const std::vector<MediaStream*>& streams,
fragmenters_[i] = new EncryptingFragmenter( fragmenters_[i] = new EncryptingFragmenter(
&moof_->tracks[i], &moof_->tracks[i],
options_.normalize_presentation_timestamp,
encryption_key.Pass(), encryption_key.Pass(),
clear_lead_in_seconds * streams[i]->info()->time_scale(), clear_lead_in_seconds * streams[i]->info()->time_scale(),
nalu_length_size); nalu_length_size);

View File

@ -144,9 +144,25 @@ Status SingleSegmentSegmenter::DoFinalizeSegment() {
vod_sidx_.reset(new SegmentIndex()); vod_sidx_.reset(new SegmentIndex());
vod_sidx_->reference_id = sidx()->reference_id; vod_sidx_->reference_id = sidx()->reference_id;
vod_sidx_->timescale = sidx()->timescale; vod_sidx_->timescale = sidx()->timescale;
// earliest_presentation_time is the earliest presentation time of any
// access unit in the reference stream in the first subsegment. if (vod_ref.earliest_presentation_time > 0) {
vod_sidx_->earliest_presentation_time = vod_ref.earliest_presentation_time; const double starting_time_in_seconds =
static_cast<double>(vod_ref.earliest_presentation_time) /
GetReferenceTimeScale();
// Give a warning if it is significant.
if (starting_time_in_seconds > 0.5) {
// Note that DASH IF player requires presentationTimeOffset to be set in
// Segment{Base,List,Template} if there is non-zero starting time. Since
// current Chromium's MSE implementation uses DTS, the player expects
// DTS to be used.
LOG(WARNING) << "Warning! Non-zero starting time (in seconds): "
<< starting_time_in_seconds
<< ". Manual adjustment of presentationTimeOffset in "
"mpd might be necessary.";
}
}
// Force earliest_presentation_time to start from 0 for VOD.
vod_sidx_->earliest_presentation_time = 0;
} }
vod_sidx_->references.push_back(vod_ref); vod_sidx_->references.push_back(vod_ref);

View File

@ -132,10 +132,6 @@ MuxerOptions PackagerTestBasic::SetupOptions(const std::string& output,
options.fragment_duration = kFragmentDurationInSecodns; options.fragment_duration = kFragmentDurationInSecodns;
options.segment_sap_aligned = kSegmentSapAligned; options.segment_sap_aligned = kSegmentSapAligned;
options.fragment_sap_aligned = kFragmentSapAligned; options.fragment_sap_aligned = kFragmentSapAligned;
// The mp4 muxer does not generate EditList, so the starting timestamp in the
// source is not carried over. Normalize the PTS so a second parse of the
// muxed output generates the same output.
options.normalize_presentation_timestamp = true;
options.num_subsegments_per_sidx = kNumSubsegmentsPerSidx; options.num_subsegments_per_sidx = kNumSubsegmentsPerSidx;
options.output_file_name = GetFullPath(output); options.output_file_name = GetFullPath(output);