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

Unified Diff: media/filters/source_buffer_stream.cc

Issue 1491513002: [MSE] Fix GC with media_time past the last appended buffer timestamp (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Implement media_time clamping to buffered ranges Created 5 years 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
« no previous file with comments | « media/filters/source_buffer_stream.h ('k') | media/filters/source_buffer_stream_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/filters/source_buffer_stream.cc
diff --git a/media/filters/source_buffer_stream.cc b/media/filters/source_buffer_stream.cc
index 4c74c2ac73011195ff49609231828857ab62ca05..619ff47ab7d4c54a1dcc070384c3ab0bfcfe5c70 100644
--- a/media/filters/source_buffer_stream.cc
+++ b/media/filters/source_buffer_stream.cc
@@ -139,7 +139,6 @@ SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config,
seek_buffer_timestamp_(kNoTimestamp()),
media_segment_start_time_(kNoDecodeTimestamp()),
range_for_next_append_(ranges_.end()),
- last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
last_output_buffer_timestamp_(kNoDecodeTimestamp()),
max_interbuffer_distance_(kNoTimestamp()),
memory_limit_(kSourceBufferAudioMemoryLimit),
@@ -155,7 +154,6 @@ SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config,
seek_buffer_timestamp_(kNoTimestamp()),
media_segment_start_time_(kNoDecodeTimestamp()),
range_for_next_append_(ranges_.end()),
- last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
last_output_buffer_timestamp_(kNoDecodeTimestamp()),
max_interbuffer_distance_(kNoTimestamp()),
memory_limit_(kSourceBufferVideoMemoryLimit),
@@ -172,7 +170,6 @@ SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config,
seek_buffer_timestamp_(kNoTimestamp()),
media_segment_start_time_(kNoDecodeTimestamp()),
range_for_next_append_(ranges_.end()),
- last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
last_output_buffer_timestamp_(kNoDecodeTimestamp()),
max_interbuffer_distance_(kNoTimestamp()),
memory_limit_(kSourceBufferAudioMemoryLimit),
@@ -202,6 +199,7 @@ void SourceBufferStream::OnNewMediaSegment(
!AreAdjacentInSequence(last_appended_buffer_timestamp_,
media_segment_start_time)) {
last_appended_buffer_timestamp_ = kNoDecodeTimestamp();
+ last_appended_buffer_duration_ = kNoTimestamp();
last_appended_buffer_is_keyframe_ = false;
DVLOG(3) << __FUNCTION__ << " next appended buffers will be in a new range";
} else if (last_range != ranges_.end()) {
@@ -269,6 +267,7 @@ bool SourceBufferStream::Append(const BufferQueue& buffers) {
if (range_for_next_append_ != ranges_.end()) {
(*range_for_next_append_)->AppendBuffersToEnd(buffers);
last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp();
+ last_appended_buffer_duration_ = buffers.back()->duration();
last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame();
} else {
DecodeTimestamp new_range_start_time = std::min(
@@ -292,6 +291,7 @@ bool SourceBufferStream::Append(const BufferQueue& buffers) {
// buffer state and return.
if (itr == buffers.end()) {
last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp();
+ last_appended_buffer_duration_ = buffers.back()->duration();
last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame();
DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
<< ": new buffers in the middle of media segment depend on"
@@ -319,6 +319,7 @@ bool SourceBufferStream::Append(const BufferQueue& buffers) {
base::Unretained(this))));
last_appended_buffer_timestamp_ =
buffers_for_new_range->back()->GetDecodeTimestamp();
+ last_appended_buffer_duration_ = buffers_for_new_range->back()->duration();
last_appended_buffer_is_keyframe_ =
buffers_for_new_range->back()->is_key_frame();
}
@@ -651,12 +652,36 @@ bool SourceBufferStream::GarbageCollectIfNeeded(DecodeTimestamp media_time,
<< " last_appended_buffer_timestamp_="
<< last_appended_buffer_timestamp_.InSecondsF();
+ if (selected_range_ && !seek_pending_ &&
+ media_time > selected_range_->GetBufferedEndTimestamp()) {
+ // Strictly speaking |media_time| (taken from HTMLMediaElement::currentTime)
+ // should always be in the buffered ranges, but media::Pipeline uses audio
+ // stream as the main time source, when audio is present.
+ // In cases when audio and video streams have different buffered ranges, the
+ // |media_time| value might be slightly outside of the video stream buffered
+ // range. In those cases we need to clamp |media_time| value to the current
+ // stream buffered ranges, to ensure the MSE garbage collection algorithm
+ // works correctly (see crbug.com/563292 for details).
+ DecodeTimestamp selected_buffered_end =
+ selected_range_->GetBufferedEndTimestamp();
+
+ DVLOG(2) << __FUNCTION__ << " media_time " << media_time.InSecondsF()
+ << " is outside of selected_range_=["
+ << selected_range_->GetStartTimestamp().InSecondsF() << ";"
+ << selected_buffered_end.InSecondsF()
+ << "] clamping media_time to be "
+ << selected_buffered_end.InSecondsF();
+ media_time = selected_buffered_end;
+ }
+
size_t bytes_freed = 0;
// 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) {
+ last_appended_buffer_duration_ != kNoTimestamp() &&
+ media_time >
+ last_appended_buffer_timestamp_ + last_appended_buffer_duration_) {
size_t between = FreeBuffersAfterLastAppended(bytes_to_free, media_time);
DVLOG(3) << __FUNCTION__ << " FreeBuffersAfterLastAppended "
<< " released " << between << " bytes"
@@ -674,6 +699,8 @@ bool SourceBufferStream::GarbageCollectIfNeeded(DecodeTimestamp media_time,
if (range_for_next_append_ != ranges_.end()) {
DCHECK((*range_for_next_append_)->GetStartTimestamp() <= media_time);
media_time = (*range_for_next_append_)->GetStartTimestamp();
+ DVLOG(3) << __FUNCTION__ << " media_time adjusted to "
+ << media_time.InSecondsF();
}
}
« no previous file with comments | « media/filters/source_buffer_stream.h ('k') | media/filters/source_buffer_stream_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698