Set fragment decoding time from input sample dts
For live streams, we cannot assume that the input decoding timestamp starts from zero. Also don't overwrite |normalize_presentation_timestamp| if the user does not want to enable it for on-demand profile. Change-Id: I1abe7926e0b25eb11dee021be964d126484d4036
This commit is contained in:
parent
fc85154bca
commit
50aea3e6f6
|
@ -90,7 +90,6 @@ bool AssignFlagsFromProfile() {
|
||||||
bool normalize_pts = FLAGS_normalize_presentation_timestamp;
|
bool normalize_pts = FLAGS_normalize_presentation_timestamp;
|
||||||
if (FLAGS_profile == "on-demand") {
|
if (FLAGS_profile == "on-demand") {
|
||||||
single_segment = true;
|
single_segment = true;
|
||||||
normalize_pts = true;
|
|
||||||
} else if (FLAGS_profile == "live") {
|
} else if (FLAGS_profile == "live") {
|
||||||
single_segment = false;
|
single_segment = false;
|
||||||
normalize_pts = false;
|
normalize_pts = false;
|
||||||
|
|
|
@ -38,6 +38,11 @@ EncryptingFragmenter::~EncryptingFragmenter() {}
|
||||||
|
|
||||||
Status EncryptingFragmenter::AddSample(scoped_refptr<MediaSample> sample) {
|
Status EncryptingFragmenter::AddSample(scoped_refptr<MediaSample> sample) {
|
||||||
DCHECK(sample);
|
DCHECK(sample);
|
||||||
|
if (!fragment_initialized()) {
|
||||||
|
Status status = InitializeFragment(sample->dts());
|
||||||
|
if (!status.ok())
|
||||||
|
return status;
|
||||||
|
}
|
||||||
if (encryptor_) {
|
if (encryptor_) {
|
||||||
Status status = EncryptSample(sample);
|
Status status = EncryptSample(sample);
|
||||||
if (!status.ok())
|
if (!status.ok())
|
||||||
|
@ -46,8 +51,8 @@ Status EncryptingFragmenter::AddSample(scoped_refptr<MediaSample> sample) {
|
||||||
return Fragmenter::AddSample(sample);
|
return Fragmenter::AddSample(sample);
|
||||||
}
|
}
|
||||||
|
|
||||||
Status EncryptingFragmenter::InitializeFragment() {
|
Status EncryptingFragmenter::InitializeFragment(int64 first_sample_dts) {
|
||||||
Status status = Fragmenter::InitializeFragment();
|
Status status = Fragmenter::InitializeFragment(first_sample_dts);
|
||||||
if (!status.ok())
|
if (!status.ok())
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ class EncryptingFragmenter : public Fragmenter {
|
||||||
/// @name Fragmenter implementation overrides.
|
/// @name Fragmenter implementation overrides.
|
||||||
/// @{
|
/// @{
|
||||||
virtual Status AddSample(scoped_refptr<MediaSample> sample) OVERRIDE;
|
virtual Status AddSample(scoped_refptr<MediaSample> sample) OVERRIDE;
|
||||||
virtual Status InitializeFragment() OVERRIDE;
|
virtual Status InitializeFragment(int64 first_sample_dts) OVERRIDE;
|
||||||
virtual void FinalizeFragment() OVERRIDE;
|
virtual void FinalizeFragment() OVERRIDE;
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ const int64 kInvalidTime = kint64max;
|
||||||
Fragmenter::Fragmenter(TrackFragment* traf,
|
Fragmenter::Fragmenter(TrackFragment* traf,
|
||||||
bool normalize_presentation_timestamp)
|
bool normalize_presentation_timestamp)
|
||||||
: traf_(traf),
|
: traf_(traf),
|
||||||
|
fragment_initialized_(false),
|
||||||
fragment_finalized_(false),
|
fragment_finalized_(false),
|
||||||
fragment_duration_(0),
|
fragment_duration_(0),
|
||||||
normalize_presentation_timestamp_(normalize_presentation_timestamp),
|
normalize_presentation_timestamp_(normalize_presentation_timestamp),
|
||||||
|
@ -35,15 +36,17 @@ Status Fragmenter::AddSample(scoped_refptr<MediaSample> sample) {
|
||||||
DCHECK(sample);
|
DCHECK(sample);
|
||||||
CHECK_GT(sample->duration(), 0);
|
CHECK_GT(sample->duration(), 0);
|
||||||
|
|
||||||
|
if (!fragment_initialized_) {
|
||||||
|
Status status = InitializeFragment(sample->dts());
|
||||||
|
if (!status.ok())
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
// Fill in sample parameters. It will be optimized later.
|
// Fill in sample parameters. It will be optimized later.
|
||||||
traf_->runs[0].sample_sizes.push_back(sample->data_size());
|
traf_->runs[0].sample_sizes.push_back(sample->data_size());
|
||||||
traf_->runs[0].sample_durations.push_back(sample->duration());
|
traf_->runs[0].sample_durations.push_back(sample->duration());
|
||||||
traf_->runs[0].sample_flags.push_back(
|
traf_->runs[0].sample_flags.push_back(
|
||||||
sample->is_key_frame() ? 0 : TrackFragmentHeader::kNonKeySampleMask);
|
sample->is_key_frame() ? 0 : TrackFragmentHeader::kNonKeySampleMask);
|
||||||
traf_->runs[0].sample_composition_time_offsets.push_back(sample->pts() -
|
|
||||||
sample->dts());
|
|
||||||
if (sample->pts() != sample->dts())
|
|
||||||
traf_->runs[0].flags |= TrackFragmentRun::kSampleCompTimeOffsetsPresentMask;
|
|
||||||
|
|
||||||
data_->AppendArray(sample->data(), sample->data_size());
|
data_->AppendArray(sample->data(), sample->data_size());
|
||||||
fragment_duration_ += sample->duration();
|
fragment_duration_ += sample->duration();
|
||||||
|
@ -70,6 +73,10 @@ Status Fragmenter::AddSample(scoped_refptr<MediaSample> sample) {
|
||||||
if (earliest_presentation_time_ > pts)
|
if (earliest_presentation_time_ > pts)
|
||||||
earliest_presentation_time_ = pts;
|
earliest_presentation_time_ = pts;
|
||||||
|
|
||||||
|
traf_->runs[0].sample_composition_time_offsets.push_back(pts - sample->dts());
|
||||||
|
if (pts != sample->dts())
|
||||||
|
traf_->runs[0].flags |= TrackFragmentRun::kSampleCompTimeOffsetsPresentMask;
|
||||||
|
|
||||||
if (sample->is_key_frame()) {
|
if (sample->is_key_frame()) {
|
||||||
if (first_sap_time_ == kInvalidTime)
|
if (first_sap_time_ == kInvalidTime)
|
||||||
first_sap_time_ = pts;
|
first_sap_time_ = pts;
|
||||||
|
@ -77,9 +84,10 @@ Status Fragmenter::AddSample(scoped_refptr<MediaSample> sample) {
|
||||||
return Status::OK;
|
return Status::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status Fragmenter::InitializeFragment() {
|
Status Fragmenter::InitializeFragment(int64 first_sample_dts) {
|
||||||
|
fragment_initialized_ = true;
|
||||||
fragment_finalized_ = false;
|
fragment_finalized_ = false;
|
||||||
traf_->decode_time.decode_time += fragment_duration_;
|
traf_->decode_time.decode_time = first_sample_dts;
|
||||||
traf_->runs.clear();
|
traf_->runs.clear();
|
||||||
traf_->runs.resize(1);
|
traf_->runs.resize(1);
|
||||||
traf_->runs[0].flags = TrackFragmentRun::kDataOffsetPresentMask;
|
traf_->runs[0].flags = TrackFragmentRun::kDataOffsetPresentMask;
|
||||||
|
@ -116,6 +124,7 @@ void Fragmenter::FinalizeFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fragment_finalized_ = true;
|
fragment_finalized_ = true;
|
||||||
|
fragment_initialized_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fragmenter::GenerateSegmentReference(SegmentReference* reference) {
|
void Fragmenter::GenerateSegmentReference(SegmentReference* reference) {
|
||||||
|
|
|
@ -40,8 +40,10 @@ class Fragmenter {
|
||||||
virtual Status AddSample(scoped_refptr<MediaSample> sample);
|
virtual Status AddSample(scoped_refptr<MediaSample> sample);
|
||||||
|
|
||||||
/// Initialize the fragment with default data.
|
/// Initialize the fragment with default data.
|
||||||
|
/// @param first_sample_dts specifies the decoding timestamp for the first
|
||||||
|
/// sample for this fragment.
|
||||||
/// @return OK on success, an error status otherwise.
|
/// @return OK on success, an error status otherwise.
|
||||||
virtual Status InitializeFragment();
|
virtual Status InitializeFragment(int64 first_sample_dts);
|
||||||
|
|
||||||
/// Finalize and optimize the fragment.
|
/// Finalize and optimize the fragment.
|
||||||
virtual void FinalizeFragment();
|
virtual void FinalizeFragment();
|
||||||
|
@ -54,6 +56,7 @@ class Fragmenter {
|
||||||
uint64 earliest_presentation_time() const {
|
uint64 earliest_presentation_time() const {
|
||||||
return earliest_presentation_time_;
|
return earliest_presentation_time_;
|
||||||
}
|
}
|
||||||
|
bool fragment_initialized() const { return fragment_initialized_; }
|
||||||
bool fragment_finalized() const { return fragment_finalized_; }
|
bool fragment_finalized() const { return fragment_finalized_; }
|
||||||
BufferWriter* data() { return data_.get(); }
|
BufferWriter* data() { return data_.get(); }
|
||||||
BufferWriter* aux_data() { return aux_data_.get(); }
|
BufferWriter* aux_data() { return aux_data_.get(); }
|
||||||
|
@ -72,6 +75,7 @@ class Fragmenter {
|
||||||
bool StartsWithSAP();
|
bool StartsWithSAP();
|
||||||
|
|
||||||
TrackFragment* traf_;
|
TrackFragment* traf_;
|
||||||
|
bool fragment_initialized_;
|
||||||
bool fragment_finalized_;
|
bool fragment_finalized_;
|
||||||
uint64 fragment_duration_;
|
uint64 fragment_duration_;
|
||||||
bool normalize_presentation_timestamp_;
|
bool normalize_presentation_timestamp_;
|
||||||
|
|
|
@ -204,8 +204,8 @@ Status Segmenter::Initialize(const std::vector<MediaStream*>& streams,
|
||||||
|
|
||||||
// Use the reference stream's time scale as movie time scale.
|
// Use the reference stream's time scale as movie time scale.
|
||||||
moov_->header.timescale = sidx_->timescale;
|
moov_->header.timescale = sidx_->timescale;
|
||||||
Status status = InitializeFragments();
|
moof_->header.sequence_number = 1;
|
||||||
return status.ok() ? DoInitialize() : status;
|
return DoInitialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
Status Segmenter::Finalize() {
|
Status Segmenter::Finalize() {
|
||||||
|
@ -320,19 +320,6 @@ uint32 Segmenter::GetReferenceStreamId() {
|
||||||
return sidx_->reference_id - 1;
|
return sidx_->reference_id - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status Segmenter::InitializeFragments() {
|
|
||||||
++moof_->header.sequence_number;
|
|
||||||
Status status;
|
|
||||||
for (std::vector<Fragmenter*>::iterator it = fragmenters_.begin();
|
|
||||||
it != fragmenters_.end();
|
|
||||||
++it) {
|
|
||||||
status = (*it)->InitializeFragment();
|
|
||||||
if (!status.ok())
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
return Status::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status Segmenter::FinalizeFragment(Fragmenter* fragmenter) {
|
Status Segmenter::FinalizeFragment(Fragmenter* fragmenter) {
|
||||||
fragmenter->FinalizeFragment();
|
fragmenter->FinalizeFragment();
|
||||||
|
|
||||||
|
@ -379,9 +366,8 @@ Status Segmenter::FinalizeFragment(Fragmenter* fragmenter) {
|
||||||
fragment_buffer_->AppendBuffer(*fragmenter->data());
|
fragment_buffer_->AppendBuffer(*fragmenter->data());
|
||||||
}
|
}
|
||||||
|
|
||||||
Status status = InitializeFragments();
|
// Increase sequence_number for next fragment.
|
||||||
if (!status.ok())
|
++moof_->header.sequence_number;
|
||||||
return status;
|
|
||||||
|
|
||||||
if (end_of_segment_)
|
if (end_of_segment_)
|
||||||
return FinalizeSegment();
|
return FinalizeSegment();
|
||||||
|
|
|
@ -111,7 +111,6 @@ class Segmenter {
|
||||||
Status FinalizeSegment();
|
Status FinalizeSegment();
|
||||||
uint32 GetReferenceStreamId();
|
uint32 GetReferenceStreamId();
|
||||||
|
|
||||||
Status InitializeFragments();
|
|
||||||
Status FinalizeFragment(Fragmenter* fragment);
|
Status FinalizeFragment(Fragmenter* fragment);
|
||||||
|
|
||||||
const MuxerOptions& options_;
|
const MuxerOptions& options_;
|
||||||
|
|
Loading…
Reference in New Issue