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

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

Powered by Google App Engine
This is Rietveld 408576698