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
This commit is contained in:
Kongqun Yang 2015-08-03 17:28:11 -07:00
parent fca2bb1e44
commit 336435fcca
3 changed files with 15 additions and 23 deletions

View File

@ -123,8 +123,6 @@ Segmenter::Segmenter(const MuxerOptions& options,
moof_(new MovieFragment()), moof_(new MovieFragment()),
fragment_buffer_(new BufferWriter()), fragment_buffer_(new BufferWriter()),
sidx_(new SegmentIndex()), sidx_(new SegmentIndex()),
segment_initialized_(false),
end_of_segment_(false),
muxer_listener_(NULL), muxer_listener_(NULL),
progress_listener_(NULL), progress_listener_(NULL),
progress_target_(0), progress_target_(0),
@ -228,11 +226,10 @@ Status Segmenter::Initialize(const std::vector<MediaStream*>& streams,
} }
Status Segmenter::Finalize() { Status Segmenter::Finalize() {
end_of_segment_ = true;
for (std::vector<Fragmenter*>::iterator it = fragmenters_.begin(); for (std::vector<Fragmenter*>::iterator it = fragmenters_.begin();
it != fragmenters_.end(); it != fragmenters_.end();
++it) { ++it) {
Status status = FinalizeFragment(*it); Status status = FinalizeFragment(true, *it);
if (!status.ok()) if (!status.ok())
return status; return status;
} }
@ -268,11 +265,6 @@ Status Segmenter::AddSample(const MediaStream* stream,
sample->duration(); sample->duration();
} }
if (!segment_initialized_) {
InitializeSegment();
segment_initialized_ = true;
}
if (fragmenter->fragment_finalized()) { if (fragmenter->fragment_finalized()) {
return Status(error::FRAGMENT_FINALIZED, return Status(error::FRAGMENT_FINALIZED,
"Current fragment is finalized already."); "Current fragment is finalized already.");
@ -285,17 +277,18 @@ Status Segmenter::AddSample(const MediaStream* stream,
finalize_fragment = true; finalize_fragment = true;
} }
} }
bool finalize_segment = false;
if (segment_durations_[stream_id] >= if (segment_durations_[stream_id] >=
options_.segment_duration * stream->info()->time_scale()) { options_.segment_duration * stream->info()->time_scale()) {
if (sample->is_key_frame() || !options_.segment_sap_aligned) { if (sample->is_key_frame() || !options_.segment_sap_aligned) {
end_of_segment_ = true; finalize_segment = true;
finalize_fragment = true; finalize_fragment = true;
} }
} }
Status status; Status status;
if (finalize_fragment) { if (finalize_fragment) {
status = FinalizeFragment(fragmenter); status = FinalizeFragment(finalize_segment, fragmenter);
if (!status.ok()) if (!status.ok())
return status; return status;
} }
@ -308,6 +301,7 @@ Status Segmenter::AddSample(const MediaStream* stream,
sample_duration_ = sample->duration(); sample_duration_ = sample->duration();
moov_->tracks[stream_id].media.header.duration += sample->duration(); moov_->tracks[stream_id].media.header.duration += sample->duration();
segment_durations_[stream_id] += sample->duration(); segment_durations_[stream_id] += sample->duration();
DCHECK_GE(segment_durations_[stream_id], fragmenter->fragment_duration());
return Status::OK; return Status::OK;
} }
@ -345,17 +339,16 @@ void Segmenter::SetComplete() {
progress_listener_->OnProgress(1.0); progress_listener_->OnProgress(1.0);
} }
void Segmenter::InitializeSegment() { Status Segmenter::FinalizeSegment() {
Status status = DoFinalizeSegment();
// Reset segment information to initial state.
sidx_->references.clear(); sidx_->references.clear();
end_of_segment_ = false;
std::vector<uint64_t>::iterator it = segment_durations_.begin(); std::vector<uint64_t>::iterator it = segment_durations_.begin();
for (; it != segment_durations_.end(); ++it) for (; it != segment_durations_.end(); ++it)
*it = 0; *it = 0;
}
Status Segmenter::FinalizeSegment() { return status;
segment_initialized_ = false;
return DoFinalizeSegment();
} }
uint32_t Segmenter::GetReferenceStreamId() { uint32_t Segmenter::GetReferenceStreamId() {
@ -363,7 +356,8 @@ uint32_t Segmenter::GetReferenceStreamId() {
return sidx_->reference_id - 1; return sidx_->reference_id - 1;
} }
Status Segmenter::FinalizeFragment(Fragmenter* fragmenter) { Status Segmenter::FinalizeFragment(bool finalize_segment,
Fragmenter* fragmenter) {
fragmenter->FinalizeFragment(); fragmenter->FinalizeFragment();
// Check if all tracks are ready for fragmentation. // Check if all tracks are ready for fragmentation.
@ -412,7 +406,7 @@ Status Segmenter::FinalizeFragment(Fragmenter* fragmenter) {
// Increase sequence_number for next fragment. // Increase sequence_number for next fragment.
++moof_->header.sequence_number; ++moof_->header.sequence_number;
if (end_of_segment_) if (finalize_segment)
return FinalizeSegment(); return FinalizeSegment();
return Status::OK; return Status::OK;

View File

@ -123,11 +123,10 @@ class Segmenter {
virtual Status DoFinalize() = 0; virtual Status DoFinalize() = 0;
virtual Status DoFinalizeSegment() = 0; virtual Status DoFinalizeSegment() = 0;
void InitializeSegment();
Status FinalizeSegment(); Status FinalizeSegment();
uint32_t GetReferenceStreamId(); uint32_t GetReferenceStreamId();
Status FinalizeFragment(Fragmenter* fragment); Status FinalizeFragment(bool finalize_segment, Fragmenter* fragment);
const MuxerOptions& options_; const MuxerOptions& options_;
scoped_ptr<FileType> ftyp_; scoped_ptr<FileType> ftyp_;
@ -138,7 +137,6 @@ class Segmenter {
std::vector<Fragmenter*> fragmenters_; std::vector<Fragmenter*> fragmenters_;
std::vector<uint64_t> segment_durations_; std::vector<uint64_t> segment_durations_;
std::map<const MediaStream*, uint32_t> stream_map_; std::map<const MediaStream*, uint32_t> stream_map_;
bool segment_initialized_;
bool end_of_segment_; bool end_of_segment_;
MuxerListener* muxer_listener_; MuxerListener* muxer_listener_;
ProgressListener* progress_listener_; ProgressListener* progress_listener_;

View File

@ -169,7 +169,7 @@ Status SingleSegmentSegmenter::DoFinalizeSegment() {
SegmentReference& vod_ref = refs[0]; SegmentReference& vod_ref = refs[0];
uint64_t first_sap_time = uint64_t first_sap_time =
refs[0].sap_delta_time + refs[0].earliest_presentation_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; vod_ref.referenced_size += refs[i].referenced_size;
// NOTE: We calculate subsegment duration based on the total duration of // NOTE: We calculate subsegment duration based on the total duration of
// this subsegment instead of subtracting earliest_presentation_time as // this subsegment instead of subtracting earliest_presentation_time as