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:
parent
66f155502d
commit
3e6190ec2b
|
@ -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
|
||||||
|
|
|
@ -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 "
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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() {}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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).
|
||||||
|
|
|
@ -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_;
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue