From 336435fccaea17e61e790fa8ad504497dbc08e93 Mon Sep 17 00:00:00 2001 From: Kongqun Yang Date: Mon, 3 Aug 2015 17:28:11 -0700 Subject: [PATCH] Address one sample fragment issue #33 The segment duration was not reset after segment was finalized. It was reset after adding one sample. This new sample was added to the new fragment but was not recorded in the new segment, which resulted in off-by-one error in the segment generation. Change-Id: I1f9e00591be6b897773bf6caf94409b4bcd2277f --- packager/media/formats/mp4/segmenter.cc | 32 ++++++++----------- packager/media/formats/mp4/segmenter.h | 4 +-- .../formats/mp4/single_segment_segmenter.cc | 2 +- 3 files changed, 15 insertions(+), 23 deletions(-) diff --git a/packager/media/formats/mp4/segmenter.cc b/packager/media/formats/mp4/segmenter.cc index ea9b004b7b..9526d764b4 100644 --- a/packager/media/formats/mp4/segmenter.cc +++ b/packager/media/formats/mp4/segmenter.cc @@ -123,8 +123,6 @@ Segmenter::Segmenter(const MuxerOptions& options, moof_(new MovieFragment()), fragment_buffer_(new BufferWriter()), sidx_(new SegmentIndex()), - segment_initialized_(false), - end_of_segment_(false), muxer_listener_(NULL), progress_listener_(NULL), progress_target_(0), @@ -228,11 +226,10 @@ Status Segmenter::Initialize(const std::vector& streams, } Status Segmenter::Finalize() { - end_of_segment_ = true; for (std::vector::iterator it = fragmenters_.begin(); it != fragmenters_.end(); ++it) { - Status status = FinalizeFragment(*it); + Status status = FinalizeFragment(true, *it); if (!status.ok()) return status; } @@ -268,11 +265,6 @@ Status Segmenter::AddSample(const MediaStream* stream, sample->duration(); } - if (!segment_initialized_) { - InitializeSegment(); - segment_initialized_ = true; - } - if (fragmenter->fragment_finalized()) { return Status(error::FRAGMENT_FINALIZED, "Current fragment is finalized already."); @@ -285,17 +277,18 @@ Status Segmenter::AddSample(const MediaStream* stream, finalize_fragment = true; } } + bool finalize_segment = false; if (segment_durations_[stream_id] >= options_.segment_duration * stream->info()->time_scale()) { if (sample->is_key_frame() || !options_.segment_sap_aligned) { - end_of_segment_ = true; + finalize_segment = true; finalize_fragment = true; } } Status status; if (finalize_fragment) { - status = FinalizeFragment(fragmenter); + status = FinalizeFragment(finalize_segment, fragmenter); if (!status.ok()) return status; } @@ -308,6 +301,7 @@ Status Segmenter::AddSample(const MediaStream* stream, sample_duration_ = sample->duration(); moov_->tracks[stream_id].media.header.duration += sample->duration(); segment_durations_[stream_id] += sample->duration(); + DCHECK_GE(segment_durations_[stream_id], fragmenter->fragment_duration()); return Status::OK; } @@ -345,17 +339,16 @@ void Segmenter::SetComplete() { progress_listener_->OnProgress(1.0); } -void Segmenter::InitializeSegment() { +Status Segmenter::FinalizeSegment() { + Status status = DoFinalizeSegment(); + + // Reset segment information to initial state. sidx_->references.clear(); - end_of_segment_ = false; std::vector::iterator it = segment_durations_.begin(); for (; it != segment_durations_.end(); ++it) *it = 0; -} -Status Segmenter::FinalizeSegment() { - segment_initialized_ = false; - return DoFinalizeSegment(); + return status; } uint32_t Segmenter::GetReferenceStreamId() { @@ -363,7 +356,8 @@ uint32_t Segmenter::GetReferenceStreamId() { return sidx_->reference_id - 1; } -Status Segmenter::FinalizeFragment(Fragmenter* fragmenter) { +Status Segmenter::FinalizeFragment(bool finalize_segment, + Fragmenter* fragmenter) { fragmenter->FinalizeFragment(); // Check if all tracks are ready for fragmentation. @@ -412,7 +406,7 @@ Status Segmenter::FinalizeFragment(Fragmenter* fragmenter) { // Increase sequence_number for next fragment. ++moof_->header.sequence_number; - if (end_of_segment_) + if (finalize_segment) return FinalizeSegment(); return Status::OK; diff --git a/packager/media/formats/mp4/segmenter.h b/packager/media/formats/mp4/segmenter.h index fbc2f52cf1..2bdb889050 100644 --- a/packager/media/formats/mp4/segmenter.h +++ b/packager/media/formats/mp4/segmenter.h @@ -123,11 +123,10 @@ class Segmenter { virtual Status DoFinalize() = 0; virtual Status DoFinalizeSegment() = 0; - void InitializeSegment(); Status FinalizeSegment(); uint32_t GetReferenceStreamId(); - Status FinalizeFragment(Fragmenter* fragment); + Status FinalizeFragment(bool finalize_segment, Fragmenter* fragment); const MuxerOptions& options_; scoped_ptr ftyp_; @@ -138,7 +137,6 @@ class Segmenter { std::vector fragmenters_; std::vector segment_durations_; std::map stream_map_; - bool segment_initialized_; bool end_of_segment_; MuxerListener* muxer_listener_; ProgressListener* progress_listener_; diff --git a/packager/media/formats/mp4/single_segment_segmenter.cc b/packager/media/formats/mp4/single_segment_segmenter.cc index b09755ad98..ef3f82e78e 100644 --- a/packager/media/formats/mp4/single_segment_segmenter.cc +++ b/packager/media/formats/mp4/single_segment_segmenter.cc @@ -169,7 +169,7 @@ Status SingleSegmentSegmenter::DoFinalizeSegment() { SegmentReference& vod_ref = refs[0]; uint64_t first_sap_time = refs[0].sap_delta_time + refs[0].earliest_presentation_time; - for (uint32_t i = 1; i < sidx()->references.size(); ++i) { + for (uint32_t i = 1; i < refs.size(); ++i) { vod_ref.referenced_size += refs[i].referenced_size; // NOTE: We calculate subsegment duration based on the total duration of // this subsegment instead of subtracting earliest_presentation_time as