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:
KongQun Yang 2014-06-30 09:32:06 -07:00
parent fc85154bca
commit 50aea3e6f6
7 changed files with 32 additions and 30 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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;
/// @}

View File

@ -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) {

View File

@ -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_;

View File

@ -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();

View File

@ -111,7 +111,6 @@ class Segmenter {
Status FinalizeSegment();
uint32 GetReferenceStreamId();
Status InitializeFragments();
Status FinalizeFragment(Fragmenter* fragment);
const MuxerOptions& options_;