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"
23 // An arbitrarily-chosen number to estimate the duration of a buffer if none
24 // is set and there's not enough information to get a better estimate.
25 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 kMaxSpliceGenerationWarningLogs
= 50,
32 kMaxSpliceGenerationSuccessLogs
= 20,
35 // Helper method that returns true if |ranges| is sorted in increasing order,
37 bool IsRangeListSorted(const std::list
<media::SourceBufferRange
*>& ranges
) {
38 DecodeTimestamp prev
= kNoDecodeTimestamp();
39 for (std::list
<SourceBufferRange
*>::const_iterator itr
=
40 ranges
.begin(); itr
!= ranges
.end(); ++itr
) {
41 if (prev
!= kNoDecodeTimestamp() && prev
>= (*itr
)->GetStartTimestamp())
43 prev
= (*itr
)->GetEndTimestamp();
48 // Returns an estimate of how far from the beginning or end of a range a buffer
49 // can be to still be considered in the range, given the |approximate_duration|
50 // of a buffer in the stream.
51 // TODO(wolenetz): Once all stream parsers emit accurate frame durations, use
52 // logic like FrameProcessor (2*last_frame_duration + last_decode_timestamp)
53 // instead of an overall maximum interbuffer delta for range discontinuity
54 // detection, and adjust similarly for splice frame discontinuity detection.
55 // See http://crbug.com/351489 and http://crbug.com/351166.
56 base::TimeDelta
ComputeFudgeRoom(base::TimeDelta approximate_duration
) {
57 // Because we do not know exactly when is the next timestamp, any buffer
58 // that starts within 2x the approximate duration of a buffer is considered
60 return 2 * approximate_duration
;
63 // The amount of time the beginning of the buffered data can differ from the
64 // start time in order to still be considered the start of stream.
65 base::TimeDelta
kSeekToStartFudgeRoom() {
66 return base::TimeDelta::FromMilliseconds(1000);
69 // Helper method for logging, converts a range into a readable string.
70 std::string
RangeToString(const SourceBufferRange
& range
) {
72 ss
<< "[" << range
.GetStartTimestamp().InSecondsF()
73 << ";" << range
.GetEndTimestamp().InSecondsF()
74 << "(" << range
.GetBufferedEndTimestamp().InSecondsF() << ")]";
78 // Helper method for logging, converts a set of ranges into a readable string.
79 std::string
RangesToString(const SourceBufferStream::RangeList
& ranges
) {
84 for (const auto* range_ptr
: ranges
) {
85 if (range_ptr
!= ranges
.front())
87 ss
<< RangeToString(*range_ptr
);
92 SourceBufferRange::GapPolicy
TypeToGapPolicy(SourceBufferStream::Type type
) {
94 case SourceBufferStream::kAudio
:
95 case SourceBufferStream::kVideo
:
96 return SourceBufferRange::NO_GAPS_ALLOWED
;
97 case SourceBufferStream::kText
:
98 return SourceBufferRange::ALLOW_GAPS
;
102 return SourceBufferRange::NO_GAPS_ALLOWED
;
107 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig
& audio_config
,
108 const scoped_refptr
<MediaLog
>& media_log
,
109 bool splice_frames_enabled
)
110 : media_log_(media_log
),
111 current_config_index_(0),
112 append_config_index_(0),
113 seek_pending_(false),
114 end_of_stream_(false),
115 seek_buffer_timestamp_(kNoTimestamp()),
116 selected_range_(NULL
),
117 media_segment_start_time_(kNoDecodeTimestamp()),
118 range_for_next_append_(ranges_
.end()),
119 new_media_segment_(false),
120 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
121 last_appended_buffer_is_keyframe_(false),
122 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
123 max_interbuffer_distance_(kNoTimestamp()),
124 memory_limit_(kSourceBufferAudioMemoryLimit
),
125 config_change_pending_(false),
126 splice_buffers_index_(0),
127 pending_buffers_complete_(false),
128 splice_frames_enabled_(splice_frames_enabled
),
129 num_splice_generation_warning_logs_(0),
130 num_splice_generation_success_logs_(0) {
131 DCHECK(audio_config
.IsValidConfig());
132 audio_configs_
.push_back(audio_config
);
135 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig
& video_config
,
136 const scoped_refptr
<MediaLog
>& media_log
,
137 bool splice_frames_enabled
)
138 : media_log_(media_log
),
139 current_config_index_(0),
140 append_config_index_(0),
141 seek_pending_(false),
142 end_of_stream_(false),
143 seek_buffer_timestamp_(kNoTimestamp()),
144 selected_range_(NULL
),
145 media_segment_start_time_(kNoDecodeTimestamp()),
146 range_for_next_append_(ranges_
.end()),
147 new_media_segment_(false),
148 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
149 last_appended_buffer_is_keyframe_(false),
150 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
151 max_interbuffer_distance_(kNoTimestamp()),
152 memory_limit_(kSourceBufferVideoMemoryLimit
),
153 config_change_pending_(false),
154 splice_buffers_index_(0),
155 pending_buffers_complete_(false),
156 splice_frames_enabled_(splice_frames_enabled
),
157 num_splice_generation_warning_logs_(0),
158 num_splice_generation_success_logs_(0) {
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 current_config_index_(0),
168 append_config_index_(0),
169 text_track_config_(text_config
),
170 seek_pending_(false),
171 end_of_stream_(false),
172 seek_buffer_timestamp_(kNoTimestamp()),
173 selected_range_(NULL
),
174 media_segment_start_time_(kNoDecodeTimestamp()),
175 range_for_next_append_(ranges_
.end()),
176 new_media_segment_(false),
177 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
178 last_appended_buffer_is_keyframe_(false),
179 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
180 max_interbuffer_distance_(kNoTimestamp()),
181 memory_limit_(kSourceBufferAudioMemoryLimit
),
182 config_change_pending_(false),
183 splice_buffers_index_(0),
184 pending_buffers_complete_(false),
185 splice_frames_enabled_(splice_frames_enabled
),
186 num_splice_generation_warning_logs_(0),
187 num_splice_generation_success_logs_(0) {}
189 SourceBufferStream::~SourceBufferStream() {
190 while (!ranges_
.empty()) {
191 delete ranges_
.front();
196 void SourceBufferStream::OnNewMediaSegment(
197 DecodeTimestamp media_segment_start_time
) {
198 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
199 << " (" << media_segment_start_time
.InSecondsF() << ")";
200 DCHECK(!end_of_stream_
);
201 media_segment_start_time_
= media_segment_start_time
;
202 new_media_segment_
= true;
204 RangeList::iterator last_range
= range_for_next_append_
;
205 range_for_next_append_
= FindExistingRangeFor(media_segment_start_time
);
207 // Only reset |last_appended_buffer_timestamp_| if this new media segment is
208 // not adjacent to the previous media segment appended to the stream.
209 if (range_for_next_append_
== ranges_
.end() ||
210 !AreAdjacentInSequence(last_appended_buffer_timestamp_
,
211 media_segment_start_time
)) {
212 last_appended_buffer_timestamp_
= kNoDecodeTimestamp();
213 last_appended_buffer_is_keyframe_
= false;
214 DVLOG(3) << __FUNCTION__
<< " next appended buffers will be in a new range";
215 } else if (last_range
!= ranges_
.end()) {
216 DCHECK(last_range
== range_for_next_append_
);
217 DVLOG(3) << __FUNCTION__
<< " next appended buffers will continue range "
218 << "unless intervening remove makes discontinuity";
222 bool SourceBufferStream::Append(const BufferQueue
& buffers
) {
223 TRACE_EVENT2("media", "SourceBufferStream::Append",
224 "stream type", GetStreamTypeName(),
225 "buffers to append", buffers
.size());
227 DCHECK(!buffers
.empty());
228 DCHECK(media_segment_start_time_
!= kNoDecodeTimestamp());
229 DCHECK(media_segment_start_time_
<= buffers
.front()->GetDecodeTimestamp());
230 DCHECK(!end_of_stream_
);
232 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName() << ": buffers dts=["
233 << buffers
.front()->GetDecodeTimestamp().InSecondsF() << ";"
234 << buffers
.back()->GetDecodeTimestamp().InSecondsF() << "] pts=["
235 << buffers
.front()->timestamp().InSecondsF() << ";"
236 << buffers
.back()->timestamp().InSecondsF() << "(last frame dur="
237 << buffers
.back()->duration().InSecondsF() << ")]";
239 // New media segments must begin with a keyframe.
240 // TODO(wolenetz): Relax this requirement. See http://crbug.com/229412.
241 if (new_media_segment_
&& !buffers
.front()->is_key_frame()) {
242 MEDIA_LOG(ERROR
, media_log_
) << "Media segment did not begin with key "
243 "frame. Support for such segments will be "
244 "available in a future version. Please see "
245 "https://crbug.com/229412.";
249 // Buffers within a media segment should be monotonically increasing.
250 if (!IsMonotonicallyIncreasing(buffers
))
253 if (media_segment_start_time_
< DecodeTimestamp() ||
254 buffers
.front()->GetDecodeTimestamp() < DecodeTimestamp()) {
255 MEDIA_LOG(ERROR
, media_log_
)
256 << "Cannot append a media segment with negative timestamps.";
260 if (!IsNextTimestampValid(buffers
.front()->GetDecodeTimestamp(),
261 buffers
.front()->is_key_frame())) {
262 const DecodeTimestamp
& dts
= buffers
.front()->GetDecodeTimestamp();
263 MEDIA_LOG(ERROR
, media_log_
)
264 << "Invalid same timestamp construct detected at"
265 << " time " << dts
.InSecondsF();
270 UpdateMaxInterbufferDistance(buffers
);
271 SetConfigIds(buffers
);
273 // Save a snapshot of stream state before range modifications are made.
274 DecodeTimestamp next_buffer_timestamp
= GetNextBufferTimestamp();
275 BufferQueue deleted_buffers
;
277 PrepareRangesForNextAppend(buffers
, &deleted_buffers
);
279 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise,
280 // create a new range with |buffers|.
281 if (range_for_next_append_
!= ranges_
.end()) {
282 (*range_for_next_append_
)->AppendBuffersToEnd(buffers
);
283 last_appended_buffer_timestamp_
= buffers
.back()->GetDecodeTimestamp();
284 last_appended_buffer_is_keyframe_
= buffers
.back()->is_key_frame();
286 DecodeTimestamp new_range_start_time
= std::min(
287 media_segment_start_time_
, buffers
.front()->GetDecodeTimestamp());
288 const BufferQueue
* buffers_for_new_range
= &buffers
;
289 BufferQueue trimmed_buffers
;
291 // If the new range is not being created because of a new media
292 // segment, then we must make sure that we start with a key frame.
293 // This can happen if the GOP in the previous append gets destroyed
294 // by a Remove() call.
295 if (!new_media_segment_
) {
296 BufferQueue::const_iterator itr
= buffers
.begin();
298 // Scan past all the non-key-frames.
299 while (itr
!= buffers
.end() && !(*itr
)->is_key_frame()) {
303 // If we didn't find a key frame, then update the last appended
304 // buffer state and return.
305 if (itr
== buffers
.end()) {
306 last_appended_buffer_timestamp_
= buffers
.back()->GetDecodeTimestamp();
307 last_appended_buffer_is_keyframe_
= buffers
.back()->is_key_frame();
308 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
309 << ": new buffers in the middle of media segment depend on"
310 "keyframe that has been removed, and contain no keyframes."
311 "Skipping further processing.";
312 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
313 << ": done. ranges_=" << RangesToString(ranges_
);
315 } else if (itr
!= buffers
.begin()) {
316 // Copy the first key frame and everything after it into
317 // |trimmed_buffers|.
318 trimmed_buffers
.assign(itr
, buffers
.end());
319 buffers_for_new_range
= &trimmed_buffers
;
322 new_range_start_time
=
323 buffers_for_new_range
->front()->GetDecodeTimestamp();
326 range_for_next_append_
=
327 AddToRanges(new SourceBufferRange(
328 TypeToGapPolicy(GetType()),
329 *buffers_for_new_range
, new_range_start_time
,
330 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance
,
331 base::Unretained(this))));
332 last_appended_buffer_timestamp_
=
333 buffers_for_new_range
->back()->GetDecodeTimestamp();
334 last_appended_buffer_is_keyframe_
=
335 buffers_for_new_range
->back()->is_key_frame();
338 new_media_segment_
= false;
340 MergeWithAdjacentRangeIfNecessary(range_for_next_append_
);
342 // Seek to try to fulfill a previous call to Seek().
344 DCHECK(!selected_range_
);
345 DCHECK(deleted_buffers
.empty());
346 Seek(seek_buffer_timestamp_
);
349 if (!deleted_buffers
.empty()) {
350 DecodeTimestamp start_of_deleted
=
351 deleted_buffers
.front()->GetDecodeTimestamp();
353 DCHECK(track_buffer_
.empty() ||
354 track_buffer_
.back()->GetDecodeTimestamp() < start_of_deleted
)
355 << "decode timestamp "
356 << track_buffer_
.back()->GetDecodeTimestamp().InSecondsF() << " sec"
357 << ", start_of_deleted " << start_of_deleted
.InSecondsF()<< " sec";
359 track_buffer_
.insert(track_buffer_
.end(), deleted_buffers
.begin(),
360 deleted_buffers
.end());
361 DVLOG(3) << __FUNCTION__
<< " Added " << deleted_buffers
.size()
362 << " deleted buffers to track buffer. TB size is now "
363 << track_buffer_
.size();
365 DVLOG(3) << __FUNCTION__
<< " No deleted buffers for track buffer";
368 // Prune any extra buffers in |track_buffer_| if new keyframes
369 // are appended to the range covered by |track_buffer_|.
370 if (!track_buffer_
.empty()) {
371 DecodeTimestamp keyframe_timestamp
=
372 FindKeyframeAfterTimestamp(track_buffer_
.front()->GetDecodeTimestamp());
373 if (keyframe_timestamp
!= kNoDecodeTimestamp())
374 PruneTrackBuffer(keyframe_timestamp
);
377 SetSelectedRangeIfNeeded(next_buffer_timestamp
);
379 GarbageCollectIfNeeded();
381 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
382 << ": done. ranges_=" << RangesToString(ranges_
);
383 DCHECK(IsRangeListSorted(ranges_
));
384 DCHECK(OnlySelectedRangeIsSeeked());
388 void SourceBufferStream::Remove(base::TimeDelta start
, base::TimeDelta end
,
389 base::TimeDelta duration
) {
390 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
391 << " (" << start
.InSecondsF() << ", " << end
.InSecondsF()
392 << ", " << duration
.InSecondsF() << ")";
393 DCHECK(start
>= base::TimeDelta()) << start
.InSecondsF();
394 DCHECK(start
< end
) << "start " << start
.InSecondsF()
395 << " end " << end
.InSecondsF();
396 DCHECK(duration
!= kNoTimestamp());
398 DecodeTimestamp start_dts
= DecodeTimestamp::FromPresentationTime(start
);
399 DecodeTimestamp end_dts
= DecodeTimestamp::FromPresentationTime(end
);
400 DecodeTimestamp remove_end_timestamp
=
401 DecodeTimestamp::FromPresentationTime(duration
);
402 DecodeTimestamp keyframe_timestamp
= FindKeyframeAfterTimestamp(end_dts
);
403 if (keyframe_timestamp
!= kNoDecodeTimestamp()) {
404 remove_end_timestamp
= keyframe_timestamp
;
405 } else if (end_dts
< remove_end_timestamp
) {
406 remove_end_timestamp
= end_dts
;
409 BufferQueue deleted_buffers
;
410 RemoveInternal(start_dts
, remove_end_timestamp
, false, &deleted_buffers
);
412 if (!deleted_buffers
.empty()) {
413 // Buffers for the current position have been removed.
414 SetSelectedRangeIfNeeded(deleted_buffers
.front()->GetDecodeTimestamp());
415 if (last_output_buffer_timestamp_
== kNoDecodeTimestamp()) {
416 // We just removed buffers for the current playback position for this
417 // stream, yet we also had output no buffer since the last Seek.
418 // Re-seek to prevent stall.
419 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
420 << ": re-seeking to " << seek_buffer_timestamp_
421 << " to prevent stall if this time becomes buffered again";
422 Seek(seek_buffer_timestamp_
);
427 void SourceBufferStream::RemoveInternal(DecodeTimestamp start
,
430 BufferQueue
* deleted_buffers
) {
431 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName() << " ("
432 << start
.InSecondsF() << ", " << end
.InSecondsF() << ", "
433 << exclude_start
<< ")";
434 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
435 << ": before remove ranges_=" << RangesToString(ranges_
);
437 DCHECK(start
>= DecodeTimestamp());
438 DCHECK(start
< end
) << "start " << start
.InSecondsF()
439 << " end " << end
.InSecondsF();
440 DCHECK(deleted_buffers
);
442 RangeList::iterator itr
= ranges_
.begin();
444 while (itr
!= ranges_
.end()) {
445 SourceBufferRange
* range
= *itr
;
446 if (range
->GetStartTimestamp() >= end
)
449 // Split off any remaining GOPs starting at or after |end| and add it to
451 SourceBufferRange
* new_range
= range
->SplitRange(end
);
453 itr
= ranges_
.insert(++itr
, new_range
);
456 // Update the selected range if the next buffer position was transferred
458 if (new_range
->HasNextBufferPosition())
459 SetSelectedRange(new_range
);
462 // Truncate the current range so that it only contains data before
463 // the removal range.
464 BufferQueue saved_buffers
;
465 bool delete_range
= range
->TruncateAt(start
, &saved_buffers
, exclude_start
);
467 // Check to see if the current playback position was removed and
468 // update the selected range appropriately.
469 if (!saved_buffers
.empty()) {
470 DCHECK(!range
->HasNextBufferPosition());
471 DCHECK(deleted_buffers
->empty());
473 *deleted_buffers
= saved_buffers
;
476 if (range
== selected_range_
&& !range
->HasNextBufferPosition())
477 SetSelectedRange(NULL
);
479 // If the current range now is completely covered by the removal
480 // range then delete it and move on.
482 DeleteAndRemoveRange(&itr
);
486 // Clear |range_for_next_append_| if we determine that the removal
487 // operation makes it impossible for the next append to be added
488 // to the current range.
489 if (range_for_next_append_
!= ranges_
.end() &&
490 *range_for_next_append_
== range
&&
491 last_appended_buffer_timestamp_
!= kNoDecodeTimestamp()) {
492 DecodeTimestamp potential_next_append_timestamp
=
493 last_appended_buffer_timestamp_
+
494 base::TimeDelta::FromInternalValue(1);
496 if (!range
->BelongsToRange(potential_next_append_timestamp
)) {
497 DVLOG(1) << "Resetting range_for_next_append_ since the next append"
498 << " can't add to the current range.";
499 range_for_next_append_
=
500 FindExistingRangeFor(potential_next_append_timestamp
);
504 // Move on to the next range.
508 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
509 << ": after remove ranges_=" << RangesToString(ranges_
);
511 DCHECK(IsRangeListSorted(ranges_
));
512 DCHECK(OnlySelectedRangeIsSeeked());
515 void SourceBufferStream::ResetSeekState() {
516 SetSelectedRange(NULL
);
517 track_buffer_
.clear();
518 config_change_pending_
= false;
519 last_output_buffer_timestamp_
= kNoDecodeTimestamp();
520 splice_buffers_index_
= 0;
521 pending_buffer_
= NULL
;
522 pending_buffers_complete_
= false;
525 bool SourceBufferStream::ShouldSeekToStartOfBuffered(
526 base::TimeDelta seek_timestamp
) const {
529 base::TimeDelta beginning_of_buffered
=
530 ranges_
.front()->GetStartTimestamp().ToPresentationTime();
531 return (seek_timestamp
<= beginning_of_buffered
&&
532 beginning_of_buffered
< kSeekToStartFudgeRoom());
535 bool SourceBufferStream::IsMonotonicallyIncreasing(
536 const BufferQueue
& buffers
) const {
537 DCHECK(!buffers
.empty());
538 DecodeTimestamp prev_timestamp
= last_appended_buffer_timestamp_
;
539 bool prev_is_keyframe
= last_appended_buffer_is_keyframe_
;
540 for (BufferQueue::const_iterator itr
= buffers
.begin();
541 itr
!= buffers
.end(); ++itr
) {
542 DecodeTimestamp current_timestamp
= (*itr
)->GetDecodeTimestamp();
543 bool current_is_keyframe
= (*itr
)->is_key_frame();
544 DCHECK(current_timestamp
!= kNoDecodeTimestamp());
545 DCHECK((*itr
)->duration() >= base::TimeDelta())
546 << "Packet with invalid duration."
547 << " pts " << (*itr
)->timestamp().InSecondsF()
548 << " dts " << (*itr
)->GetDecodeTimestamp().InSecondsF()
549 << " dur " << (*itr
)->duration().InSecondsF();
551 if (prev_timestamp
!= kNoDecodeTimestamp()) {
552 if (current_timestamp
< prev_timestamp
) {
553 MEDIA_LOG(ERROR
, media_log_
)
554 << "Buffers did not monotonically increase.";
558 if (current_timestamp
== prev_timestamp
&&
559 !SourceBufferRange::AllowSameTimestamp(prev_is_keyframe
,
560 current_is_keyframe
)) {
561 MEDIA_LOG(ERROR
, media_log_
) << "Unexpected combination of buffers with"
562 << " the same timestamp detected at "
563 << current_timestamp
.InSecondsF();
568 prev_timestamp
= current_timestamp
;
569 prev_is_keyframe
= current_is_keyframe
;
574 bool SourceBufferStream::IsNextTimestampValid(
575 DecodeTimestamp next_timestamp
, bool next_is_keyframe
) const {
576 return (last_appended_buffer_timestamp_
!= next_timestamp
) ||
577 new_media_segment_
||
578 SourceBufferRange::AllowSameTimestamp(last_appended_buffer_is_keyframe_
,
583 bool SourceBufferStream::OnlySelectedRangeIsSeeked() const {
584 for (RangeList::const_iterator itr
= ranges_
.begin();
585 itr
!= ranges_
.end(); ++itr
) {
586 if ((*itr
)->HasNextBufferPosition() && (*itr
) != selected_range_
)
589 return !selected_range_
|| selected_range_
->HasNextBufferPosition();
592 void SourceBufferStream::UpdateMaxInterbufferDistance(
593 const BufferQueue
& buffers
) {
594 DCHECK(!buffers
.empty());
595 DecodeTimestamp prev_timestamp
= last_appended_buffer_timestamp_
;
596 for (BufferQueue::const_iterator itr
= buffers
.begin();
597 itr
!= buffers
.end(); ++itr
) {
598 DecodeTimestamp current_timestamp
= (*itr
)->GetDecodeTimestamp();
599 DCHECK(current_timestamp
!= kNoDecodeTimestamp());
601 base::TimeDelta interbuffer_distance
= (*itr
)->duration();
602 DCHECK(interbuffer_distance
>= base::TimeDelta());
604 if (prev_timestamp
!= kNoDecodeTimestamp()) {
605 interbuffer_distance
=
606 std::max(current_timestamp
- prev_timestamp
, interbuffer_distance
);
609 if (interbuffer_distance
> base::TimeDelta()) {
610 if (max_interbuffer_distance_
== kNoTimestamp()) {
611 max_interbuffer_distance_
= interbuffer_distance
;
613 max_interbuffer_distance_
=
614 std::max(max_interbuffer_distance_
, interbuffer_distance
);
617 prev_timestamp
= current_timestamp
;
621 void SourceBufferStream::SetConfigIds(const BufferQueue
& buffers
) {
622 for (BufferQueue::const_iterator itr
= buffers
.begin();
623 itr
!= buffers
.end(); ++itr
) {
624 (*itr
)->SetConfigId(append_config_index_
);
628 void SourceBufferStream::GarbageCollectIfNeeded() {
629 // Compute size of |ranges_|.
630 size_t ranges_size
= 0;
631 for (RangeList::iterator itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
)
632 ranges_size
+= (*itr
)->size_in_bytes();
634 // Return if we're under or at the memory limit.
635 if (ranges_size
<= memory_limit_
)
638 size_t bytes_to_free
= ranges_size
- memory_limit_
;
640 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName() << ": Before GC"
641 << " ranges_size=" << ranges_size
642 << " ranges_=" << RangesToString(ranges_
)
643 << " memory_limit_=" << memory_limit_
;
645 // Begin deleting after the last appended buffer.
646 size_t bytes_freed
= FreeBuffersAfterLastAppended(bytes_to_free
);
648 // Begin deleting from the front.
649 if (bytes_freed
< bytes_to_free
)
650 bytes_freed
+= FreeBuffers(bytes_to_free
- bytes_freed
, false);
652 // Begin deleting from the back.
653 if (bytes_freed
< bytes_to_free
)
654 bytes_freed
+= FreeBuffers(bytes_to_free
- bytes_freed
, true);
656 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName() << ": After GC"
657 << " bytes_freed=" << bytes_freed
658 << " ranges_=" << RangesToString(ranges_
);
661 size_t SourceBufferStream::FreeBuffersAfterLastAppended(
662 size_t total_bytes_to_free
) {
663 DecodeTimestamp next_buffer_timestamp
= GetNextBufferTimestamp();
664 if (last_appended_buffer_timestamp_
== kNoDecodeTimestamp() ||
665 next_buffer_timestamp
== kNoDecodeTimestamp() ||
666 last_appended_buffer_timestamp_
>= next_buffer_timestamp
) {
670 DecodeTimestamp remove_range_start
= last_appended_buffer_timestamp_
;
671 if (last_appended_buffer_is_keyframe_
)
672 remove_range_start
+= GetMaxInterbufferDistance();
674 DecodeTimestamp remove_range_start_keyframe
= FindKeyframeAfterTimestamp(
676 if (remove_range_start_keyframe
!= kNoDecodeTimestamp())
677 remove_range_start
= remove_range_start_keyframe
;
678 if (remove_range_start
>= next_buffer_timestamp
)
681 DecodeTimestamp remove_range_end
;
682 size_t bytes_freed
= GetRemovalRange(remove_range_start
,
683 next_buffer_timestamp
,
686 if (bytes_freed
> 0) {
687 Remove(remove_range_start
.ToPresentationTime(),
688 remove_range_end
.ToPresentationTime(),
689 next_buffer_timestamp
.ToPresentationTime());
695 size_t SourceBufferStream::GetRemovalRange(
696 DecodeTimestamp start_timestamp
, DecodeTimestamp end_timestamp
,
697 size_t total_bytes_to_free
, DecodeTimestamp
* removal_end_timestamp
) {
698 DCHECK(start_timestamp
>= DecodeTimestamp()) << start_timestamp
.InSecondsF();
699 DCHECK(start_timestamp
< end_timestamp
)
700 << "start " << start_timestamp
.InSecondsF()
701 << ", end " << end_timestamp
.InSecondsF();
703 size_t bytes_freed
= 0;
705 for (RangeList::iterator itr
= ranges_
.begin();
706 itr
!= ranges_
.end() && bytes_freed
< total_bytes_to_free
; ++itr
) {
707 SourceBufferRange
* range
= *itr
;
708 if (range
->GetStartTimestamp() >= end_timestamp
)
710 if (range
->GetEndTimestamp() < start_timestamp
)
713 size_t bytes_to_free
= total_bytes_to_free
- bytes_freed
;
714 size_t bytes_removed
= range
->GetRemovalGOP(
715 start_timestamp
, end_timestamp
, bytes_to_free
, removal_end_timestamp
);
716 bytes_freed
+= bytes_removed
;
721 size_t SourceBufferStream::FreeBuffers(size_t total_bytes_to_free
,
722 bool reverse_direction
) {
723 TRACE_EVENT2("media", "SourceBufferStream::FreeBuffers",
724 "total bytes to free", total_bytes_to_free
,
725 "reverse direction", reverse_direction
);
727 DCHECK_GT(total_bytes_to_free
, 0u);
728 size_t bytes_freed
= 0;
730 // This range will save the last GOP appended to |range_for_next_append_|
731 // if the buffers surrounding it get deleted during garbage collection.
732 SourceBufferRange
* new_range_for_append
= NULL
;
734 while (!ranges_
.empty() && bytes_freed
< total_bytes_to_free
) {
735 SourceBufferRange
* current_range
= NULL
;
737 size_t bytes_deleted
= 0;
739 if (reverse_direction
) {
740 current_range
= ranges_
.back();
741 if (current_range
->LastGOPContainsNextBufferPosition()) {
742 DCHECK_EQ(current_range
, selected_range_
);
745 bytes_deleted
= current_range
->DeleteGOPFromBack(&buffers
);
747 current_range
= ranges_
.front();
748 if (current_range
->FirstGOPContainsNextBufferPosition()) {
749 DCHECK_EQ(current_range
, selected_range_
);
752 bytes_deleted
= current_range
->DeleteGOPFromFront(&buffers
);
755 // Check to see if we've just deleted the GOP that was last appended.
756 DecodeTimestamp end_timestamp
= buffers
.back()->GetDecodeTimestamp();
757 if (end_timestamp
== last_appended_buffer_timestamp_
) {
758 DCHECK(last_appended_buffer_timestamp_
!= kNoDecodeTimestamp());
759 DCHECK(!new_range_for_append
);
760 // Create a new range containing these buffers.
761 new_range_for_append
= new SourceBufferRange(
762 TypeToGapPolicy(GetType()),
763 buffers
, kNoDecodeTimestamp(),
764 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance
,
765 base::Unretained(this)));
766 range_for_next_append_
= ranges_
.end();
768 bytes_freed
+= bytes_deleted
;
771 if (current_range
->size_in_bytes() == 0) {
772 DCHECK_NE(current_range
, selected_range_
);
773 DCHECK(range_for_next_append_
== ranges_
.end() ||
774 *range_for_next_append_
!= current_range
);
775 delete current_range
;
776 reverse_direction
? ranges_
.pop_back() : ranges_
.pop_front();
780 // Insert |new_range_for_append| into |ranges_|, if applicable.
781 if (new_range_for_append
) {
782 range_for_next_append_
= AddToRanges(new_range_for_append
);
783 DCHECK(range_for_next_append_
!= ranges_
.end());
785 // Check to see if we need to merge |new_range_for_append| with the range
786 // before or after it. |new_range_for_append| is created whenever the last
787 // GOP appended is encountered, regardless of whether any buffers after it
788 // are ultimately deleted. Merging is necessary if there were no buffers
789 // (or very few buffers) deleted after creating |new_range_for_append|.
790 if (range_for_next_append_
!= ranges_
.begin()) {
791 RangeList::iterator range_before_next
= range_for_next_append_
;
793 MergeWithAdjacentRangeIfNecessary(range_before_next
);
795 MergeWithAdjacentRangeIfNecessary(range_for_next_append_
);
800 void SourceBufferStream::PrepareRangesForNextAppend(
801 const BufferQueue
& new_buffers
, BufferQueue
* deleted_buffers
) {
802 DCHECK(deleted_buffers
);
804 bool temporarily_select_range
= false;
805 if (!track_buffer_
.empty()) {
806 DecodeTimestamp tb_timestamp
= track_buffer_
.back()->GetDecodeTimestamp();
807 DecodeTimestamp seek_timestamp
= FindKeyframeAfterTimestamp(tb_timestamp
);
808 if (seek_timestamp
!= kNoDecodeTimestamp() &&
809 seek_timestamp
< new_buffers
.front()->GetDecodeTimestamp() &&
810 range_for_next_append_
!= ranges_
.end() &&
811 (*range_for_next_append_
)->BelongsToRange(seek_timestamp
)) {
812 DCHECK(tb_timestamp
< seek_timestamp
);
813 DCHECK(!selected_range_
);
814 DCHECK(!(*range_for_next_append_
)->HasNextBufferPosition());
816 // If there are GOPs between the end of the track buffer and the
817 // beginning of the new buffers, then temporarily seek the range
818 // so that the buffers between these two times will be deposited in
819 // |deleted_buffers| as if they were part of the current playback
821 // TODO(acolwell): Figure out a more elegant way to do this.
822 SeekAndSetSelectedRange(*range_for_next_append_
, seek_timestamp
);
823 temporarily_select_range
= true;
827 // Handle splices between the existing buffers and the new buffers. If a
828 // splice is generated the timestamp and duration of the first buffer in
829 // |new_buffers| will be modified.
830 if (splice_frames_enabled_
)
831 GenerateSpliceFrame(new_buffers
);
833 DecodeTimestamp prev_timestamp
= last_appended_buffer_timestamp_
;
834 bool prev_is_keyframe
= last_appended_buffer_is_keyframe_
;
835 DecodeTimestamp next_timestamp
= new_buffers
.front()->GetDecodeTimestamp();
836 bool next_is_keyframe
= new_buffers
.front()->is_key_frame();
838 if (prev_timestamp
!= kNoDecodeTimestamp() &&
839 prev_timestamp
!= next_timestamp
) {
840 // Clean up the old buffers between the last appended buffer and the
841 // beginning of |new_buffers|.
842 RemoveInternal(prev_timestamp
, next_timestamp
, true, deleted_buffers
);
845 // Make the delete range exclusive if we are dealing with an allowed same
846 // timestamp situation. This prevents the first buffer in the current append
847 // from deleting the last buffer in the previous append if both buffers
848 // have the same timestamp.
850 // The delete range should never be exclusive if a splice frame was generated
851 // because we don't generate splice frames for same timestamp situations.
852 DCHECK(new_buffers
.front()->splice_timestamp() !=
853 new_buffers
.front()->timestamp());
854 const bool exclude_start
=
855 new_buffers
.front()->splice_buffers().empty() &&
856 prev_timestamp
== next_timestamp
&&
857 SourceBufferRange::AllowSameTimestamp(prev_is_keyframe
, next_is_keyframe
);
859 // Delete the buffers that |new_buffers| overlaps.
860 DecodeTimestamp start
= new_buffers
.front()->GetDecodeTimestamp();
861 DecodeTimestamp end
= new_buffers
.back()->GetDecodeTimestamp();
862 base::TimeDelta duration
= new_buffers
.back()->duration();
864 // Set end time for remove to include the duration of last buffer. If the
865 // duration is estimated, use 1 microsecond instead to ensure frames are not
866 // accidentally removed due to over-estimation.
867 if (duration
!= kNoTimestamp() && duration
> base::TimeDelta() &&
868 !new_buffers
.back()->is_duration_estimated()) {
871 // TODO(chcunningham): Emit warning when 0ms durations are not expected.
872 // http://crbug.com/312836
873 end
+= base::TimeDelta::FromInternalValue(1);
876 RemoveInternal(start
, end
, exclude_start
, deleted_buffers
);
878 // Restore the range seek state if necessary.
879 if (temporarily_select_range
)
880 SetSelectedRange(NULL
);
883 bool SourceBufferStream::AreAdjacentInSequence(
884 DecodeTimestamp first_timestamp
, DecodeTimestamp second_timestamp
) const {
885 return first_timestamp
< second_timestamp
&&
887 first_timestamp
+ ComputeFudgeRoom(GetMaxInterbufferDistance());
890 void SourceBufferStream::PruneTrackBuffer(const DecodeTimestamp timestamp
) {
891 // If we don't have the next timestamp, we don't have anything to delete.
892 if (timestamp
== kNoDecodeTimestamp())
895 while (!track_buffer_
.empty() &&
896 track_buffer_
.back()->GetDecodeTimestamp() >= timestamp
) {
897 track_buffer_
.pop_back();
901 void SourceBufferStream::MergeWithAdjacentRangeIfNecessary(
902 const RangeList::iterator
& range_with_new_buffers_itr
) {
903 DCHECK(range_with_new_buffers_itr
!= ranges_
.end());
905 SourceBufferRange
* range_with_new_buffers
= *range_with_new_buffers_itr
;
906 RangeList::iterator next_range_itr
= range_with_new_buffers_itr
;
909 if (next_range_itr
== ranges_
.end() ||
910 !range_with_new_buffers
->CanAppendRangeToEnd(**next_range_itr
)) {
914 bool transfer_current_position
= selected_range_
== *next_range_itr
;
915 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
916 << " merging " << RangeToString(*range_with_new_buffers
)
917 << " into " << RangeToString(**next_range_itr
);
918 range_with_new_buffers
->AppendRangeToEnd(**next_range_itr
,
919 transfer_current_position
);
920 // Update |selected_range_| pointer if |range| has become selected after
922 if (transfer_current_position
)
923 SetSelectedRange(range_with_new_buffers
);
925 if (next_range_itr
== range_for_next_append_
)
926 range_for_next_append_
= range_with_new_buffers_itr
;
928 DeleteAndRemoveRange(&next_range_itr
);
931 void SourceBufferStream::Seek(base::TimeDelta timestamp
) {
932 DCHECK(timestamp
>= base::TimeDelta());
933 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
934 << " (" << timestamp
.InSecondsF() << ")";
937 seek_buffer_timestamp_
= timestamp
;
938 seek_pending_
= true;
940 if (ShouldSeekToStartOfBuffered(timestamp
)) {
941 ranges_
.front()->SeekToStart();
942 SetSelectedRange(ranges_
.front());
943 seek_pending_
= false;
947 DecodeTimestamp seek_dts
= DecodeTimestamp::FromPresentationTime(timestamp
);
949 RangeList::iterator itr
= ranges_
.end();
950 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
951 if ((*itr
)->CanSeekTo(seek_dts
))
955 if (itr
== ranges_
.end())
958 SeekAndSetSelectedRange(*itr
, seek_dts
);
959 seek_pending_
= false;
962 bool SourceBufferStream::IsSeekPending() const {
963 return seek_pending_
&& !IsEndOfStreamReached();
966 void SourceBufferStream::OnSetDuration(base::TimeDelta duration
) {
967 DecodeTimestamp duration_dts
=
968 DecodeTimestamp::FromPresentationTime(duration
);
969 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
970 << " (" << duration
.InSecondsF() << ")";
972 RangeList::iterator itr
= ranges_
.end();
973 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
974 if ((*itr
)->GetEndTimestamp() > duration_dts
)
977 if (itr
== ranges_
.end())
980 // Need to partially truncate this range.
981 if ((*itr
)->GetStartTimestamp() < duration_dts
) {
982 bool delete_range
= (*itr
)->TruncateAt(duration_dts
, NULL
, false);
983 if ((*itr
== selected_range_
) && !selected_range_
->HasNextBufferPosition())
984 SetSelectedRange(NULL
);
987 DeleteAndRemoveRange(&itr
);
993 // Delete all ranges that begin after |duration_dts|.
994 while (itr
!= ranges_
.end()) {
995 // If we're about to delete the selected range, also reset the seek state.
996 DCHECK((*itr
)->GetStartTimestamp() >= duration_dts
);
997 if (*itr
== selected_range_
)
999 DeleteAndRemoveRange(&itr
);
1003 SourceBufferStream::Status
SourceBufferStream::GetNextBuffer(
1004 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1005 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName();
1006 if (!pending_buffer_
.get()) {
1007 const SourceBufferStream::Status status
= GetNextBufferInternal(out_buffer
);
1008 if (status
!= SourceBufferStream::kSuccess
||
1009 !SetPendingBuffer(out_buffer
)) {
1010 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1011 << ": no pending buffer, returning status " << status
;
1016 if (!pending_buffer_
->splice_buffers().empty()) {
1017 const SourceBufferStream::Status status
=
1018 HandleNextBufferWithSplice(out_buffer
);
1019 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1020 << ": handled next buffer with splice, returning status "
1025 DCHECK(pending_buffer_
->preroll_buffer().get());
1027 const SourceBufferStream::Status status
=
1028 HandleNextBufferWithPreroll(out_buffer
);
1029 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1030 << ": handled next buffer with preroll, returning status "
1035 SourceBufferStream::Status
SourceBufferStream::HandleNextBufferWithSplice(
1036 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1037 const BufferQueue
& splice_buffers
= pending_buffer_
->splice_buffers();
1038 const size_t last_splice_buffer_index
= splice_buffers
.size() - 1;
1040 // Are there any splice buffers left to hand out? The last buffer should be
1041 // handed out separately since it represents the first post-splice buffer.
1042 if (splice_buffers_index_
< last_splice_buffer_index
) {
1043 // Account for config changes which occur between fade out buffers.
1044 if (current_config_index_
!=
1045 splice_buffers
[splice_buffers_index_
]->GetConfigId()) {
1046 config_change_pending_
= true;
1047 DVLOG(1) << "Config change (splice buffer config ID does not match).";
1048 return SourceBufferStream::kConfigChange
;
1051 // Every pre splice buffer must have the same splice_timestamp().
1052 DCHECK(pending_buffer_
->splice_timestamp() ==
1053 splice_buffers
[splice_buffers_index_
]->splice_timestamp());
1055 // No pre splice buffers should have preroll.
1056 DCHECK(!splice_buffers
[splice_buffers_index_
]->preroll_buffer().get());
1058 *out_buffer
= splice_buffers
[splice_buffers_index_
++];
1059 return SourceBufferStream::kSuccess
;
1062 // Did we hand out the last pre-splice buffer on the previous call?
1063 if (!pending_buffers_complete_
) {
1064 DCHECK_EQ(splice_buffers_index_
, last_splice_buffer_index
);
1065 pending_buffers_complete_
= true;
1066 config_change_pending_
= true;
1067 DVLOG(1) << "Config change (forced for fade in of splice frame).";
1068 return SourceBufferStream::kConfigChange
;
1071 // All pre-splice buffers have been handed out and a config change completed,
1072 // so hand out the final buffer for fade in. Because a config change is
1073 // always issued prior to handing out this buffer, any changes in config id
1074 // have been inherently handled.
1075 DCHECK(pending_buffers_complete_
);
1076 DCHECK_EQ(splice_buffers_index_
, splice_buffers
.size() - 1);
1077 DCHECK(splice_buffers
.back()->splice_timestamp() == kNoTimestamp());
1078 *out_buffer
= splice_buffers
.back();
1079 pending_buffer_
= NULL
;
1081 // If the last splice buffer has preroll, hand off to the preroll handler.
1082 return SetPendingBuffer(out_buffer
) ? HandleNextBufferWithPreroll(out_buffer
)
1083 : SourceBufferStream::kSuccess
;
1086 SourceBufferStream::Status
SourceBufferStream::HandleNextBufferWithPreroll(
1087 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1088 // Any config change should have already been handled.
1089 DCHECK_EQ(current_config_index_
, pending_buffer_
->GetConfigId());
1091 // Check if the preroll buffer has already been handed out.
1092 if (!pending_buffers_complete_
) {
1093 pending_buffers_complete_
= true;
1094 *out_buffer
= pending_buffer_
->preroll_buffer();
1095 return SourceBufferStream::kSuccess
;
1098 // Preroll complete, hand out the final buffer.
1099 *out_buffer
= pending_buffer_
;
1100 pending_buffer_
= NULL
;
1101 return SourceBufferStream::kSuccess
;
1104 SourceBufferStream::Status
SourceBufferStream::GetNextBufferInternal(
1105 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1106 CHECK(!config_change_pending_
);
1108 if (!track_buffer_
.empty()) {
1109 DCHECK(!selected_range_
);
1110 scoped_refptr
<StreamParserBuffer
>& next_buffer
= track_buffer_
.front();
1112 // If the next buffer is an audio splice frame, the next effective config id
1113 // comes from the first splice buffer.
1114 if (next_buffer
->GetSpliceBufferConfigId(0) != current_config_index_
) {
1115 config_change_pending_
= true;
1116 DVLOG(1) << "Config change (track buffer config ID does not match).";
1117 return kConfigChange
;
1120 DVLOG(3) << __FUNCTION__
<< " Next buffer coming from track_buffer_";
1121 *out_buffer
= next_buffer
;
1122 track_buffer_
.pop_front();
1123 last_output_buffer_timestamp_
= (*out_buffer
)->GetDecodeTimestamp();
1125 // If the track buffer becomes empty, then try to set the selected range
1126 // based on the timestamp of this buffer being returned.
1127 if (track_buffer_
.empty())
1128 SetSelectedRangeIfNeeded(last_output_buffer_timestamp_
);
1133 DCHECK(track_buffer_
.empty());
1134 if (!selected_range_
|| !selected_range_
->HasNextBuffer()) {
1135 if (IsEndOfStreamReached()) {
1136 return kEndOfStream
;
1138 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
1139 << ": returning kNeedBuffer "
1140 << (selected_range_
? "(selected range has no next buffer)"
1141 : "(no selected range)");
1145 if (selected_range_
->GetNextConfigId() != current_config_index_
) {
1146 config_change_pending_
= true;
1147 DVLOG(1) << "Config change (selected range config ID does not match).";
1148 return kConfigChange
;
1151 CHECK(selected_range_
->GetNextBuffer(out_buffer
));
1152 last_output_buffer_timestamp_
= (*out_buffer
)->GetDecodeTimestamp();
1156 DecodeTimestamp
SourceBufferStream::GetNextBufferTimestamp() {
1157 if (!track_buffer_
.empty())
1158 return track_buffer_
.front()->GetDecodeTimestamp();
1160 if (!selected_range_
)
1161 return kNoDecodeTimestamp();
1163 DCHECK(selected_range_
->HasNextBufferPosition());
1164 return selected_range_
->GetNextTimestamp();
1167 SourceBufferStream::RangeList::iterator
1168 SourceBufferStream::FindExistingRangeFor(DecodeTimestamp start_timestamp
) {
1169 for (RangeList::iterator itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1170 if ((*itr
)->BelongsToRange(start_timestamp
))
1173 return ranges_
.end();
1176 SourceBufferStream::RangeList::iterator
1177 SourceBufferStream::AddToRanges(SourceBufferRange
* new_range
) {
1178 DecodeTimestamp start_timestamp
= new_range
->GetStartTimestamp();
1179 RangeList::iterator itr
= ranges_
.end();
1180 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1181 if ((*itr
)->GetStartTimestamp() > start_timestamp
)
1184 return ranges_
.insert(itr
, new_range
);
1187 SourceBufferStream::RangeList::iterator
1188 SourceBufferStream::GetSelectedRangeItr() {
1189 DCHECK(selected_range_
);
1190 RangeList::iterator itr
= ranges_
.end();
1191 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1192 if (*itr
== selected_range_
)
1195 DCHECK(itr
!= ranges_
.end());
1199 void SourceBufferStream::SeekAndSetSelectedRange(
1200 SourceBufferRange
* range
, DecodeTimestamp seek_timestamp
) {
1202 range
->Seek(seek_timestamp
);
1203 SetSelectedRange(range
);
1206 void SourceBufferStream::SetSelectedRange(SourceBufferRange
* range
) {
1207 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
1208 << ": " << selected_range_
<< " -> " << range
;
1209 if (selected_range_
)
1210 selected_range_
->ResetNextBufferPosition();
1211 DCHECK(!range
|| range
->HasNextBufferPosition());
1212 selected_range_
= range
;
1215 Ranges
<base::TimeDelta
> SourceBufferStream::GetBufferedTime() const {
1216 Ranges
<base::TimeDelta
> ranges
;
1217 for (RangeList::const_iterator itr
= ranges_
.begin();
1218 itr
!= ranges_
.end(); ++itr
) {
1219 ranges
.Add((*itr
)->GetStartTimestamp().ToPresentationTime(),
1220 (*itr
)->GetBufferedEndTimestamp().ToPresentationTime());
1225 base::TimeDelta
SourceBufferStream::GetBufferedDuration() const {
1226 if (ranges_
.empty())
1227 return base::TimeDelta();
1229 return ranges_
.back()->GetBufferedEndTimestamp().ToPresentationTime();
1232 void SourceBufferStream::MarkEndOfStream() {
1233 DCHECK(!end_of_stream_
);
1234 end_of_stream_
= true;
1237 void SourceBufferStream::UnmarkEndOfStream() {
1238 DCHECK(end_of_stream_
);
1239 end_of_stream_
= false;
1242 bool SourceBufferStream::IsEndOfStreamReached() const {
1243 if (!end_of_stream_
|| !track_buffer_
.empty())
1246 if (ranges_
.empty())
1249 if (seek_pending_
) {
1250 base::TimeDelta last_range_end_time
=
1251 ranges_
.back()->GetBufferedEndTimestamp().ToPresentationTime();
1252 return seek_buffer_timestamp_
>= last_range_end_time
;
1255 if (!selected_range_
)
1258 return selected_range_
== ranges_
.back();
1261 const AudioDecoderConfig
& SourceBufferStream::GetCurrentAudioDecoderConfig() {
1262 if (config_change_pending_
)
1263 CompleteConfigChange();
1264 return audio_configs_
[current_config_index_
];
1267 const VideoDecoderConfig
& SourceBufferStream::GetCurrentVideoDecoderConfig() {
1268 if (config_change_pending_
)
1269 CompleteConfigChange();
1270 return video_configs_
[current_config_index_
];
1273 const TextTrackConfig
& SourceBufferStream::GetCurrentTextTrackConfig() {
1274 return text_track_config_
;
1277 base::TimeDelta
SourceBufferStream::GetMaxInterbufferDistance() const {
1278 if (max_interbuffer_distance_
== kNoTimestamp())
1279 return base::TimeDelta::FromMilliseconds(kDefaultBufferDurationInMs
);
1280 return max_interbuffer_distance_
;
1283 bool SourceBufferStream::UpdateAudioConfig(const AudioDecoderConfig
& config
) {
1284 DCHECK(!audio_configs_
.empty());
1285 DCHECK(video_configs_
.empty());
1286 DVLOG(3) << "UpdateAudioConfig.";
1288 if (audio_configs_
[0].codec() != config
.codec()) {
1289 MEDIA_LOG(ERROR
, media_log_
) << "Audio codec changes not allowed.";
1293 if (audio_configs_
[0].is_encrypted() != config
.is_encrypted()) {
1294 MEDIA_LOG(ERROR
, media_log_
) << "Audio encryption changes not allowed.";
1298 // Check to see if the new config matches an existing one.
1299 for (size_t i
= 0; i
< audio_configs_
.size(); ++i
) {
1300 if (config
.Matches(audio_configs_
[i
])) {
1301 append_config_index_
= i
;
1306 // No matches found so let's add this one to the list.
1307 append_config_index_
= audio_configs_
.size();
1308 DVLOG(2) << "New audio config - index: " << append_config_index_
;
1309 audio_configs_
.resize(audio_configs_
.size() + 1);
1310 audio_configs_
[append_config_index_
] = config
;
1314 bool SourceBufferStream::UpdateVideoConfig(const VideoDecoderConfig
& config
) {
1315 DCHECK(!video_configs_
.empty());
1316 DCHECK(audio_configs_
.empty());
1317 DVLOG(3) << "UpdateVideoConfig.";
1319 if (video_configs_
[0].codec() != config
.codec()) {
1320 MEDIA_LOG(ERROR
, media_log_
) << "Video codec changes not allowed.";
1324 if (video_configs_
[0].is_encrypted() != config
.is_encrypted()) {
1325 MEDIA_LOG(ERROR
, media_log_
) << "Video encryption changes not allowed.";
1329 // Check to see if the new config matches an existing one.
1330 for (size_t i
= 0; i
< video_configs_
.size(); ++i
) {
1331 if (config
.Matches(video_configs_
[i
])) {
1332 append_config_index_
= i
;
1337 // No matches found so let's add this one to the list.
1338 append_config_index_
= video_configs_
.size();
1339 DVLOG(2) << "New video config - index: " << append_config_index_
;
1340 video_configs_
.resize(video_configs_
.size() + 1);
1341 video_configs_
[append_config_index_
] = config
;
1345 void SourceBufferStream::CompleteConfigChange() {
1346 config_change_pending_
= false;
1348 if (pending_buffer_
.get()) {
1349 current_config_index_
=
1350 pending_buffer_
->GetSpliceBufferConfigId(splice_buffers_index_
);
1354 if (!track_buffer_
.empty()) {
1355 current_config_index_
= track_buffer_
.front()->GetSpliceBufferConfigId(0);
1359 if (selected_range_
&& selected_range_
->HasNextBuffer())
1360 current_config_index_
= selected_range_
->GetNextConfigId();
1363 void SourceBufferStream::SetSelectedRangeIfNeeded(
1364 const DecodeTimestamp timestamp
) {
1365 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1366 << "(" << timestamp
.InSecondsF() << ")";
1368 if (selected_range_
) {
1369 DCHECK(track_buffer_
.empty());
1373 if (!track_buffer_
.empty()) {
1374 DCHECK(!selected_range_
);
1378 DecodeTimestamp start_timestamp
= timestamp
;
1380 // If the next buffer timestamp is not known then use a timestamp just after
1381 // the timestamp on the last buffer returned by GetNextBuffer().
1382 if (start_timestamp
== kNoDecodeTimestamp()) {
1383 if (last_output_buffer_timestamp_
== kNoDecodeTimestamp()) {
1384 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1385 << " no previous output timestamp";
1389 start_timestamp
= last_output_buffer_timestamp_
+
1390 base::TimeDelta::FromInternalValue(1);
1393 DecodeTimestamp seek_timestamp
=
1394 FindNewSelectedRangeSeekTimestamp(start_timestamp
);
1396 // If we don't have buffered data to seek to, then return.
1397 if (seek_timestamp
== kNoDecodeTimestamp()) {
1398 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1399 << " couldn't find new selected range seek timestamp";
1403 DCHECK(track_buffer_
.empty());
1404 SeekAndSetSelectedRange(*FindExistingRangeFor(seek_timestamp
),
1408 DecodeTimestamp
SourceBufferStream::FindNewSelectedRangeSeekTimestamp(
1409 const DecodeTimestamp start_timestamp
) {
1410 DCHECK(start_timestamp
!= kNoDecodeTimestamp());
1411 DCHECK(start_timestamp
>= DecodeTimestamp());
1413 RangeList::iterator itr
= ranges_
.begin();
1415 for (; itr
!= ranges_
.end(); ++itr
) {
1416 if ((*itr
)->GetEndTimestamp() >= start_timestamp
) {
1421 if (itr
== ranges_
.end()) {
1422 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1423 << " no buffered data for dts=" << start_timestamp
.InSecondsF();
1424 return kNoDecodeTimestamp();
1427 // First check for a keyframe timestamp >= |start_timestamp|
1428 // in the current range.
1429 DecodeTimestamp keyframe_timestamp
=
1430 (*itr
)->NextKeyframeTimestamp(start_timestamp
);
1432 if (keyframe_timestamp
!= kNoDecodeTimestamp())
1433 return keyframe_timestamp
;
1435 // If a keyframe was not found then look for a keyframe that is
1436 // "close enough" in the current or next range.
1437 DecodeTimestamp end_timestamp
=
1438 start_timestamp
+ ComputeFudgeRoom(GetMaxInterbufferDistance());
1439 DCHECK(start_timestamp
< end_timestamp
);
1441 // Make sure the current range doesn't start beyond |end_timestamp|.
1442 if ((*itr
)->GetStartTimestamp() >= end_timestamp
)
1443 return kNoDecodeTimestamp();
1445 keyframe_timestamp
= (*itr
)->KeyframeBeforeTimestamp(end_timestamp
);
1447 // Check to see if the keyframe is within the acceptable range
1448 // (|start_timestamp|, |end_timestamp|].
1449 if (keyframe_timestamp
!= kNoDecodeTimestamp() &&
1450 start_timestamp
< keyframe_timestamp
&&
1451 keyframe_timestamp
<= end_timestamp
) {
1452 return keyframe_timestamp
;
1455 // If |end_timestamp| is within this range, then no other checks are
1457 if (end_timestamp
<= (*itr
)->GetEndTimestamp())
1458 return kNoDecodeTimestamp();
1460 // Move on to the next range.
1463 // Return early if the next range does not contain |end_timestamp|.
1464 if (itr
== ranges_
.end() || (*itr
)->GetStartTimestamp() >= end_timestamp
)
1465 return kNoDecodeTimestamp();
1467 keyframe_timestamp
= (*itr
)->KeyframeBeforeTimestamp(end_timestamp
);
1469 // Check to see if the keyframe is within the acceptable range
1470 // (|start_timestamp|, |end_timestamp|].
1471 if (keyframe_timestamp
!= kNoDecodeTimestamp() &&
1472 start_timestamp
< keyframe_timestamp
&&
1473 keyframe_timestamp
<= end_timestamp
) {
1474 return keyframe_timestamp
;
1477 return kNoDecodeTimestamp();
1480 DecodeTimestamp
SourceBufferStream::FindKeyframeAfterTimestamp(
1481 const DecodeTimestamp timestamp
) {
1482 DCHECK(timestamp
!= kNoDecodeTimestamp());
1484 RangeList::iterator itr
= FindExistingRangeFor(timestamp
);
1486 if (itr
== ranges_
.end())
1487 return kNoDecodeTimestamp();
1489 // First check for a keyframe timestamp >= |timestamp|
1490 // in the current range.
1491 return (*itr
)->NextKeyframeTimestamp(timestamp
);
1494 std::string
SourceBufferStream::GetStreamTypeName() const {
1495 switch (GetType()) {
1507 SourceBufferStream::Type
SourceBufferStream::GetType() const {
1508 if (!audio_configs_
.empty())
1510 if (!video_configs_
.empty())
1512 DCHECK_NE(text_track_config_
.kind(), kTextNone
);
1516 void SourceBufferStream::DeleteAndRemoveRange(RangeList::iterator
* itr
) {
1517 DVLOG(1) << __FUNCTION__
;
1519 DCHECK(*itr
!= ranges_
.end());
1520 if (**itr
== selected_range_
) {
1521 DVLOG(1) << __FUNCTION__
<< " deleting selected range.";
1522 SetSelectedRange(NULL
);
1525 if (*itr
== range_for_next_append_
) {
1526 DVLOG(1) << __FUNCTION__
<< " deleting range_for_next_append_.";
1527 range_for_next_append_
= ranges_
.end();
1528 last_appended_buffer_timestamp_
= kNoDecodeTimestamp();
1529 last_appended_buffer_is_keyframe_
= false;
1533 *itr
= ranges_
.erase(*itr
);
1536 void SourceBufferStream::GenerateSpliceFrame(const BufferQueue
& new_buffers
) {
1537 DCHECK(!new_buffers
.empty());
1539 // Splice frames are only supported for audio.
1540 if (GetType() != kAudio
)
1543 // Find the overlapped range (if any).
1544 const base::TimeDelta splice_timestamp
= new_buffers
.front()->timestamp();
1545 const DecodeTimestamp splice_dts
=
1546 DecodeTimestamp::FromPresentationTime(splice_timestamp
);
1547 RangeList::iterator range_itr
= FindExistingRangeFor(splice_dts
);
1548 if (range_itr
== ranges_
.end())
1551 const DecodeTimestamp max_splice_end_dts
=
1552 splice_dts
+ base::TimeDelta::FromMilliseconds(
1553 AudioSplicer::kCrossfadeDurationInMilliseconds
);
1555 // Find all buffers involved before the splice point.
1556 BufferQueue pre_splice_buffers
;
1557 if (!(*range_itr
)->GetBuffersInRange(
1558 splice_dts
, max_splice_end_dts
, &pre_splice_buffers
)) {
1562 // If there are gaps in the timeline, it's possible that we only find buffers
1563 // after the splice point but within the splice range. For simplicity, we do
1564 // not generate splice frames in this case.
1566 // We also do not want to generate splices if the first new buffer replaces an
1567 // existing buffer exactly.
1568 if (pre_splice_buffers
.front()->timestamp() >= splice_timestamp
) {
1569 LIMITED_MEDIA_LOG(DEBUG
, media_log_
, num_splice_generation_warning_logs_
,
1570 kMaxSpliceGenerationWarningLogs
)
1571 << "Skipping splice frame generation: first new buffer at "
1572 << splice_timestamp
.InMicroseconds()
1573 << "us begins at or before existing buffer at "
1574 << pre_splice_buffers
.front()->timestamp().InMicroseconds() << "us.";
1575 DVLOG(1) << "Skipping splice: overlapped buffers begin at or after the "
1576 "first new buffer.";
1580 // If any |pre_splice_buffers| are already splices or preroll, do not generate
1582 for (size_t i
= 0; i
< pre_splice_buffers
.size(); ++i
) {
1583 const BufferQueue
& original_splice_buffers
=
1584 pre_splice_buffers
[i
]->splice_buffers();
1585 if (!original_splice_buffers
.empty()) {
1586 LIMITED_MEDIA_LOG(DEBUG
, media_log_
, num_splice_generation_warning_logs_
,
1587 kMaxSpliceGenerationWarningLogs
)
1588 << "Skipping splice frame generation: overlapped buffers at "
1589 << pre_splice_buffers
[i
]->timestamp().InMicroseconds()
1590 << "us are in a previously buffered splice.";
1591 DVLOG(1) << "Can't generate splice: overlapped buffers contain a "
1592 "pre-existing splice.";
1596 if (pre_splice_buffers
[i
]->preroll_buffer().get()) {
1597 LIMITED_MEDIA_LOG(DEBUG
, media_log_
, num_splice_generation_warning_logs_
,
1598 kMaxSpliceGenerationWarningLogs
)
1599 << "Skipping splice frame generation: overlapped buffers at "
1600 << pre_splice_buffers
[i
]->timestamp().InMicroseconds()
1601 << "us contain preroll.";
1602 DVLOG(1) << "Can't generate splice: overlapped buffers contain preroll.";
1607 // Don't generate splice frames which represent less than a millisecond (which
1608 // is frequently the extent of timestamp resolution for poorly encoded media)
1609 // or less than two samples (need at least two to crossfade).
1610 const base::TimeDelta splice_duration
=
1611 pre_splice_buffers
.back()->timestamp() +
1612 pre_splice_buffers
.back()->duration() - splice_timestamp
;
1613 const base::TimeDelta minimum_splice_duration
= std::max(
1614 base::TimeDelta::FromMilliseconds(1),
1615 base::TimeDelta::FromSecondsD(
1616 2.0 / audio_configs_
[append_config_index_
].samples_per_second()));
1617 if (splice_duration
< minimum_splice_duration
) {
1618 LIMITED_MEDIA_LOG(DEBUG
, media_log_
, num_splice_generation_warning_logs_
,
1619 kMaxSpliceGenerationWarningLogs
)
1620 << "Skipping splice frame generation: not enough samples for splicing "
1622 << splice_timestamp
.InMicroseconds() << "us. Have "
1623 << splice_duration
.InMicroseconds() << "us, but need "
1624 << minimum_splice_duration
.InMicroseconds() << "us.";
1625 DVLOG(1) << "Can't generate splice: not enough samples for crossfade; have "
1626 << splice_duration
.InMicroseconds() << "us, but need "
1627 << minimum_splice_duration
.InMicroseconds() << "us.";
1631 DVLOG(1) << "Generating splice frame @ " << new_buffers
.front()->timestamp()
1632 << ", splice duration: " << splice_duration
.InMicroseconds()
1634 LIMITED_MEDIA_LOG(DEBUG
, media_log_
, num_splice_generation_success_logs_
,
1635 kMaxSpliceGenerationSuccessLogs
)
1636 << "Generated splice of overlap duration "
1637 << splice_duration
.InMicroseconds() << "us into new buffer at "
1638 << splice_timestamp
.InMicroseconds() << "us.";
1639 new_buffers
.front()->ConvertToSpliceBuffer(pre_splice_buffers
);
1642 bool SourceBufferStream::SetPendingBuffer(
1643 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1644 DCHECK(out_buffer
->get());
1645 DCHECK(!pending_buffer_
.get());
1647 const bool have_splice_buffers
= !(*out_buffer
)->splice_buffers().empty();
1648 const bool have_preroll_buffer
= !!(*out_buffer
)->preroll_buffer().get();
1650 if (!have_splice_buffers
&& !have_preroll_buffer
)
1653 DCHECK_NE(have_splice_buffers
, have_preroll_buffer
);
1654 splice_buffers_index_
= 0;
1655 pending_buffer_
.swap(*out_buffer
);
1656 pending_buffers_complete_
= false;
1660 } // namespace media