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
3 // found in the LICENSE file.
5 #include "media/filters/source_buffer_stream.h"
11 #include "base/bind.h"
12 #include "base/logging.h"
13 #include "base/trace_event/trace_event.h"
14 #include "media/base/audio_splicer.h"
15 #include "media/filters/source_buffer_platform.h"
16 #include "media/filters/source_buffer_range.h"
22 // An arbitrarily-chosen number to estimate the duration of a buffer if none is
23 // set and there's not enough information to get a better estimate.
24 const int kDefaultBufferDurationInMs
= 125;
26 // Limit the number of MEDIA_LOG() logs for splice buffer generation warnings
27 // and successes. Though these values are high enough to possibly exhaust the
28 // media internals event cache (along with other events), these logs are
29 // important for debugging splice generation.
30 const int kMaxSpliceGenerationWarningLogs
= 50;
31 const int kMaxSpliceGenerationSuccessLogs
= 20;
33 // Limit the number of MEDIA_LOG() logs for track buffer time gaps.
34 const int kMaxTrackBufferGapWarningLogs
= 20;
36 // Helper method that returns true if |ranges| is sorted in increasing order,
38 bool IsRangeListSorted(const std::list
<media::SourceBufferRange
*>& ranges
) {
39 DecodeTimestamp prev
= kNoDecodeTimestamp();
40 for (std::list
<SourceBufferRange
*>::const_iterator itr
=
41 ranges
.begin(); itr
!= ranges
.end(); ++itr
) {
42 if (prev
!= kNoDecodeTimestamp() && prev
>= (*itr
)->GetStartTimestamp())
44 prev
= (*itr
)->GetEndTimestamp();
49 // Returns an estimate of how far from the beginning or end of a range a buffer
50 // can be to still be considered in the range, given the |approximate_duration|
51 // of a buffer in the stream.
52 // TODO(wolenetz): Once all stream parsers emit accurate frame durations, use
53 // logic like FrameProcessor (2*last_frame_duration + last_decode_timestamp)
54 // instead of an overall maximum interbuffer delta for range discontinuity
55 // detection, and adjust similarly for splice frame discontinuity detection.
56 // See http://crbug.com/351489 and http://crbug.com/351166.
57 base::TimeDelta
ComputeFudgeRoom(base::TimeDelta approximate_duration
) {
58 // Because we do not know exactly when is the next timestamp, any buffer
59 // that starts within 2x the approximate duration of a buffer is considered
61 return 2 * approximate_duration
;
64 // The amount of time the beginning of the buffered data can differ from the
65 // start time in order to still be considered the start of stream.
66 base::TimeDelta
kSeekToStartFudgeRoom() {
67 return base::TimeDelta::FromMilliseconds(1000);
70 // Helper method for logging, converts a range into a readable string.
71 std::string
RangeToString(const SourceBufferRange
& range
) {
72 if (range
.size_in_bytes() == 0) {
76 ss
<< "[" << range
.GetStartTimestamp().InSecondsF()
77 << ";" << range
.GetEndTimestamp().InSecondsF()
78 << "(" << range
.GetBufferedEndTimestamp().InSecondsF() << ")]";
82 // Helper method for logging, converts a set of ranges into a readable string.
83 std::string
RangesToString(const SourceBufferStream::RangeList
& ranges
) {
88 for (const auto* range_ptr
: ranges
) {
89 if (range_ptr
!= ranges
.front())
91 ss
<< RangeToString(*range_ptr
);
96 std::string
BufferQueueToLogString(
97 const SourceBufferStream::BufferQueue
& buffers
) {
98 std::stringstream result
;
99 if (buffers
.front()->GetDecodeTimestamp().InMicroseconds() ==
100 buffers
.front()->timestamp().InMicroseconds() &&
101 buffers
.back()->GetDecodeTimestamp().InMicroseconds() ==
102 buffers
.back()->timestamp().InMicroseconds()) {
103 result
<< "dts/pts=[" << buffers
.front()->timestamp().InSecondsF() << ";"
104 << buffers
.back()->timestamp().InSecondsF() << "(last frame dur="
105 << buffers
.back()->duration().InSecondsF() << ")]";
107 result
<< "dts=[" << buffers
.front()->GetDecodeTimestamp().InSecondsF()
108 << ";" << buffers
.back()->GetDecodeTimestamp().InSecondsF()
109 << "] pts=[" << buffers
.front()->timestamp().InSecondsF() << ";"
110 << buffers
.back()->timestamp().InSecondsF() << "(last frame dur="
111 << buffers
.back()->duration().InSecondsF() << ")]";
116 SourceBufferRange::GapPolicy
TypeToGapPolicy(SourceBufferStream::Type type
) {
118 case SourceBufferStream::kAudio
:
119 case SourceBufferStream::kVideo
:
120 return SourceBufferRange::NO_GAPS_ALLOWED
;
121 case SourceBufferStream::kText
:
122 return SourceBufferRange::ALLOW_GAPS
;
126 return SourceBufferRange::NO_GAPS_ALLOWED
;
131 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig
& audio_config
,
132 const scoped_refptr
<MediaLog
>& media_log
,
133 bool splice_frames_enabled
)
134 : media_log_(media_log
),
135 seek_buffer_timestamp_(kNoTimestamp()),
136 media_segment_start_time_(kNoDecodeTimestamp()),
137 range_for_next_append_(ranges_
.end()),
138 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
139 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
140 max_interbuffer_distance_(kNoTimestamp()),
141 memory_limit_(kSourceBufferAudioMemoryLimit
),
142 splice_frames_enabled_(splice_frames_enabled
) {
143 DCHECK(audio_config
.IsValidConfig());
144 audio_configs_
.push_back(audio_config
);
147 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig
& video_config
,
148 const scoped_refptr
<MediaLog
>& media_log
,
149 bool splice_frames_enabled
)
150 : media_log_(media_log
),
151 seek_buffer_timestamp_(kNoTimestamp()),
152 media_segment_start_time_(kNoDecodeTimestamp()),
153 range_for_next_append_(ranges_
.end()),
154 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
155 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
156 max_interbuffer_distance_(kNoTimestamp()),
157 memory_limit_(kSourceBufferVideoMemoryLimit
),
158 splice_frames_enabled_(splice_frames_enabled
) {
159 DCHECK(video_config
.IsValidConfig());
160 video_configs_
.push_back(video_config
);
163 SourceBufferStream::SourceBufferStream(const TextTrackConfig
& text_config
,
164 const scoped_refptr
<MediaLog
>& media_log
,
165 bool splice_frames_enabled
)
166 : media_log_(media_log
),
167 text_track_config_(text_config
),
168 seek_buffer_timestamp_(kNoTimestamp()),
169 media_segment_start_time_(kNoDecodeTimestamp()),
170 range_for_next_append_(ranges_
.end()),
171 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
172 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
173 max_interbuffer_distance_(kNoTimestamp()),
174 memory_limit_(kSourceBufferAudioMemoryLimit
),
175 splice_frames_enabled_(splice_frames_enabled
) {}
177 SourceBufferStream::~SourceBufferStream() {
178 while (!ranges_
.empty()) {
179 delete ranges_
.front();
184 void SourceBufferStream::OnNewMediaSegment(
185 DecodeTimestamp media_segment_start_time
) {
186 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
187 << " (" << media_segment_start_time
.InSecondsF() << ")";
188 DCHECK(!end_of_stream_
);
189 media_segment_start_time_
= media_segment_start_time
;
190 new_media_segment_
= true;
192 RangeList::iterator last_range
= range_for_next_append_
;
193 range_for_next_append_
= FindExistingRangeFor(media_segment_start_time
);
195 // Only reset |last_appended_buffer_timestamp_| if this new media segment is
196 // not adjacent to the previous media segment appended to the stream.
197 if (range_for_next_append_
== ranges_
.end() ||
198 !AreAdjacentInSequence(last_appended_buffer_timestamp_
,
199 media_segment_start_time
)) {
200 last_appended_buffer_timestamp_
= kNoDecodeTimestamp();
201 last_appended_buffer_is_keyframe_
= false;
202 DVLOG(3) << __FUNCTION__
<< " next appended buffers will be in a new range";
203 } else if (last_range
!= ranges_
.end()) {
204 DCHECK(last_range
== range_for_next_append_
);
205 DVLOG(3) << __FUNCTION__
<< " next appended buffers will continue range "
206 << "unless intervening remove makes discontinuity";
210 bool SourceBufferStream::Append(const BufferQueue
& buffers
) {
211 TRACE_EVENT2("media", "SourceBufferStream::Append",
212 "stream type", GetStreamTypeName(),
213 "buffers to append", buffers
.size());
215 DCHECK(!buffers
.empty());
216 DCHECK(media_segment_start_time_
!= kNoDecodeTimestamp());
217 DCHECK(media_segment_start_time_
<= buffers
.front()->GetDecodeTimestamp());
218 DCHECK(!end_of_stream_
);
220 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
221 << ": buffers " << BufferQueueToLogString(buffers
);
223 // New media segments must begin with a keyframe.
224 // TODO(wolenetz): Relax this requirement. See http://crbug.com/229412.
225 if (new_media_segment_
&& !buffers
.front()->is_key_frame()) {
226 MEDIA_LOG(ERROR
, media_log_
) << "Media segment did not begin with key "
227 "frame. Support for such segments will be "
228 "available in a future version. Please see "
229 "https://crbug.com/229412.";
233 // Buffers within a media segment should be monotonically increasing.
234 if (!IsMonotonicallyIncreasing(buffers
))
237 if (media_segment_start_time_
< DecodeTimestamp() ||
238 buffers
.front()->GetDecodeTimestamp() < DecodeTimestamp()) {
239 MEDIA_LOG(ERROR
, media_log_
)
240 << "Cannot append a media segment with negative timestamps.";
244 if (!IsNextTimestampValid(buffers
.front()->GetDecodeTimestamp(),
245 buffers
.front()->is_key_frame())) {
246 const DecodeTimestamp
& dts
= buffers
.front()->GetDecodeTimestamp();
247 MEDIA_LOG(ERROR
, media_log_
)
248 << "Invalid same timestamp construct detected at"
249 << " time " << dts
.InSecondsF();
254 UpdateMaxInterbufferDistance(buffers
);
255 SetConfigIds(buffers
);
257 // Save a snapshot of stream state before range modifications are made.
258 DecodeTimestamp next_buffer_timestamp
= GetNextBufferTimestamp();
259 BufferQueue deleted_buffers
;
261 PrepareRangesForNextAppend(buffers
, &deleted_buffers
);
263 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise,
264 // create a new range with |buffers|.
265 if (range_for_next_append_
!= ranges_
.end()) {
266 (*range_for_next_append_
)->AppendBuffersToEnd(buffers
);
267 last_appended_buffer_timestamp_
= buffers
.back()->GetDecodeTimestamp();
268 last_appended_buffer_is_keyframe_
= buffers
.back()->is_key_frame();
270 DecodeTimestamp new_range_start_time
= std::min(
271 media_segment_start_time_
, buffers
.front()->GetDecodeTimestamp());
272 const BufferQueue
* buffers_for_new_range
= &buffers
;
273 BufferQueue trimmed_buffers
;
275 // If the new range is not being created because of a new media
276 // segment, then we must make sure that we start with a key frame.
277 // This can happen if the GOP in the previous append gets destroyed
278 // by a Remove() call.
279 if (!new_media_segment_
) {
280 BufferQueue::const_iterator itr
= buffers
.begin();
282 // Scan past all the non-key-frames.
283 while (itr
!= buffers
.end() && !(*itr
)->is_key_frame()) {
287 // If we didn't find a key frame, then update the last appended
288 // buffer state and return.
289 if (itr
== buffers
.end()) {
290 last_appended_buffer_timestamp_
= buffers
.back()->GetDecodeTimestamp();
291 last_appended_buffer_is_keyframe_
= buffers
.back()->is_key_frame();
292 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
293 << ": new buffers in the middle of media segment depend on"
294 "keyframe that has been removed, and contain no keyframes."
295 "Skipping further processing.";
296 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
297 << ": done. ranges_=" << RangesToString(ranges_
);
299 } else if (itr
!= buffers
.begin()) {
300 // Copy the first key frame and everything after it into
301 // |trimmed_buffers|.
302 trimmed_buffers
.assign(itr
, buffers
.end());
303 buffers_for_new_range
= &trimmed_buffers
;
306 new_range_start_time
=
307 buffers_for_new_range
->front()->GetDecodeTimestamp();
310 range_for_next_append_
=
311 AddToRanges(new SourceBufferRange(
312 TypeToGapPolicy(GetType()),
313 *buffers_for_new_range
, new_range_start_time
,
314 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance
,
315 base::Unretained(this))));
316 last_appended_buffer_timestamp_
=
317 buffers_for_new_range
->back()->GetDecodeTimestamp();
318 last_appended_buffer_is_keyframe_
=
319 buffers_for_new_range
->back()->is_key_frame();
322 new_media_segment_
= false;
324 MergeWithAdjacentRangeIfNecessary(range_for_next_append_
);
326 // Seek to try to fulfill a previous call to Seek().
328 DCHECK(!selected_range_
);
329 DCHECK(deleted_buffers
.empty());
330 Seek(seek_buffer_timestamp_
);
333 if (!deleted_buffers
.empty()) {
334 DecodeTimestamp start_of_deleted
=
335 deleted_buffers
.front()->GetDecodeTimestamp();
337 DCHECK(track_buffer_
.empty() ||
338 track_buffer_
.back()->GetDecodeTimestamp() < start_of_deleted
)
339 << "decode timestamp "
340 << track_buffer_
.back()->GetDecodeTimestamp().InSecondsF() << " sec"
341 << ", start_of_deleted " << start_of_deleted
.InSecondsF()<< " sec";
343 track_buffer_
.insert(track_buffer_
.end(), deleted_buffers
.begin(),
344 deleted_buffers
.end());
345 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName() << " Added "
346 << deleted_buffers
.size()
347 << " buffers to track buffer. TB size is now "
348 << track_buffer_
.size();
350 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
351 << " No deleted buffers for track buffer";
354 // Prune any extra buffers in |track_buffer_| if new keyframes
355 // are appended to the range covered by |track_buffer_|.
356 if (!track_buffer_
.empty()) {
357 DecodeTimestamp keyframe_timestamp
=
358 FindKeyframeAfterTimestamp(track_buffer_
.front()->GetDecodeTimestamp());
359 if (keyframe_timestamp
!= kNoDecodeTimestamp())
360 PruneTrackBuffer(keyframe_timestamp
);
363 SetSelectedRangeIfNeeded(next_buffer_timestamp
);
365 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
366 << ": done. ranges_=" << RangesToString(ranges_
);
367 DCHECK(IsRangeListSorted(ranges_
));
368 DCHECK(OnlySelectedRangeIsSeeked());
372 void SourceBufferStream::Remove(base::TimeDelta start
, base::TimeDelta end
,
373 base::TimeDelta duration
) {
374 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
375 << " (" << start
.InSecondsF() << ", " << end
.InSecondsF()
376 << ", " << duration
.InSecondsF() << ")";
377 DCHECK(start
>= base::TimeDelta()) << start
.InSecondsF();
378 DCHECK(start
< end
) << "start " << start
.InSecondsF()
379 << " end " << end
.InSecondsF();
380 DCHECK(duration
!= kNoTimestamp());
382 DecodeTimestamp start_dts
= DecodeTimestamp::FromPresentationTime(start
);
383 DecodeTimestamp end_dts
= DecodeTimestamp::FromPresentationTime(end
);
384 DecodeTimestamp remove_end_timestamp
=
385 DecodeTimestamp::FromPresentationTime(duration
);
386 DecodeTimestamp keyframe_timestamp
= FindKeyframeAfterTimestamp(end_dts
);
387 if (keyframe_timestamp
!= kNoDecodeTimestamp()) {
388 remove_end_timestamp
= keyframe_timestamp
;
389 } else if (end_dts
< remove_end_timestamp
) {
390 remove_end_timestamp
= end_dts
;
393 BufferQueue deleted_buffers
;
394 RemoveInternal(start_dts
, remove_end_timestamp
, false, &deleted_buffers
);
396 if (!deleted_buffers
.empty()) {
397 // Buffers for the current position have been removed.
398 SetSelectedRangeIfNeeded(deleted_buffers
.front()->GetDecodeTimestamp());
399 if (last_output_buffer_timestamp_
== kNoDecodeTimestamp()) {
400 // We just removed buffers for the current playback position for this
401 // stream, yet we also had output no buffer since the last Seek.
402 // Re-seek to prevent stall.
403 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
404 << ": re-seeking to " << seek_buffer_timestamp_
405 << " to prevent stall if this time becomes buffered again";
406 Seek(seek_buffer_timestamp_
);
411 void SourceBufferStream::RemoveInternal(DecodeTimestamp start
,
414 BufferQueue
* deleted_buffers
) {
415 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName() << " ("
416 << start
.InSecondsF() << ", " << end
.InSecondsF() << ", "
417 << exclude_start
<< ")";
418 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
419 << ": before remove ranges_=" << RangesToString(ranges_
);
421 DCHECK(start
>= DecodeTimestamp());
422 DCHECK(start
< end
) << "start " << start
.InSecondsF()
423 << " end " << end
.InSecondsF();
424 DCHECK(deleted_buffers
);
426 RangeList::iterator itr
= ranges_
.begin();
428 while (itr
!= ranges_
.end()) {
429 SourceBufferRange
* range
= *itr
;
430 if (range
->GetStartTimestamp() >= end
)
433 // Split off any remaining GOPs starting at or after |end| and add it to
435 SourceBufferRange
* new_range
= range
->SplitRange(end
);
437 itr
= ranges_
.insert(++itr
, new_range
);
440 // Update the selected range if the next buffer position was transferred
442 if (new_range
->HasNextBufferPosition())
443 SetSelectedRange(new_range
);
446 // Truncate the current range so that it only contains data before
447 // the removal range.
448 BufferQueue saved_buffers
;
449 bool delete_range
= range
->TruncateAt(start
, &saved_buffers
, exclude_start
);
451 // Check to see if the current playback position was removed and
452 // update the selected range appropriately.
453 if (!saved_buffers
.empty()) {
454 DCHECK(!range
->HasNextBufferPosition());
455 DCHECK(deleted_buffers
->empty());
457 *deleted_buffers
= saved_buffers
;
460 if (range
== selected_range_
&& !range
->HasNextBufferPosition())
461 SetSelectedRange(NULL
);
463 // If the current range now is completely covered by the removal
464 // range then delete it and move on.
466 DeleteAndRemoveRange(&itr
);
470 // Clear |range_for_next_append_| if we determine that the removal
471 // operation makes it impossible for the next append to be added
472 // to the current range.
473 if (range_for_next_append_
!= ranges_
.end() &&
474 *range_for_next_append_
== range
&&
475 last_appended_buffer_timestamp_
!= kNoDecodeTimestamp()) {
476 DecodeTimestamp potential_next_append_timestamp
=
477 last_appended_buffer_timestamp_
+
478 base::TimeDelta::FromInternalValue(1);
480 if (!range
->BelongsToRange(potential_next_append_timestamp
)) {
481 DVLOG(1) << "Resetting range_for_next_append_ since the next append"
482 << " can't add to the current range.";
483 range_for_next_append_
=
484 FindExistingRangeFor(potential_next_append_timestamp
);
488 // Move on to the next range.
492 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
493 << ": after remove ranges_=" << RangesToString(ranges_
);
495 DCHECK(IsRangeListSorted(ranges_
));
496 DCHECK(OnlySelectedRangeIsSeeked());
499 void SourceBufferStream::ResetSeekState() {
500 SetSelectedRange(NULL
);
501 track_buffer_
.clear();
502 config_change_pending_
= false;
503 last_output_buffer_timestamp_
= kNoDecodeTimestamp();
504 just_exhausted_track_buffer_
= false;
505 splice_buffers_index_
= 0;
506 pending_buffer_
= NULL
;
507 pending_buffers_complete_
= false;
510 bool SourceBufferStream::ShouldSeekToStartOfBuffered(
511 base::TimeDelta seek_timestamp
) const {
514 base::TimeDelta beginning_of_buffered
=
515 ranges_
.front()->GetStartTimestamp().ToPresentationTime();
516 return (seek_timestamp
<= beginning_of_buffered
&&
517 beginning_of_buffered
< kSeekToStartFudgeRoom());
520 bool SourceBufferStream::IsMonotonicallyIncreasing(
521 const BufferQueue
& buffers
) const {
522 DCHECK(!buffers
.empty());
523 DecodeTimestamp prev_timestamp
= last_appended_buffer_timestamp_
;
524 bool prev_is_keyframe
= last_appended_buffer_is_keyframe_
;
525 for (BufferQueue::const_iterator itr
= buffers
.begin();
526 itr
!= buffers
.end(); ++itr
) {
527 DecodeTimestamp current_timestamp
= (*itr
)->GetDecodeTimestamp();
528 bool current_is_keyframe
= (*itr
)->is_key_frame();
529 DCHECK(current_timestamp
!= kNoDecodeTimestamp());
530 DCHECK((*itr
)->duration() >= base::TimeDelta())
531 << "Packet with invalid duration."
532 << " pts " << (*itr
)->timestamp().InSecondsF()
533 << " dts " << (*itr
)->GetDecodeTimestamp().InSecondsF()
534 << " dur " << (*itr
)->duration().InSecondsF();
536 if (prev_timestamp
!= kNoDecodeTimestamp()) {
537 if (current_timestamp
< prev_timestamp
) {
538 MEDIA_LOG(ERROR
, media_log_
)
539 << "Buffers did not monotonically increase.";
543 if (current_timestamp
== prev_timestamp
&&
544 !SourceBufferRange::AllowSameTimestamp(prev_is_keyframe
,
545 current_is_keyframe
)) {
546 MEDIA_LOG(ERROR
, media_log_
) << "Unexpected combination of buffers with"
547 << " the same timestamp detected at "
548 << current_timestamp
.InSecondsF();
553 prev_timestamp
= current_timestamp
;
554 prev_is_keyframe
= current_is_keyframe
;
559 bool SourceBufferStream::IsNextTimestampValid(
560 DecodeTimestamp next_timestamp
, bool next_is_keyframe
) const {
561 return (last_appended_buffer_timestamp_
!= next_timestamp
) ||
562 new_media_segment_
||
563 SourceBufferRange::AllowSameTimestamp(last_appended_buffer_is_keyframe_
,
568 bool SourceBufferStream::OnlySelectedRangeIsSeeked() const {
569 for (RangeList::const_iterator itr
= ranges_
.begin();
570 itr
!= ranges_
.end(); ++itr
) {
571 if ((*itr
)->HasNextBufferPosition() && (*itr
) != selected_range_
)
574 return !selected_range_
|| selected_range_
->HasNextBufferPosition();
577 void SourceBufferStream::UpdateMaxInterbufferDistance(
578 const BufferQueue
& buffers
) {
579 DCHECK(!buffers
.empty());
580 DecodeTimestamp prev_timestamp
= last_appended_buffer_timestamp_
;
581 for (BufferQueue::const_iterator itr
= buffers
.begin();
582 itr
!= buffers
.end(); ++itr
) {
583 DecodeTimestamp current_timestamp
= (*itr
)->GetDecodeTimestamp();
584 DCHECK(current_timestamp
!= kNoDecodeTimestamp());
586 base::TimeDelta interbuffer_distance
= (*itr
)->duration();
587 DCHECK(interbuffer_distance
>= base::TimeDelta());
589 if (prev_timestamp
!= kNoDecodeTimestamp()) {
590 interbuffer_distance
=
591 std::max(current_timestamp
- prev_timestamp
, interbuffer_distance
);
594 if (interbuffer_distance
> base::TimeDelta()) {
595 if (max_interbuffer_distance_
== kNoTimestamp()) {
596 max_interbuffer_distance_
= interbuffer_distance
;
598 max_interbuffer_distance_
=
599 std::max(max_interbuffer_distance_
, interbuffer_distance
);
602 prev_timestamp
= current_timestamp
;
606 void SourceBufferStream::SetConfigIds(const BufferQueue
& buffers
) {
607 for (BufferQueue::const_iterator itr
= buffers
.begin();
608 itr
!= buffers
.end(); ++itr
) {
609 (*itr
)->SetConfigId(append_config_index_
);
613 bool SourceBufferStream::GarbageCollectIfNeeded(DecodeTimestamp media_time
,
614 size_t newDataSize
) {
615 DCHECK(media_time
!= kNoDecodeTimestamp());
616 // Compute size of |ranges_|.
617 size_t ranges_size
= GetBufferedSize();
619 // Sanity and overflow checks
620 if ((newDataSize
> memory_limit_
) ||
621 (ranges_size
+ newDataSize
< ranges_size
))
624 // Return if we're under or at the memory limit.
625 if (ranges_size
+ newDataSize
<= memory_limit_
)
628 size_t bytes_to_free
= ranges_size
+ newDataSize
- memory_limit_
;
630 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName() << ": Before GC"
631 << " media_time=" << media_time
.InSecondsF()
632 << " ranges_=" << RangesToString(ranges_
)
633 << " ranges_size=" << ranges_size
634 << " newDataSize=" << newDataSize
635 << " memory_limit_=" << memory_limit_
636 << " last_appended_buffer_timestamp_="
637 << last_appended_buffer_timestamp_
.InSecondsF();
639 size_t bytes_freed
= 0;
641 // If last appended buffer position was earlier than the current playback time
642 // then try deleting data between last append and current media_time.
643 if (last_appended_buffer_timestamp_
!= kNoDecodeTimestamp() &&
644 last_appended_buffer_timestamp_
< media_time
) {
645 size_t between
= FreeBuffersAfterLastAppended(bytes_to_free
, media_time
);
646 DVLOG(3) << __FUNCTION__
<< " FreeBuffersAfterLastAppended "
647 << " released " << between
<< " bytes"
648 << " ranges_=" << RangesToString(ranges_
);
649 bytes_freed
+= between
;
651 // If the last append happened before the current playback position
652 // |media_time|, then JS player is probably preparing to seek back and we
653 // should try to preserve all most recently appended data (which is in
654 // range_for_next_append_) from being removed by GC (see crbug.com/440173)
655 if (range_for_next_append_
!= ranges_
.end()) {
656 DCHECK((*range_for_next_append_
)->GetStartTimestamp() <= media_time
);
657 media_time
= (*range_for_next_append_
)->GetStartTimestamp();
661 // Try removing data from the front of the SourceBuffer up to |media_time|
663 if (bytes_freed
< bytes_to_free
) {
664 size_t front
= FreeBuffers(bytes_to_free
- bytes_freed
, media_time
, false);
665 DVLOG(3) << __FUNCTION__
<< " Removed " << front
<< " bytes from the front"
666 << " ranges_=" << RangesToString(ranges_
);
667 bytes_freed
+= front
;
670 // Try removing data from the back of the SourceBuffer, until we reach the
671 // most recent append position.
672 if (bytes_freed
< bytes_to_free
) {
673 size_t back
= FreeBuffers(bytes_to_free
- bytes_freed
, media_time
, true);
674 DVLOG(3) << __FUNCTION__
<< " Removed " << back
<< " bytes from the back"
675 << " ranges_=" << RangesToString(ranges_
);
679 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName() << ": After GC"
680 << " bytes_to_free=" << bytes_to_free
681 << " bytes_freed=" << bytes_freed
682 << " ranges_=" << RangesToString(ranges_
);
684 return bytes_freed
>= bytes_to_free
;
687 size_t SourceBufferStream::FreeBuffersAfterLastAppended(
688 size_t total_bytes_to_free
, DecodeTimestamp media_time
) {
689 DVLOG(4) << __FUNCTION__
<< " last_appended_buffer_timestamp_="
690 << last_appended_buffer_timestamp_
.InSecondsF()
691 << " media_time=" << media_time
.InSecondsF();
693 DecodeTimestamp remove_range_start
= last_appended_buffer_timestamp_
;
694 if (last_appended_buffer_is_keyframe_
)
695 remove_range_start
+= GetMaxInterbufferDistance();
697 DecodeTimestamp remove_range_start_keyframe
= FindKeyframeAfterTimestamp(
699 if (remove_range_start_keyframe
!= kNoDecodeTimestamp())
700 remove_range_start
= remove_range_start_keyframe
;
701 if (remove_range_start
>= media_time
)
704 DecodeTimestamp remove_range_end
;
705 size_t bytes_freed
= GetRemovalRange(remove_range_start
,
709 if (bytes_freed
> 0) {
710 DVLOG(4) << __FUNCTION__
<< " removing ["
711 << remove_range_start
.ToPresentationTime().InSecondsF() << ";"
712 << remove_range_end
.ToPresentationTime().InSecondsF() << "]";
713 Remove(remove_range_start
.ToPresentationTime(),
714 remove_range_end
.ToPresentationTime(),
715 media_time
.ToPresentationTime());
721 size_t SourceBufferStream::GetRemovalRange(
722 DecodeTimestamp start_timestamp
, DecodeTimestamp end_timestamp
,
723 size_t total_bytes_to_free
, DecodeTimestamp
* removal_end_timestamp
) {
724 DCHECK(start_timestamp
>= DecodeTimestamp()) << start_timestamp
.InSecondsF();
725 DCHECK(start_timestamp
< end_timestamp
)
726 << "start " << start_timestamp
.InSecondsF()
727 << ", end " << end_timestamp
.InSecondsF();
729 size_t bytes_freed
= 0;
731 for (RangeList::iterator itr
= ranges_
.begin();
732 itr
!= ranges_
.end() && bytes_freed
< total_bytes_to_free
; ++itr
) {
733 SourceBufferRange
* range
= *itr
;
734 if (range
->GetStartTimestamp() >= end_timestamp
)
736 if (range
->GetEndTimestamp() < start_timestamp
)
739 size_t bytes_to_free
= total_bytes_to_free
- bytes_freed
;
740 size_t bytes_removed
= range
->GetRemovalGOP(
741 start_timestamp
, end_timestamp
, bytes_to_free
, removal_end_timestamp
);
742 bytes_freed
+= bytes_removed
;
747 size_t SourceBufferStream::FreeBuffers(size_t total_bytes_to_free
,
748 DecodeTimestamp media_time
,
749 bool reverse_direction
) {
750 TRACE_EVENT2("media", "SourceBufferStream::FreeBuffers",
751 "total bytes to free", total_bytes_to_free
,
752 "reverse direction", reverse_direction
);
754 DCHECK_GT(total_bytes_to_free
, 0u);
755 size_t bytes_freed
= 0;
757 // This range will save the last GOP appended to |range_for_next_append_|
758 // if the buffers surrounding it get deleted during garbage collection.
759 SourceBufferRange
* new_range_for_append
= NULL
;
761 while (!ranges_
.empty() && bytes_freed
< total_bytes_to_free
) {
762 SourceBufferRange
* current_range
= NULL
;
764 size_t bytes_deleted
= 0;
766 if (reverse_direction
) {
767 current_range
= ranges_
.back();
768 DVLOG(5) << "current_range=" << RangeToString(*current_range
);
769 if (current_range
->LastGOPContainsNextBufferPosition()) {
770 DCHECK_EQ(current_range
, selected_range_
);
771 DVLOG(5) << "current_range contains next read position, stopping GC";
774 DVLOG(5) << "Deleting GOP from back: " << RangeToString(*current_range
);
775 bytes_deleted
= current_range
->DeleteGOPFromBack(&buffers
);
777 current_range
= ranges_
.front();
778 DVLOG(5) << "current_range=" << RangeToString(*current_range
);
779 if (!current_range
->FirstGOPEarlierThanMediaTime(media_time
)) {
780 // We have removed all data up to the GOP that contains current playback
781 // position, we can't delete any further.
782 DVLOG(5) << "current_range contains playback position, stopping GC";
785 DVLOG(4) << "Deleting GOP from front: " << RangeToString(*current_range
);
786 bytes_deleted
= current_range
->DeleteGOPFromFront(&buffers
);
789 // Check to see if we've just deleted the GOP that was last appended.
790 DecodeTimestamp end_timestamp
= buffers
.back()->GetDecodeTimestamp();
791 if (end_timestamp
== last_appended_buffer_timestamp_
) {
792 DCHECK(last_appended_buffer_timestamp_
!= kNoDecodeTimestamp());
793 DCHECK(!new_range_for_append
);
795 // Create a new range containing these buffers.
796 new_range_for_append
= new SourceBufferRange(
797 TypeToGapPolicy(GetType()),
798 buffers
, kNoDecodeTimestamp(),
799 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance
,
800 base::Unretained(this)));
801 range_for_next_append_
= ranges_
.end();
803 bytes_freed
+= bytes_deleted
;
806 if (current_range
->size_in_bytes() == 0) {
807 DCHECK_NE(current_range
, selected_range_
);
808 DCHECK(range_for_next_append_
== ranges_
.end() ||
809 *range_for_next_append_
!= current_range
);
810 delete current_range
;
811 reverse_direction
? ranges_
.pop_back() : ranges_
.pop_front();
814 if (reverse_direction
&& new_range_for_append
) {
815 // We don't want to delete any further, or we'll be creating gaps
820 // Insert |new_range_for_append| into |ranges_|, if applicable.
821 if (new_range_for_append
) {
822 range_for_next_append_
= AddToRanges(new_range_for_append
);
823 DCHECK(range_for_next_append_
!= ranges_
.end());
825 // Check to see if we need to merge |new_range_for_append| with the range
826 // before or after it. |new_range_for_append| is created whenever the last
827 // GOP appended is encountered, regardless of whether any buffers after it
828 // are ultimately deleted. Merging is necessary if there were no buffers
829 // (or very few buffers) deleted after creating |new_range_for_append|.
830 if (range_for_next_append_
!= ranges_
.begin()) {
831 RangeList::iterator range_before_next
= range_for_next_append_
;
833 MergeWithAdjacentRangeIfNecessary(range_before_next
);
835 MergeWithAdjacentRangeIfNecessary(range_for_next_append_
);
840 void SourceBufferStream::PrepareRangesForNextAppend(
841 const BufferQueue
& new_buffers
, BufferQueue
* deleted_buffers
) {
842 DCHECK(deleted_buffers
);
844 bool temporarily_select_range
= false;
845 if (!track_buffer_
.empty()) {
846 DecodeTimestamp tb_timestamp
= track_buffer_
.back()->GetDecodeTimestamp();
847 DecodeTimestamp seek_timestamp
= FindKeyframeAfterTimestamp(tb_timestamp
);
848 if (seek_timestamp
!= kNoDecodeTimestamp() &&
849 seek_timestamp
< new_buffers
.front()->GetDecodeTimestamp() &&
850 range_for_next_append_
!= ranges_
.end() &&
851 (*range_for_next_append_
)->BelongsToRange(seek_timestamp
)) {
852 DCHECK(tb_timestamp
< seek_timestamp
);
853 DCHECK(!selected_range_
);
854 DCHECK(!(*range_for_next_append_
)->HasNextBufferPosition());
856 // If there are GOPs between the end of the track buffer and the
857 // beginning of the new buffers, then temporarily seek the range
858 // so that the buffers between these two times will be deposited in
859 // |deleted_buffers| as if they were part of the current playback
861 // TODO(acolwell): Figure out a more elegant way to do this.
862 SeekAndSetSelectedRange(*range_for_next_append_
, seek_timestamp
);
863 temporarily_select_range
= true;
867 // Handle splices between the existing buffers and the new buffers. If a
868 // splice is generated the timestamp and duration of the first buffer in
869 // |new_buffers| will be modified.
870 if (splice_frames_enabled_
)
871 GenerateSpliceFrame(new_buffers
);
873 DecodeTimestamp prev_timestamp
= last_appended_buffer_timestamp_
;
874 bool prev_is_keyframe
= last_appended_buffer_is_keyframe_
;
875 DecodeTimestamp next_timestamp
= new_buffers
.front()->GetDecodeTimestamp();
876 bool next_is_keyframe
= new_buffers
.front()->is_key_frame();
878 if (prev_timestamp
!= kNoDecodeTimestamp() &&
879 prev_timestamp
!= next_timestamp
) {
880 // Clean up the old buffers between the last appended buffer and the
881 // beginning of |new_buffers|.
882 RemoveInternal(prev_timestamp
, next_timestamp
, true, deleted_buffers
);
885 // Make the delete range exclusive if we are dealing with an allowed same
886 // timestamp situation. This prevents the first buffer in the current append
887 // from deleting the last buffer in the previous append if both buffers
888 // have the same timestamp.
890 // The delete range should never be exclusive if a splice frame was generated
891 // because we don't generate splice frames for same timestamp situations.
892 DCHECK(new_buffers
.front()->splice_timestamp() !=
893 new_buffers
.front()->timestamp());
894 const bool exclude_start
=
895 new_buffers
.front()->splice_buffers().empty() &&
896 prev_timestamp
== next_timestamp
&&
897 SourceBufferRange::AllowSameTimestamp(prev_is_keyframe
, next_is_keyframe
);
899 // Delete the buffers that |new_buffers| overlaps.
900 DecodeTimestamp start
= new_buffers
.front()->GetDecodeTimestamp();
901 DecodeTimestamp end
= new_buffers
.back()->GetDecodeTimestamp();
902 base::TimeDelta duration
= new_buffers
.back()->duration();
904 // Set end time for remove to include the duration of last buffer. If the
905 // duration is estimated, use 1 microsecond instead to ensure frames are not
906 // accidentally removed due to over-estimation.
907 if (duration
!= kNoTimestamp() && duration
> base::TimeDelta() &&
908 !new_buffers
.back()->is_duration_estimated()) {
911 // TODO(chcunningham): Emit warning when 0ms durations are not expected.
912 // http://crbug.com/312836
913 end
+= base::TimeDelta::FromInternalValue(1);
916 RemoveInternal(start
, end
, exclude_start
, deleted_buffers
);
918 // Restore the range seek state if necessary.
919 if (temporarily_select_range
)
920 SetSelectedRange(NULL
);
923 bool SourceBufferStream::AreAdjacentInSequence(
924 DecodeTimestamp first_timestamp
, DecodeTimestamp second_timestamp
) const {
925 return first_timestamp
< second_timestamp
&&
927 first_timestamp
+ ComputeFudgeRoom(GetMaxInterbufferDistance());
930 void SourceBufferStream::PruneTrackBuffer(const DecodeTimestamp timestamp
) {
931 // If we don't have the next timestamp, we don't have anything to delete.
932 if (timestamp
== kNoDecodeTimestamp())
935 while (!track_buffer_
.empty() &&
936 track_buffer_
.back()->GetDecodeTimestamp() >= timestamp
) {
937 track_buffer_
.pop_back();
939 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
940 << " Removed all buffers with DTS >= " << timestamp
.InSecondsF()
941 << ". New track buffer size:" << track_buffer_
.size();
944 void SourceBufferStream::MergeWithAdjacentRangeIfNecessary(
945 const RangeList::iterator
& range_with_new_buffers_itr
) {
946 DCHECK(range_with_new_buffers_itr
!= ranges_
.end());
948 SourceBufferRange
* range_with_new_buffers
= *range_with_new_buffers_itr
;
949 RangeList::iterator next_range_itr
= range_with_new_buffers_itr
;
952 if (next_range_itr
== ranges_
.end() ||
953 !range_with_new_buffers
->CanAppendRangeToEnd(**next_range_itr
)) {
957 bool transfer_current_position
= selected_range_
== *next_range_itr
;
958 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
959 << " merging " << RangeToString(*range_with_new_buffers
)
960 << " into " << RangeToString(**next_range_itr
);
961 range_with_new_buffers
->AppendRangeToEnd(**next_range_itr
,
962 transfer_current_position
);
963 // Update |selected_range_| pointer if |range| has become selected after
965 if (transfer_current_position
)
966 SetSelectedRange(range_with_new_buffers
);
968 if (next_range_itr
== range_for_next_append_
)
969 range_for_next_append_
= range_with_new_buffers_itr
;
971 DeleteAndRemoveRange(&next_range_itr
);
974 void SourceBufferStream::Seek(base::TimeDelta timestamp
) {
975 DCHECK(timestamp
>= base::TimeDelta());
976 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
977 << " (" << timestamp
.InSecondsF() << ")";
980 seek_buffer_timestamp_
= timestamp
;
981 seek_pending_
= true;
983 if (ShouldSeekToStartOfBuffered(timestamp
)) {
984 ranges_
.front()->SeekToStart();
985 SetSelectedRange(ranges_
.front());
986 seek_pending_
= false;
990 DecodeTimestamp seek_dts
= DecodeTimestamp::FromPresentationTime(timestamp
);
992 RangeList::iterator itr
= ranges_
.end();
993 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
994 if ((*itr
)->CanSeekTo(seek_dts
))
998 if (itr
== ranges_
.end())
1001 SeekAndSetSelectedRange(*itr
, seek_dts
);
1002 seek_pending_
= false;
1005 bool SourceBufferStream::IsSeekPending() const {
1006 return seek_pending_
&& !IsEndOfStreamReached();
1009 void SourceBufferStream::OnSetDuration(base::TimeDelta duration
) {
1010 DecodeTimestamp duration_dts
=
1011 DecodeTimestamp::FromPresentationTime(duration
);
1012 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
1013 << " (" << duration
.InSecondsF() << ")";
1015 RangeList::iterator itr
= ranges_
.end();
1016 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1017 if ((*itr
)->GetEndTimestamp() > duration_dts
)
1020 if (itr
== ranges_
.end())
1023 // Need to partially truncate this range.
1024 if ((*itr
)->GetStartTimestamp() < duration_dts
) {
1025 bool delete_range
= (*itr
)->TruncateAt(duration_dts
, NULL
, false);
1026 if ((*itr
== selected_range_
) && !selected_range_
->HasNextBufferPosition())
1027 SetSelectedRange(NULL
);
1030 DeleteAndRemoveRange(&itr
);
1036 // Delete all ranges that begin after |duration_dts|.
1037 while (itr
!= ranges_
.end()) {
1038 // If we're about to delete the selected range, also reset the seek state.
1039 DCHECK((*itr
)->GetStartTimestamp() >= duration_dts
);
1040 if (*itr
== selected_range_
)
1042 DeleteAndRemoveRange(&itr
);
1046 SourceBufferStream::Status
SourceBufferStream::GetNextBuffer(
1047 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1048 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName();
1049 if (!pending_buffer_
.get()) {
1050 const SourceBufferStream::Status status
= GetNextBufferInternal(out_buffer
);
1051 if (status
!= SourceBufferStream::kSuccess
||
1052 !SetPendingBuffer(out_buffer
)) {
1053 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1054 << ": no pending buffer, returning status " << status
;
1059 if (!pending_buffer_
->splice_buffers().empty()) {
1060 const SourceBufferStream::Status status
=
1061 HandleNextBufferWithSplice(out_buffer
);
1062 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1063 << ": handled next buffer with splice, returning status "
1068 DCHECK(pending_buffer_
->preroll_buffer().get());
1070 const SourceBufferStream::Status status
=
1071 HandleNextBufferWithPreroll(out_buffer
);
1072 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1073 << ": handled next buffer with preroll, returning status "
1078 SourceBufferStream::Status
SourceBufferStream::HandleNextBufferWithSplice(
1079 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1080 const BufferQueue
& splice_buffers
= pending_buffer_
->splice_buffers();
1081 const size_t last_splice_buffer_index
= splice_buffers
.size() - 1;
1083 // Are there any splice buffers left to hand out? The last buffer should be
1084 // handed out separately since it represents the first post-splice buffer.
1085 if (splice_buffers_index_
< last_splice_buffer_index
) {
1086 // Account for config changes which occur between fade out buffers.
1087 if (current_config_index_
!=
1088 splice_buffers
[splice_buffers_index_
]->GetConfigId()) {
1089 config_change_pending_
= true;
1090 DVLOG(1) << "Config change (splice buffer config ID does not match).";
1091 return SourceBufferStream::kConfigChange
;
1094 // Every pre splice buffer must have the same splice_timestamp().
1095 DCHECK(pending_buffer_
->splice_timestamp() ==
1096 splice_buffers
[splice_buffers_index_
]->splice_timestamp());
1098 // No pre splice buffers should have preroll.
1099 DCHECK(!splice_buffers
[splice_buffers_index_
]->preroll_buffer().get());
1101 *out_buffer
= splice_buffers
[splice_buffers_index_
++];
1102 return SourceBufferStream::kSuccess
;
1105 // Did we hand out the last pre-splice buffer on the previous call?
1106 if (!pending_buffers_complete_
) {
1107 DCHECK_EQ(splice_buffers_index_
, last_splice_buffer_index
);
1108 pending_buffers_complete_
= true;
1109 config_change_pending_
= true;
1110 DVLOG(1) << "Config change (forced for fade in of splice frame).";
1111 return SourceBufferStream::kConfigChange
;
1114 // All pre-splice buffers have been handed out and a config change completed,
1115 // so hand out the final buffer for fade in. Because a config change is
1116 // always issued prior to handing out this buffer, any changes in config id
1117 // have been inherently handled.
1118 DCHECK(pending_buffers_complete_
);
1119 DCHECK_EQ(splice_buffers_index_
, splice_buffers
.size() - 1);
1120 DCHECK(splice_buffers
.back()->splice_timestamp() == kNoTimestamp());
1121 *out_buffer
= splice_buffers
.back();
1122 pending_buffer_
= NULL
;
1124 // If the last splice buffer has preroll, hand off to the preroll handler.
1125 return SetPendingBuffer(out_buffer
) ? HandleNextBufferWithPreroll(out_buffer
)
1126 : SourceBufferStream::kSuccess
;
1129 SourceBufferStream::Status
SourceBufferStream::HandleNextBufferWithPreroll(
1130 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1131 // Any config change should have already been handled.
1132 DCHECK_EQ(current_config_index_
, pending_buffer_
->GetConfigId());
1134 // Check if the preroll buffer has already been handed out.
1135 if (!pending_buffers_complete_
) {
1136 pending_buffers_complete_
= true;
1137 *out_buffer
= pending_buffer_
->preroll_buffer();
1138 return SourceBufferStream::kSuccess
;
1141 // Preroll complete, hand out the final buffer.
1142 *out_buffer
= pending_buffer_
;
1143 pending_buffer_
= NULL
;
1144 return SourceBufferStream::kSuccess
;
1147 SourceBufferStream::Status
SourceBufferStream::GetNextBufferInternal(
1148 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1149 CHECK(!config_change_pending_
);
1151 if (!track_buffer_
.empty()) {
1152 DCHECK(!selected_range_
);
1153 scoped_refptr
<StreamParserBuffer
>& next_buffer
= track_buffer_
.front();
1155 // If the next buffer is an audio splice frame, the next effective config id
1156 // comes from the first splice buffer.
1157 if (next_buffer
->GetSpliceBufferConfigId(0) != current_config_index_
) {
1158 config_change_pending_
= true;
1159 DVLOG(1) << "Config change (track buffer config ID does not match).";
1160 return kConfigChange
;
1163 DVLOG(3) << __FUNCTION__
<< " Next buffer coming from track_buffer_";
1164 *out_buffer
= next_buffer
;
1165 track_buffer_
.pop_front();
1166 WarnIfTrackBufferExhaustionSkipsForward(*out_buffer
);
1167 last_output_buffer_timestamp_
= (*out_buffer
)->GetDecodeTimestamp();
1169 // If the track buffer becomes empty, then try to set the selected range
1170 // based on the timestamp of this buffer being returned.
1171 if (track_buffer_
.empty()) {
1172 just_exhausted_track_buffer_
= true;
1173 SetSelectedRangeIfNeeded(last_output_buffer_timestamp_
);
1179 DCHECK(track_buffer_
.empty());
1180 if (!selected_range_
|| !selected_range_
->HasNextBuffer()) {
1181 if (IsEndOfStreamReached()) {
1182 return kEndOfStream
;
1184 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
1185 << ": returning kNeedBuffer "
1186 << (selected_range_
? "(selected range has no next buffer)"
1187 : "(no selected range)");
1191 if (selected_range_
->GetNextConfigId() != current_config_index_
) {
1192 config_change_pending_
= true;
1193 DVLOG(1) << "Config change (selected range config ID does not match).";
1194 return kConfigChange
;
1197 CHECK(selected_range_
->GetNextBuffer(out_buffer
));
1198 WarnIfTrackBufferExhaustionSkipsForward(*out_buffer
);
1199 last_output_buffer_timestamp_
= (*out_buffer
)->GetDecodeTimestamp();
1203 void SourceBufferStream::WarnIfTrackBufferExhaustionSkipsForward(
1204 const scoped_refptr
<StreamParserBuffer
>& next_buffer
) {
1205 if (!just_exhausted_track_buffer_
)
1208 just_exhausted_track_buffer_
= false;
1209 DCHECK(next_buffer
->is_key_frame());
1210 DecodeTimestamp next_output_buffer_timestamp
=
1211 next_buffer
->GetDecodeTimestamp();
1212 base::TimeDelta delta
=
1213 next_output_buffer_timestamp
- last_output_buffer_timestamp_
;
1214 DCHECK_GE(delta
, base::TimeDelta());
1215 if (delta
> GetMaxInterbufferDistance()) {
1216 LIMITED_MEDIA_LOG(DEBUG
, media_log_
, num_track_buffer_gap_warning_logs_
,
1217 kMaxTrackBufferGapWarningLogs
)
1218 << "Media append that overlapped current playback position caused time "
1220 << GetStreamTypeName() << " stream because the next keyframe is "
1221 << delta
.InMilliseconds() << "ms beyond last overlapped frame. Media "
1222 "may appear temporarily frozen.";
1226 DecodeTimestamp
SourceBufferStream::GetNextBufferTimestamp() {
1227 if (!track_buffer_
.empty())
1228 return track_buffer_
.front()->GetDecodeTimestamp();
1230 if (!selected_range_
)
1231 return kNoDecodeTimestamp();
1233 DCHECK(selected_range_
->HasNextBufferPosition());
1234 return selected_range_
->GetNextTimestamp();
1237 SourceBufferStream::RangeList::iterator
1238 SourceBufferStream::FindExistingRangeFor(DecodeTimestamp start_timestamp
) {
1239 for (RangeList::iterator itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1240 if ((*itr
)->BelongsToRange(start_timestamp
))
1243 return ranges_
.end();
1246 SourceBufferStream::RangeList::iterator
1247 SourceBufferStream::AddToRanges(SourceBufferRange
* new_range
) {
1248 DecodeTimestamp start_timestamp
= new_range
->GetStartTimestamp();
1249 RangeList::iterator itr
= ranges_
.end();
1250 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1251 if ((*itr
)->GetStartTimestamp() > start_timestamp
)
1254 return ranges_
.insert(itr
, new_range
);
1257 SourceBufferStream::RangeList::iterator
1258 SourceBufferStream::GetSelectedRangeItr() {
1259 DCHECK(selected_range_
);
1260 RangeList::iterator itr
= ranges_
.end();
1261 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1262 if (*itr
== selected_range_
)
1265 DCHECK(itr
!= ranges_
.end());
1269 void SourceBufferStream::SeekAndSetSelectedRange(
1270 SourceBufferRange
* range
, DecodeTimestamp seek_timestamp
) {
1272 range
->Seek(seek_timestamp
);
1273 SetSelectedRange(range
);
1276 void SourceBufferStream::SetSelectedRange(SourceBufferRange
* range
) {
1277 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName() << ": "
1278 << selected_range_
<< " "
1279 << (selected_range_
? RangeToString(*selected_range_
) : "")
1280 << " -> " << range
<< " " << (range
? RangeToString(*range
) : "");
1281 if (selected_range_
)
1282 selected_range_
->ResetNextBufferPosition();
1283 DCHECK(!range
|| range
->HasNextBufferPosition());
1284 selected_range_
= range
;
1287 Ranges
<base::TimeDelta
> SourceBufferStream::GetBufferedTime() const {
1288 Ranges
<base::TimeDelta
> ranges
;
1289 for (RangeList::const_iterator itr
= ranges_
.begin();
1290 itr
!= ranges_
.end(); ++itr
) {
1291 ranges
.Add((*itr
)->GetStartTimestamp().ToPresentationTime(),
1292 (*itr
)->GetBufferedEndTimestamp().ToPresentationTime());
1297 base::TimeDelta
SourceBufferStream::GetBufferedDuration() const {
1298 if (ranges_
.empty())
1299 return base::TimeDelta();
1301 return ranges_
.back()->GetBufferedEndTimestamp().ToPresentationTime();
1304 size_t SourceBufferStream::GetBufferedSize() const {
1305 size_t ranges_size
= 0;
1306 for (const auto& range
: ranges_
)
1307 ranges_size
+= range
->size_in_bytes();
1311 void SourceBufferStream::MarkEndOfStream() {
1312 DCHECK(!end_of_stream_
);
1313 end_of_stream_
= true;
1316 void SourceBufferStream::UnmarkEndOfStream() {
1317 DCHECK(end_of_stream_
);
1318 end_of_stream_
= false;
1321 bool SourceBufferStream::IsEndOfStreamReached() const {
1322 if (!end_of_stream_
|| !track_buffer_
.empty())
1325 if (ranges_
.empty())
1328 if (seek_pending_
) {
1329 base::TimeDelta last_range_end_time
=
1330 ranges_
.back()->GetBufferedEndTimestamp().ToPresentationTime();
1331 return seek_buffer_timestamp_
>= last_range_end_time
;
1334 if (!selected_range_
)
1337 return selected_range_
== ranges_
.back();
1340 const AudioDecoderConfig
& SourceBufferStream::GetCurrentAudioDecoderConfig() {
1341 if (config_change_pending_
)
1342 CompleteConfigChange();
1343 return audio_configs_
[current_config_index_
];
1346 const VideoDecoderConfig
& SourceBufferStream::GetCurrentVideoDecoderConfig() {
1347 if (config_change_pending_
)
1348 CompleteConfigChange();
1349 return video_configs_
[current_config_index_
];
1352 const TextTrackConfig
& SourceBufferStream::GetCurrentTextTrackConfig() {
1353 return text_track_config_
;
1356 base::TimeDelta
SourceBufferStream::GetMaxInterbufferDistance() const {
1357 if (max_interbuffer_distance_
== kNoTimestamp())
1358 return base::TimeDelta::FromMilliseconds(kDefaultBufferDurationInMs
);
1359 return max_interbuffer_distance_
;
1362 bool SourceBufferStream::UpdateAudioConfig(const AudioDecoderConfig
& config
) {
1363 DCHECK(!audio_configs_
.empty());
1364 DCHECK(video_configs_
.empty());
1365 DVLOG(3) << "UpdateAudioConfig.";
1367 if (audio_configs_
[0].codec() != config
.codec()) {
1368 MEDIA_LOG(ERROR
, media_log_
) << "Audio codec changes not allowed.";
1372 if (audio_configs_
[0].is_encrypted() != config
.is_encrypted()) {
1373 MEDIA_LOG(ERROR
, media_log_
) << "Audio encryption changes not allowed.";
1377 // Check to see if the new config matches an existing one.
1378 for (size_t i
= 0; i
< audio_configs_
.size(); ++i
) {
1379 if (config
.Matches(audio_configs_
[i
])) {
1380 append_config_index_
= i
;
1385 // No matches found so let's add this one to the list.
1386 append_config_index_
= audio_configs_
.size();
1387 DVLOG(2) << "New audio config - index: " << append_config_index_
;
1388 audio_configs_
.resize(audio_configs_
.size() + 1);
1389 audio_configs_
[append_config_index_
] = config
;
1393 bool SourceBufferStream::UpdateVideoConfig(const VideoDecoderConfig
& config
) {
1394 DCHECK(!video_configs_
.empty());
1395 DCHECK(audio_configs_
.empty());
1396 DVLOG(3) << "UpdateVideoConfig.";
1398 if (video_configs_
[0].codec() != config
.codec()) {
1399 MEDIA_LOG(ERROR
, media_log_
) << "Video codec changes not allowed.";
1403 if (video_configs_
[0].is_encrypted() != config
.is_encrypted()) {
1404 MEDIA_LOG(ERROR
, media_log_
) << "Video encryption changes not allowed.";
1408 // Check to see if the new config matches an existing one.
1409 for (size_t i
= 0; i
< video_configs_
.size(); ++i
) {
1410 if (config
.Matches(video_configs_
[i
])) {
1411 append_config_index_
= i
;
1416 // No matches found so let's add this one to the list.
1417 append_config_index_
= video_configs_
.size();
1418 DVLOG(2) << "New video config - index: " << append_config_index_
;
1419 video_configs_
.resize(video_configs_
.size() + 1);
1420 video_configs_
[append_config_index_
] = config
;
1424 void SourceBufferStream::CompleteConfigChange() {
1425 config_change_pending_
= false;
1427 if (pending_buffer_
.get()) {
1428 current_config_index_
=
1429 pending_buffer_
->GetSpliceBufferConfigId(splice_buffers_index_
);
1433 if (!track_buffer_
.empty()) {
1434 current_config_index_
= track_buffer_
.front()->GetSpliceBufferConfigId(0);
1438 if (selected_range_
&& selected_range_
->HasNextBuffer())
1439 current_config_index_
= selected_range_
->GetNextConfigId();
1442 void SourceBufferStream::SetSelectedRangeIfNeeded(
1443 const DecodeTimestamp timestamp
) {
1444 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1445 << "(" << timestamp
.InSecondsF() << ")";
1447 if (selected_range_
) {
1448 DCHECK(track_buffer_
.empty());
1452 if (!track_buffer_
.empty()) {
1453 DCHECK(!selected_range_
);
1457 DecodeTimestamp start_timestamp
= timestamp
;
1459 // If the next buffer timestamp is not known then use a timestamp just after
1460 // the timestamp on the last buffer returned by GetNextBuffer().
1461 if (start_timestamp
== kNoDecodeTimestamp()) {
1462 if (last_output_buffer_timestamp_
== kNoDecodeTimestamp()) {
1463 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1464 << " no previous output timestamp";
1468 start_timestamp
= last_output_buffer_timestamp_
+
1469 base::TimeDelta::FromInternalValue(1);
1472 DecodeTimestamp seek_timestamp
=
1473 FindNewSelectedRangeSeekTimestamp(start_timestamp
);
1475 // If we don't have buffered data to seek to, then return.
1476 if (seek_timestamp
== kNoDecodeTimestamp()) {
1477 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1478 << " couldn't find new selected range seek timestamp";
1482 DCHECK(track_buffer_
.empty());
1483 SeekAndSetSelectedRange(*FindExistingRangeFor(seek_timestamp
),
1487 DecodeTimestamp
SourceBufferStream::FindNewSelectedRangeSeekTimestamp(
1488 const DecodeTimestamp start_timestamp
) {
1489 DCHECK(start_timestamp
!= kNoDecodeTimestamp());
1490 DCHECK(start_timestamp
>= DecodeTimestamp());
1492 RangeList::iterator itr
= ranges_
.begin();
1494 for (; itr
!= ranges_
.end(); ++itr
) {
1495 if ((*itr
)->GetEndTimestamp() >= start_timestamp
) {
1500 if (itr
== ranges_
.end()) {
1501 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1502 << " no buffered data for dts=" << start_timestamp
.InSecondsF();
1503 return kNoDecodeTimestamp();
1506 // First check for a keyframe timestamp >= |start_timestamp|
1507 // in the current range.
1508 DecodeTimestamp keyframe_timestamp
=
1509 (*itr
)->NextKeyframeTimestamp(start_timestamp
);
1511 if (keyframe_timestamp
!= kNoDecodeTimestamp())
1512 return keyframe_timestamp
;
1514 // If a keyframe was not found then look for a keyframe that is
1515 // "close enough" in the current or next range.
1516 DecodeTimestamp end_timestamp
=
1517 start_timestamp
+ ComputeFudgeRoom(GetMaxInterbufferDistance());
1518 DCHECK(start_timestamp
< end_timestamp
);
1520 // Make sure the current range doesn't start beyond |end_timestamp|.
1521 if ((*itr
)->GetStartTimestamp() >= end_timestamp
)
1522 return kNoDecodeTimestamp();
1524 keyframe_timestamp
= (*itr
)->KeyframeBeforeTimestamp(end_timestamp
);
1526 // Check to see if the keyframe is within the acceptable range
1527 // (|start_timestamp|, |end_timestamp|].
1528 if (keyframe_timestamp
!= kNoDecodeTimestamp() &&
1529 start_timestamp
< keyframe_timestamp
&&
1530 keyframe_timestamp
<= end_timestamp
) {
1531 return keyframe_timestamp
;
1534 // If |end_timestamp| is within this range, then no other checks are
1536 if (end_timestamp
<= (*itr
)->GetEndTimestamp())
1537 return kNoDecodeTimestamp();
1539 // Move on to the next range.
1542 // Return early if the next range does not contain |end_timestamp|.
1543 if (itr
== ranges_
.end() || (*itr
)->GetStartTimestamp() >= end_timestamp
)
1544 return kNoDecodeTimestamp();
1546 keyframe_timestamp
= (*itr
)->KeyframeBeforeTimestamp(end_timestamp
);
1548 // Check to see if the keyframe is within the acceptable range
1549 // (|start_timestamp|, |end_timestamp|].
1550 if (keyframe_timestamp
!= kNoDecodeTimestamp() &&
1551 start_timestamp
< keyframe_timestamp
&&
1552 keyframe_timestamp
<= end_timestamp
) {
1553 return keyframe_timestamp
;
1556 return kNoDecodeTimestamp();
1559 DecodeTimestamp
SourceBufferStream::FindKeyframeAfterTimestamp(
1560 const DecodeTimestamp timestamp
) {
1561 DCHECK(timestamp
!= kNoDecodeTimestamp());
1563 RangeList::iterator itr
= FindExistingRangeFor(timestamp
);
1565 if (itr
== ranges_
.end())
1566 return kNoDecodeTimestamp();
1568 // First check for a keyframe timestamp >= |timestamp|
1569 // in the current range.
1570 return (*itr
)->NextKeyframeTimestamp(timestamp
);
1573 std::string
SourceBufferStream::GetStreamTypeName() const {
1574 switch (GetType()) {
1586 SourceBufferStream::Type
SourceBufferStream::GetType() const {
1587 if (!audio_configs_
.empty())
1589 if (!video_configs_
.empty())
1591 DCHECK_NE(text_track_config_
.kind(), kTextNone
);
1595 void SourceBufferStream::DeleteAndRemoveRange(RangeList::iterator
* itr
) {
1596 DVLOG(1) << __FUNCTION__
;
1598 DCHECK(*itr
!= ranges_
.end());
1599 if (**itr
== selected_range_
) {
1600 DVLOG(1) << __FUNCTION__
<< " deleting selected range.";
1601 SetSelectedRange(NULL
);
1604 if (*itr
== range_for_next_append_
) {
1605 DVLOG(1) << __FUNCTION__
<< " deleting range_for_next_append_.";
1606 range_for_next_append_
= ranges_
.end();
1607 last_appended_buffer_timestamp_
= kNoDecodeTimestamp();
1608 last_appended_buffer_is_keyframe_
= false;
1612 *itr
= ranges_
.erase(*itr
);
1615 void SourceBufferStream::GenerateSpliceFrame(const BufferQueue
& new_buffers
) {
1616 DCHECK(!new_buffers
.empty());
1618 // Splice frames are only supported for audio.
1619 if (GetType() != kAudio
)
1622 // Find the overlapped range (if any).
1623 const base::TimeDelta splice_timestamp
= new_buffers
.front()->timestamp();
1624 const DecodeTimestamp splice_dts
=
1625 DecodeTimestamp::FromPresentationTime(splice_timestamp
);
1626 RangeList::iterator range_itr
= FindExistingRangeFor(splice_dts
);
1627 if (range_itr
== ranges_
.end())
1630 const DecodeTimestamp max_splice_end_dts
=
1631 splice_dts
+ base::TimeDelta::FromMilliseconds(
1632 AudioSplicer::kCrossfadeDurationInMilliseconds
);
1634 // Find all buffers involved before the splice point.
1635 BufferQueue pre_splice_buffers
;
1636 if (!(*range_itr
)->GetBuffersInRange(
1637 splice_dts
, max_splice_end_dts
, &pre_splice_buffers
)) {
1641 // If there are gaps in the timeline, it's possible that we only find buffers
1642 // after the splice point but within the splice range. For simplicity, we do
1643 // not generate splice frames in this case.
1645 // We also do not want to generate splices if the first new buffer replaces an
1646 // existing buffer exactly.
1647 if (pre_splice_buffers
.front()->timestamp() >= splice_timestamp
) {
1648 LIMITED_MEDIA_LOG(DEBUG
, media_log_
, num_splice_generation_warning_logs_
,
1649 kMaxSpliceGenerationWarningLogs
)
1650 << "Skipping splice frame generation: first new buffer at "
1651 << splice_timestamp
.InMicroseconds()
1652 << "us begins at or before existing buffer at "
1653 << pre_splice_buffers
.front()->timestamp().InMicroseconds() << "us.";
1654 DVLOG(1) << "Skipping splice: overlapped buffers begin at or after the "
1655 "first new buffer.";
1659 // If any |pre_splice_buffers| are already splices or preroll, do not generate
1661 for (size_t i
= 0; i
< pre_splice_buffers
.size(); ++i
) {
1662 const BufferQueue
& original_splice_buffers
=
1663 pre_splice_buffers
[i
]->splice_buffers();
1664 if (!original_splice_buffers
.empty()) {
1665 LIMITED_MEDIA_LOG(DEBUG
, media_log_
, num_splice_generation_warning_logs_
,
1666 kMaxSpliceGenerationWarningLogs
)
1667 << "Skipping splice frame generation: overlapped buffers at "
1668 << pre_splice_buffers
[i
]->timestamp().InMicroseconds()
1669 << "us are in a previously buffered splice.";
1670 DVLOG(1) << "Can't generate splice: overlapped buffers contain a "
1671 "pre-existing splice.";
1675 if (pre_splice_buffers
[i
]->preroll_buffer().get()) {
1676 LIMITED_MEDIA_LOG(DEBUG
, media_log_
, num_splice_generation_warning_logs_
,
1677 kMaxSpliceGenerationWarningLogs
)
1678 << "Skipping splice frame generation: overlapped buffers at "
1679 << pre_splice_buffers
[i
]->timestamp().InMicroseconds()
1680 << "us contain preroll.";
1681 DVLOG(1) << "Can't generate splice: overlapped buffers contain preroll.";
1686 // Don't generate splice frames which represent less than a millisecond (which
1687 // is frequently the extent of timestamp resolution for poorly encoded media)
1688 // or less than two samples (need at least two to crossfade).
1689 const base::TimeDelta splice_duration
=
1690 pre_splice_buffers
.back()->timestamp() +
1691 pre_splice_buffers
.back()->duration() - splice_timestamp
;
1692 const base::TimeDelta minimum_splice_duration
= std::max(
1693 base::TimeDelta::FromMilliseconds(1),
1694 base::TimeDelta::FromSecondsD(
1695 2.0 / audio_configs_
[append_config_index_
].samples_per_second()));
1696 if (splice_duration
< minimum_splice_duration
) {
1697 LIMITED_MEDIA_LOG(DEBUG
, media_log_
, num_splice_generation_warning_logs_
,
1698 kMaxSpliceGenerationWarningLogs
)
1699 << "Skipping splice frame generation: not enough samples for splicing "
1701 << splice_timestamp
.InMicroseconds() << "us. Have "
1702 << splice_duration
.InMicroseconds() << "us, but need "
1703 << minimum_splice_duration
.InMicroseconds() << "us.";
1704 DVLOG(1) << "Can't generate splice: not enough samples for crossfade; have "
1705 << splice_duration
.InMicroseconds() << "us, but need "
1706 << minimum_splice_duration
.InMicroseconds() << "us.";
1710 DVLOG(1) << "Generating splice frame @ " << new_buffers
.front()->timestamp()
1711 << ", splice duration: " << splice_duration
.InMicroseconds()
1713 LIMITED_MEDIA_LOG(DEBUG
, media_log_
, num_splice_generation_success_logs_
,
1714 kMaxSpliceGenerationSuccessLogs
)
1715 << "Generated splice of overlap duration "
1716 << splice_duration
.InMicroseconds() << "us into new buffer at "
1717 << splice_timestamp
.InMicroseconds() << "us.";
1718 new_buffers
.front()->ConvertToSpliceBuffer(pre_splice_buffers
);
1721 bool SourceBufferStream::SetPendingBuffer(
1722 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1723 DCHECK(out_buffer
->get());
1724 DCHECK(!pending_buffer_
.get());
1726 const bool have_splice_buffers
= !(*out_buffer
)->splice_buffers().empty();
1727 const bool have_preroll_buffer
= !!(*out_buffer
)->preroll_buffer().get();
1729 if (!have_splice_buffers
&& !have_preroll_buffer
)
1732 DCHECK_NE(have_splice_buffers
, have_preroll_buffer
);
1733 splice_buffers_index_
= 0;
1734 pending_buffer_
.swap(*out_buffer
);
1735 pending_buffers_complete_
= false;
1739 } // namespace media