| Index: media/filters/source_buffer_stream.cc
|
| diff --git a/media/filters/source_buffer_stream.cc b/media/filters/source_buffer_stream.cc
|
| index a57c11278e7af5d306531802f211c4fc9f63ec4c..5fdc619bc896ef3e0bb9a4e599f26553d1982b8e 100644
|
| --- a/media/filters/source_buffer_stream.cc
|
| +++ b/media/filters/source_buffer_stream.cc
|
| @@ -207,9 +207,7 @@ void SourceBufferStream::OnStartOfCodedFrameGroup(
|
| if (range_for_next_append_ == ranges_.end() ||
|
| !AreAdjacentInSequence(last_appended_buffer_timestamp_,
|
| coded_frame_group_start_time)) {
|
| - last_appended_buffer_timestamp_ = kNoDecodeTimestamp();
|
| - last_appended_buffer_duration_ = kNoTimestamp;
|
| - last_appended_buffer_is_keyframe_ = false;
|
| + ResetLastAppendedState();
|
| DVLOG(3) << __func__ << " next appended buffers will "
|
| << (range_for_next_append_ == ranges_.end()
|
| ? "be in a new range"
|
| @@ -454,6 +452,50 @@ DecodeTimestamp SourceBufferStream::PotentialNextAppendTimestamp() const {
|
| return kNoDecodeTimestamp();
|
| }
|
|
|
| +void SourceBufferStream::UpdateLastAppendStateForRemove(
|
| + DecodeTimestamp remove_start,
|
| + DecodeTimestamp remove_end,
|
| + bool exclude_start) {
|
| + // TODO(chcunningham): change exclude_start to include_start in this class and
|
| + // SourceBufferRange. Negatives are hard to reason about.
|
| + bool include_start = !exclude_start;
|
| +
|
| + // No need to check previous append's GOP if starting a new CFG. New CFG is
|
| + // already required to begin with a key frame.
|
| + if (new_coded_frame_group_)
|
| + return;
|
| +
|
| + if (range_for_next_append_ != ranges_.end()) {
|
| + if (last_appended_buffer_timestamp_ != kNoDecodeTimestamp()) {
|
| + DCHECK((*range_for_next_append_)
|
| + ->BelongsToRange(last_appended_buffer_timestamp_));
|
| +
|
| + // Note start and end of last appended GOP.
|
| + DecodeTimestamp gop_end = last_appended_buffer_timestamp_;
|
| + DecodeTimestamp gop_start =
|
| + (*range_for_next_append_)->KeyframeBeforeTimestamp(gop_end);
|
| +
|
| + // If last append is about to be disrupted, reset associated state so we
|
| + // know to create a new range for future appends and require an initial
|
| + // key frame.
|
| + if (((include_start && remove_start == gop_end) ||
|
| + remove_start < gop_end) &&
|
| + remove_end > gop_start) {
|
| + DVLOG(2) << __func__ << " " << GetStreamTypeName()
|
| + << " Resetting next append state for remove ("
|
| + << remove_start.InSecondsF() << ", " << remove_end.InSecondsF()
|
| + << ", " << exclude_start << ")";
|
| + range_for_next_append_ = ranges_.end();
|
| + ResetLastAppendedState();
|
| + }
|
| + } else {
|
| + NOTREACHED() << __func__ << " " << GetStreamTypeName()
|
| + << " range_for_next_append_ set, but not tracking last"
|
| + << " append nor new coded frame group.";
|
| + }
|
| + }
|
| +}
|
| +
|
| void SourceBufferStream::RemoveInternal(DecodeTimestamp start,
|
| DecodeTimestamp end,
|
| bool exclude_start,
|
| @@ -469,8 +511,10 @@ void SourceBufferStream::RemoveInternal(DecodeTimestamp start,
|
| << " end " << end.InSecondsF();
|
| DCHECK(deleted_buffers);
|
|
|
| - RangeList::iterator itr = ranges_.begin();
|
| + // Doing this upfront simplifies decisions about range_for_next_append_ below.
|
| + UpdateLastAppendStateForRemove(start, end, exclude_start);
|
|
|
| + RangeList::iterator itr = ranges_.begin();
|
| while (itr != ranges_.end()) {
|
| SourceBufferRange* range = *itr;
|
| if (range->GetStartTimestamp() >= end)
|
| @@ -564,6 +608,12 @@ void SourceBufferStream::ResetSeekState() {
|
| pending_buffers_complete_ = false;
|
| }
|
|
|
| +void SourceBufferStream::ResetLastAppendedState() {
|
| + last_appended_buffer_timestamp_ = kNoDecodeTimestamp();
|
| + last_appended_buffer_duration_ = kNoTimestamp;
|
| + last_appended_buffer_is_keyframe_ = false;
|
| +}
|
| +
|
| bool SourceBufferStream::ShouldSeekToStartOfBuffered(
|
| base::TimeDelta seek_timestamp) const {
|
| if (ranges_.empty())
|
| @@ -1113,39 +1163,25 @@ bool SourceBufferStream::IsSeekPending() const {
|
| }
|
|
|
| void SourceBufferStream::OnSetDuration(base::TimeDelta duration) {
|
| - DecodeTimestamp duration_dts =
|
| - DecodeTimestamp::FromPresentationTime(duration);
|
| DVLOG(1) << __func__ << " " << GetStreamTypeName() << " ("
|
| << duration.InSecondsF() << ")";
|
| + DCHECK(!end_of_stream_);
|
|
|
| - RangeList::iterator itr = ranges_.end();
|
| - for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
|
| - if ((*itr)->GetEndTimestamp() > duration_dts)
|
| - break;
|
| - }
|
| - if (itr == ranges_.end())
|
| + if (ranges_.empty())
|
| return;
|
|
|
| - // Need to partially truncate this range.
|
| - if ((*itr)->GetStartTimestamp() < duration_dts) {
|
| - bool delete_range = (*itr)->TruncateAt(duration_dts, NULL, false);
|
| - if ((*itr == selected_range_) && !selected_range_->HasNextBufferPosition())
|
| - SetSelectedRange(NULL);
|
| + DecodeTimestamp start = DecodeTimestamp::FromPresentationTime(duration);
|
| + DecodeTimestamp end = ranges_.back()->GetBufferedEndTimestamp();
|
|
|
| - if (delete_range) {
|
| - DeleteAndRemoveRange(&itr);
|
| - } else {
|
| - ++itr;
|
| - }
|
| - }
|
| + // Trim the end if it exceeds the new duration.
|
| + if (start < end) {
|
| + BufferQueue deleted_buffers;
|
| + RemoveInternal(start, end, false, &deleted_buffers);
|
|
|
| - // Delete all ranges that begin after |duration_dts|.
|
| - while (itr != ranges_.end()) {
|
| - // If we're about to delete the selected range, also reset the seek state.
|
| - DCHECK((*itr)->GetStartTimestamp() >= duration_dts);
|
| - if (*itr == selected_range_)
|
| - ResetSeekState();
|
| - DeleteAndRemoveRange(&itr);
|
| + if (!deleted_buffers.empty()) {
|
| + // Truncation removed current position. Clear selected range.
|
| + SetSelectedRange(NULL);
|
| + }
|
| }
|
| }
|
|
|
| @@ -1684,8 +1720,7 @@ void SourceBufferStream::DeleteAndRemoveRange(RangeList::iterator* itr) {
|
| if (*itr == range_for_next_append_) {
|
| DVLOG(1) << __func__ << " deleting range_for_next_append_.";
|
| range_for_next_append_ = ranges_.end();
|
| - last_appended_buffer_timestamp_ = kNoDecodeTimestamp();
|
| - last_appended_buffer_is_keyframe_ = false;
|
| + ResetLastAppendedState();
|
| }
|
|
|
| delete **itr;
|
|
|