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/base/timestamp_constants.h"
16 #include "media/filters/source_buffer_platform.h"
17 #include "media/filters/source_buffer_range.h"
23 // An arbitrarily-chosen number to estimate the duration of a buffer if none is
24 // set and there's not enough information to get a better estimate.
25 const int kDefaultBufferDurationInMs
= 125;
27 // Limit the number of MEDIA_LOG() logs for splice buffer generation warnings
28 // and successes. Though these values are high enough to possibly exhaust the
29 // media internals event cache (along with other events), these logs are
30 // important for debugging splice generation.
31 const int kMaxSpliceGenerationWarningLogs
= 50;
32 const int kMaxSpliceGenerationSuccessLogs
= 20;
34 // Limit the number of MEDIA_LOG() logs for track buffer time gaps.
35 const int kMaxTrackBufferGapWarningLogs
= 20;
37 // Helper method that returns true if |ranges| is sorted in increasing order,
39 bool IsRangeListSorted(const std::list
<media::SourceBufferRange
*>& ranges
) {
40 DecodeTimestamp prev
= kNoDecodeTimestamp();
41 for (std::list
<SourceBufferRange
*>::const_iterator itr
=
42 ranges
.begin(); itr
!= ranges
.end(); ++itr
) {
43 if (prev
!= kNoDecodeTimestamp() && prev
>= (*itr
)->GetStartTimestamp())
45 prev
= (*itr
)->GetEndTimestamp();
50 // Returns an estimate of how far from the beginning or end of a range a buffer
51 // can be to still be considered in the range, given the |approximate_duration|
52 // of a buffer in the stream.
53 // TODO(wolenetz): Once all stream parsers emit accurate frame durations, use
54 // logic like FrameProcessor (2*last_frame_duration + last_decode_timestamp)
55 // instead of an overall maximum interbuffer delta for range discontinuity
56 // detection, and adjust similarly for splice frame discontinuity detection.
57 // See http://crbug.com/351489 and http://crbug.com/351166.
58 base::TimeDelta
ComputeFudgeRoom(base::TimeDelta approximate_duration
) {
59 // Because we do not know exactly when is the next timestamp, any buffer
60 // that starts within 2x the approximate duration of a buffer is considered
62 return 2 * approximate_duration
;
65 // The amount of time the beginning of the buffered data can differ from the
66 // start time in order to still be considered the start of stream.
67 base::TimeDelta
kSeekToStartFudgeRoom() {
68 return base::TimeDelta::FromMilliseconds(1000);
71 // Helper method for logging, converts a range into a readable string.
72 std::string
RangeToString(const SourceBufferRange
& range
) {
73 if (range
.size_in_bytes() == 0) {
77 ss
<< "[" << range
.GetStartTimestamp().InSecondsF()
78 << ";" << range
.GetEndTimestamp().InSecondsF()
79 << "(" << range
.GetBufferedEndTimestamp().InSecondsF() << ")]";
83 // Helper method for logging, converts a set of ranges into a readable string.
84 std::string
RangesToString(const SourceBufferStream::RangeList
& ranges
) {
89 for (const auto* range_ptr
: ranges
) {
90 if (range_ptr
!= ranges
.front())
92 ss
<< RangeToString(*range_ptr
);
97 std::string
BufferQueueToLogString(
98 const SourceBufferStream::BufferQueue
& buffers
) {
99 std::stringstream result
;
100 if (buffers
.front()->GetDecodeTimestamp().InMicroseconds() ==
101 buffers
.front()->timestamp().InMicroseconds() &&
102 buffers
.back()->GetDecodeTimestamp().InMicroseconds() ==
103 buffers
.back()->timestamp().InMicroseconds()) {
104 result
<< "dts/pts=[" << buffers
.front()->timestamp().InSecondsF() << ";"
105 << buffers
.back()->timestamp().InSecondsF() << "(last frame dur="
106 << buffers
.back()->duration().InSecondsF() << ")]";
108 result
<< "dts=[" << buffers
.front()->GetDecodeTimestamp().InSecondsF()
109 << ";" << buffers
.back()->GetDecodeTimestamp().InSecondsF()
110 << "] pts=[" << buffers
.front()->timestamp().InSecondsF() << ";"
111 << buffers
.back()->timestamp().InSecondsF() << "(last frame dur="
112 << buffers
.back()->duration().InSecondsF() << ")]";
117 SourceBufferRange::GapPolicy
TypeToGapPolicy(SourceBufferStream::Type type
) {
119 case SourceBufferStream::kAudio
:
120 case SourceBufferStream::kVideo
:
121 return SourceBufferRange::NO_GAPS_ALLOWED
;
122 case SourceBufferStream::kText
:
123 return SourceBufferRange::ALLOW_GAPS
;
127 return SourceBufferRange::NO_GAPS_ALLOWED
;
132 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig
& audio_config
,
133 const scoped_refptr
<MediaLog
>& media_log
,
134 bool splice_frames_enabled
)
135 : media_log_(media_log
),
136 seek_buffer_timestamp_(kNoTimestamp()),
137 media_segment_start_time_(kNoDecodeTimestamp()),
138 range_for_next_append_(ranges_
.end()),
139 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
140 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
141 max_interbuffer_distance_(kNoTimestamp()),
142 memory_limit_(kSourceBufferAudioMemoryLimit
),
143 splice_frames_enabled_(splice_frames_enabled
) {
144 DCHECK(audio_config
.IsValidConfig());
145 audio_configs_
.push_back(audio_config
);
148 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig
& video_config
,
149 const scoped_refptr
<MediaLog
>& media_log
,
150 bool splice_frames_enabled
)
151 : media_log_(media_log
),
152 seek_buffer_timestamp_(kNoTimestamp()),
153 media_segment_start_time_(kNoDecodeTimestamp()),
154 range_for_next_append_(ranges_
.end()),
155 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
156 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
157 max_interbuffer_distance_(kNoTimestamp()),
158 memory_limit_(kSourceBufferVideoMemoryLimit
),
159 splice_frames_enabled_(splice_frames_enabled
) {
160 DCHECK(video_config
.IsValidConfig());
161 video_configs_
.push_back(video_config
);
164 SourceBufferStream::SourceBufferStream(const TextTrackConfig
& text_config
,
165 const scoped_refptr
<MediaLog
>& media_log
,
166 bool splice_frames_enabled
)
167 : media_log_(media_log
),
168 text_track_config_(text_config
),
169 seek_buffer_timestamp_(kNoTimestamp()),
170 media_segment_start_time_(kNoDecodeTimestamp()),
171 range_for_next_append_(ranges_
.end()),
172 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
173 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
174 max_interbuffer_distance_(kNoTimestamp()),
175 memory_limit_(kSourceBufferAudioMemoryLimit
),
176 splice_frames_enabled_(splice_frames_enabled
) {}
178 SourceBufferStream::~SourceBufferStream() {
179 while (!ranges_
.empty()) {
180 delete ranges_
.front();
185 void SourceBufferStream::OnNewMediaSegment(
186 DecodeTimestamp media_segment_start_time
) {
187 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
188 << " (" << media_segment_start_time
.InSecondsF() << ")";
189 DCHECK(!end_of_stream_
);
190 media_segment_start_time_
= media_segment_start_time
;
191 new_media_segment_
= true;
193 RangeList::iterator last_range
= range_for_next_append_
;
194 range_for_next_append_
= FindExistingRangeFor(media_segment_start_time
);
196 // Only reset |last_appended_buffer_timestamp_| if this new media segment is
197 // not adjacent to the previous media segment appended to the stream.
198 if (range_for_next_append_
== ranges_
.end() ||
199 !AreAdjacentInSequence(last_appended_buffer_timestamp_
,
200 media_segment_start_time
)) {
201 last_appended_buffer_timestamp_
= kNoDecodeTimestamp();
202 last_appended_buffer_is_keyframe_
= false;
203 DVLOG(3) << __FUNCTION__
<< " next appended buffers will be in a new range";
204 } else if (last_range
!= ranges_
.end()) {
205 DCHECK(last_range
== range_for_next_append_
);
206 DVLOG(3) << __FUNCTION__
<< " next appended buffers will continue range "
207 << "unless intervening remove makes discontinuity";
211 bool SourceBufferStream::Append(const BufferQueue
& buffers
) {
212 TRACE_EVENT2("media", "SourceBufferStream::Append",
213 "stream type", GetStreamTypeName(),
214 "buffers to append", buffers
.size());
216 DCHECK(!buffers
.empty());
217 DCHECK(media_segment_start_time_
!= kNoDecodeTimestamp());
218 DCHECK(media_segment_start_time_
<= buffers
.front()->GetDecodeTimestamp());
219 DCHECK(!end_of_stream_
);
221 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
222 << ": buffers " << BufferQueueToLogString(buffers
);
224 // New media segments must begin with a keyframe.
225 // TODO(wolenetz): Relax this requirement. See http://crbug.com/229412.
226 if (new_media_segment_
&& !buffers
.front()->is_key_frame()) {
227 MEDIA_LOG(ERROR
, media_log_
) << "Media segment did not begin with key "
228 "frame. Support for such segments will be "
229 "available in a future version. Please see "
230 "https://crbug.com/229412.";
234 // Buffers within a media segment should be monotonically increasing.
235 if (!IsMonotonicallyIncreasing(buffers
))
238 if (media_segment_start_time_
< DecodeTimestamp() ||
239 buffers
.front()->GetDecodeTimestamp() < DecodeTimestamp()) {
240 MEDIA_LOG(ERROR
, media_log_
)
241 << "Cannot append a media segment with negative timestamps.";
245 if (!IsNextTimestampValid(buffers
.front()->GetDecodeTimestamp(),
246 buffers
.front()->is_key_frame())) {
247 const DecodeTimestamp
& dts
= buffers
.front()->GetDecodeTimestamp();
248 MEDIA_LOG(ERROR
, media_log_
)
249 << "Invalid same timestamp construct detected at"
250 << " time " << dts
.InSecondsF();
255 UpdateMaxInterbufferDistance(buffers
);
256 SetConfigIds(buffers
);
258 // Save a snapshot of stream state before range modifications are made.
259 DecodeTimestamp next_buffer_timestamp
= GetNextBufferTimestamp();
260 BufferQueue deleted_buffers
;
262 PrepareRangesForNextAppend(buffers
, &deleted_buffers
);
264 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise,
265 // create a new range with |buffers|.
266 if (range_for_next_append_
!= ranges_
.end()) {
267 (*range_for_next_append_
)->AppendBuffersToEnd(buffers
);
268 last_appended_buffer_timestamp_
= buffers
.back()->GetDecodeTimestamp();
269 last_appended_buffer_is_keyframe_
= buffers
.back()->is_key_frame();
271 DecodeTimestamp new_range_start_time
= std::min(
272 media_segment_start_time_
, buffers
.front()->GetDecodeTimestamp());
273 const BufferQueue
* buffers_for_new_range
= &buffers
;
274 BufferQueue trimmed_buffers
;
276 // If the new range is not being created because of a new media
277 // segment, then we must make sure that we start with a key frame.
278 // This can happen if the GOP in the previous append gets destroyed
279 // by a Remove() call.
280 if (!new_media_segment_
) {
281 BufferQueue::const_iterator itr
= buffers
.begin();
283 // Scan past all the non-key-frames.
284 while (itr
!= buffers
.end() && !(*itr
)->is_key_frame()) {
288 // If we didn't find a key frame, then update the last appended
289 // buffer state and return.
290 if (itr
== buffers
.end()) {
291 last_appended_buffer_timestamp_
= buffers
.back()->GetDecodeTimestamp();
292 last_appended_buffer_is_keyframe_
= buffers
.back()->is_key_frame();
293 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
294 << ": new buffers in the middle of media segment depend on"
295 "keyframe that has been removed, and contain no keyframes."
296 "Skipping further processing.";
297 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
298 << ": done. ranges_=" << RangesToString(ranges_
);
300 } else if (itr
!= buffers
.begin()) {
301 // Copy the first key frame and everything after it into
302 // |trimmed_buffers|.
303 trimmed_buffers
.assign(itr
, buffers
.end());
304 buffers_for_new_range
= &trimmed_buffers
;
307 new_range_start_time
=
308 buffers_for_new_range
->front()->GetDecodeTimestamp();
311 range_for_next_append_
=
312 AddToRanges(new SourceBufferRange(
313 TypeToGapPolicy(GetType()),
314 *buffers_for_new_range
, new_range_start_time
,
315 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance
,
316 base::Unretained(this))));
317 last_appended_buffer_timestamp_
=
318 buffers_for_new_range
->back()->GetDecodeTimestamp();
319 last_appended_buffer_is_keyframe_
=
320 buffers_for_new_range
->back()->is_key_frame();
323 new_media_segment_
= false;
325 MergeWithAdjacentRangeIfNecessary(range_for_next_append_
);
327 // Seek to try to fulfill a previous call to Seek().
329 DCHECK(!selected_range_
);
330 DCHECK(deleted_buffers
.empty());
331 Seek(seek_buffer_timestamp_
);
334 if (!deleted_buffers
.empty()) {
335 DecodeTimestamp start_of_deleted
=
336 deleted_buffers
.front()->GetDecodeTimestamp();
338 DCHECK(track_buffer_
.empty() ||
339 track_buffer_
.back()->GetDecodeTimestamp() < start_of_deleted
)
340 << "decode timestamp "
341 << track_buffer_
.back()->GetDecodeTimestamp().InSecondsF() << " sec"
342 << ", start_of_deleted " << start_of_deleted
.InSecondsF()<< " sec";
344 track_buffer_
.insert(track_buffer_
.end(), deleted_buffers
.begin(),
345 deleted_buffers
.end());
346 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName() << " Added "
347 << deleted_buffers
.size()
348 << " buffers to track buffer. TB size is now "
349 << track_buffer_
.size();
351 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
352 << " No deleted buffers for track buffer";
355 // Prune any extra buffers in |track_buffer_| if new keyframes
356 // are appended to the range covered by |track_buffer_|.
357 if (!track_buffer_
.empty()) {
358 DecodeTimestamp keyframe_timestamp
=
359 FindKeyframeAfterTimestamp(track_buffer_
.front()->GetDecodeTimestamp());
360 if (keyframe_timestamp
!= kNoDecodeTimestamp())
361 PruneTrackBuffer(keyframe_timestamp
);
364 SetSelectedRangeIfNeeded(next_buffer_timestamp
);
366 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
367 << ": done. ranges_=" << RangesToString(ranges_
);
368 DCHECK(IsRangeListSorted(ranges_
));
369 DCHECK(OnlySelectedRangeIsSeeked());
373 void SourceBufferStream::Remove(base::TimeDelta start
, base::TimeDelta end
,
374 base::TimeDelta duration
) {
375 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
376 << " (" << start
.InSecondsF() << ", " << end
.InSecondsF()
377 << ", " << duration
.InSecondsF() << ")";
378 DCHECK(start
>= base::TimeDelta()) << start
.InSecondsF();
379 DCHECK(start
< end
) << "start " << start
.InSecondsF()
380 << " end " << end
.InSecondsF();
381 DCHECK(duration
!= kNoTimestamp());
383 DecodeTimestamp start_dts
= DecodeTimestamp::FromPresentationTime(start
);
384 DecodeTimestamp end_dts
= DecodeTimestamp::FromPresentationTime(end
);
385 DecodeTimestamp remove_end_timestamp
=
386 DecodeTimestamp::FromPresentationTime(duration
);
387 DecodeTimestamp keyframe_timestamp
= FindKeyframeAfterTimestamp(end_dts
);
388 if (keyframe_timestamp
!= kNoDecodeTimestamp()) {
389 remove_end_timestamp
= keyframe_timestamp
;
390 } else if (end_dts
< remove_end_timestamp
) {
391 remove_end_timestamp
= end_dts
;
394 BufferQueue deleted_buffers
;
395 RemoveInternal(start_dts
, remove_end_timestamp
, false, &deleted_buffers
);
397 if (!deleted_buffers
.empty()) {
398 // Buffers for the current position have been removed.
399 SetSelectedRangeIfNeeded(deleted_buffers
.front()->GetDecodeTimestamp());
400 if (last_output_buffer_timestamp_
== kNoDecodeTimestamp()) {
401 // We just removed buffers for the current playback position for this
402 // stream, yet we also had output no buffer since the last Seek.
403 // Re-seek to prevent stall.
404 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
405 << ": re-seeking to " << seek_buffer_timestamp_
406 << " to prevent stall if this time becomes buffered again";
407 Seek(seek_buffer_timestamp_
);
412 void SourceBufferStream::RemoveInternal(DecodeTimestamp start
,
415 BufferQueue
* deleted_buffers
) {
416 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName() << " ("
417 << start
.InSecondsF() << ", " << end
.InSecondsF() << ", "
418 << exclude_start
<< ")";
419 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
420 << ": before remove ranges_=" << RangesToString(ranges_
);
422 DCHECK(start
>= DecodeTimestamp());
423 DCHECK(start
< end
) << "start " << start
.InSecondsF()
424 << " end " << end
.InSecondsF();
425 DCHECK(deleted_buffers
);
427 RangeList::iterator itr
= ranges_
.begin();
429 while (itr
!= ranges_
.end()) {
430 SourceBufferRange
* range
= *itr
;
431 if (range
->GetStartTimestamp() >= end
)
434 // Split off any remaining GOPs starting at or after |end| and add it to
436 SourceBufferRange
* new_range
= range
->SplitRange(end
);
438 itr
= ranges_
.insert(++itr
, new_range
);
441 // Update the selected range if the next buffer position was transferred
443 if (new_range
->HasNextBufferPosition())
444 SetSelectedRange(new_range
);
447 // Truncate the current range so that it only contains data before
448 // the removal range.
449 BufferQueue saved_buffers
;
450 bool delete_range
= range
->TruncateAt(start
, &saved_buffers
, exclude_start
);
452 // Check to see if the current playback position was removed and
453 // update the selected range appropriately.
454 if (!saved_buffers
.empty()) {
455 DCHECK(!range
->HasNextBufferPosition());
456 DCHECK(deleted_buffers
->empty());
458 *deleted_buffers
= saved_buffers
;
461 if (range
== selected_range_
&& !range
->HasNextBufferPosition())
462 SetSelectedRange(NULL
);
464 // If the current range now is completely covered by the removal
465 // range then delete it and move on.
467 DeleteAndRemoveRange(&itr
);
471 // Clear |range_for_next_append_| if we determine that the removal
472 // operation makes it impossible for the next append to be added
473 // to the current range.
474 if (range_for_next_append_
!= ranges_
.end() &&
475 *range_for_next_append_
== range
&&
476 last_appended_buffer_timestamp_
!= kNoDecodeTimestamp()) {
477 DecodeTimestamp potential_next_append_timestamp
=
478 last_appended_buffer_timestamp_
+
479 base::TimeDelta::FromInternalValue(1);
481 if (!range
->BelongsToRange(potential_next_append_timestamp
)) {
482 DVLOG(1) << "Resetting range_for_next_append_ since the next append"
483 << " can't add to the current range.";
484 range_for_next_append_
=
485 FindExistingRangeFor(potential_next_append_timestamp
);
489 // Move on to the next range.
493 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
494 << ": after remove ranges_=" << RangesToString(ranges_
);
496 DCHECK(IsRangeListSorted(ranges_
));
497 DCHECK(OnlySelectedRangeIsSeeked());
500 void SourceBufferStream::ResetSeekState() {
501 SetSelectedRange(NULL
);
502 track_buffer_
.clear();
503 config_change_pending_
= false;
504 last_output_buffer_timestamp_
= kNoDecodeTimestamp();
505 just_exhausted_track_buffer_
= false;
506 splice_buffers_index_
= 0;
507 pending_buffer_
= NULL
;
508 pending_buffers_complete_
= false;
511 bool SourceBufferStream::ShouldSeekToStartOfBuffered(
512 base::TimeDelta seek_timestamp
) const {
515 base::TimeDelta beginning_of_buffered
=
516 ranges_
.front()->GetStartTimestamp().ToPresentationTime();
517 return (seek_timestamp
<= beginning_of_buffered
&&
518 beginning_of_buffered
< kSeekToStartFudgeRoom());
521 bool SourceBufferStream::IsMonotonicallyIncreasing(
522 const BufferQueue
& buffers
) const {
523 DCHECK(!buffers
.empty());
524 DecodeTimestamp prev_timestamp
= last_appended_buffer_timestamp_
;
525 bool prev_is_keyframe
= last_appended_buffer_is_keyframe_
;
526 for (BufferQueue::const_iterator itr
= buffers
.begin();
527 itr
!= buffers
.end(); ++itr
) {
528 DecodeTimestamp current_timestamp
= (*itr
)->GetDecodeTimestamp();
529 bool current_is_keyframe
= (*itr
)->is_key_frame();
530 DCHECK(current_timestamp
!= kNoDecodeTimestamp());
531 DCHECK((*itr
)->duration() >= base::TimeDelta())
532 << "Packet with invalid duration."
533 << " pts " << (*itr
)->timestamp().InSecondsF()
534 << " dts " << (*itr
)->GetDecodeTimestamp().InSecondsF()
535 << " dur " << (*itr
)->duration().InSecondsF();
537 if (prev_timestamp
!= kNoDecodeTimestamp()) {
538 if (current_timestamp
< prev_timestamp
) {
539 MEDIA_LOG(ERROR
, media_log_
)
540 << "Buffers did not monotonically increase.";
544 if (current_timestamp
== prev_timestamp
&&
545 !SourceBufferRange::AllowSameTimestamp(prev_is_keyframe
,
546 current_is_keyframe
)) {
547 MEDIA_LOG(ERROR
, media_log_
) << "Unexpected combination of buffers with"
548 << " the same timestamp detected at "
549 << current_timestamp
.InSecondsF();
554 prev_timestamp
= current_timestamp
;
555 prev_is_keyframe
= current_is_keyframe
;
560 bool SourceBufferStream::IsNextTimestampValid(
561 DecodeTimestamp next_timestamp
, bool next_is_keyframe
) const {
562 return (last_appended_buffer_timestamp_
!= next_timestamp
) ||
563 new_media_segment_
||
564 SourceBufferRange::AllowSameTimestamp(last_appended_buffer_is_keyframe_
,
569 bool SourceBufferStream::OnlySelectedRangeIsSeeked() const {
570 for (RangeList::const_iterator itr
= ranges_
.begin();
571 itr
!= ranges_
.end(); ++itr
) {
572 if ((*itr
)->HasNextBufferPosition() && (*itr
) != selected_range_
)
575 return !selected_range_
|| selected_range_
->HasNextBufferPosition();
578 void SourceBufferStream::UpdateMaxInterbufferDistance(
579 const BufferQueue
& buffers
) {
580 DCHECK(!buffers
.empty());
581 DecodeTimestamp prev_timestamp
= last_appended_buffer_timestamp_
;
582 for (BufferQueue::const_iterator itr
= buffers
.begin();
583 itr
!= buffers
.end(); ++itr
) {
584 DecodeTimestamp current_timestamp
= (*itr
)->GetDecodeTimestamp();
585 DCHECK(current_timestamp
!= kNoDecodeTimestamp());
587 base::TimeDelta interbuffer_distance
= (*itr
)->duration();
588 DCHECK(interbuffer_distance
>= base::TimeDelta());
590 if (prev_timestamp
!= kNoDecodeTimestamp()) {
591 interbuffer_distance
=
592 std::max(current_timestamp
- prev_timestamp
, interbuffer_distance
);
595 if (interbuffer_distance
> base::TimeDelta()) {
596 if (max_interbuffer_distance_
== kNoTimestamp()) {
597 max_interbuffer_distance_
= interbuffer_distance
;
599 max_interbuffer_distance_
=
600 std::max(max_interbuffer_distance_
, interbuffer_distance
);
603 prev_timestamp
= current_timestamp
;
607 void SourceBufferStream::SetConfigIds(const BufferQueue
& buffers
) {
608 for (BufferQueue::const_iterator itr
= buffers
.begin();
609 itr
!= buffers
.end(); ++itr
) {
610 (*itr
)->SetConfigId(append_config_index_
);
614 bool SourceBufferStream::GarbageCollectIfNeeded(DecodeTimestamp media_time
,
615 size_t newDataSize
) {
616 DCHECK(media_time
!= kNoDecodeTimestamp());
617 // Compute size of |ranges_|.
618 size_t ranges_size
= GetBufferedSize();
620 // Sanity and overflow checks
621 if ((newDataSize
> memory_limit_
) ||
622 (ranges_size
+ newDataSize
< ranges_size
))
625 // Return if we're under or at the memory limit.
626 if (ranges_size
+ newDataSize
<= memory_limit_
)
629 size_t bytes_to_free
= ranges_size
+ newDataSize
- memory_limit_
;
631 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName() << ": Before GC"
632 << " media_time=" << media_time
.InSecondsF()
633 << " ranges_=" << RangesToString(ranges_
)
634 << " ranges_size=" << ranges_size
635 << " newDataSize=" << newDataSize
636 << " memory_limit_=" << memory_limit_
637 << " last_appended_buffer_timestamp_="
638 << last_appended_buffer_timestamp_
.InSecondsF();
640 size_t bytes_freed
= 0;
642 // If last appended buffer position was earlier than the current playback time
643 // then try deleting data between last append and current media_time.
644 if (last_appended_buffer_timestamp_
!= kNoDecodeTimestamp() &&
645 last_appended_buffer_timestamp_
< media_time
) {
646 size_t between
= FreeBuffersAfterLastAppended(bytes_to_free
, media_time
);
647 DVLOG(3) << __FUNCTION__
<< " FreeBuffersAfterLastAppended "
648 << " released " << between
<< " bytes"
649 << " ranges_=" << RangesToString(ranges_
);
650 bytes_freed
+= between
;
652 // If the last append happened before the current playback position
653 // |media_time|, then JS player is probably preparing to seek back and we
654 // should try to preserve all most recently appended data (which is in
655 // range_for_next_append_) from being removed by GC (see crbug.com/440173)
656 if (range_for_next_append_
!= ranges_
.end()) {
657 DCHECK((*range_for_next_append_
)->GetStartTimestamp() <= media_time
);
658 media_time
= (*range_for_next_append_
)->GetStartTimestamp();
662 // Try removing data from the front of the SourceBuffer up to |media_time|
664 if (bytes_freed
< bytes_to_free
) {
665 size_t front
= FreeBuffers(bytes_to_free
- bytes_freed
, media_time
, false);
666 DVLOG(3) << __FUNCTION__
<< " Removed " << front
<< " bytes from the front"
667 << " ranges_=" << RangesToString(ranges_
);
668 bytes_freed
+= front
;
671 // Try removing data from the back of the SourceBuffer, until we reach the
672 // most recent append position.
673 if (bytes_freed
< bytes_to_free
) {
674 size_t back
= FreeBuffers(bytes_to_free
- bytes_freed
, media_time
, true);
675 DVLOG(3) << __FUNCTION__
<< " Removed " << back
<< " bytes from the back"
676 << " ranges_=" << RangesToString(ranges_
);
680 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName() << ": After GC"
681 << " bytes_to_free=" << bytes_to_free
682 << " bytes_freed=" << bytes_freed
683 << " ranges_=" << RangesToString(ranges_
);
685 return bytes_freed
>= bytes_to_free
;
688 size_t SourceBufferStream::FreeBuffersAfterLastAppended(
689 size_t total_bytes_to_free
, DecodeTimestamp media_time
) {
690 DVLOG(4) << __FUNCTION__
<< " last_appended_buffer_timestamp_="
691 << last_appended_buffer_timestamp_
.InSecondsF()
692 << " media_time=" << media_time
.InSecondsF();
694 DecodeTimestamp remove_range_start
= last_appended_buffer_timestamp_
;
695 if (last_appended_buffer_is_keyframe_
)
696 remove_range_start
+= GetMaxInterbufferDistance();
698 DecodeTimestamp remove_range_start_keyframe
= FindKeyframeAfterTimestamp(
700 if (remove_range_start_keyframe
!= kNoDecodeTimestamp())
701 remove_range_start
= remove_range_start_keyframe
;
702 if (remove_range_start
>= media_time
)
705 DecodeTimestamp remove_range_end
;
706 size_t bytes_freed
= GetRemovalRange(remove_range_start
,
710 if (bytes_freed
> 0) {
711 DVLOG(4) << __FUNCTION__
<< " removing ["
712 << remove_range_start
.ToPresentationTime().InSecondsF() << ";"
713 << remove_range_end
.ToPresentationTime().InSecondsF() << "]";
714 Remove(remove_range_start
.ToPresentationTime(),
715 remove_range_end
.ToPresentationTime(),
716 media_time
.ToPresentationTime());
722 size_t SourceBufferStream::GetRemovalRange(
723 DecodeTimestamp start_timestamp
, DecodeTimestamp end_timestamp
,
724 size_t total_bytes_to_free
, DecodeTimestamp
* removal_end_timestamp
) {
725 DCHECK(start_timestamp
>= DecodeTimestamp()) << start_timestamp
.InSecondsF();
726 DCHECK(start_timestamp
< end_timestamp
)
727 << "start " << start_timestamp
.InSecondsF()
728 << ", end " << end_timestamp
.InSecondsF();
730 size_t bytes_freed
= 0;
732 for (RangeList::iterator itr
= ranges_
.begin();
733 itr
!= ranges_
.end() && bytes_freed
< total_bytes_to_free
; ++itr
) {
734 SourceBufferRange
* range
= *itr
;
735 if (range
->GetStartTimestamp() >= end_timestamp
)
737 if (range
->GetEndTimestamp() < start_timestamp
)
740 size_t bytes_to_free
= total_bytes_to_free
- bytes_freed
;
741 size_t bytes_removed
= range
->GetRemovalGOP(
742 start_timestamp
, end_timestamp
, bytes_to_free
, removal_end_timestamp
);
743 bytes_freed
+= bytes_removed
;
748 size_t SourceBufferStream::FreeBuffers(size_t total_bytes_to_free
,
749 DecodeTimestamp media_time
,
750 bool reverse_direction
) {
751 TRACE_EVENT2("media", "SourceBufferStream::FreeBuffers",
752 "total bytes to free", total_bytes_to_free
,
753 "reverse direction", reverse_direction
);
755 DCHECK_GT(total_bytes_to_free
, 0u);
756 size_t bytes_freed
= 0;
758 // This range will save the last GOP appended to |range_for_next_append_|
759 // if the buffers surrounding it get deleted during garbage collection.
760 SourceBufferRange
* new_range_for_append
= NULL
;
762 while (!ranges_
.empty() && bytes_freed
< total_bytes_to_free
) {
763 SourceBufferRange
* current_range
= NULL
;
765 size_t bytes_deleted
= 0;
767 if (reverse_direction
) {
768 current_range
= ranges_
.back();
769 DVLOG(5) << "current_range=" << RangeToString(*current_range
);
770 if (current_range
->LastGOPContainsNextBufferPosition()) {
771 DCHECK_EQ(current_range
, selected_range_
);
772 DVLOG(5) << "current_range contains next read position, stopping GC";
775 DVLOG(5) << "Deleting GOP from back: " << RangeToString(*current_range
);
776 bytes_deleted
= current_range
->DeleteGOPFromBack(&buffers
);
778 current_range
= ranges_
.front();
779 DVLOG(5) << "current_range=" << RangeToString(*current_range
);
780 if (!current_range
->FirstGOPEarlierThanMediaTime(media_time
)) {
781 // We have removed all data up to the GOP that contains current playback
782 // position, we can't delete any further.
783 DVLOG(5) << "current_range contains playback position, stopping GC";
786 DVLOG(4) << "Deleting GOP from front: " << RangeToString(*current_range
);
787 bytes_deleted
= current_range
->DeleteGOPFromFront(&buffers
);
790 // Check to see if we've just deleted the GOP that was last appended.
791 DecodeTimestamp end_timestamp
= buffers
.back()->GetDecodeTimestamp();
792 if (end_timestamp
== last_appended_buffer_timestamp_
) {
793 DCHECK(last_appended_buffer_timestamp_
!= kNoDecodeTimestamp());
794 DCHECK(!new_range_for_append
);
796 // Create a new range containing these buffers.
797 new_range_for_append
= new SourceBufferRange(
798 TypeToGapPolicy(GetType()),
799 buffers
, kNoDecodeTimestamp(),
800 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance
,
801 base::Unretained(this)));
802 range_for_next_append_
= ranges_
.end();
804 bytes_freed
+= bytes_deleted
;
807 if (current_range
->size_in_bytes() == 0) {
808 DCHECK_NE(current_range
, selected_range_
);
809 DCHECK(range_for_next_append_
== ranges_
.end() ||
810 *range_for_next_append_
!= current_range
);
811 delete current_range
;
812 reverse_direction
? ranges_
.pop_back() : ranges_
.pop_front();
815 if (reverse_direction
&& new_range_for_append
) {
816 // We don't want to delete any further, or we'll be creating gaps
821 // Insert |new_range_for_append| into |ranges_|, if applicable.
822 if (new_range_for_append
) {
823 range_for_next_append_
= AddToRanges(new_range_for_append
);
824 DCHECK(range_for_next_append_
!= ranges_
.end());
826 // Check to see if we need to merge |new_range_for_append| with the range
827 // before or after it. |new_range_for_append| is created whenever the last
828 // GOP appended is encountered, regardless of whether any buffers after it
829 // are ultimately deleted. Merging is necessary if there were no buffers
830 // (or very few buffers) deleted after creating |new_range_for_append|.
831 if (range_for_next_append_
!= ranges_
.begin()) {
832 RangeList::iterator range_before_next
= range_for_next_append_
;
834 MergeWithAdjacentRangeIfNecessary(range_before_next
);
836 MergeWithAdjacentRangeIfNecessary(range_for_next_append_
);
841 void SourceBufferStream::PrepareRangesForNextAppend(
842 const BufferQueue
& new_buffers
, BufferQueue
* deleted_buffers
) {
843 DCHECK(deleted_buffers
);
845 bool temporarily_select_range
= false;
846 if (!track_buffer_
.empty()) {
847 DecodeTimestamp tb_timestamp
= track_buffer_
.back()->GetDecodeTimestamp();
848 DecodeTimestamp seek_timestamp
= FindKeyframeAfterTimestamp(tb_timestamp
);
849 if (seek_timestamp
!= kNoDecodeTimestamp() &&
850 seek_timestamp
< new_buffers
.front()->GetDecodeTimestamp() &&
851 range_for_next_append_
!= ranges_
.end() &&
852 (*range_for_next_append_
)->BelongsToRange(seek_timestamp
)) {
853 DCHECK(tb_timestamp
< seek_timestamp
);
854 DCHECK(!selected_range_
);
855 DCHECK(!(*range_for_next_append_
)->HasNextBufferPosition());
857 // If there are GOPs between the end of the track buffer and the
858 // beginning of the new buffers, then temporarily seek the range
859 // so that the buffers between these two times will be deposited in
860 // |deleted_buffers| as if they were part of the current playback
862 // TODO(acolwell): Figure out a more elegant way to do this.
863 SeekAndSetSelectedRange(*range_for_next_append_
, seek_timestamp
);
864 temporarily_select_range
= true;
868 // Handle splices between the existing buffers and the new buffers. If a
869 // splice is generated the timestamp and duration of the first buffer in
870 // |new_buffers| will be modified.
871 if (splice_frames_enabled_
)
872 GenerateSpliceFrame(new_buffers
);
874 DecodeTimestamp prev_timestamp
= last_appended_buffer_timestamp_
;
875 bool prev_is_keyframe
= last_appended_buffer_is_keyframe_
;
876 DecodeTimestamp next_timestamp
= new_buffers
.front()->GetDecodeTimestamp();
877 bool next_is_keyframe
= new_buffers
.front()->is_key_frame();
879 if (prev_timestamp
!= kNoDecodeTimestamp() &&
880 prev_timestamp
!= next_timestamp
) {
881 // Clean up the old buffers between the last appended buffer and the
882 // beginning of |new_buffers|.
883 RemoveInternal(prev_timestamp
, next_timestamp
, true, deleted_buffers
);
886 // Make the delete range exclusive if we are dealing with an allowed same
887 // timestamp situation. This prevents the first buffer in the current append
888 // from deleting the last buffer in the previous append if both buffers
889 // have the same timestamp.
891 // The delete range should never be exclusive if a splice frame was generated
892 // because we don't generate splice frames for same timestamp situations.
893 DCHECK(new_buffers
.front()->splice_timestamp() !=
894 new_buffers
.front()->timestamp());
895 const bool exclude_start
=
896 new_buffers
.front()->splice_buffers().empty() &&
897 prev_timestamp
== next_timestamp
&&
898 SourceBufferRange::AllowSameTimestamp(prev_is_keyframe
, next_is_keyframe
);
900 // Delete the buffers that |new_buffers| overlaps.
901 DecodeTimestamp start
= new_buffers
.front()->GetDecodeTimestamp();
902 DecodeTimestamp end
= new_buffers
.back()->GetDecodeTimestamp();
903 base::TimeDelta duration
= new_buffers
.back()->duration();
905 // Set end time for remove to include the duration of last buffer. If the
906 // duration is estimated, use 1 microsecond instead to ensure frames are not
907 // accidentally removed due to over-estimation.
908 if (duration
!= kNoTimestamp() && duration
> base::TimeDelta() &&
909 !new_buffers
.back()->is_duration_estimated()) {
912 // TODO(chcunningham): Emit warning when 0ms durations are not expected.
913 // http://crbug.com/312836
914 end
+= base::TimeDelta::FromInternalValue(1);
917 RemoveInternal(start
, end
, exclude_start
, deleted_buffers
);
919 // Restore the range seek state if necessary.
920 if (temporarily_select_range
)
921 SetSelectedRange(NULL
);
924 bool SourceBufferStream::AreAdjacentInSequence(
925 DecodeTimestamp first_timestamp
, DecodeTimestamp second_timestamp
) const {
926 return first_timestamp
< second_timestamp
&&
928 first_timestamp
+ ComputeFudgeRoom(GetMaxInterbufferDistance());
931 void SourceBufferStream::PruneTrackBuffer(const DecodeTimestamp timestamp
) {
932 // If we don't have the next timestamp, we don't have anything to delete.
933 if (timestamp
== kNoDecodeTimestamp())
936 while (!track_buffer_
.empty() &&
937 track_buffer_
.back()->GetDecodeTimestamp() >= timestamp
) {
938 track_buffer_
.pop_back();
940 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
941 << " Removed all buffers with DTS >= " << timestamp
.InSecondsF()
942 << ". New track buffer size:" << track_buffer_
.size();
945 void SourceBufferStream::MergeWithAdjacentRangeIfNecessary(
946 const RangeList::iterator
& range_with_new_buffers_itr
) {
947 DCHECK(range_with_new_buffers_itr
!= ranges_
.end());
949 SourceBufferRange
* range_with_new_buffers
= *range_with_new_buffers_itr
;
950 RangeList::iterator next_range_itr
= range_with_new_buffers_itr
;
953 if (next_range_itr
== ranges_
.end() ||
954 !range_with_new_buffers
->CanAppendRangeToEnd(**next_range_itr
)) {
958 bool transfer_current_position
= selected_range_
== *next_range_itr
;
959 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
960 << " merging " << RangeToString(*range_with_new_buffers
)
961 << " into " << RangeToString(**next_range_itr
);
962 range_with_new_buffers
->AppendRangeToEnd(**next_range_itr
,
963 transfer_current_position
);
964 // Update |selected_range_| pointer if |range| has become selected after
966 if (transfer_current_position
)
967 SetSelectedRange(range_with_new_buffers
);
969 if (next_range_itr
== range_for_next_append_
)
970 range_for_next_append_
= range_with_new_buffers_itr
;
972 DeleteAndRemoveRange(&next_range_itr
);
975 void SourceBufferStream::Seek(base::TimeDelta timestamp
) {
976 DCHECK(timestamp
>= base::TimeDelta());
977 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
978 << " (" << timestamp
.InSecondsF() << ")";
981 seek_buffer_timestamp_
= timestamp
;
982 seek_pending_
= true;
984 if (ShouldSeekToStartOfBuffered(timestamp
)) {
985 ranges_
.front()->SeekToStart();
986 SetSelectedRange(ranges_
.front());
987 seek_pending_
= false;
991 DecodeTimestamp seek_dts
= DecodeTimestamp::FromPresentationTime(timestamp
);
993 RangeList::iterator itr
= ranges_
.end();
994 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
995 if ((*itr
)->CanSeekTo(seek_dts
))
999 if (itr
== ranges_
.end())
1002 SeekAndSetSelectedRange(*itr
, seek_dts
);
1003 seek_pending_
= false;
1006 bool SourceBufferStream::IsSeekPending() const {
1007 return seek_pending_
&& !IsEndOfStreamReached();
1010 void SourceBufferStream::OnSetDuration(base::TimeDelta duration
) {
1011 DecodeTimestamp duration_dts
=
1012 DecodeTimestamp::FromPresentationTime(duration
);
1013 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
1014 << " (" << duration
.InSecondsF() << ")";
1016 RangeList::iterator itr
= ranges_
.end();
1017 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1018 if ((*itr
)->GetEndTimestamp() > duration_dts
)
1021 if (itr
== ranges_
.end())
1024 // Need to partially truncate this range.
1025 if ((*itr
)->GetStartTimestamp() < duration_dts
) {
1026 bool delete_range
= (*itr
)->TruncateAt(duration_dts
, NULL
, false);
1027 if ((*itr
== selected_range_
) && !selected_range_
->HasNextBufferPosition())
1028 SetSelectedRange(NULL
);
1031 DeleteAndRemoveRange(&itr
);
1037 // Delete all ranges that begin after |duration_dts|.
1038 while (itr
!= ranges_
.end()) {
1039 // If we're about to delete the selected range, also reset the seek state.
1040 DCHECK((*itr
)->GetStartTimestamp() >= duration_dts
);
1041 if (*itr
== selected_range_
)
1043 DeleteAndRemoveRange(&itr
);
1047 SourceBufferStream::Status
SourceBufferStream::GetNextBuffer(
1048 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1049 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName();
1050 if (!pending_buffer_
.get()) {
1051 const SourceBufferStream::Status status
= GetNextBufferInternal(out_buffer
);
1052 if (status
!= SourceBufferStream::kSuccess
||
1053 !SetPendingBuffer(out_buffer
)) {
1054 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1055 << ": no pending buffer, returning status " << status
;
1060 if (!pending_buffer_
->splice_buffers().empty()) {
1061 const SourceBufferStream::Status status
=
1062 HandleNextBufferWithSplice(out_buffer
);
1063 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1064 << ": handled next buffer with splice, returning status "
1069 DCHECK(pending_buffer_
->preroll_buffer().get());
1071 const SourceBufferStream::Status status
=
1072 HandleNextBufferWithPreroll(out_buffer
);
1073 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1074 << ": handled next buffer with preroll, returning status "
1079 SourceBufferStream::Status
SourceBufferStream::HandleNextBufferWithSplice(
1080 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1081 const BufferQueue
& splice_buffers
= pending_buffer_
->splice_buffers();
1082 const size_t last_splice_buffer_index
= splice_buffers
.size() - 1;
1084 // Are there any splice buffers left to hand out? The last buffer should be
1085 // handed out separately since it represents the first post-splice buffer.
1086 if (splice_buffers_index_
< last_splice_buffer_index
) {
1087 // Account for config changes which occur between fade out buffers.
1088 if (current_config_index_
!=
1089 splice_buffers
[splice_buffers_index_
]->GetConfigId()) {
1090 config_change_pending_
= true;
1091 DVLOG(1) << "Config change (splice buffer config ID does not match).";
1092 return SourceBufferStream::kConfigChange
;
1095 // Every pre splice buffer must have the same splice_timestamp().
1096 DCHECK(pending_buffer_
->splice_timestamp() ==
1097 splice_buffers
[splice_buffers_index_
]->splice_timestamp());
1099 // No pre splice buffers should have preroll.
1100 DCHECK(!splice_buffers
[splice_buffers_index_
]->preroll_buffer().get());
1102 *out_buffer
= splice_buffers
[splice_buffers_index_
++];
1103 return SourceBufferStream::kSuccess
;
1106 // Did we hand out the last pre-splice buffer on the previous call?
1107 if (!pending_buffers_complete_
) {
1108 DCHECK_EQ(splice_buffers_index_
, last_splice_buffer_index
);
1109 pending_buffers_complete_
= true;
1110 config_change_pending_
= true;
1111 DVLOG(1) << "Config change (forced for fade in of splice frame).";
1112 return SourceBufferStream::kConfigChange
;
1115 // All pre-splice buffers have been handed out and a config change completed,
1116 // so hand out the final buffer for fade in. Because a config change is
1117 // always issued prior to handing out this buffer, any changes in config id
1118 // have been inherently handled.
1119 DCHECK(pending_buffers_complete_
);
1120 DCHECK_EQ(splice_buffers_index_
, splice_buffers
.size() - 1);
1121 DCHECK(splice_buffers
.back()->splice_timestamp() == kNoTimestamp());
1122 *out_buffer
= splice_buffers
.back();
1123 pending_buffer_
= NULL
;
1125 // If the last splice buffer has preroll, hand off to the preroll handler.
1126 return SetPendingBuffer(out_buffer
) ? HandleNextBufferWithPreroll(out_buffer
)
1127 : SourceBufferStream::kSuccess
;
1130 SourceBufferStream::Status
SourceBufferStream::HandleNextBufferWithPreroll(
1131 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1132 // Any config change should have already been handled.
1133 DCHECK_EQ(current_config_index_
, pending_buffer_
->GetConfigId());
1135 // Check if the preroll buffer has already been handed out.
1136 if (!pending_buffers_complete_
) {
1137 pending_buffers_complete_
= true;
1138 *out_buffer
= pending_buffer_
->preroll_buffer();
1139 return SourceBufferStream::kSuccess
;
1142 // Preroll complete, hand out the final buffer.
1143 *out_buffer
= pending_buffer_
;
1144 pending_buffer_
= NULL
;
1145 return SourceBufferStream::kSuccess
;
1148 SourceBufferStream::Status
SourceBufferStream::GetNextBufferInternal(
1149 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1150 CHECK(!config_change_pending_
);
1152 if (!track_buffer_
.empty()) {
1153 DCHECK(!selected_range_
);
1154 scoped_refptr
<StreamParserBuffer
>& next_buffer
= track_buffer_
.front();
1156 // If the next buffer is an audio splice frame, the next effective config id
1157 // comes from the first splice buffer.
1158 if (next_buffer
->GetSpliceBufferConfigId(0) != current_config_index_
) {
1159 config_change_pending_
= true;
1160 DVLOG(1) << "Config change (track buffer config ID does not match).";
1161 return kConfigChange
;
1164 DVLOG(3) << __FUNCTION__
<< " Next buffer coming from track_buffer_";
1165 *out_buffer
= next_buffer
;
1166 track_buffer_
.pop_front();
1167 WarnIfTrackBufferExhaustionSkipsForward(*out_buffer
);
1168 last_output_buffer_timestamp_
= (*out_buffer
)->GetDecodeTimestamp();
1170 // If the track buffer becomes empty, then try to set the selected range
1171 // based on the timestamp of this buffer being returned.
1172 if (track_buffer_
.empty()) {
1173 just_exhausted_track_buffer_
= true;
1174 SetSelectedRangeIfNeeded(last_output_buffer_timestamp_
);
1180 DCHECK(track_buffer_
.empty());
1181 if (!selected_range_
|| !selected_range_
->HasNextBuffer()) {
1182 if (IsEndOfStreamReached()) {
1183 return kEndOfStream
;
1185 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
1186 << ": returning kNeedBuffer "
1187 << (selected_range_
? "(selected range has no next buffer)"
1188 : "(no selected range)");
1192 if (selected_range_
->GetNextConfigId() != current_config_index_
) {
1193 config_change_pending_
= true;
1194 DVLOG(1) << "Config change (selected range config ID does not match).";
1195 return kConfigChange
;
1198 CHECK(selected_range_
->GetNextBuffer(out_buffer
));
1199 WarnIfTrackBufferExhaustionSkipsForward(*out_buffer
);
1200 last_output_buffer_timestamp_
= (*out_buffer
)->GetDecodeTimestamp();
1204 void SourceBufferStream::WarnIfTrackBufferExhaustionSkipsForward(
1205 const scoped_refptr
<StreamParserBuffer
>& next_buffer
) {
1206 if (!just_exhausted_track_buffer_
)
1209 just_exhausted_track_buffer_
= false;
1210 DCHECK(next_buffer
->is_key_frame());
1211 DecodeTimestamp next_output_buffer_timestamp
=
1212 next_buffer
->GetDecodeTimestamp();
1213 base::TimeDelta delta
=
1214 next_output_buffer_timestamp
- last_output_buffer_timestamp_
;
1215 DCHECK_GE(delta
, base::TimeDelta());
1216 if (delta
> GetMaxInterbufferDistance()) {
1217 LIMITED_MEDIA_LOG(DEBUG
, media_log_
, num_track_buffer_gap_warning_logs_
,
1218 kMaxTrackBufferGapWarningLogs
)
1219 << "Media append that overlapped current playback position caused time "
1221 << GetStreamTypeName() << " stream because the next keyframe is "
1222 << delta
.InMilliseconds() << "ms beyond last overlapped frame. Media "
1223 "may appear temporarily frozen.";
1227 DecodeTimestamp
SourceBufferStream::GetNextBufferTimestamp() {
1228 if (!track_buffer_
.empty())
1229 return track_buffer_
.front()->GetDecodeTimestamp();
1231 if (!selected_range_
)
1232 return kNoDecodeTimestamp();
1234 DCHECK(selected_range_
->HasNextBufferPosition());
1235 return selected_range_
->GetNextTimestamp();
1238 SourceBufferStream::RangeList::iterator
1239 SourceBufferStream::FindExistingRangeFor(DecodeTimestamp start_timestamp
) {
1240 for (RangeList::iterator itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1241 if ((*itr
)->BelongsToRange(start_timestamp
))
1244 return ranges_
.end();
1247 SourceBufferStream::RangeList::iterator
1248 SourceBufferStream::AddToRanges(SourceBufferRange
* new_range
) {
1249 DecodeTimestamp start_timestamp
= new_range
->GetStartTimestamp();
1250 RangeList::iterator itr
= ranges_
.end();
1251 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1252 if ((*itr
)->GetStartTimestamp() > start_timestamp
)
1255 return ranges_
.insert(itr
, new_range
);
1258 SourceBufferStream::RangeList::iterator
1259 SourceBufferStream::GetSelectedRangeItr() {
1260 DCHECK(selected_range_
);
1261 RangeList::iterator itr
= ranges_
.end();
1262 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1263 if (*itr
== selected_range_
)
1266 DCHECK(itr
!= ranges_
.end());
1270 void SourceBufferStream::SeekAndSetSelectedRange(
1271 SourceBufferRange
* range
, DecodeTimestamp seek_timestamp
) {
1273 range
->Seek(seek_timestamp
);
1274 SetSelectedRange(range
);
1277 void SourceBufferStream::SetSelectedRange(SourceBufferRange
* range
) {
1278 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName() << ": "
1279 << selected_range_
<< " "
1280 << (selected_range_
? RangeToString(*selected_range_
) : "")
1281 << " -> " << range
<< " " << (range
? RangeToString(*range
) : "");
1282 if (selected_range_
)
1283 selected_range_
->ResetNextBufferPosition();
1284 DCHECK(!range
|| range
->HasNextBufferPosition());
1285 selected_range_
= range
;
1288 Ranges
<base::TimeDelta
> SourceBufferStream::GetBufferedTime() const {
1289 Ranges
<base::TimeDelta
> ranges
;
1290 for (RangeList::const_iterator itr
= ranges_
.begin();
1291 itr
!= ranges_
.end(); ++itr
) {
1292 ranges
.Add((*itr
)->GetStartTimestamp().ToPresentationTime(),
1293 (*itr
)->GetBufferedEndTimestamp().ToPresentationTime());
1298 base::TimeDelta
SourceBufferStream::GetBufferedDuration() const {
1299 if (ranges_
.empty())
1300 return base::TimeDelta();
1302 return ranges_
.back()->GetBufferedEndTimestamp().ToPresentationTime();
1305 size_t SourceBufferStream::GetBufferedSize() const {
1306 size_t ranges_size
= 0;
1307 for (const auto& range
: ranges_
)
1308 ranges_size
+= range
->size_in_bytes();
1312 void SourceBufferStream::MarkEndOfStream() {
1313 DCHECK(!end_of_stream_
);
1314 end_of_stream_
= true;
1317 void SourceBufferStream::UnmarkEndOfStream() {
1318 DCHECK(end_of_stream_
);
1319 end_of_stream_
= false;
1322 bool SourceBufferStream::IsEndOfStreamReached() const {
1323 if (!end_of_stream_
|| !track_buffer_
.empty())
1326 if (ranges_
.empty())
1329 if (seek_pending_
) {
1330 base::TimeDelta last_range_end_time
=
1331 ranges_
.back()->GetBufferedEndTimestamp().ToPresentationTime();
1332 return seek_buffer_timestamp_
>= last_range_end_time
;
1335 if (!selected_range_
)
1338 return selected_range_
== ranges_
.back();
1341 const AudioDecoderConfig
& SourceBufferStream::GetCurrentAudioDecoderConfig() {
1342 if (config_change_pending_
)
1343 CompleteConfigChange();
1344 return audio_configs_
[current_config_index_
];
1347 const VideoDecoderConfig
& SourceBufferStream::GetCurrentVideoDecoderConfig() {
1348 if (config_change_pending_
)
1349 CompleteConfigChange();
1350 return video_configs_
[current_config_index_
];
1353 const TextTrackConfig
& SourceBufferStream::GetCurrentTextTrackConfig() {
1354 return text_track_config_
;
1357 base::TimeDelta
SourceBufferStream::GetMaxInterbufferDistance() const {
1358 if (max_interbuffer_distance_
== kNoTimestamp())
1359 return base::TimeDelta::FromMilliseconds(kDefaultBufferDurationInMs
);
1360 return max_interbuffer_distance_
;
1363 bool SourceBufferStream::UpdateAudioConfig(const AudioDecoderConfig
& config
) {
1364 DCHECK(!audio_configs_
.empty());
1365 DCHECK(video_configs_
.empty());
1366 DVLOG(3) << "UpdateAudioConfig.";
1368 if (audio_configs_
[0].codec() != config
.codec()) {
1369 MEDIA_LOG(ERROR
, media_log_
) << "Audio codec changes not allowed.";
1373 if (audio_configs_
[0].is_encrypted() != config
.is_encrypted()) {
1374 MEDIA_LOG(ERROR
, media_log_
) << "Audio encryption changes not allowed.";
1378 // Check to see if the new config matches an existing one.
1379 for (size_t i
= 0; i
< audio_configs_
.size(); ++i
) {
1380 if (config
.Matches(audio_configs_
[i
])) {
1381 append_config_index_
= i
;
1386 // No matches found so let's add this one to the list.
1387 append_config_index_
= audio_configs_
.size();
1388 DVLOG(2) << "New audio config - index: " << append_config_index_
;
1389 audio_configs_
.resize(audio_configs_
.size() + 1);
1390 audio_configs_
[append_config_index_
] = config
;
1394 bool SourceBufferStream::UpdateVideoConfig(const VideoDecoderConfig
& config
) {
1395 DCHECK(!video_configs_
.empty());
1396 DCHECK(audio_configs_
.empty());
1397 DVLOG(3) << "UpdateVideoConfig.";
1399 if (video_configs_
[0].codec() != config
.codec()) {
1400 MEDIA_LOG(ERROR
, media_log_
) << "Video codec changes not allowed.";
1404 if (video_configs_
[0].is_encrypted() != config
.is_encrypted()) {
1405 MEDIA_LOG(ERROR
, media_log_
) << "Video encryption changes not allowed.";
1409 // Check to see if the new config matches an existing one.
1410 for (size_t i
= 0; i
< video_configs_
.size(); ++i
) {
1411 if (config
.Matches(video_configs_
[i
])) {
1412 append_config_index_
= i
;
1417 // No matches found so let's add this one to the list.
1418 append_config_index_
= video_configs_
.size();
1419 DVLOG(2) << "New video config - index: " << append_config_index_
;
1420 video_configs_
.resize(video_configs_
.size() + 1);
1421 video_configs_
[append_config_index_
] = config
;
1425 void SourceBufferStream::CompleteConfigChange() {
1426 config_change_pending_
= false;
1428 if (pending_buffer_
.get()) {
1429 current_config_index_
=
1430 pending_buffer_
->GetSpliceBufferConfigId(splice_buffers_index_
);
1434 if (!track_buffer_
.empty()) {
1435 current_config_index_
= track_buffer_
.front()->GetSpliceBufferConfigId(0);
1439 if (selected_range_
&& selected_range_
->HasNextBuffer())
1440 current_config_index_
= selected_range_
->GetNextConfigId();
1443 void SourceBufferStream::SetSelectedRangeIfNeeded(
1444 const DecodeTimestamp timestamp
) {
1445 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1446 << "(" << timestamp
.InSecondsF() << ")";
1448 if (selected_range_
) {
1449 DCHECK(track_buffer_
.empty());
1453 if (!track_buffer_
.empty()) {
1454 DCHECK(!selected_range_
);
1458 DecodeTimestamp start_timestamp
= timestamp
;
1460 // If the next buffer timestamp is not known then use a timestamp just after
1461 // the timestamp on the last buffer returned by GetNextBuffer().
1462 if (start_timestamp
== kNoDecodeTimestamp()) {
1463 if (last_output_buffer_timestamp_
== kNoDecodeTimestamp()) {
1464 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1465 << " no previous output timestamp";
1469 start_timestamp
= last_output_buffer_timestamp_
+
1470 base::TimeDelta::FromInternalValue(1);
1473 DecodeTimestamp seek_timestamp
=
1474 FindNewSelectedRangeSeekTimestamp(start_timestamp
);
1476 // If we don't have buffered data to seek to, then return.
1477 if (seek_timestamp
== kNoDecodeTimestamp()) {
1478 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1479 << " couldn't find new selected range seek timestamp";
1483 DCHECK(track_buffer_
.empty());
1484 SeekAndSetSelectedRange(*FindExistingRangeFor(seek_timestamp
),
1488 DecodeTimestamp
SourceBufferStream::FindNewSelectedRangeSeekTimestamp(
1489 const DecodeTimestamp start_timestamp
) {
1490 DCHECK(start_timestamp
!= kNoDecodeTimestamp());
1491 DCHECK(start_timestamp
>= DecodeTimestamp());
1493 RangeList::iterator itr
= ranges_
.begin();
1495 for (; itr
!= ranges_
.end(); ++itr
) {
1496 if ((*itr
)->GetEndTimestamp() >= start_timestamp
) {
1501 if (itr
== ranges_
.end()) {
1502 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1503 << " no buffered data for dts=" << start_timestamp
.InSecondsF();
1504 return kNoDecodeTimestamp();
1507 // First check for a keyframe timestamp >= |start_timestamp|
1508 // in the current range.
1509 DecodeTimestamp keyframe_timestamp
=
1510 (*itr
)->NextKeyframeTimestamp(start_timestamp
);
1512 if (keyframe_timestamp
!= kNoDecodeTimestamp())
1513 return keyframe_timestamp
;
1515 // If a keyframe was not found then look for a keyframe that is
1516 // "close enough" in the current or next range.
1517 DecodeTimestamp end_timestamp
=
1518 start_timestamp
+ ComputeFudgeRoom(GetMaxInterbufferDistance());
1519 DCHECK(start_timestamp
< end_timestamp
);
1521 // Make sure the current range doesn't start beyond |end_timestamp|.
1522 if ((*itr
)->GetStartTimestamp() >= end_timestamp
)
1523 return kNoDecodeTimestamp();
1525 keyframe_timestamp
= (*itr
)->KeyframeBeforeTimestamp(end_timestamp
);
1527 // Check to see if the keyframe is within the acceptable range
1528 // (|start_timestamp|, |end_timestamp|].
1529 if (keyframe_timestamp
!= kNoDecodeTimestamp() &&
1530 start_timestamp
< keyframe_timestamp
&&
1531 keyframe_timestamp
<= end_timestamp
) {
1532 return keyframe_timestamp
;
1535 // If |end_timestamp| is within this range, then no other checks are
1537 if (end_timestamp
<= (*itr
)->GetEndTimestamp())
1538 return kNoDecodeTimestamp();
1540 // Move on to the next range.
1543 // Return early if the next range does not contain |end_timestamp|.
1544 if (itr
== ranges_
.end() || (*itr
)->GetStartTimestamp() >= end_timestamp
)
1545 return kNoDecodeTimestamp();
1547 keyframe_timestamp
= (*itr
)->KeyframeBeforeTimestamp(end_timestamp
);
1549 // Check to see if the keyframe is within the acceptable range
1550 // (|start_timestamp|, |end_timestamp|].
1551 if (keyframe_timestamp
!= kNoDecodeTimestamp() &&
1552 start_timestamp
< keyframe_timestamp
&&
1553 keyframe_timestamp
<= end_timestamp
) {
1554 return keyframe_timestamp
;
1557 return kNoDecodeTimestamp();
1560 DecodeTimestamp
SourceBufferStream::FindKeyframeAfterTimestamp(
1561 const DecodeTimestamp timestamp
) {
1562 DCHECK(timestamp
!= kNoDecodeTimestamp());
1564 RangeList::iterator itr
= FindExistingRangeFor(timestamp
);
1566 if (itr
== ranges_
.end())
1567 return kNoDecodeTimestamp();
1569 // First check for a keyframe timestamp >= |timestamp|
1570 // in the current range.
1571 return (*itr
)->NextKeyframeTimestamp(timestamp
);
1574 std::string
SourceBufferStream::GetStreamTypeName() const {
1575 switch (GetType()) {
1587 SourceBufferStream::Type
SourceBufferStream::GetType() const {
1588 if (!audio_configs_
.empty())
1590 if (!video_configs_
.empty())
1592 DCHECK_NE(text_track_config_
.kind(), kTextNone
);
1596 void SourceBufferStream::DeleteAndRemoveRange(RangeList::iterator
* itr
) {
1597 DVLOG(1) << __FUNCTION__
;
1599 DCHECK(*itr
!= ranges_
.end());
1600 if (**itr
== selected_range_
) {
1601 DVLOG(1) << __FUNCTION__
<< " deleting selected range.";
1602 SetSelectedRange(NULL
);
1605 if (*itr
== range_for_next_append_
) {
1606 DVLOG(1) << __FUNCTION__
<< " deleting range_for_next_append_.";
1607 range_for_next_append_
= ranges_
.end();
1608 last_appended_buffer_timestamp_
= kNoDecodeTimestamp();
1609 last_appended_buffer_is_keyframe_
= false;
1613 *itr
= ranges_
.erase(*itr
);
1616 void SourceBufferStream::GenerateSpliceFrame(const BufferQueue
& new_buffers
) {
1617 DCHECK(!new_buffers
.empty());
1619 // Splice frames are only supported for audio.
1620 if (GetType() != kAudio
)
1623 // Find the overlapped range (if any).
1624 const base::TimeDelta splice_timestamp
= new_buffers
.front()->timestamp();
1625 const DecodeTimestamp splice_dts
=
1626 DecodeTimestamp::FromPresentationTime(splice_timestamp
);
1627 RangeList::iterator range_itr
= FindExistingRangeFor(splice_dts
);
1628 if (range_itr
== ranges_
.end())
1631 const DecodeTimestamp max_splice_end_dts
=
1632 splice_dts
+ base::TimeDelta::FromMilliseconds(
1633 AudioSplicer::kCrossfadeDurationInMilliseconds
);
1635 // Find all buffers involved before the splice point.
1636 BufferQueue pre_splice_buffers
;
1637 if (!(*range_itr
)->GetBuffersInRange(
1638 splice_dts
, max_splice_end_dts
, &pre_splice_buffers
)) {
1642 // If there are gaps in the timeline, it's possible that we only find buffers
1643 // after the splice point but within the splice range. For simplicity, we do
1644 // not generate splice frames in this case.
1646 // We also do not want to generate splices if the first new buffer replaces an
1647 // existing buffer exactly.
1648 if (pre_splice_buffers
.front()->timestamp() >= splice_timestamp
) {
1649 LIMITED_MEDIA_LOG(DEBUG
, media_log_
, num_splice_generation_warning_logs_
,
1650 kMaxSpliceGenerationWarningLogs
)
1651 << "Skipping splice frame generation: first new buffer at "
1652 << splice_timestamp
.InMicroseconds()
1653 << "us begins at or before existing buffer at "
1654 << pre_splice_buffers
.front()->timestamp().InMicroseconds() << "us.";
1655 DVLOG(1) << "Skipping splice: overlapped buffers begin at or after the "
1656 "first new buffer.";
1660 // If any |pre_splice_buffers| are already splices or preroll, do not generate
1662 for (size_t i
= 0; i
< pre_splice_buffers
.size(); ++i
) {
1663 const BufferQueue
& original_splice_buffers
=
1664 pre_splice_buffers
[i
]->splice_buffers();
1665 if (!original_splice_buffers
.empty()) {
1666 LIMITED_MEDIA_LOG(DEBUG
, media_log_
, num_splice_generation_warning_logs_
,
1667 kMaxSpliceGenerationWarningLogs
)
1668 << "Skipping splice frame generation: overlapped buffers at "
1669 << pre_splice_buffers
[i
]->timestamp().InMicroseconds()
1670 << "us are in a previously buffered splice.";
1671 DVLOG(1) << "Can't generate splice: overlapped buffers contain a "
1672 "pre-existing splice.";
1676 if (pre_splice_buffers
[i
]->preroll_buffer().get()) {
1677 LIMITED_MEDIA_LOG(DEBUG
, media_log_
, num_splice_generation_warning_logs_
,
1678 kMaxSpliceGenerationWarningLogs
)
1679 << "Skipping splice frame generation: overlapped buffers at "
1680 << pre_splice_buffers
[i
]->timestamp().InMicroseconds()
1681 << "us contain preroll.";
1682 DVLOG(1) << "Can't generate splice: overlapped buffers contain preroll.";
1687 // Don't generate splice frames which represent less than a millisecond (which
1688 // is frequently the extent of timestamp resolution for poorly encoded media)
1689 // or less than two samples (need at least two to crossfade).
1690 const base::TimeDelta splice_duration
=
1691 pre_splice_buffers
.back()->timestamp() +
1692 pre_splice_buffers
.back()->duration() - splice_timestamp
;
1693 const base::TimeDelta minimum_splice_duration
= std::max(
1694 base::TimeDelta::FromMilliseconds(1),
1695 base::TimeDelta::FromSecondsD(
1696 2.0 / audio_configs_
[append_config_index_
].samples_per_second()));
1697 if (splice_duration
< minimum_splice_duration
) {
1698 LIMITED_MEDIA_LOG(DEBUG
, media_log_
, num_splice_generation_warning_logs_
,
1699 kMaxSpliceGenerationWarningLogs
)
1700 << "Skipping splice frame generation: not enough samples for splicing "
1702 << splice_timestamp
.InMicroseconds() << "us. Have "
1703 << splice_duration
.InMicroseconds() << "us, but need "
1704 << minimum_splice_duration
.InMicroseconds() << "us.";
1705 DVLOG(1) << "Can't generate splice: not enough samples for crossfade; have "
1706 << splice_duration
.InMicroseconds() << "us, but need "
1707 << minimum_splice_duration
.InMicroseconds() << "us.";
1711 DVLOG(1) << "Generating splice frame @ " << new_buffers
.front()->timestamp()
1712 << ", splice duration: " << splice_duration
.InMicroseconds()
1714 LIMITED_MEDIA_LOG(DEBUG
, media_log_
, num_splice_generation_success_logs_
,
1715 kMaxSpliceGenerationSuccessLogs
)
1716 << "Generated splice of overlap duration "
1717 << splice_duration
.InMicroseconds() << "us into new buffer at "
1718 << splice_timestamp
.InMicroseconds() << "us.";
1719 new_buffers
.front()->ConvertToSpliceBuffer(pre_splice_buffers
);
1722 bool SourceBufferStream::SetPendingBuffer(
1723 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1724 DCHECK(out_buffer
->get());
1725 DCHECK(!pending_buffer_
.get());
1727 const bool have_splice_buffers
= !(*out_buffer
)->splice_buffers().empty();
1728 const bool have_preroll_buffer
= !!(*out_buffer
)->preroll_buffer().get();
1730 if (!have_splice_buffers
&& !have_preroll_buffer
)
1733 DCHECK_NE(have_splice_buffers
, have_preroll_buffer
);
1734 splice_buffers_index_
= 0;
1735 pending_buffer_
.swap(*out_buffer
);
1736 pending_buffers_complete_
= false;
1740 } // namespace media