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"
10 #include "base/bind.h"
11 #include "base/debug/trace_event.h"
12 #include "base/logging.h"
13 #include "media/base/audio_splicer.h"
14 #include "media/filters/source_buffer_platform.h"
15 #include "media/filters/source_buffer_range.h"
19 // Helper method that returns true if |ranges| is sorted in increasing order,
21 static bool IsRangeListSorted(
22 const std::list
<media::SourceBufferRange
*>& ranges
) {
23 DecodeTimestamp prev
= kNoDecodeTimestamp();
24 for (std::list
<SourceBufferRange
*>::const_iterator itr
=
25 ranges
.begin(); itr
!= ranges
.end(); ++itr
) {
26 if (prev
!= kNoDecodeTimestamp() && prev
>= (*itr
)->GetStartTimestamp())
28 prev
= (*itr
)->GetEndTimestamp();
33 // Returns an estimate of how far from the beginning or end of a range a buffer
34 // can be to still be considered in the range, given the |approximate_duration|
35 // of a buffer in the stream.
36 // TODO(wolenetz): Once all stream parsers emit accurate frame durations, use
37 // logic like FrameProcessor (2*last_frame_duration + last_decode_timestamp)
38 // instead of an overall maximum interbuffer delta for range discontinuity
39 // detection, and adjust similarly for splice frame discontinuity detection.
40 // See http://crbug.com/351489 and http://crbug.com/351166.
41 static base::TimeDelta
ComputeFudgeRoom(base::TimeDelta approximate_duration
) {
42 // Because we do not know exactly when is the next timestamp, any buffer
43 // that starts within 2x the approximate duration of a buffer is considered
45 return 2 * approximate_duration
;
48 // An arbitrarily-chosen number to estimate the duration of a buffer if none
49 // is set and there's not enough information to get a better estimate.
50 static int kDefaultBufferDurationInMs
= 125;
52 // The amount of time the beginning of the buffered data can differ from the
53 // start time in order to still be considered the start of stream.
54 static base::TimeDelta
kSeekToStartFudgeRoom() {
55 return base::TimeDelta::FromMilliseconds(1000);
58 static SourceBufferRange::GapPolicy
TypeToGapPolicy(
59 SourceBufferStream::Type type
) {
61 case SourceBufferStream::kAudio
:
62 case SourceBufferStream::kVideo
:
63 return SourceBufferRange::NO_GAPS_ALLOWED
;
64 case SourceBufferStream::kText
:
65 return SourceBufferRange::ALLOW_GAPS
;
69 return SourceBufferRange::NO_GAPS_ALLOWED
;
72 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig
& audio_config
,
74 bool splice_frames_enabled
)
76 current_config_index_(0),
77 append_config_index_(0),
79 end_of_stream_(false),
80 seek_buffer_timestamp_(kNoTimestamp()),
81 selected_range_(NULL
),
82 media_segment_start_time_(kNoDecodeTimestamp()),
83 range_for_next_append_(ranges_
.end()),
84 new_media_segment_(false),
85 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
86 last_appended_buffer_is_keyframe_(false),
87 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
88 max_interbuffer_distance_(kNoTimestamp()),
89 memory_limit_(kSourceBufferAudioMemoryLimit
),
90 config_change_pending_(false),
91 splice_buffers_index_(0),
92 pending_buffers_complete_(false),
93 splice_frames_enabled_(splice_frames_enabled
) {
94 DCHECK(audio_config
.IsValidConfig());
95 audio_configs_
.push_back(audio_config
);
98 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig
& video_config
,
100 bool splice_frames_enabled
)
102 current_config_index_(0),
103 append_config_index_(0),
104 seek_pending_(false),
105 end_of_stream_(false),
106 seek_buffer_timestamp_(kNoTimestamp()),
107 selected_range_(NULL
),
108 media_segment_start_time_(kNoDecodeTimestamp()),
109 range_for_next_append_(ranges_
.end()),
110 new_media_segment_(false),
111 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
112 last_appended_buffer_is_keyframe_(false),
113 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
114 max_interbuffer_distance_(kNoTimestamp()),
115 memory_limit_(kSourceBufferVideoMemoryLimit
),
116 config_change_pending_(false),
117 splice_buffers_index_(0),
118 pending_buffers_complete_(false),
119 splice_frames_enabled_(splice_frames_enabled
) {
120 DCHECK(video_config
.IsValidConfig());
121 video_configs_
.push_back(video_config
);
124 SourceBufferStream::SourceBufferStream(const TextTrackConfig
& text_config
,
126 bool splice_frames_enabled
)
128 current_config_index_(0),
129 append_config_index_(0),
130 text_track_config_(text_config
),
131 seek_pending_(false),
132 end_of_stream_(false),
133 seek_buffer_timestamp_(kNoTimestamp()),
134 selected_range_(NULL
),
135 media_segment_start_time_(kNoDecodeTimestamp()),
136 range_for_next_append_(ranges_
.end()),
137 new_media_segment_(false),
138 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
139 last_appended_buffer_is_keyframe_(false),
140 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
141 max_interbuffer_distance_(kNoTimestamp()),
142 memory_limit_(kSourceBufferAudioMemoryLimit
),
143 config_change_pending_(false),
144 splice_buffers_index_(0),
145 pending_buffers_complete_(false),
146 splice_frames_enabled_(splice_frames_enabled
) {}
148 SourceBufferStream::~SourceBufferStream() {
149 while (!ranges_
.empty()) {
150 delete ranges_
.front();
155 void SourceBufferStream::OnNewMediaSegment(
156 DecodeTimestamp media_segment_start_time
) {
157 DVLOG(1) << __FUNCTION__
<< "(" << media_segment_start_time
.InSecondsF()
159 DCHECK(!end_of_stream_
);
160 media_segment_start_time_
= media_segment_start_time
;
161 new_media_segment_
= true;
163 RangeList::iterator last_range
= range_for_next_append_
;
164 range_for_next_append_
= FindExistingRangeFor(media_segment_start_time
);
166 // Only reset |last_appended_buffer_timestamp_| if this new media segment is
167 // not adjacent to the previous media segment appended to the stream.
168 if (range_for_next_append_
== ranges_
.end() ||
169 !AreAdjacentInSequence(last_appended_buffer_timestamp_
,
170 media_segment_start_time
)) {
171 last_appended_buffer_timestamp_
= kNoDecodeTimestamp();
172 last_appended_buffer_is_keyframe_
= false;
173 DVLOG(3) << __FUNCTION__
<< " next appended buffers will be in a new range";
174 } else if (last_range
!= ranges_
.end()) {
175 DCHECK(last_range
== range_for_next_append_
);
176 DVLOG(3) << __FUNCTION__
<< " next appended buffers will continue range "
177 << "unless intervening remove makes discontinuity";
181 bool SourceBufferStream::Append(const BufferQueue
& buffers
) {
182 TRACE_EVENT2("media", "SourceBufferStream::Append",
183 "stream type", GetStreamTypeName(),
184 "buffers to append", buffers
.size());
186 DCHECK(!buffers
.empty());
187 DCHECK(media_segment_start_time_
!= kNoDecodeTimestamp());
188 DCHECK(media_segment_start_time_
<= buffers
.front()->GetDecodeTimestamp());
189 DCHECK(!end_of_stream_
);
191 // New media segments must begin with a keyframe.
192 if (new_media_segment_
&& !buffers
.front()->is_key_frame()) {
193 MEDIA_LOG(log_cb_
) << "Media segment did not begin with key frame.";
197 // Buffers within a media segment should be monotonically increasing.
198 if (!IsMonotonicallyIncreasing(buffers
))
201 if (media_segment_start_time_
< DecodeTimestamp() ||
202 buffers
.front()->GetDecodeTimestamp() < DecodeTimestamp()) {
204 << "Cannot append a media segment with negative timestamps.";
208 if (!IsNextTimestampValid(buffers
.front()->GetDecodeTimestamp(),
209 buffers
.front()->is_key_frame())) {
210 MEDIA_LOG(log_cb_
) << "Invalid same timestamp construct detected at time "
211 << buffers
.front()->GetDecodeTimestamp().InSecondsF();
216 UpdateMaxInterbufferDistance(buffers
);
217 SetConfigIds(buffers
);
219 // Save a snapshot of stream state before range modifications are made.
220 DecodeTimestamp next_buffer_timestamp
= GetNextBufferTimestamp();
221 BufferQueue deleted_buffers
;
223 PrepareRangesForNextAppend(buffers
, &deleted_buffers
);
225 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise,
226 // create a new range with |buffers|.
227 if (range_for_next_append_
!= ranges_
.end()) {
228 (*range_for_next_append_
)->AppendBuffersToEnd(buffers
);
229 last_appended_buffer_timestamp_
= buffers
.back()->GetDecodeTimestamp();
230 last_appended_buffer_is_keyframe_
= buffers
.back()->is_key_frame();
232 DecodeTimestamp new_range_start_time
= std::min(
233 media_segment_start_time_
, buffers
.front()->GetDecodeTimestamp());
234 const BufferQueue
* buffers_for_new_range
= &buffers
;
235 BufferQueue trimmed_buffers
;
237 // If the new range is not being created because of a new media
238 // segment, then we must make sure that we start with a key frame.
239 // This can happen if the GOP in the previous append gets destroyed
240 // by a Remove() call.
241 if (!new_media_segment_
) {
242 BufferQueue::const_iterator itr
= buffers
.begin();
244 // Scan past all the non-key-frames.
245 while (itr
!= buffers
.end() && !(*itr
)->is_key_frame()) {
249 // If we didn't find a key frame, then update the last appended
250 // buffer state and return.
251 if (itr
== buffers
.end()) {
252 last_appended_buffer_timestamp_
= buffers
.back()->GetDecodeTimestamp();
253 last_appended_buffer_is_keyframe_
= buffers
.back()->is_key_frame();
255 } else if (itr
!= buffers
.begin()) {
256 // Copy the first key frame and everything after it into
257 // |trimmed_buffers|.
258 trimmed_buffers
.assign(itr
, buffers
.end());
259 buffers_for_new_range
= &trimmed_buffers
;
262 new_range_start_time
=
263 buffers_for_new_range
->front()->GetDecodeTimestamp();
266 range_for_next_append_
=
267 AddToRanges(new SourceBufferRange(
268 TypeToGapPolicy(GetType()),
269 *buffers_for_new_range
, new_range_start_time
,
270 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance
,
271 base::Unretained(this))));
272 last_appended_buffer_timestamp_
=
273 buffers_for_new_range
->back()->GetDecodeTimestamp();
274 last_appended_buffer_is_keyframe_
=
275 buffers_for_new_range
->back()->is_key_frame();
278 new_media_segment_
= false;
280 MergeWithAdjacentRangeIfNecessary(range_for_next_append_
);
282 // Seek to try to fulfill a previous call to Seek().
284 DCHECK(!selected_range_
);
285 DCHECK(deleted_buffers
.empty());
286 Seek(seek_buffer_timestamp_
);
289 if (!deleted_buffers
.empty()) {
290 DecodeTimestamp start_of_deleted
=
291 deleted_buffers
.front()->GetDecodeTimestamp();
293 DCHECK(track_buffer_
.empty() ||
294 track_buffer_
.back()->GetDecodeTimestamp() < start_of_deleted
)
295 << "decode timestamp "
296 << track_buffer_
.back()->GetDecodeTimestamp().InSecondsF() << " sec"
297 << ", start_of_deleted " << start_of_deleted
.InSecondsF()<< " sec";
299 track_buffer_
.insert(track_buffer_
.end(), deleted_buffers
.begin(),
300 deleted_buffers
.end());
303 // Prune any extra buffers in |track_buffer_| if new keyframes
304 // are appended to the range covered by |track_buffer_|.
305 if (!track_buffer_
.empty()) {
306 DecodeTimestamp keyframe_timestamp
=
307 FindKeyframeAfterTimestamp(track_buffer_
.front()->GetDecodeTimestamp());
308 if (keyframe_timestamp
!= kNoDecodeTimestamp())
309 PruneTrackBuffer(keyframe_timestamp
);
312 SetSelectedRangeIfNeeded(next_buffer_timestamp
);
314 GarbageCollectIfNeeded();
316 DCHECK(IsRangeListSorted(ranges_
));
317 DCHECK(OnlySelectedRangeIsSeeked());
321 void SourceBufferStream::Remove(base::TimeDelta start
, base::TimeDelta end
,
322 base::TimeDelta duration
) {
323 DVLOG(1) << __FUNCTION__
<< "(" << start
.InSecondsF()
324 << ", " << end
.InSecondsF()
325 << ", " << duration
.InSecondsF() << ")";
326 DCHECK(start
>= base::TimeDelta()) << start
.InSecondsF();
327 DCHECK(start
< end
) << "start " << start
.InSecondsF()
328 << " end " << end
.InSecondsF();
329 DCHECK(duration
!= kNoTimestamp());
331 DecodeTimestamp start_dts
= DecodeTimestamp::FromPresentationTime(start
);
332 DecodeTimestamp end_dts
= DecodeTimestamp::FromPresentationTime(end
);
333 DecodeTimestamp remove_end_timestamp
=
334 DecodeTimestamp::FromPresentationTime(duration
);
335 DecodeTimestamp keyframe_timestamp
= FindKeyframeAfterTimestamp(end_dts
);
336 if (keyframe_timestamp
!= kNoDecodeTimestamp()) {
337 remove_end_timestamp
= keyframe_timestamp
;
338 } else if (end_dts
< remove_end_timestamp
) {
339 remove_end_timestamp
= end_dts
;
342 BufferQueue deleted_buffers
;
343 RemoveInternal(start_dts
, remove_end_timestamp
, false, &deleted_buffers
);
345 if (!deleted_buffers
.empty())
346 SetSelectedRangeIfNeeded(deleted_buffers
.front()->GetDecodeTimestamp());
349 void SourceBufferStream::RemoveInternal(
350 DecodeTimestamp start
, DecodeTimestamp end
, bool is_exclusive
,
351 BufferQueue
* deleted_buffers
) {
352 DVLOG(1) << __FUNCTION__
<< "(" << start
.InSecondsF()
353 << ", " << end
.InSecondsF()
354 << ", " << is_exclusive
<< ")";
356 DCHECK(start
>= DecodeTimestamp());
357 DCHECK(start
< end
) << "start " << start
.InSecondsF()
358 << " end " << end
.InSecondsF();
359 DCHECK(deleted_buffers
);
361 RangeList::iterator itr
= ranges_
.begin();
363 while (itr
!= ranges_
.end()) {
364 SourceBufferRange
* range
= *itr
;
365 if (range
->GetStartTimestamp() >= end
)
368 // Split off any remaining end piece and add it to |ranges_|.
369 SourceBufferRange
* new_range
= range
->SplitRange(end
, is_exclusive
);
371 itr
= ranges_
.insert(++itr
, new_range
);
374 // Update the selected range if the next buffer position was transferred
376 if (new_range
->HasNextBufferPosition())
377 SetSelectedRange(new_range
);
380 // Truncate the current range so that it only contains data before
381 // the removal range.
382 BufferQueue saved_buffers
;
383 bool delete_range
= range
->TruncateAt(start
, &saved_buffers
, is_exclusive
);
385 // Check to see if the current playback position was removed and
386 // update the selected range appropriately.
387 if (!saved_buffers
.empty()) {
388 DCHECK(!range
->HasNextBufferPosition());
389 DCHECK(deleted_buffers
->empty());
391 *deleted_buffers
= saved_buffers
;
394 if (range
== selected_range_
&& !range
->HasNextBufferPosition())
395 SetSelectedRange(NULL
);
397 // If the current range now is completely covered by the removal
398 // range then delete it and move on.
400 DeleteAndRemoveRange(&itr
);
404 // Clear |range_for_next_append_| if we determine that the removal
405 // operation makes it impossible for the next append to be added
406 // to the current range.
407 if (range_for_next_append_
!= ranges_
.end() &&
408 *range_for_next_append_
== range
&&
409 last_appended_buffer_timestamp_
!= kNoDecodeTimestamp()) {
410 DecodeTimestamp potential_next_append_timestamp
=
411 last_appended_buffer_timestamp_
+
412 base::TimeDelta::FromInternalValue(1);
414 if (!range
->BelongsToRange(potential_next_append_timestamp
)) {
415 DVLOG(1) << "Resetting range_for_next_append_ since the next append"
416 << " can't add to the current range.";
417 range_for_next_append_
=
418 FindExistingRangeFor(potential_next_append_timestamp
);
422 // Move on to the next range.
426 DCHECK(IsRangeListSorted(ranges_
));
427 DCHECK(OnlySelectedRangeIsSeeked());
428 DVLOG(1) << __FUNCTION__
<< " : done";
431 void SourceBufferStream::ResetSeekState() {
432 SetSelectedRange(NULL
);
433 track_buffer_
.clear();
434 config_change_pending_
= false;
435 last_output_buffer_timestamp_
= kNoDecodeTimestamp();
436 splice_buffers_index_
= 0;
437 pending_buffer_
= NULL
;
438 pending_buffers_complete_
= false;
441 bool SourceBufferStream::ShouldSeekToStartOfBuffered(
442 base::TimeDelta seek_timestamp
) const {
445 base::TimeDelta beginning_of_buffered
=
446 ranges_
.front()->GetStartTimestamp().ToPresentationTime();
447 return (seek_timestamp
<= beginning_of_buffered
&&
448 beginning_of_buffered
< kSeekToStartFudgeRoom());
451 bool SourceBufferStream::IsMonotonicallyIncreasing(
452 const BufferQueue
& buffers
) const {
453 DCHECK(!buffers
.empty());
454 DecodeTimestamp prev_timestamp
= last_appended_buffer_timestamp_
;
455 bool prev_is_keyframe
= last_appended_buffer_is_keyframe_
;
456 for (BufferQueue::const_iterator itr
= buffers
.begin();
457 itr
!= buffers
.end(); ++itr
) {
458 DecodeTimestamp current_timestamp
= (*itr
)->GetDecodeTimestamp();
459 bool current_is_keyframe
= (*itr
)->is_key_frame();
460 DCHECK(current_timestamp
!= kNoDecodeTimestamp());
461 DCHECK((*itr
)->duration() >= base::TimeDelta())
462 << "Packet with invalid duration."
463 << " pts " << (*itr
)->timestamp().InSecondsF()
464 << " dts " << (*itr
)->GetDecodeTimestamp().InSecondsF()
465 << " dur " << (*itr
)->duration().InSecondsF();
467 if (prev_timestamp
!= kNoDecodeTimestamp()) {
468 if (current_timestamp
< prev_timestamp
) {
469 MEDIA_LOG(log_cb_
) << "Buffers were not monotonically increasing.";
473 if (current_timestamp
== prev_timestamp
&&
474 !SourceBufferRange::AllowSameTimestamp(prev_is_keyframe
,
475 current_is_keyframe
)) {
476 MEDIA_LOG(log_cb_
) << "Unexpected combination of buffers with the"
477 << " same timestamp detected at "
478 << current_timestamp
.InSecondsF();
483 prev_timestamp
= current_timestamp
;
484 prev_is_keyframe
= current_is_keyframe
;
489 bool SourceBufferStream::IsNextTimestampValid(
490 DecodeTimestamp next_timestamp
, bool next_is_keyframe
) const {
491 return (last_appended_buffer_timestamp_
!= next_timestamp
) ||
492 new_media_segment_
||
493 SourceBufferRange::AllowSameTimestamp(last_appended_buffer_is_keyframe_
,
498 bool SourceBufferStream::OnlySelectedRangeIsSeeked() const {
499 for (RangeList::const_iterator itr
= ranges_
.begin();
500 itr
!= ranges_
.end(); ++itr
) {
501 if ((*itr
)->HasNextBufferPosition() && (*itr
) != selected_range_
)
504 return !selected_range_
|| selected_range_
->HasNextBufferPosition();
507 void SourceBufferStream::UpdateMaxInterbufferDistance(
508 const BufferQueue
& buffers
) {
509 DCHECK(!buffers
.empty());
510 DecodeTimestamp prev_timestamp
= last_appended_buffer_timestamp_
;
511 for (BufferQueue::const_iterator itr
= buffers
.begin();
512 itr
!= buffers
.end(); ++itr
) {
513 DecodeTimestamp current_timestamp
= (*itr
)->GetDecodeTimestamp();
514 DCHECK(current_timestamp
!= kNoDecodeTimestamp());
516 base::TimeDelta interbuffer_distance
= (*itr
)->duration();
517 DCHECK(interbuffer_distance
>= base::TimeDelta());
519 if (prev_timestamp
!= kNoDecodeTimestamp()) {
520 interbuffer_distance
=
521 std::max(current_timestamp
- prev_timestamp
, interbuffer_distance
);
524 if (interbuffer_distance
> base::TimeDelta()) {
525 if (max_interbuffer_distance_
== kNoTimestamp()) {
526 max_interbuffer_distance_
= interbuffer_distance
;
528 max_interbuffer_distance_
=
529 std::max(max_interbuffer_distance_
, interbuffer_distance
);
532 prev_timestamp
= current_timestamp
;
536 void SourceBufferStream::SetConfigIds(const BufferQueue
& buffers
) {
537 for (BufferQueue::const_iterator itr
= buffers
.begin();
538 itr
!= buffers
.end(); ++itr
) {
539 (*itr
)->SetConfigId(append_config_index_
);
543 void SourceBufferStream::GarbageCollectIfNeeded() {
544 // Compute size of |ranges_|.
546 for (RangeList::iterator itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
)
547 ranges_size
+= (*itr
)->size_in_bytes();
549 // Return if we're under or at the memory limit.
550 if (ranges_size
<= memory_limit_
)
553 int bytes_to_free
= ranges_size
- memory_limit_
;
555 // Begin deleting after the last appended buffer.
556 int bytes_freed
= FreeBuffersAfterLastAppended(bytes_to_free
);
558 // Begin deleting from the front.
559 if (bytes_to_free
- bytes_freed
> 0)
560 bytes_freed
+= FreeBuffers(bytes_to_free
- bytes_freed
, false);
562 // Begin deleting from the back.
563 if (bytes_to_free
- bytes_freed
> 0)
564 FreeBuffers(bytes_to_free
- bytes_freed
, true);
567 int SourceBufferStream::FreeBuffersAfterLastAppended(int total_bytes_to_free
) {
568 DecodeTimestamp next_buffer_timestamp
= GetNextBufferTimestamp();
569 if (last_appended_buffer_timestamp_
== kNoDecodeTimestamp() ||
570 next_buffer_timestamp
== kNoDecodeTimestamp() ||
571 last_appended_buffer_timestamp_
>= next_buffer_timestamp
) {
575 DecodeTimestamp remove_range_start
= last_appended_buffer_timestamp_
;
576 if (last_appended_buffer_is_keyframe_
)
577 remove_range_start
+= GetMaxInterbufferDistance();
579 DecodeTimestamp remove_range_start_keyframe
= FindKeyframeAfterTimestamp(
581 if (remove_range_start_keyframe
!= kNoDecodeTimestamp())
582 remove_range_start
= remove_range_start_keyframe
;
583 if (remove_range_start
>= next_buffer_timestamp
)
586 DecodeTimestamp remove_range_end
;
587 int bytes_freed
= GetRemovalRange(
588 remove_range_start
, next_buffer_timestamp
, total_bytes_to_free
,
590 if (bytes_freed
> 0) {
591 Remove(remove_range_start
.ToPresentationTime(),
592 remove_range_end
.ToPresentationTime(),
593 next_buffer_timestamp
.ToPresentationTime());
599 int SourceBufferStream::GetRemovalRange(
600 DecodeTimestamp start_timestamp
, DecodeTimestamp end_timestamp
,
601 int total_bytes_to_free
, DecodeTimestamp
* removal_end_timestamp
) {
602 DCHECK(start_timestamp
>= DecodeTimestamp()) << start_timestamp
.InSecondsF();
603 DCHECK(start_timestamp
< end_timestamp
)
604 << "start " << start_timestamp
.InSecondsF()
605 << ", end " << end_timestamp
.InSecondsF();
607 int bytes_to_free
= total_bytes_to_free
;
610 for (RangeList::iterator itr
= ranges_
.begin();
611 itr
!= ranges_
.end() && bytes_to_free
> 0; ++itr
) {
612 SourceBufferRange
* range
= *itr
;
613 if (range
->GetStartTimestamp() >= end_timestamp
)
615 if (range
->GetEndTimestamp() < start_timestamp
)
618 int bytes_removed
= range
->GetRemovalGOP(
619 start_timestamp
, end_timestamp
, bytes_to_free
, removal_end_timestamp
);
620 bytes_to_free
-= bytes_removed
;
621 bytes_freed
+= bytes_removed
;
626 int SourceBufferStream::FreeBuffers(int total_bytes_to_free
,
627 bool reverse_direction
) {
628 TRACE_EVENT2("media", "SourceBufferStream::FreeBuffers",
629 "total bytes to free", total_bytes_to_free
,
630 "reverse direction", reverse_direction
);
632 DCHECK_GT(total_bytes_to_free
, 0);
633 int bytes_to_free
= total_bytes_to_free
;
636 // This range will save the last GOP appended to |range_for_next_append_|
637 // if the buffers surrounding it get deleted during garbage collection.
638 SourceBufferRange
* new_range_for_append
= NULL
;
640 while (!ranges_
.empty() && bytes_to_free
> 0) {
641 SourceBufferRange
* current_range
= NULL
;
643 int bytes_deleted
= 0;
645 if (reverse_direction
) {
646 current_range
= ranges_
.back();
647 if (current_range
->LastGOPContainsNextBufferPosition()) {
648 DCHECK_EQ(current_range
, selected_range_
);
651 bytes_deleted
= current_range
->DeleteGOPFromBack(&buffers
);
653 current_range
= ranges_
.front();
654 if (current_range
->FirstGOPContainsNextBufferPosition()) {
655 DCHECK_EQ(current_range
, selected_range_
);
658 bytes_deleted
= current_range
->DeleteGOPFromFront(&buffers
);
661 // Check to see if we've just deleted the GOP that was last appended.
662 DecodeTimestamp end_timestamp
= buffers
.back()->GetDecodeTimestamp();
663 if (end_timestamp
== last_appended_buffer_timestamp_
) {
664 DCHECK(last_appended_buffer_timestamp_
!= kNoDecodeTimestamp());
665 DCHECK(!new_range_for_append
);
666 // Create a new range containing these buffers.
667 new_range_for_append
= new SourceBufferRange(
668 TypeToGapPolicy(GetType()),
669 buffers
, kNoDecodeTimestamp(),
670 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance
,
671 base::Unretained(this)));
672 range_for_next_append_
= ranges_
.end();
674 bytes_to_free
-= bytes_deleted
;
675 bytes_freed
+= bytes_deleted
;
678 if (current_range
->size_in_bytes() == 0) {
679 DCHECK_NE(current_range
, selected_range_
);
680 DCHECK(range_for_next_append_
== ranges_
.end() ||
681 *range_for_next_append_
!= current_range
);
682 delete current_range
;
683 reverse_direction
? ranges_
.pop_back() : ranges_
.pop_front();
687 // Insert |new_range_for_append| into |ranges_|, if applicable.
688 if (new_range_for_append
) {
689 range_for_next_append_
= AddToRanges(new_range_for_append
);
690 DCHECK(range_for_next_append_
!= ranges_
.end());
692 // Check to see if we need to merge |new_range_for_append| with the range
693 // before or after it. |new_range_for_append| is created whenever the last
694 // GOP appended is encountered, regardless of whether any buffers after it
695 // are ultimately deleted. Merging is necessary if there were no buffers
696 // (or very few buffers) deleted after creating |new_range_for_append|.
697 if (range_for_next_append_
!= ranges_
.begin()) {
698 RangeList::iterator range_before_next
= range_for_next_append_
;
700 MergeWithAdjacentRangeIfNecessary(range_before_next
);
702 MergeWithAdjacentRangeIfNecessary(range_for_next_append_
);
707 void SourceBufferStream::PrepareRangesForNextAppend(
708 const BufferQueue
& new_buffers
, BufferQueue
* deleted_buffers
) {
709 DCHECK(deleted_buffers
);
711 bool temporarily_select_range
= false;
712 if (!track_buffer_
.empty()) {
713 DecodeTimestamp tb_timestamp
= track_buffer_
.back()->GetDecodeTimestamp();
714 DecodeTimestamp seek_timestamp
= FindKeyframeAfterTimestamp(tb_timestamp
);
715 if (seek_timestamp
!= kNoDecodeTimestamp() &&
716 seek_timestamp
< new_buffers
.front()->GetDecodeTimestamp() &&
717 range_for_next_append_
!= ranges_
.end() &&
718 (*range_for_next_append_
)->BelongsToRange(seek_timestamp
)) {
719 DCHECK(tb_timestamp
< seek_timestamp
);
720 DCHECK(!selected_range_
);
721 DCHECK(!(*range_for_next_append_
)->HasNextBufferPosition());
723 // If there are GOPs between the end of the track buffer and the
724 // beginning of the new buffers, then temporarily seek the range
725 // so that the buffers between these two times will be deposited in
726 // |deleted_buffers| as if they were part of the current playback
728 // TODO(acolwell): Figure out a more elegant way to do this.
729 SeekAndSetSelectedRange(*range_for_next_append_
, seek_timestamp
);
730 temporarily_select_range
= true;
734 // Handle splices between the existing buffers and the new buffers. If a
735 // splice is generated the timestamp and duration of the first buffer in
736 // |new_buffers| will be modified.
737 if (splice_frames_enabled_
)
738 GenerateSpliceFrame(new_buffers
);
740 DecodeTimestamp prev_timestamp
= last_appended_buffer_timestamp_
;
741 bool prev_is_keyframe
= last_appended_buffer_is_keyframe_
;
742 DecodeTimestamp next_timestamp
= new_buffers
.front()->GetDecodeTimestamp();
743 bool next_is_keyframe
= new_buffers
.front()->is_key_frame();
745 if (prev_timestamp
!= kNoDecodeTimestamp() &&
746 prev_timestamp
!= next_timestamp
) {
747 // Clean up the old buffers between the last appended buffer and the
748 // beginning of |new_buffers|.
749 RemoveInternal(prev_timestamp
, next_timestamp
, true, deleted_buffers
);
752 // Make the delete range exclusive if we are dealing with an allowed same
753 // timestamp situation. This prevents the first buffer in the current append
754 // from deleting the last buffer in the previous append if both buffers
755 // have the same timestamp.
757 // The delete range should never be exclusive if a splice frame was generated
758 // because we don't generate splice frames for same timestamp situations.
759 DCHECK(new_buffers
.front()->splice_timestamp() !=
760 new_buffers
.front()->timestamp());
761 const bool is_exclusive
=
762 new_buffers
.front()->splice_buffers().empty() &&
763 prev_timestamp
== next_timestamp
&&
764 SourceBufferRange::AllowSameTimestamp(prev_is_keyframe
, next_is_keyframe
);
766 // Delete the buffers that |new_buffers| overlaps.
767 DecodeTimestamp start
= new_buffers
.front()->GetDecodeTimestamp();
768 DecodeTimestamp end
= new_buffers
.back()->GetDecodeTimestamp();
769 base::TimeDelta duration
= new_buffers
.back()->duration();
771 if (duration
!= kNoTimestamp() && duration
> base::TimeDelta()) {
774 // TODO(acolwell): Ensure all buffers actually have proper
775 // duration info so that this hack isn't needed.
776 // http://crbug.com/312836
777 end
+= base::TimeDelta::FromInternalValue(1);
780 RemoveInternal(start
, end
, is_exclusive
, deleted_buffers
);
782 // Restore the range seek state if necessary.
783 if (temporarily_select_range
)
784 SetSelectedRange(NULL
);
787 bool SourceBufferStream::AreAdjacentInSequence(
788 DecodeTimestamp first_timestamp
, DecodeTimestamp second_timestamp
) const {
789 return first_timestamp
< second_timestamp
&&
791 first_timestamp
+ ComputeFudgeRoom(GetMaxInterbufferDistance());
794 void SourceBufferStream::PruneTrackBuffer(const DecodeTimestamp timestamp
) {
795 // If we don't have the next timestamp, we don't have anything to delete.
796 if (timestamp
== kNoDecodeTimestamp())
799 while (!track_buffer_
.empty() &&
800 track_buffer_
.back()->GetDecodeTimestamp() >= timestamp
) {
801 track_buffer_
.pop_back();
805 void SourceBufferStream::MergeWithAdjacentRangeIfNecessary(
806 const RangeList::iterator
& range_with_new_buffers_itr
) {
807 DCHECK(range_with_new_buffers_itr
!= ranges_
.end());
809 SourceBufferRange
* range_with_new_buffers
= *range_with_new_buffers_itr
;
810 RangeList::iterator next_range_itr
= range_with_new_buffers_itr
;
813 if (next_range_itr
== ranges_
.end() ||
814 !range_with_new_buffers
->CanAppendRangeToEnd(**next_range_itr
)) {
818 bool transfer_current_position
= selected_range_
== *next_range_itr
;
819 range_with_new_buffers
->AppendRangeToEnd(**next_range_itr
,
820 transfer_current_position
);
821 // Update |selected_range_| pointer if |range| has become selected after
823 if (transfer_current_position
)
824 SetSelectedRange(range_with_new_buffers
);
826 if (next_range_itr
== range_for_next_append_
)
827 range_for_next_append_
= range_with_new_buffers_itr
;
829 DeleteAndRemoveRange(&next_range_itr
);
832 void SourceBufferStream::Seek(base::TimeDelta timestamp
) {
833 DCHECK(timestamp
>= base::TimeDelta());
836 if (ShouldSeekToStartOfBuffered(timestamp
)) {
837 ranges_
.front()->SeekToStart();
838 SetSelectedRange(ranges_
.front());
839 seek_pending_
= false;
843 seek_buffer_timestamp_
= timestamp
;
844 seek_pending_
= true;
846 DecodeTimestamp seek_dts
= DecodeTimestamp::FromPresentationTime(timestamp
);
848 RangeList::iterator itr
= ranges_
.end();
849 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
850 if ((*itr
)->CanSeekTo(seek_dts
))
854 if (itr
== ranges_
.end())
857 SeekAndSetSelectedRange(*itr
, seek_dts
);
858 seek_pending_
= false;
861 bool SourceBufferStream::IsSeekPending() const {
862 return !(end_of_stream_
&& IsEndSelected()) && seek_pending_
;
865 void SourceBufferStream::OnSetDuration(base::TimeDelta duration
) {
866 DecodeTimestamp duration_dts
=
867 DecodeTimestamp::FromPresentationTime(duration
);
869 RangeList::iterator itr
= ranges_
.end();
870 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
871 if ((*itr
)->GetEndTimestamp() > duration_dts
)
874 if (itr
== ranges_
.end())
877 // Need to partially truncate this range.
878 if ((*itr
)->GetStartTimestamp() < duration_dts
) {
879 bool delete_range
= (*itr
)->TruncateAt(duration_dts
, NULL
, false);
880 if ((*itr
== selected_range_
) && !selected_range_
->HasNextBufferPosition())
881 SetSelectedRange(NULL
);
884 DeleteAndRemoveRange(&itr
);
890 // Delete all ranges that begin after |duration_dts|.
891 while (itr
!= ranges_
.end()) {
892 // If we're about to delete the selected range, also reset the seek state.
893 DCHECK((*itr
)->GetStartTimestamp() >= duration_dts
);
894 if (*itr
== selected_range_
)
896 DeleteAndRemoveRange(&itr
);
900 SourceBufferStream::Status
SourceBufferStream::GetNextBuffer(
901 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
902 if (!pending_buffer_
.get()) {
903 const SourceBufferStream::Status status
= GetNextBufferInternal(out_buffer
);
904 if (status
!= SourceBufferStream::kSuccess
|| !SetPendingBuffer(out_buffer
))
908 if (!pending_buffer_
->splice_buffers().empty())
909 return HandleNextBufferWithSplice(out_buffer
);
911 DCHECK(pending_buffer_
->preroll_buffer().get());
912 return HandleNextBufferWithPreroll(out_buffer
);
915 SourceBufferStream::Status
SourceBufferStream::HandleNextBufferWithSplice(
916 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
917 const BufferQueue
& splice_buffers
= pending_buffer_
->splice_buffers();
918 const size_t last_splice_buffer_index
= splice_buffers
.size() - 1;
920 // Are there any splice buffers left to hand out? The last buffer should be
921 // handed out separately since it represents the first post-splice buffer.
922 if (splice_buffers_index_
< last_splice_buffer_index
) {
923 // Account for config changes which occur between fade out buffers.
924 if (current_config_index_
!=
925 splice_buffers
[splice_buffers_index_
]->GetConfigId()) {
926 config_change_pending_
= true;
927 DVLOG(1) << "Config change (splice buffer config ID does not match).";
928 return SourceBufferStream::kConfigChange
;
931 // Every pre splice buffer must have the same splice_timestamp().
932 DCHECK(pending_buffer_
->splice_timestamp() ==
933 splice_buffers
[splice_buffers_index_
]->splice_timestamp());
935 // No pre splice buffers should have preroll.
936 DCHECK(!splice_buffers
[splice_buffers_index_
]->preroll_buffer().get());
938 *out_buffer
= splice_buffers
[splice_buffers_index_
++];
939 return SourceBufferStream::kSuccess
;
942 // Did we hand out the last pre-splice buffer on the previous call?
943 if (!pending_buffers_complete_
) {
944 DCHECK_EQ(splice_buffers_index_
, last_splice_buffer_index
);
945 pending_buffers_complete_
= true;
946 config_change_pending_
= true;
947 DVLOG(1) << "Config change (forced for fade in of splice frame).";
948 return SourceBufferStream::kConfigChange
;
951 // All pre-splice buffers have been handed out and a config change completed,
952 // so hand out the final buffer for fade in. Because a config change is
953 // always issued prior to handing out this buffer, any changes in config id
954 // have been inherently handled.
955 DCHECK(pending_buffers_complete_
);
956 DCHECK_EQ(splice_buffers_index_
, splice_buffers
.size() - 1);
957 DCHECK(splice_buffers
.back()->splice_timestamp() == kNoTimestamp());
958 *out_buffer
= splice_buffers
.back();
959 pending_buffer_
= NULL
;
961 // If the last splice buffer has preroll, hand off to the preroll handler.
962 return SetPendingBuffer(out_buffer
) ? HandleNextBufferWithPreroll(out_buffer
)
963 : SourceBufferStream::kSuccess
;
966 SourceBufferStream::Status
SourceBufferStream::HandleNextBufferWithPreroll(
967 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
968 // Any config change should have already been handled.
969 DCHECK_EQ(current_config_index_
, pending_buffer_
->GetConfigId());
971 // Check if the preroll buffer has already been handed out.
972 if (!pending_buffers_complete_
) {
973 pending_buffers_complete_
= true;
974 *out_buffer
= pending_buffer_
->preroll_buffer();
975 return SourceBufferStream::kSuccess
;
978 // Preroll complete, hand out the final buffer.
979 *out_buffer
= pending_buffer_
;
980 pending_buffer_
= NULL
;
981 return SourceBufferStream::kSuccess
;
984 SourceBufferStream::Status
SourceBufferStream::GetNextBufferInternal(
985 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
986 CHECK(!config_change_pending_
);
988 if (!track_buffer_
.empty()) {
989 DCHECK(!selected_range_
);
990 scoped_refptr
<StreamParserBuffer
>& next_buffer
= track_buffer_
.front();
992 // If the next buffer is an audio splice frame, the next effective config id
993 // comes from the first splice buffer.
994 if (next_buffer
->GetSpliceBufferConfigId(0) != current_config_index_
) {
995 config_change_pending_
= true;
996 DVLOG(1) << "Config change (track buffer config ID does not match).";
997 return kConfigChange
;
1000 *out_buffer
= next_buffer
;
1001 track_buffer_
.pop_front();
1002 last_output_buffer_timestamp_
= (*out_buffer
)->GetDecodeTimestamp();
1004 // If the track buffer becomes empty, then try to set the selected range
1005 // based on the timestamp of this buffer being returned.
1006 if (track_buffer_
.empty())
1007 SetSelectedRangeIfNeeded(last_output_buffer_timestamp_
);
1012 if (!selected_range_
|| !selected_range_
->HasNextBuffer()) {
1013 if (end_of_stream_
&& IsEndSelected())
1014 return kEndOfStream
;
1018 if (selected_range_
->GetNextConfigId() != current_config_index_
) {
1019 config_change_pending_
= true;
1020 DVLOG(1) << "Config change (selected range config ID does not match).";
1021 return kConfigChange
;
1024 CHECK(selected_range_
->GetNextBuffer(out_buffer
));
1025 last_output_buffer_timestamp_
= (*out_buffer
)->GetDecodeTimestamp();
1029 DecodeTimestamp
SourceBufferStream::GetNextBufferTimestamp() {
1030 if (!track_buffer_
.empty())
1031 return track_buffer_
.front()->GetDecodeTimestamp();
1033 if (!selected_range_
)
1034 return kNoDecodeTimestamp();
1036 DCHECK(selected_range_
->HasNextBufferPosition());
1037 return selected_range_
->GetNextTimestamp();
1040 SourceBufferStream::RangeList::iterator
1041 SourceBufferStream::FindExistingRangeFor(DecodeTimestamp start_timestamp
) {
1042 for (RangeList::iterator itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1043 if ((*itr
)->BelongsToRange(start_timestamp
))
1046 return ranges_
.end();
1049 SourceBufferStream::RangeList::iterator
1050 SourceBufferStream::AddToRanges(SourceBufferRange
* new_range
) {
1051 DecodeTimestamp start_timestamp
= new_range
->GetStartTimestamp();
1052 RangeList::iterator itr
= ranges_
.end();
1053 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1054 if ((*itr
)->GetStartTimestamp() > start_timestamp
)
1057 return ranges_
.insert(itr
, new_range
);
1060 SourceBufferStream::RangeList::iterator
1061 SourceBufferStream::GetSelectedRangeItr() {
1062 DCHECK(selected_range_
);
1063 RangeList::iterator itr
= ranges_
.end();
1064 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1065 if (*itr
== selected_range_
)
1068 DCHECK(itr
!= ranges_
.end());
1072 void SourceBufferStream::SeekAndSetSelectedRange(
1073 SourceBufferRange
* range
, DecodeTimestamp seek_timestamp
) {
1075 range
->Seek(seek_timestamp
);
1076 SetSelectedRange(range
);
1079 void SourceBufferStream::SetSelectedRange(SourceBufferRange
* range
) {
1080 DVLOG(1) << __FUNCTION__
<< " : " << selected_range_
<< " -> " << range
;
1081 if (selected_range_
)
1082 selected_range_
->ResetNextBufferPosition();
1083 DCHECK(!range
|| range
->HasNextBufferPosition());
1084 selected_range_
= range
;
1087 Ranges
<base::TimeDelta
> SourceBufferStream::GetBufferedTime() const {
1088 Ranges
<base::TimeDelta
> ranges
;
1089 for (RangeList::const_iterator itr
= ranges_
.begin();
1090 itr
!= ranges_
.end(); ++itr
) {
1091 ranges
.Add((*itr
)->GetStartTimestamp().ToPresentationTime(),
1092 (*itr
)->GetBufferedEndTimestamp().ToPresentationTime());
1097 base::TimeDelta
SourceBufferStream::GetBufferedDuration() const {
1098 if (ranges_
.empty())
1099 return base::TimeDelta();
1101 return ranges_
.back()->GetBufferedEndTimestamp().ToPresentationTime();
1104 void SourceBufferStream::MarkEndOfStream() {
1105 DCHECK(!end_of_stream_
);
1106 end_of_stream_
= true;
1109 void SourceBufferStream::UnmarkEndOfStream() {
1110 DCHECK(end_of_stream_
);
1111 end_of_stream_
= false;
1114 bool SourceBufferStream::IsEndSelected() const {
1115 if (ranges_
.empty())
1118 if (seek_pending_
) {
1119 base::TimeDelta last_range_end_time
=
1120 ranges_
.back()->GetBufferedEndTimestamp().ToPresentationTime();
1121 return seek_buffer_timestamp_
>= last_range_end_time
;
1124 return selected_range_
== ranges_
.back();
1127 const AudioDecoderConfig
& SourceBufferStream::GetCurrentAudioDecoderConfig() {
1128 if (config_change_pending_
)
1129 CompleteConfigChange();
1130 return audio_configs_
[current_config_index_
];
1133 const VideoDecoderConfig
& SourceBufferStream::GetCurrentVideoDecoderConfig() {
1134 if (config_change_pending_
)
1135 CompleteConfigChange();
1136 return video_configs_
[current_config_index_
];
1139 const TextTrackConfig
& SourceBufferStream::GetCurrentTextTrackConfig() {
1140 return text_track_config_
;
1143 base::TimeDelta
SourceBufferStream::GetMaxInterbufferDistance() const {
1144 if (max_interbuffer_distance_
== kNoTimestamp())
1145 return base::TimeDelta::FromMilliseconds(kDefaultBufferDurationInMs
);
1146 return max_interbuffer_distance_
;
1149 bool SourceBufferStream::UpdateAudioConfig(const AudioDecoderConfig
& config
) {
1150 DCHECK(!audio_configs_
.empty());
1151 DCHECK(video_configs_
.empty());
1152 DVLOG(3) << "UpdateAudioConfig.";
1154 if (audio_configs_
[0].codec() != config
.codec()) {
1155 MEDIA_LOG(log_cb_
) << "Audio codec changes not allowed.";
1159 if (audio_configs_
[0].is_encrypted() != config
.is_encrypted()) {
1160 MEDIA_LOG(log_cb_
) << "Audio encryption changes not allowed.";
1164 // Check to see if the new config matches an existing one.
1165 for (size_t i
= 0; i
< audio_configs_
.size(); ++i
) {
1166 if (config
.Matches(audio_configs_
[i
])) {
1167 append_config_index_
= i
;
1172 // No matches found so let's add this one to the list.
1173 append_config_index_
= audio_configs_
.size();
1174 DVLOG(2) << "New audio config - index: " << append_config_index_
;
1175 audio_configs_
.resize(audio_configs_
.size() + 1);
1176 audio_configs_
[append_config_index_
] = config
;
1180 bool SourceBufferStream::UpdateVideoConfig(const VideoDecoderConfig
& config
) {
1181 DCHECK(!video_configs_
.empty());
1182 DCHECK(audio_configs_
.empty());
1183 DVLOG(3) << "UpdateVideoConfig.";
1185 if (video_configs_
[0].codec() != config
.codec()) {
1186 MEDIA_LOG(log_cb_
) << "Video codec changes not allowed.";
1190 if (video_configs_
[0].is_encrypted() != config
.is_encrypted()) {
1191 MEDIA_LOG(log_cb_
) << "Video encryption changes not allowed.";
1195 // Check to see if the new config matches an existing one.
1196 for (size_t i
= 0; i
< video_configs_
.size(); ++i
) {
1197 if (config
.Matches(video_configs_
[i
])) {
1198 append_config_index_
= i
;
1203 // No matches found so let's add this one to the list.
1204 append_config_index_
= video_configs_
.size();
1205 DVLOG(2) << "New video config - index: " << append_config_index_
;
1206 video_configs_
.resize(video_configs_
.size() + 1);
1207 video_configs_
[append_config_index_
] = config
;
1211 void SourceBufferStream::CompleteConfigChange() {
1212 config_change_pending_
= false;
1214 if (pending_buffer_
.get()) {
1215 current_config_index_
=
1216 pending_buffer_
->GetSpliceBufferConfigId(splice_buffers_index_
);
1220 if (!track_buffer_
.empty()) {
1221 current_config_index_
= track_buffer_
.front()->GetSpliceBufferConfigId(0);
1225 if (selected_range_
&& selected_range_
->HasNextBuffer())
1226 current_config_index_
= selected_range_
->GetNextConfigId();
1229 void SourceBufferStream::SetSelectedRangeIfNeeded(
1230 const DecodeTimestamp timestamp
) {
1231 DVLOG(1) << __FUNCTION__
<< "(" << timestamp
.InSecondsF() << ")";
1233 if (selected_range_
) {
1234 DCHECK(track_buffer_
.empty());
1238 if (!track_buffer_
.empty()) {
1239 DCHECK(!selected_range_
);
1243 DecodeTimestamp start_timestamp
= timestamp
;
1245 // If the next buffer timestamp is not known then use a timestamp just after
1246 // the timestamp on the last buffer returned by GetNextBuffer().
1247 if (start_timestamp
== kNoDecodeTimestamp()) {
1248 if (last_output_buffer_timestamp_
== kNoDecodeTimestamp())
1251 start_timestamp
= last_output_buffer_timestamp_
+
1252 base::TimeDelta::FromInternalValue(1);
1255 DecodeTimestamp seek_timestamp
=
1256 FindNewSelectedRangeSeekTimestamp(start_timestamp
);
1258 // If we don't have buffered data to seek to, then return.
1259 if (seek_timestamp
== kNoDecodeTimestamp())
1262 DCHECK(track_buffer_
.empty());
1263 SeekAndSetSelectedRange(*FindExistingRangeFor(seek_timestamp
),
1267 DecodeTimestamp
SourceBufferStream::FindNewSelectedRangeSeekTimestamp(
1268 const DecodeTimestamp start_timestamp
) {
1269 DCHECK(start_timestamp
!= kNoDecodeTimestamp());
1270 DCHECK(start_timestamp
>= DecodeTimestamp());
1272 RangeList::iterator itr
= ranges_
.begin();
1274 for (; itr
!= ranges_
.end(); ++itr
) {
1275 if ((*itr
)->GetEndTimestamp() >= start_timestamp
) {
1280 if (itr
== ranges_
.end())
1281 return kNoDecodeTimestamp();
1283 // First check for a keyframe timestamp >= |start_timestamp|
1284 // in the current range.
1285 DecodeTimestamp keyframe_timestamp
=
1286 (*itr
)->NextKeyframeTimestamp(start_timestamp
);
1288 if (keyframe_timestamp
!= kNoDecodeTimestamp())
1289 return keyframe_timestamp
;
1291 // If a keyframe was not found then look for a keyframe that is
1292 // "close enough" in the current or next range.
1293 DecodeTimestamp end_timestamp
=
1294 start_timestamp
+ ComputeFudgeRoom(GetMaxInterbufferDistance());
1295 DCHECK(start_timestamp
< end_timestamp
);
1297 // Make sure the current range doesn't start beyond |end_timestamp|.
1298 if ((*itr
)->GetStartTimestamp() >= end_timestamp
)
1299 return kNoDecodeTimestamp();
1301 keyframe_timestamp
= (*itr
)->KeyframeBeforeTimestamp(end_timestamp
);
1303 // Check to see if the keyframe is within the acceptable range
1304 // (|start_timestamp|, |end_timestamp|].
1305 if (keyframe_timestamp
!= kNoDecodeTimestamp() &&
1306 start_timestamp
< keyframe_timestamp
&&
1307 keyframe_timestamp
<= end_timestamp
) {
1308 return keyframe_timestamp
;
1311 // If |end_timestamp| is within this range, then no other checks are
1313 if (end_timestamp
<= (*itr
)->GetEndTimestamp())
1314 return kNoDecodeTimestamp();
1316 // Move on to the next range.
1319 // Return early if the next range does not contain |end_timestamp|.
1320 if (itr
== ranges_
.end() || (*itr
)->GetStartTimestamp() >= end_timestamp
)
1321 return kNoDecodeTimestamp();
1323 keyframe_timestamp
= (*itr
)->KeyframeBeforeTimestamp(end_timestamp
);
1325 // Check to see if the keyframe is within the acceptable range
1326 // (|start_timestamp|, |end_timestamp|].
1327 if (keyframe_timestamp
!= kNoDecodeTimestamp() &&
1328 start_timestamp
< keyframe_timestamp
&&
1329 keyframe_timestamp
<= end_timestamp
) {
1330 return keyframe_timestamp
;
1333 return kNoDecodeTimestamp();
1336 DecodeTimestamp
SourceBufferStream::FindKeyframeAfterTimestamp(
1337 const DecodeTimestamp timestamp
) {
1338 DCHECK(timestamp
!= kNoDecodeTimestamp());
1340 RangeList::iterator itr
= FindExistingRangeFor(timestamp
);
1342 if (itr
== ranges_
.end())
1343 return kNoDecodeTimestamp();
1345 // First check for a keyframe timestamp >= |timestamp|
1346 // in the current range.
1347 return (*itr
)->NextKeyframeTimestamp(timestamp
);
1350 std::string
SourceBufferStream::GetStreamTypeName() const {
1351 switch (GetType()) {
1363 SourceBufferStream::Type
SourceBufferStream::GetType() const {
1364 if (!audio_configs_
.empty())
1366 if (!video_configs_
.empty())
1368 DCHECK_NE(text_track_config_
.kind(), kTextNone
);
1372 void SourceBufferStream::DeleteAndRemoveRange(RangeList::iterator
* itr
) {
1373 DVLOG(1) << __FUNCTION__
;
1375 DCHECK(*itr
!= ranges_
.end());
1376 if (**itr
== selected_range_
) {
1377 DVLOG(1) << __FUNCTION__
<< " deleting selected range.";
1378 SetSelectedRange(NULL
);
1381 if (*itr
== range_for_next_append_
) {
1382 DVLOG(1) << __FUNCTION__
<< " deleting range_for_next_append_.";
1383 range_for_next_append_
= ranges_
.end();
1384 last_appended_buffer_timestamp_
= kNoDecodeTimestamp();
1385 last_appended_buffer_is_keyframe_
= false;
1389 *itr
= ranges_
.erase(*itr
);
1392 void SourceBufferStream::GenerateSpliceFrame(const BufferQueue
& new_buffers
) {
1393 DCHECK(!new_buffers
.empty());
1395 // Splice frames are only supported for audio.
1396 if (GetType() != kAudio
)
1399 // Find the overlapped range (if any).
1400 const base::TimeDelta splice_timestamp
= new_buffers
.front()->timestamp();
1401 const DecodeTimestamp splice_dts
=
1402 DecodeTimestamp::FromPresentationTime(splice_timestamp
);
1403 RangeList::iterator range_itr
= FindExistingRangeFor(splice_dts
);
1404 if (range_itr
== ranges_
.end())
1407 const DecodeTimestamp max_splice_end_dts
=
1408 splice_dts
+ base::TimeDelta::FromMilliseconds(
1409 AudioSplicer::kCrossfadeDurationInMilliseconds
);
1411 // Find all buffers involved before the splice point.
1412 BufferQueue pre_splice_buffers
;
1413 if (!(*range_itr
)->GetBuffersInRange(
1414 splice_dts
, max_splice_end_dts
, &pre_splice_buffers
)) {
1418 // If there are gaps in the timeline, it's possible that we only find buffers
1419 // after the splice point but within the splice range. For simplicity, we do
1420 // not generate splice frames in this case.
1422 // We also do not want to generate splices if the first new buffer replaces an
1423 // existing buffer exactly.
1424 if (pre_splice_buffers
.front()->timestamp() >= splice_timestamp
)
1427 // If any |pre_splice_buffers| are already splices or preroll, do not generate
1429 for (size_t i
= 0; i
< pre_splice_buffers
.size(); ++i
) {
1430 const BufferQueue
& original_splice_buffers
=
1431 pre_splice_buffers
[i
]->splice_buffers();
1432 if (!original_splice_buffers
.empty()) {
1433 DVLOG(1) << "Can't generate splice: overlapped buffers contain a "
1434 "pre-existing splice.";
1438 if (pre_splice_buffers
[i
]->preroll_buffer().get()) {
1439 DVLOG(1) << "Can't generate splice: overlapped buffers contain preroll.";
1444 // Don't generate splice frames which represent less than two frames, since we
1445 // need at least that much to generate a crossfade. Per the spec, make this
1446 // check using the sample rate of the overlapping buffers.
1447 const base::TimeDelta splice_duration
=
1448 pre_splice_buffers
.back()->timestamp() +
1449 pre_splice_buffers
.back()->duration() - splice_timestamp
;
1450 const base::TimeDelta minimum_splice_duration
= base::TimeDelta::FromSecondsD(
1451 2.0 / audio_configs_
[append_config_index_
].samples_per_second());
1452 if (splice_duration
< minimum_splice_duration
) {
1453 DVLOG(1) << "Can't generate splice: not enough samples for crossfade; have "
1454 << splice_duration
.InMicroseconds() << " us, but need "
1455 << minimum_splice_duration
.InMicroseconds() << " us.";
1459 new_buffers
.front()->ConvertToSpliceBuffer(pre_splice_buffers
);
1462 bool SourceBufferStream::SetPendingBuffer(
1463 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1464 DCHECK(out_buffer
->get());
1465 DCHECK(!pending_buffer_
.get());
1467 const bool have_splice_buffers
= !(*out_buffer
)->splice_buffers().empty();
1468 const bool have_preroll_buffer
= !!(*out_buffer
)->preroll_buffer().get();
1470 if (!have_splice_buffers
&& !have_preroll_buffer
)
1473 DCHECK_NE(have_splice_buffers
, have_preroll_buffer
);
1474 splice_buffers_index_
= 0;
1475 pending_buffer_
.swap(*out_buffer
);
1476 pending_buffers_complete_
= false;
1480 } // namespace media