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;
|
||||
if (FLAGS_profile == "on-demand") {
|
||||
single_segment = true;
|
||||
normalize_pts = true;
|
||||
} else if (FLAGS_profile == "live") {
|
||||
single_segment = false;
|
||||
normalize_pts = false;
|
||||
|
|
|
@ -38,6 +38,11 @@ EncryptingFragmenter::~EncryptingFragmenter() {}
|
|||
|
||||
Status EncryptingFragmenter::AddSample(scoped_refptr<MediaSample> sample) {
|
||||
DCHECK(sample);
|
||||
if (!fragment_initialized()) {
|
||||
Status status = InitializeFragment(sample->dts());
|
||||
if (!status.ok())
|
||||
return status;
|
||||
}
|
||||
if (encryptor_) {
|
||||
Status status = EncryptSample(sample);
|
||||
if (!status.ok())
|
||||
|
@ -46,8 +51,8 @@ Status EncryptingFragmenter::AddSample(scoped_refptr<MediaSample> sample) {
|
|||
return Fragmenter::AddSample(sample);
|
||||
}
|
||||
|
||||
Status EncryptingFragmenter::InitializeFragment() {
|
||||
Status status = Fragmenter::InitializeFragment();
|
||||
Status EncryptingFragmenter::InitializeFragment(int64 first_sample_dts) {
|
||||
Status status = Fragmenter::InitializeFragment(first_sample_dts);
|
||||
if (!status.ok())
|
||||
return status;
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ class EncryptingFragmenter : public Fragmenter {
|
|||
/// @name Fragmenter implementation overrides.
|
||||
/// @{
|
||||
virtual Status AddSample(scoped_refptr<MediaSample> sample) OVERRIDE;
|
||||
virtual Status InitializeFragment() OVERRIDE;
|
||||
virtual Status InitializeFragment(int64 first_sample_dts) OVERRIDE;
|
||||
virtual void FinalizeFragment() OVERRIDE;
|
||||
/// @}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ const int64 kInvalidTime = kint64max;
|
|||
Fragmenter::Fragmenter(TrackFragment* traf,
|
||||
bool normalize_presentation_timestamp)
|
||||
: traf_(traf),
|
||||
fragment_initialized_(false),
|
||||
fragment_finalized_(false),
|
||||
fragment_duration_(0),
|
||||
normalize_presentation_timestamp_(normalize_presentation_timestamp),
|
||||
|
@ -35,15 +36,17 @@ Status Fragmenter::AddSample(scoped_refptr<MediaSample> sample) {
|
|||
DCHECK(sample);
|
||||
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.
|
||||
traf_->runs[0].sample_sizes.push_back(sample->data_size());
|
||||
traf_->runs[0].sample_durations.push_back(sample->duration());
|
||||
traf_->runs[0].sample_flags.push_back(
|
||||
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());
|
||||
fragment_duration_ += sample->duration();
|
||||
|
@ -70,6 +73,10 @@ Status Fragmenter::AddSample(scoped_refptr<MediaSample> sample) {
|
|||
if (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 (first_sap_time_ == kInvalidTime)
|
||||
first_sap_time_ = pts;
|
||||
|
@ -77,9 +84,10 @@ Status Fragmenter::AddSample(scoped_refptr<MediaSample> sample) {
|
|||
return Status::OK;
|
||||
}
|
||||
|
||||
Status Fragmenter::InitializeFragment() {
|
||||
Status Fragmenter::InitializeFragment(int64 first_sample_dts) {
|
||||
fragment_initialized_ = true;
|
||||
fragment_finalized_ = false;
|
||||
traf_->decode_time.decode_time += fragment_duration_;
|
||||
traf_->decode_time.decode_time = first_sample_dts;
|
||||
traf_->runs.clear();
|
||||
traf_->runs.resize(1);
|
||||
traf_->runs[0].flags = TrackFragmentRun::kDataOffsetPresentMask;
|
||||
|
@ -116,6 +124,7 @@ void Fragmenter::FinalizeFragment() {
|
|||
}
|
||||
|
||||
fragment_finalized_ = true;
|
||||
fragment_initialized_ = false;
|
||||
}
|
||||
|
||||
void Fragmenter::GenerateSegmentReference(SegmentReference* reference) {
|
||||
|
|
|
@ -40,8 +40,10 @@ class Fragmenter {
|
|||
virtual Status AddSample(scoped_refptr<MediaSample> sample);
|
||||
|
||||
/// 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.
|
||||
virtual Status InitializeFragment();
|
||||
virtual Status InitializeFragment(int64 first_sample_dts);
|
||||
|
||||
/// Finalize and optimize the fragment.
|
||||
virtual void FinalizeFragment();
|
||||
|
@ -54,6 +56,7 @@ class Fragmenter {
|
|||
uint64 earliest_presentation_time() const {
|
||||
return earliest_presentation_time_;
|
||||
}
|
||||
bool fragment_initialized() const { return fragment_initialized_; }
|
||||
bool fragment_finalized() const { return fragment_finalized_; }
|
||||
BufferWriter* data() { return data_.get(); }
|
||||
BufferWriter* aux_data() { return aux_data_.get(); }
|
||||
|
@ -72,6 +75,7 @@ class Fragmenter {
|
|||
bool StartsWithSAP();
|
||||
|
||||
TrackFragment* traf_;
|
||||
bool fragment_initialized_;
|
||||
bool fragment_finalized_;
|
||||
uint64 fragment_duration_;
|
||||
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.
|
||||
moov_->header.timescale = sidx_->timescale;
|
||||
Status status = InitializeFragments();
|
||||
return status.ok() ? DoInitialize() : status;
|
||||
moof_->header.sequence_number = 1;
|
||||
return DoInitialize();
|
||||
}
|
||||
|
||||
Status Segmenter::Finalize() {
|
||||
|
@ -320,19 +320,6 @@ uint32 Segmenter::GetReferenceStreamId() {
|
|||
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) {
|
||||
fragmenter->FinalizeFragment();
|
||||
|
||||
|
@ -379,9 +366,8 @@ Status Segmenter::FinalizeFragment(Fragmenter* fragmenter) {
|
|||
fragment_buffer_->AppendBuffer(*fragmenter->data());
|
||||
}
|
||||
|
||||
Status status = InitializeFragments();
|
||||
if (!status.ok())
|
||||
return status;
|
||||
// Increase sequence_number for next fragment.
|
||||
++moof_->header.sequence_number;
|
||||
|
||||
if (end_of_segment_)
|
||||
return FinalizeSegment();
|
||||
|
|
|
@ -111,7 +111,6 @@ class Segmenter {
|
|||
Status FinalizeSegment();
|
||||
uint32 GetReferenceStreamId();
|
||||
|
||||
Status InitializeFragments();
|
||||
Status FinalizeFragment(Fragmenter* fragment);
|
||||
|
||||
const MuxerOptions& options_;
|
||||
|
|
Loading…
Reference in New Issue