Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(862)

Unified Diff: media/filters/source_buffer_stream.cc

Issue 1008463002: Fix MSE GC, make it less aggressive, more spec-compliant (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: A bit more informative logging + fixed unit test Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: media/filters/source_buffer_stream.cc
diff --git a/media/filters/source_buffer_stream.cc b/media/filters/source_buffer_stream.cc
index 75c9c31fd344fab814e09c442fa15429f1422097..11383b2f5696ca0bd2977df057fbfea680ca25a4 100644
--- a/media/filters/source_buffer_stream.cc
+++ b/media/filters/source_buffer_stream.cc
@@ -392,8 +392,6 @@ bool SourceBufferStream::Append(const BufferQueue& buffers) {
SetSelectedRangeIfNeeded(next_buffer_timestamp);
- GarbageCollectIfNeeded();
-
DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
<< ": done. ranges_=" << RangesToString(ranges_);
DCHECK(IsRangeListSorted(ranges_));
@@ -641,7 +639,8 @@ void SourceBufferStream::SetConfigIds(const BufferQueue& buffers) {
}
}
-void SourceBufferStream::GarbageCollectIfNeeded() {
+bool SourceBufferStream::GarbageCollectIfNeeded(DecodeTimestamp media_time) {
+ DCHECK(media_time != kNoDecodeTimestamp());
// Compute size of |ranges_|.
size_t ranges_size = 0;
for (RangeList::iterator itr = ranges_.begin(); itr != ranges_.end(); ++itr)
@@ -649,39 +648,71 @@ void SourceBufferStream::GarbageCollectIfNeeded() {
// Return if we're under or at the memory limit.
if (ranges_size <= memory_limit_)
- return;
+ return true;
size_t bytes_to_free = ranges_size - memory_limit_;
DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName() << ": Before GC"
- << " ranges_size=" << ranges_size
+ << " media_time=" << media_time.InSecondsF()
<< " ranges_=" << RangesToString(ranges_)
- << " memory_limit_=" << memory_limit_;
+ << " ranges_size=" << ranges_size
+ << " memory_limit_=" << memory_limit_
+ << " last_appended_buffer_timestamp_="
+ << last_appended_buffer_timestamp_.InSecondsF();
- // Begin deleting after the last appended buffer.
- size_t bytes_freed = FreeBuffersAfterLastAppended(bytes_to_free);
+ size_t bytes_freed = 0;
- // Begin deleting from the front.
- if (bytes_freed < bytes_to_free)
- bytes_freed += FreeBuffers(bytes_to_free - bytes_freed, false);
+ // If last appended buffer position was earlier than the current playback time
+ // then try deleting data between last append and current media_time.
+ if (last_appended_buffer_timestamp_ != kNoDecodeTimestamp() &&
+ last_appended_buffer_timestamp_ < media_time) {
+ size_t between = FreeBuffersAfterLastAppended(bytes_to_free, media_time);
+ DVLOG(3) << __FUNCTION__ << " FreeBuffersAfterLastAppended "
+ << " released " << between << " bytes"
+ << " ranges_=" << RangesToString(ranges_);
+ bytes_freed += between;
+
+ // If the last append happened before the current playback position
+ // |media_time|, then JS player is probably preparing to seek back and we
+ // should try to preserve all most recently appended data (which is in
+ // range_for_next_append_) from being removed by GC (see crbug.com/440173)
+ if (range_for_next_append_ != ranges_.end()) {
+ DCHECK((*range_for_next_append_)->GetStartTimestamp() <= media_time);
+ media_time = (*range_for_next_append_)->GetStartTimestamp();
wolenetz 2015/08/12 21:09:57 This may be too lax, though web apps can follow-up
servolk 2015/08/13 00:31:42 Wait, we will only adjust media time here if range
+ }
+ }
- // Begin deleting from the back.
- if (bytes_freed < bytes_to_free)
- bytes_freed += FreeBuffers(bytes_to_free - bytes_freed, true);
+ // Try removing data from the front of the SourceBuffer up to |media_time|
+ // position.
+ if (bytes_freed < bytes_to_free) {
+ size_t front = FreeBuffers(bytes_to_free - bytes_freed, media_time, false);
+ DVLOG(3) << __FUNCTION__ << " Removed " << front << " bytes from the front"
+ << " ranges_=" << RangesToString(ranges_);
+ bytes_freed += front;
+ }
+
+ // Try removing data from the back of the SourceBuffer, until we reach the
+ // most recent append position.
+ if (bytes_freed < bytes_to_free) {
+ size_t back = FreeBuffers(bytes_to_free - bytes_freed, media_time, true);
+ DVLOG(3) << __FUNCTION__ << " Removed " << back << " bytes from the back"
+ << " ranges_=" << RangesToString(ranges_);
+ bytes_freed += back;
+ }
DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName() << ": After GC"
+ << " bytes_to_free=" << bytes_to_free
<< " bytes_freed=" << bytes_freed
<< " ranges_=" << RangesToString(ranges_);
+
+ return bytes_freed >= bytes_to_free;
}
size_t SourceBufferStream::FreeBuffersAfterLastAppended(
- size_t total_bytes_to_free) {
- DecodeTimestamp next_buffer_timestamp = GetNextBufferTimestamp();
- if (last_appended_buffer_timestamp_ == kNoDecodeTimestamp() ||
- next_buffer_timestamp == kNoDecodeTimestamp() ||
- last_appended_buffer_timestamp_ >= next_buffer_timestamp) {
- return 0;
- }
+ size_t total_bytes_to_free, DecodeTimestamp media_time) {
+ DVLOG(4) << __FUNCTION__ << " last_appended_buffer_timestamp_="
+ << last_appended_buffer_timestamp_.InSecondsF()
+ << " media_time=" << media_time.InSecondsF();
DecodeTimestamp remove_range_start = last_appended_buffer_timestamp_;
if (last_appended_buffer_is_keyframe_)
@@ -691,18 +722,21 @@ size_t SourceBufferStream::FreeBuffersAfterLastAppended(
remove_range_start);
if (remove_range_start_keyframe != kNoDecodeTimestamp())
remove_range_start = remove_range_start_keyframe;
- if (remove_range_start >= next_buffer_timestamp)
+ if (remove_range_start >= media_time)
return 0;
DecodeTimestamp remove_range_end;
size_t bytes_freed = GetRemovalRange(remove_range_start,
- next_buffer_timestamp,
+ media_time,
total_bytes_to_free,
&remove_range_end);
if (bytes_freed > 0) {
+ DVLOG(4) << __FUNCTION__ << " removing ["
+ << remove_range_start.ToPresentationTime().InSecondsF() << ";"
+ << remove_range_end.ToPresentationTime().InSecondsF() << "]";
Remove(remove_range_start.ToPresentationTime(),
remove_range_end.ToPresentationTime(),
- next_buffer_timestamp.ToPresentationTime());
+ media_time.ToPresentationTime());
}
return bytes_freed;
@@ -735,6 +769,7 @@ size_t SourceBufferStream::GetRemovalRange(
}
size_t SourceBufferStream::FreeBuffers(size_t total_bytes_to_free,
+ DecodeTimestamp media_time,
bool reverse_direction) {
TRACE_EVENT2("media", "SourceBufferStream::FreeBuffers",
"total bytes to free", total_bytes_to_free,
@@ -754,17 +789,24 @@ size_t SourceBufferStream::FreeBuffers(size_t total_bytes_to_free,
if (reverse_direction) {
current_range = ranges_.back();
+ DVLOG(5) << "current_range=" << RangeToString(*current_range);
if (current_range->LastGOPContainsNextBufferPosition()) {
DCHECK_EQ(current_range, selected_range_);
+ DVLOG(5) << "current_range contains next read position, stopping GC";
break;
}
+ DVLOG(5) << "Deleting GOP from back: " << RangeToString(*current_range);
bytes_deleted = current_range->DeleteGOPFromBack(&buffers);
} else {
current_range = ranges_.front();
- if (current_range->FirstGOPContainsNextBufferPosition()) {
- DCHECK_EQ(current_range, selected_range_);
+ DVLOG(5) << "current_range=" << RangeToString(*current_range);
+ if (!current_range->FirstGOPEarlierThanMediaTime(media_time)) {
+ // We have removed all data up to the GOP that contains current playback
+ // position, we can't delete any further.
+ DVLOG(5) << "current_range contains playback position, stopping GC";
break;
}
+ DVLOG(4) << "Deleting GOP from front: " << RangeToString(*current_range);
bytes_deleted = current_range->DeleteGOPFromFront(&buffers);
}
@@ -773,6 +815,7 @@ size_t SourceBufferStream::FreeBuffers(size_t total_bytes_to_free,
if (end_timestamp == last_appended_buffer_timestamp_) {
DCHECK(last_appended_buffer_timestamp_ != kNoDecodeTimestamp());
DCHECK(!new_range_for_append);
+
// Create a new range containing these buffers.
new_range_for_append = new SourceBufferRange(
TypeToGapPolicy(GetType()),
@@ -791,6 +834,11 @@ size_t SourceBufferStream::FreeBuffers(size_t total_bytes_to_free,
delete current_range;
reverse_direction ? ranges_.pop_back() : ranges_.pop_front();
}
+
+ if (reverse_direction && new_range_for_append) {
+ // We don't want to delete any further, or we'll be creating gaps
+ break;
+ }
}
// Insert |new_range_for_append| into |ranges_|, if applicable.
@@ -1220,8 +1268,10 @@ void SourceBufferStream::SeekAndSetSelectedRange(
}
void SourceBufferStream::SetSelectedRange(SourceBufferRange* range) {
- DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
- << ": " << selected_range_ << " -> " << range;
+ DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() << ": "
+ << selected_range_ << " "
+ << (selected_range_ ? RangeToString(*selected_range_) : "")
+ << " -> " << range << " " << (range ? RangeToString(*range) : "");
if (selected_range_)
selected_range_->ResetNextBufferPosition();
DCHECK(!range || range->HasNextBufferPosition());

Powered by Google App Engine
This is Rietveld 408576698