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

Side by Side 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: cr feedback 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/filters/source_buffer_stream.h" 5 #include "media/filters/source_buffer_stream.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <map> 8 #include <map>
9 #include <sstream> 9 #include <sstream>
10 10
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 132
133 } // namespace 133 } // namespace
134 134
135 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config, 135 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config,
136 const scoped_refptr<MediaLog>& media_log, 136 const scoped_refptr<MediaLog>& media_log,
137 bool splice_frames_enabled) 137 bool splice_frames_enabled)
138 : media_log_(media_log), 138 : media_log_(media_log),
139 seek_buffer_timestamp_(kNoTimestamp()), 139 seek_buffer_timestamp_(kNoTimestamp()),
140 media_segment_start_time_(kNoDecodeTimestamp()), 140 media_segment_start_time_(kNoDecodeTimestamp()),
141 range_for_next_append_(ranges_.end()), 141 range_for_next_append_(ranges_.end()),
142 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
143 last_output_buffer_timestamp_(kNoDecodeTimestamp()), 142 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
144 max_interbuffer_distance_(kNoTimestamp()), 143 max_interbuffer_distance_(kNoTimestamp()),
145 memory_limit_(kSourceBufferAudioMemoryLimit), 144 memory_limit_(kSourceBufferAudioMemoryLimit),
146 splice_frames_enabled_(splice_frames_enabled) { 145 splice_frames_enabled_(splice_frames_enabled) {
147 DCHECK(audio_config.IsValidConfig()); 146 DCHECK(audio_config.IsValidConfig());
148 audio_configs_.push_back(audio_config); 147 audio_configs_.push_back(audio_config);
149 } 148 }
150 149
151 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config, 150 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config,
152 const scoped_refptr<MediaLog>& media_log, 151 const scoped_refptr<MediaLog>& media_log,
153 bool splice_frames_enabled) 152 bool splice_frames_enabled)
154 : media_log_(media_log), 153 : media_log_(media_log),
155 seek_buffer_timestamp_(kNoTimestamp()), 154 seek_buffer_timestamp_(kNoTimestamp()),
156 media_segment_start_time_(kNoDecodeTimestamp()), 155 media_segment_start_time_(kNoDecodeTimestamp()),
157 range_for_next_append_(ranges_.end()), 156 range_for_next_append_(ranges_.end()),
158 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
159 last_output_buffer_timestamp_(kNoDecodeTimestamp()), 157 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
160 max_interbuffer_distance_(kNoTimestamp()), 158 max_interbuffer_distance_(kNoTimestamp()),
161 memory_limit_(kSourceBufferVideoMemoryLimit), 159 memory_limit_(kSourceBufferVideoMemoryLimit),
162 splice_frames_enabled_(splice_frames_enabled) { 160 splice_frames_enabled_(splice_frames_enabled) {
163 DCHECK(video_config.IsValidConfig()); 161 DCHECK(video_config.IsValidConfig());
164 video_configs_.push_back(video_config); 162 video_configs_.push_back(video_config);
165 } 163 }
166 164
167 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config, 165 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config,
168 const scoped_refptr<MediaLog>& media_log, 166 const scoped_refptr<MediaLog>& media_log,
169 bool splice_frames_enabled) 167 bool splice_frames_enabled)
170 : media_log_(media_log), 168 : media_log_(media_log),
171 text_track_config_(text_config), 169 text_track_config_(text_config),
172 seek_buffer_timestamp_(kNoTimestamp()), 170 seek_buffer_timestamp_(kNoTimestamp()),
173 media_segment_start_time_(kNoDecodeTimestamp()), 171 media_segment_start_time_(kNoDecodeTimestamp()),
174 range_for_next_append_(ranges_.end()), 172 range_for_next_append_(ranges_.end()),
175 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
176 last_output_buffer_timestamp_(kNoDecodeTimestamp()), 173 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
177 max_interbuffer_distance_(kNoTimestamp()), 174 max_interbuffer_distance_(kNoTimestamp()),
178 memory_limit_(kSourceBufferAudioMemoryLimit), 175 memory_limit_(kSourceBufferAudioMemoryLimit),
179 splice_frames_enabled_(splice_frames_enabled) {} 176 splice_frames_enabled_(splice_frames_enabled) {}
180 177
181 SourceBufferStream::~SourceBufferStream() { 178 SourceBufferStream::~SourceBufferStream() {
182 while (!ranges_.empty()) { 179 while (!ranges_.empty()) {
183 delete ranges_.front(); 180 delete ranges_.front();
184 ranges_.pop_front(); 181 ranges_.pop_front();
185 } 182 }
186 } 183 }
187 184
188 void SourceBufferStream::OnNewMediaSegment( 185 void SourceBufferStream::OnNewMediaSegment(
189 DecodeTimestamp media_segment_start_time) { 186 DecodeTimestamp media_segment_start_time) {
190 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() 187 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
191 << " (" << media_segment_start_time.InSecondsF() << ")"; 188 << " (" << media_segment_start_time.InSecondsF() << ")";
192 DCHECK(!end_of_stream_); 189 DCHECK(!end_of_stream_);
193 media_segment_start_time_ = media_segment_start_time; 190 media_segment_start_time_ = media_segment_start_time;
194 new_media_segment_ = true; 191 new_media_segment_ = true;
195 192
196 RangeList::iterator last_range = range_for_next_append_; 193 RangeList::iterator last_range = range_for_next_append_;
197 range_for_next_append_ = FindExistingRangeFor(media_segment_start_time); 194 range_for_next_append_ = FindExistingRangeFor(media_segment_start_time);
198 195
199 // Only reset |last_appended_buffer_timestamp_| if this new media segment is 196 // Only reset |last_appended_buffer_timestamp_| if this new media segment is
200 // not adjacent to the previous media segment appended to the stream. 197 // not adjacent to the previous media segment appended to the stream.
201 if (range_for_next_append_ == ranges_.end() || 198 if (range_for_next_append_ == ranges_.end() ||
202 !AreAdjacentInSequence(last_appended_buffer_timestamp_, 199 !AreAdjacentInSequence(last_appended_buffer_timestamp_,
203 media_segment_start_time)) { 200 media_segment_start_time)) {
204 last_appended_buffer_timestamp_ = kNoDecodeTimestamp(); 201 last_appended_buffer_timestamp_ = kNoDecodeTimestamp();
202 last_appended_buffer_duration_ = kNoTimestamp();
205 last_appended_buffer_is_keyframe_ = false; 203 last_appended_buffer_is_keyframe_ = false;
206 DVLOG(3) << __FUNCTION__ << " next appended buffers will be in a new range"; 204 DVLOG(3) << __FUNCTION__ << " next appended buffers will be in a new range";
207 } else if (last_range != ranges_.end()) { 205 } else if (last_range != ranges_.end()) {
208 DCHECK(last_range == range_for_next_append_); 206 DCHECK(last_range == range_for_next_append_);
209 DVLOG(3) << __FUNCTION__ << " next appended buffers will continue range " 207 DVLOG(3) << __FUNCTION__ << " next appended buffers will continue range "
210 << "unless intervening remove makes discontinuity"; 208 << "unless intervening remove makes discontinuity";
211 } 209 }
212 } 210 }
213 211
214 bool SourceBufferStream::Append(const BufferQueue& buffers) { 212 bool SourceBufferStream::Append(const BufferQueue& buffers) {
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 DecodeTimestamp next_buffer_timestamp = GetNextBufferTimestamp(); 260 DecodeTimestamp next_buffer_timestamp = GetNextBufferTimestamp();
263 BufferQueue deleted_buffers; 261 BufferQueue deleted_buffers;
264 262
265 PrepareRangesForNextAppend(buffers, &deleted_buffers); 263 PrepareRangesForNextAppend(buffers, &deleted_buffers);
266 264
267 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise, 265 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise,
268 // create a new range with |buffers|. 266 // create a new range with |buffers|.
269 if (range_for_next_append_ != ranges_.end()) { 267 if (range_for_next_append_ != ranges_.end()) {
270 (*range_for_next_append_)->AppendBuffersToEnd(buffers); 268 (*range_for_next_append_)->AppendBuffersToEnd(buffers);
271 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp(); 269 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp();
270 last_appended_buffer_duration_ = buffers.back()->duration();
272 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame(); 271 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame();
273 } else { 272 } else {
274 DecodeTimestamp new_range_start_time = std::min( 273 DecodeTimestamp new_range_start_time = std::min(
275 media_segment_start_time_, buffers.front()->GetDecodeTimestamp()); 274 media_segment_start_time_, buffers.front()->GetDecodeTimestamp());
276 const BufferQueue* buffers_for_new_range = &buffers; 275 const BufferQueue* buffers_for_new_range = &buffers;
277 BufferQueue trimmed_buffers; 276 BufferQueue trimmed_buffers;
278 277
279 // If the new range is not being created because of a new media 278 // If the new range is not being created because of a new media
280 // segment, then we must make sure that we start with a key frame. 279 // segment, then we must make sure that we start with a key frame.
281 // This can happen if the GOP in the previous append gets destroyed 280 // This can happen if the GOP in the previous append gets destroyed
282 // by a Remove() call. 281 // by a Remove() call.
283 if (!new_media_segment_) { 282 if (!new_media_segment_) {
284 BufferQueue::const_iterator itr = buffers.begin(); 283 BufferQueue::const_iterator itr = buffers.begin();
285 284
286 // Scan past all the non-key-frames. 285 // Scan past all the non-key-frames.
287 while (itr != buffers.end() && !(*itr)->is_key_frame()) { 286 while (itr != buffers.end() && !(*itr)->is_key_frame()) {
288 ++itr; 287 ++itr;
289 } 288 }
290 289
291 // If we didn't find a key frame, then update the last appended 290 // If we didn't find a key frame, then update the last appended
292 // buffer state and return. 291 // buffer state and return.
293 if (itr == buffers.end()) { 292 if (itr == buffers.end()) {
294 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp(); 293 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp();
294 last_appended_buffer_duration_ = buffers.back()->duration();
295 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame(); 295 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame();
296 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() 296 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
297 << ": new buffers in the middle of media segment depend on" 297 << ": new buffers in the middle of media segment depend on"
298 "keyframe that has been removed, and contain no keyframes." 298 "keyframe that has been removed, and contain no keyframes."
299 "Skipping further processing."; 299 "Skipping further processing.";
300 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() 300 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
301 << ": done. ranges_=" << RangesToString(ranges_); 301 << ": done. ranges_=" << RangesToString(ranges_);
302 return true; 302 return true;
303 } else if (itr != buffers.begin()) { 303 } else if (itr != buffers.begin()) {
304 // Copy the first key frame and everything after it into 304 // Copy the first key frame and everything after it into
305 // |trimmed_buffers|. 305 // |trimmed_buffers|.
306 trimmed_buffers.assign(itr, buffers.end()); 306 trimmed_buffers.assign(itr, buffers.end());
307 buffers_for_new_range = &trimmed_buffers; 307 buffers_for_new_range = &trimmed_buffers;
308 } 308 }
309 309
310 new_range_start_time = 310 new_range_start_time =
311 buffers_for_new_range->front()->GetDecodeTimestamp(); 311 buffers_for_new_range->front()->GetDecodeTimestamp();
312 } 312 }
313 313
314 range_for_next_append_ = 314 range_for_next_append_ =
315 AddToRanges(new SourceBufferRange( 315 AddToRanges(new SourceBufferRange(
316 TypeToGapPolicy(GetType()), 316 TypeToGapPolicy(GetType()),
317 *buffers_for_new_range, new_range_start_time, 317 *buffers_for_new_range, new_range_start_time,
318 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance, 318 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance,
319 base::Unretained(this)))); 319 base::Unretained(this))));
320 last_appended_buffer_timestamp_ = 320 last_appended_buffer_timestamp_ =
321 buffers_for_new_range->back()->GetDecodeTimestamp(); 321 buffers_for_new_range->back()->GetDecodeTimestamp();
322 last_appended_buffer_duration_ = buffers_for_new_range->back()->duration();
322 last_appended_buffer_is_keyframe_ = 323 last_appended_buffer_is_keyframe_ =
323 buffers_for_new_range->back()->is_key_frame(); 324 buffers_for_new_range->back()->is_key_frame();
324 } 325 }
325 326
326 new_media_segment_ = false; 327 new_media_segment_ = false;
327 328
328 MergeWithAdjacentRangeIfNecessary(range_for_next_append_); 329 MergeWithAdjacentRangeIfNecessary(range_for_next_append_);
329 330
330 // Seek to try to fulfill a previous call to Seek(). 331 // Seek to try to fulfill a previous call to Seek().
331 if (seek_pending_) { 332 if (seek_pending_) {
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
649 << " newDataSize=" << newDataSize 650 << " newDataSize=" << newDataSize
650 << " memory_limit_=" << memory_limit_ 651 << " memory_limit_=" << memory_limit_
651 << " last_appended_buffer_timestamp_=" 652 << " last_appended_buffer_timestamp_="
652 << last_appended_buffer_timestamp_.InSecondsF(); 653 << last_appended_buffer_timestamp_.InSecondsF();
653 654
654 size_t bytes_freed = 0; 655 size_t bytes_freed = 0;
655 656
656 // If last appended buffer position was earlier than the current playback time 657 // If last appended buffer position was earlier than the current playback time
657 // then try deleting data between last append and current media_time. 658 // then try deleting data between last append and current media_time.
658 if (last_appended_buffer_timestamp_ != kNoDecodeTimestamp() && 659 if (last_appended_buffer_timestamp_ != kNoDecodeTimestamp() &&
659 last_appended_buffer_timestamp_ < media_time) { 660 last_appended_buffer_duration_ != kNoTimestamp() &&
661 media_time >
662 last_appended_buffer_timestamp_ + last_appended_buffer_duration_) {
660 size_t between = FreeBuffersAfterLastAppended(bytes_to_free, media_time); 663 size_t between = FreeBuffersAfterLastAppended(bytes_to_free, media_time);
661 DVLOG(3) << __FUNCTION__ << " FreeBuffersAfterLastAppended " 664 DVLOG(3) << __FUNCTION__ << " FreeBuffersAfterLastAppended "
662 << " released " << between << " bytes" 665 << " released " << between << " bytes"
663 << " ranges_=" << RangesToString(ranges_); 666 << " ranges_=" << RangesToString(ranges_);
664 bytes_freed += between; 667 bytes_freed += between;
665 668
666 // Some players start appending data at the new seek target position before 669 // Some players start appending data at the new seek target position before
667 // actually initiating the seek operation (i.e. they try to improve seek 670 // actually initiating the seek operation (i.e. they try to improve seek
668 // performance by prebuffering some data at the seek target position and 671 // performance by prebuffering some data at the seek target position and
669 // initiating seek once enough data is pre-buffered. In those cases we'll 672 // initiating seek once enough data is pre-buffered. In those cases we'll
670 // see that data is being appended at some new position, but there is no 673 // see that data is being appended at some new position, but there is no
671 // pending seek reported yet. In this situation we need to try preserving 674 // pending seek reported yet. In this situation we need to try preserving
672 // the most recently appended data, i.e. data belonging to the same buffered 675 // the most recently appended data, i.e. data belonging to the same buffered
673 // range as the most recent append. 676 // range as the most recent append.
674 if (range_for_next_append_ != ranges_.end()) { 677 if (range_for_next_append_ != ranges_.end()) {
675 DCHECK((*range_for_next_append_)->GetStartTimestamp() <= media_time); 678 DCHECK((*range_for_next_append_)->GetStartTimestamp() <= media_time);
676 media_time = (*range_for_next_append_)->GetStartTimestamp(); 679 media_time = (*range_for_next_append_)->GetStartTimestamp();
680 DVLOG(3) << __FUNCTION__ << " media_time adjusted to "
681 << media_time.InSecondsF();
677 } 682 }
678 } 683 }
679 684
680 // If there is an unsatisfied pending seek, we can safely remove all data that 685 // If there is an unsatisfied pending seek, we can safely remove all data that
681 // is earlier than seek target, then remove from the back until we reach the 686 // is earlier than seek target, then remove from the back until we reach the
682 // most recently appended GOP and then remove from the front if we still don't 687 // most recently appended GOP and then remove from the front if we still don't
683 // have enough space for the upcoming append. 688 // have enough space for the upcoming append.
684 if (bytes_freed < bytes_to_free && seek_pending_) { 689 if (bytes_freed < bytes_to_free && seek_pending_) {
685 DCHECK(!ranges_.empty()); 690 DCHECK(!ranges_.empty());
686 // All data earlier than the seek target |media_time| can be removed safely 691 // All data earlier than the seek target |media_time| can be removed safely
(...skipping 1068 matching lines...) Expand 10 before | Expand all | Expand 10 after
1755 return false; 1760 return false;
1756 1761
1757 DCHECK_NE(have_splice_buffers, have_preroll_buffer); 1762 DCHECK_NE(have_splice_buffers, have_preroll_buffer);
1758 splice_buffers_index_ = 0; 1763 splice_buffers_index_ = 0;
1759 pending_buffer_.swap(*out_buffer); 1764 pending_buffer_.swap(*out_buffer);
1760 pending_buffers_complete_ = false; 1765 pending_buffers_complete_ = false;
1761 return true; 1766 return true;
1762 } 1767 }
1763 1768
1764 } // namespace media 1769 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698