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"
20 // Helper method that returns true if |ranges| is sorted in increasing order,
22 static bool IsRangeListSorted(
23 const std::list
<media::SourceBufferRange
*>& ranges
) {
24 DecodeTimestamp prev
= kNoDecodeTimestamp();
25 for (std::list
<SourceBufferRange
*>::const_iterator itr
=
26 ranges
.begin(); itr
!= ranges
.end(); ++itr
) {
27 if (prev
!= kNoDecodeTimestamp() && prev
>= (*itr
)->GetStartTimestamp())
29 prev
= (*itr
)->GetEndTimestamp();
34 // Returns an estimate of how far from the beginning or end of a range a buffer
35 // can be to still be considered in the range, given the |approximate_duration|
36 // of a buffer in the stream.
37 // TODO(wolenetz): Once all stream parsers emit accurate frame durations, use
38 // logic like FrameProcessor (2*last_frame_duration + last_decode_timestamp)
39 // instead of an overall maximum interbuffer delta for range discontinuity
40 // detection, and adjust similarly for splice frame discontinuity detection.
41 // See http://crbug.com/351489 and http://crbug.com/351166.
42 static base::TimeDelta
ComputeFudgeRoom(base::TimeDelta approximate_duration
) {
43 // Because we do not know exactly when is the next timestamp, any buffer
44 // that starts within 2x the approximate duration of a buffer is considered
46 return 2 * approximate_duration
;
49 // An arbitrarily-chosen number to estimate the duration of a buffer if none
50 // is set and there's not enough information to get a better estimate.
51 static int kDefaultBufferDurationInMs
= 125;
53 // The amount of time the beginning of the buffered data can differ from the
54 // start time in order to still be considered the start of stream.
55 static base::TimeDelta
kSeekToStartFudgeRoom() {
56 return base::TimeDelta::FromMilliseconds(1000);
59 // Helper method for logging, converts a range into a readable string.
60 static std::string
RangeToString(const SourceBufferRange
& range
) {
62 ss
<< "[" << range
.GetStartTimestamp().InSecondsF()
63 << ";" << range
.GetEndTimestamp().InSecondsF()
64 << "(" << range
.GetBufferedEndTimestamp().InSecondsF() << ")]";
68 // Helper method for logging, converts a set of ranges into a readable string.
69 static std::string
RangesToString(const SourceBufferStream::RangeList
& ranges
) {
74 for (const auto* range_ptr
: ranges
) {
75 if (range_ptr
!= ranges
.front())
77 ss
<< RangeToString(*range_ptr
);
82 static SourceBufferRange::GapPolicy
TypeToGapPolicy(
83 SourceBufferStream::Type type
) {
85 case SourceBufferStream::kAudio
:
86 case SourceBufferStream::kVideo
:
87 return SourceBufferRange::NO_GAPS_ALLOWED
;
88 case SourceBufferStream::kText
:
89 return SourceBufferRange::ALLOW_GAPS
;
93 return SourceBufferRange::NO_GAPS_ALLOWED
;
96 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig
& audio_config
,
98 bool splice_frames_enabled
)
100 current_config_index_(0),
101 append_config_index_(0),
102 seek_pending_(false),
103 end_of_stream_(false),
104 seek_buffer_timestamp_(kNoTimestamp()),
105 selected_range_(NULL
),
106 media_segment_start_time_(kNoDecodeTimestamp()),
107 range_for_next_append_(ranges_
.end()),
108 new_media_segment_(false),
109 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
110 last_appended_buffer_is_keyframe_(false),
111 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
112 max_interbuffer_distance_(kNoTimestamp()),
113 memory_limit_(kSourceBufferAudioMemoryLimit
),
114 config_change_pending_(false),
115 splice_buffers_index_(0),
116 pending_buffers_complete_(false),
117 splice_frames_enabled_(splice_frames_enabled
) {
118 DCHECK(audio_config
.IsValidConfig());
119 audio_configs_
.push_back(audio_config
);
122 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig
& video_config
,
124 bool splice_frames_enabled
)
126 current_config_index_(0),
127 append_config_index_(0),
128 seek_pending_(false),
129 end_of_stream_(false),
130 seek_buffer_timestamp_(kNoTimestamp()),
131 selected_range_(NULL
),
132 media_segment_start_time_(kNoDecodeTimestamp()),
133 range_for_next_append_(ranges_
.end()),
134 new_media_segment_(false),
135 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
136 last_appended_buffer_is_keyframe_(false),
137 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
138 max_interbuffer_distance_(kNoTimestamp()),
139 memory_limit_(kSourceBufferVideoMemoryLimit
),
140 config_change_pending_(false),
141 splice_buffers_index_(0),
142 pending_buffers_complete_(false),
143 splice_frames_enabled_(splice_frames_enabled
) {
144 DCHECK(video_config
.IsValidConfig());
145 video_configs_
.push_back(video_config
);
148 SourceBufferStream::SourceBufferStream(const TextTrackConfig
& text_config
,
150 bool splice_frames_enabled
)
152 current_config_index_(0),
153 append_config_index_(0),
154 text_track_config_(text_config
),
155 seek_pending_(false),
156 end_of_stream_(false),
157 seek_buffer_timestamp_(kNoTimestamp()),
158 selected_range_(NULL
),
159 media_segment_start_time_(kNoDecodeTimestamp()),
160 range_for_next_append_(ranges_
.end()),
161 new_media_segment_(false),
162 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
163 last_appended_buffer_is_keyframe_(false),
164 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
165 max_interbuffer_distance_(kNoTimestamp()),
166 memory_limit_(kSourceBufferAudioMemoryLimit
),
167 config_change_pending_(false),
168 splice_buffers_index_(0),
169 pending_buffers_complete_(false),
170 splice_frames_enabled_(splice_frames_enabled
) {
173 SourceBufferStream::~SourceBufferStream() {
174 while (!ranges_
.empty()) {
175 delete ranges_
.front();
180 void SourceBufferStream::OnNewMediaSegment(
181 DecodeTimestamp media_segment_start_time
) {
182 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
183 << " (" << media_segment_start_time
.InSecondsF() << ")";
184 DCHECK(!end_of_stream_
);
185 media_segment_start_time_
= media_segment_start_time
;
186 new_media_segment_
= true;
188 RangeList::iterator last_range
= range_for_next_append_
;
189 range_for_next_append_
= FindExistingRangeFor(media_segment_start_time
);
191 // Only reset |last_appended_buffer_timestamp_| if this new media segment is
192 // not adjacent to the previous media segment appended to the stream.
193 if (range_for_next_append_
== ranges_
.end() ||
194 !AreAdjacentInSequence(last_appended_buffer_timestamp_
,
195 media_segment_start_time
)) {
196 last_appended_buffer_timestamp_
= kNoDecodeTimestamp();
197 last_appended_buffer_is_keyframe_
= false;
198 DVLOG(3) << __FUNCTION__
<< " next appended buffers will be in a new range";
199 } else if (last_range
!= ranges_
.end()) {
200 DCHECK(last_range
== range_for_next_append_
);
201 DVLOG(3) << __FUNCTION__
<< " next appended buffers will continue range "
202 << "unless intervening remove makes discontinuity";
206 bool SourceBufferStream::Append(const BufferQueue
& buffers
) {
207 TRACE_EVENT2("media", "SourceBufferStream::Append",
208 "stream type", GetStreamTypeName(),
209 "buffers to append", buffers
.size());
211 DCHECK(!buffers
.empty());
212 DCHECK(media_segment_start_time_
!= kNoDecodeTimestamp());
213 DCHECK(media_segment_start_time_
<= buffers
.front()->GetDecodeTimestamp());
214 DCHECK(!end_of_stream_
);
216 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName() << ": buffers dts=["
217 << buffers
.front()->GetDecodeTimestamp().InSecondsF() << ";"
218 << buffers
.back()->GetDecodeTimestamp().InSecondsF() << "] pts=["
219 << buffers
.front()->timestamp().InSecondsF() << ";"
220 << buffers
.back()->timestamp().InSecondsF() << "(last frame dur="
221 << buffers
.back()->duration().InSecondsF() << ")]";
223 // New media segments must begin with a keyframe.
224 // TODO(wolenetz): Relax this requirement. See http://crbug.com/229412.
225 if (new_media_segment_
&& !buffers
.front()->is_key_frame()) {
226 MEDIA_LOG(ERROR
, log_cb_
) << "Media segment did not begin with key frame.";
230 // Buffers within a media segment should be monotonically increasing.
231 if (!IsMonotonicallyIncreasing(buffers
))
234 if (media_segment_start_time_
< DecodeTimestamp() ||
235 buffers
.front()->GetDecodeTimestamp() < DecodeTimestamp()) {
236 MEDIA_LOG(ERROR
, log_cb_
)
237 << "Cannot append a media segment with negative timestamps.";
241 if (!IsNextTimestampValid(buffers
.front()->GetDecodeTimestamp(),
242 buffers
.front()->is_key_frame())) {
243 const DecodeTimestamp
& dts
= buffers
.front()->GetDecodeTimestamp();
244 MEDIA_LOG(ERROR
, log_cb_
) << "Invalid same timestamp construct detected at"
245 << " time " << dts
.InSecondsF();
250 UpdateMaxInterbufferDistance(buffers
);
251 SetConfigIds(buffers
);
253 // Save a snapshot of stream state before range modifications are made.
254 DecodeTimestamp next_buffer_timestamp
= GetNextBufferTimestamp();
255 BufferQueue deleted_buffers
;
257 PrepareRangesForNextAppend(buffers
, &deleted_buffers
);
259 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise,
260 // create a new range with |buffers|.
261 if (range_for_next_append_
!= ranges_
.end()) {
262 (*range_for_next_append_
)->AppendBuffersToEnd(buffers
);
263 last_appended_buffer_timestamp_
= buffers
.back()->GetDecodeTimestamp();
264 last_appended_buffer_is_keyframe_
= buffers
.back()->is_key_frame();
266 DecodeTimestamp new_range_start_time
= std::min(
267 media_segment_start_time_
, buffers
.front()->GetDecodeTimestamp());
268 const BufferQueue
* buffers_for_new_range
= &buffers
;
269 BufferQueue trimmed_buffers
;
271 // If the new range is not being created because of a new media
272 // segment, then we must make sure that we start with a key frame.
273 // This can happen if the GOP in the previous append gets destroyed
274 // by a Remove() call.
275 if (!new_media_segment_
) {
276 BufferQueue::const_iterator itr
= buffers
.begin();
278 // Scan past all the non-key-frames.
279 while (itr
!= buffers
.end() && !(*itr
)->is_key_frame()) {
283 // If we didn't find a key frame, then update the last appended
284 // buffer state and return.
285 if (itr
== buffers
.end()) {
286 last_appended_buffer_timestamp_
= buffers
.back()->GetDecodeTimestamp();
287 last_appended_buffer_is_keyframe_
= buffers
.back()->is_key_frame();
288 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
289 << ": new buffers in the middle of media segment depend on"
290 "keyframe that has been removed, and contain no keyframes."
291 "Skipping further processing.";
292 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
293 << ": done. ranges_=" << RangesToString(ranges_
);
295 } else if (itr
!= buffers
.begin()) {
296 // Copy the first key frame and everything after it into
297 // |trimmed_buffers|.
298 trimmed_buffers
.assign(itr
, buffers
.end());
299 buffers_for_new_range
= &trimmed_buffers
;
302 new_range_start_time
=
303 buffers_for_new_range
->front()->GetDecodeTimestamp();
306 range_for_next_append_
=
307 AddToRanges(new SourceBufferRange(
308 TypeToGapPolicy(GetType()),
309 *buffers_for_new_range
, new_range_start_time
,
310 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance
,
311 base::Unretained(this))));
312 last_appended_buffer_timestamp_
=
313 buffers_for_new_range
->back()->GetDecodeTimestamp();
314 last_appended_buffer_is_keyframe_
=
315 buffers_for_new_range
->back()->is_key_frame();
318 new_media_segment_
= false;
320 MergeWithAdjacentRangeIfNecessary(range_for_next_append_
);
322 // Seek to try to fulfill a previous call to Seek().
324 DCHECK(!selected_range_
);
325 DCHECK(deleted_buffers
.empty());
326 Seek(seek_buffer_timestamp_
);
329 if (!deleted_buffers
.empty()) {
330 DecodeTimestamp start_of_deleted
=
331 deleted_buffers
.front()->GetDecodeTimestamp();
333 DCHECK(track_buffer_
.empty() ||
334 track_buffer_
.back()->GetDecodeTimestamp() < start_of_deleted
)
335 << "decode timestamp "
336 << track_buffer_
.back()->GetDecodeTimestamp().InSecondsF() << " sec"
337 << ", start_of_deleted " << start_of_deleted
.InSecondsF()<< " sec";
339 track_buffer_
.insert(track_buffer_
.end(), deleted_buffers
.begin(),
340 deleted_buffers
.end());
341 DVLOG(3) << __FUNCTION__
<< " Added " << deleted_buffers
.size()
342 << " deleted buffers to track buffer. TB size is now "
343 << track_buffer_
.size();
345 DVLOG(3) << __FUNCTION__
<< " No deleted buffers for track buffer";
348 // Prune any extra buffers in |track_buffer_| if new keyframes
349 // are appended to the range covered by |track_buffer_|.
350 if (!track_buffer_
.empty()) {
351 DecodeTimestamp keyframe_timestamp
=
352 FindKeyframeAfterTimestamp(track_buffer_
.front()->GetDecodeTimestamp());
353 if (keyframe_timestamp
!= kNoDecodeTimestamp())
354 PruneTrackBuffer(keyframe_timestamp
);
357 SetSelectedRangeIfNeeded(next_buffer_timestamp
);
359 GarbageCollectIfNeeded();
361 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
362 << ": done. ranges_=" << RangesToString(ranges_
);
363 DCHECK(IsRangeListSorted(ranges_
));
364 DCHECK(OnlySelectedRangeIsSeeked());
368 void SourceBufferStream::Remove(base::TimeDelta start
, base::TimeDelta end
,
369 base::TimeDelta duration
) {
370 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
371 << " (" << start
.InSecondsF() << ", " << end
.InSecondsF()
372 << ", " << duration
.InSecondsF() << ")";
373 DCHECK(start
>= base::TimeDelta()) << start
.InSecondsF();
374 DCHECK(start
< end
) << "start " << start
.InSecondsF()
375 << " end " << end
.InSecondsF();
376 DCHECK(duration
!= kNoTimestamp());
378 DecodeTimestamp start_dts
= DecodeTimestamp::FromPresentationTime(start
);
379 DecodeTimestamp end_dts
= DecodeTimestamp::FromPresentationTime(end
);
380 DecodeTimestamp remove_end_timestamp
=
381 DecodeTimestamp::FromPresentationTime(duration
);
382 DecodeTimestamp keyframe_timestamp
= FindKeyframeAfterTimestamp(end_dts
);
383 if (keyframe_timestamp
!= kNoDecodeTimestamp()) {
384 remove_end_timestamp
= keyframe_timestamp
;
385 } else if (end_dts
< remove_end_timestamp
) {
386 remove_end_timestamp
= end_dts
;
389 BufferQueue deleted_buffers
;
390 RemoveInternal(start_dts
, remove_end_timestamp
, false, &deleted_buffers
);
392 if (!deleted_buffers
.empty()) {
393 // Buffers for the current position have been removed.
394 SetSelectedRangeIfNeeded(deleted_buffers
.front()->GetDecodeTimestamp());
395 if (last_output_buffer_timestamp_
== kNoDecodeTimestamp()) {
396 // We just removed buffers for the current playback position for this
397 // stream, yet we also had output no buffer since the last Seek.
398 // Re-seek to prevent stall.
399 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
400 << ": re-seeking to " << seek_buffer_timestamp_
401 << " to prevent stall if this time becomes buffered again";
402 Seek(seek_buffer_timestamp_
);
407 void SourceBufferStream::RemoveInternal(DecodeTimestamp start
,
410 BufferQueue
* deleted_buffers
) {
411 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName() << " ("
412 << start
.InSecondsF() << ", " << end
.InSecondsF() << ", "
413 << exclude_start
<< ")";
414 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
415 << ": before remove ranges_=" << RangesToString(ranges_
);
417 DCHECK(start
>= DecodeTimestamp());
418 DCHECK(start
< end
) << "start " << start
.InSecondsF()
419 << " end " << end
.InSecondsF();
420 DCHECK(deleted_buffers
);
422 RangeList::iterator itr
= ranges_
.begin();
424 while (itr
!= ranges_
.end()) {
425 SourceBufferRange
* range
= *itr
;
426 if (range
->GetStartTimestamp() >= end
)
429 // Split off any remaining GOPs starting at or after |end| and add it to
431 SourceBufferRange
* new_range
= range
->SplitRange(end
);
433 itr
= ranges_
.insert(++itr
, new_range
);
436 // Update the selected range if the next buffer position was transferred
438 if (new_range
->HasNextBufferPosition())
439 SetSelectedRange(new_range
);
442 // Truncate the current range so that it only contains data before
443 // the removal range.
444 BufferQueue saved_buffers
;
445 bool delete_range
= range
->TruncateAt(start
, &saved_buffers
, exclude_start
);
447 // Check to see if the current playback position was removed and
448 // update the selected range appropriately.
449 if (!saved_buffers
.empty()) {
450 DCHECK(!range
->HasNextBufferPosition());
451 DCHECK(deleted_buffers
->empty());
453 *deleted_buffers
= saved_buffers
;
456 if (range
== selected_range_
&& !range
->HasNextBufferPosition())
457 SetSelectedRange(NULL
);
459 // If the current range now is completely covered by the removal
460 // range then delete it and move on.
462 DeleteAndRemoveRange(&itr
);
466 // Clear |range_for_next_append_| if we determine that the removal
467 // operation makes it impossible for the next append to be added
468 // to the current range.
469 if (range_for_next_append_
!= ranges_
.end() &&
470 *range_for_next_append_
== range
&&
471 last_appended_buffer_timestamp_
!= kNoDecodeTimestamp()) {
472 DecodeTimestamp potential_next_append_timestamp
=
473 last_appended_buffer_timestamp_
+
474 base::TimeDelta::FromInternalValue(1);
476 if (!range
->BelongsToRange(potential_next_append_timestamp
)) {
477 DVLOG(1) << "Resetting range_for_next_append_ since the next append"
478 << " can't add to the current range.";
479 range_for_next_append_
=
480 FindExistingRangeFor(potential_next_append_timestamp
);
484 // Move on to the next range.
488 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
489 << ": after remove ranges_=" << RangesToString(ranges_
);
491 DCHECK(IsRangeListSorted(ranges_
));
492 DCHECK(OnlySelectedRangeIsSeeked());
495 void SourceBufferStream::ResetSeekState() {
496 SetSelectedRange(NULL
);
497 track_buffer_
.clear();
498 config_change_pending_
= false;
499 last_output_buffer_timestamp_
= kNoDecodeTimestamp();
500 splice_buffers_index_
= 0;
501 pending_buffer_
= NULL
;
502 pending_buffers_complete_
= false;
505 bool SourceBufferStream::ShouldSeekToStartOfBuffered(
506 base::TimeDelta seek_timestamp
) const {
509 base::TimeDelta beginning_of_buffered
=
510 ranges_
.front()->GetStartTimestamp().ToPresentationTime();
511 return (seek_timestamp
<= beginning_of_buffered
&&
512 beginning_of_buffered
< kSeekToStartFudgeRoom());
515 bool SourceBufferStream::IsMonotonicallyIncreasing(
516 const BufferQueue
& buffers
) const {
517 DCHECK(!buffers
.empty());
518 DecodeTimestamp prev_timestamp
= last_appended_buffer_timestamp_
;
519 bool prev_is_keyframe
= last_appended_buffer_is_keyframe_
;
520 for (BufferQueue::const_iterator itr
= buffers
.begin();
521 itr
!= buffers
.end(); ++itr
) {
522 DecodeTimestamp current_timestamp
= (*itr
)->GetDecodeTimestamp();
523 bool current_is_keyframe
= (*itr
)->is_key_frame();
524 DCHECK(current_timestamp
!= kNoDecodeTimestamp());
525 DCHECK((*itr
)->duration() >= base::TimeDelta())
526 << "Packet with invalid duration."
527 << " pts " << (*itr
)->timestamp().InSecondsF()
528 << " dts " << (*itr
)->GetDecodeTimestamp().InSecondsF()
529 << " dur " << (*itr
)->duration().InSecondsF();
531 if (prev_timestamp
!= kNoDecodeTimestamp()) {
532 if (current_timestamp
< prev_timestamp
) {
533 MEDIA_LOG(ERROR
, log_cb_
) << "Buffers did not monotonically increase.";
537 if (current_timestamp
== prev_timestamp
&&
538 !SourceBufferRange::AllowSameTimestamp(prev_is_keyframe
,
539 current_is_keyframe
)) {
540 MEDIA_LOG(ERROR
, log_cb_
) << "Unexpected combination of buffers with"
541 << " the same timestamp detected at "
542 << current_timestamp
.InSecondsF();
547 prev_timestamp
= current_timestamp
;
548 prev_is_keyframe
= current_is_keyframe
;
553 bool SourceBufferStream::IsNextTimestampValid(
554 DecodeTimestamp next_timestamp
, bool next_is_keyframe
) const {
555 return (last_appended_buffer_timestamp_
!= next_timestamp
) ||
556 new_media_segment_
||
557 SourceBufferRange::AllowSameTimestamp(last_appended_buffer_is_keyframe_
,
562 bool SourceBufferStream::OnlySelectedRangeIsSeeked() const {
563 for (RangeList::const_iterator itr
= ranges_
.begin();
564 itr
!= ranges_
.end(); ++itr
) {
565 if ((*itr
)->HasNextBufferPosition() && (*itr
) != selected_range_
)
568 return !selected_range_
|| selected_range_
->HasNextBufferPosition();
571 void SourceBufferStream::UpdateMaxInterbufferDistance(
572 const BufferQueue
& buffers
) {
573 DCHECK(!buffers
.empty());
574 DecodeTimestamp prev_timestamp
= last_appended_buffer_timestamp_
;
575 for (BufferQueue::const_iterator itr
= buffers
.begin();
576 itr
!= buffers
.end(); ++itr
) {
577 DecodeTimestamp current_timestamp
= (*itr
)->GetDecodeTimestamp();
578 DCHECK(current_timestamp
!= kNoDecodeTimestamp());
580 base::TimeDelta interbuffer_distance
= (*itr
)->duration();
581 DCHECK(interbuffer_distance
>= base::TimeDelta());
583 if (prev_timestamp
!= kNoDecodeTimestamp()) {
584 interbuffer_distance
=
585 std::max(current_timestamp
- prev_timestamp
, interbuffer_distance
);
588 if (interbuffer_distance
> base::TimeDelta()) {
589 if (max_interbuffer_distance_
== kNoTimestamp()) {
590 max_interbuffer_distance_
= interbuffer_distance
;
592 max_interbuffer_distance_
=
593 std::max(max_interbuffer_distance_
, interbuffer_distance
);
596 prev_timestamp
= current_timestamp
;
600 void SourceBufferStream::SetConfigIds(const BufferQueue
& buffers
) {
601 for (BufferQueue::const_iterator itr
= buffers
.begin();
602 itr
!= buffers
.end(); ++itr
) {
603 (*itr
)->SetConfigId(append_config_index_
);
607 void SourceBufferStream::GarbageCollectIfNeeded() {
608 // Compute size of |ranges_|.
610 for (RangeList::iterator itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
)
611 ranges_size
+= (*itr
)->size_in_bytes();
613 // Return if we're under or at the memory limit.
614 if (ranges_size
<= memory_limit_
)
617 int bytes_to_free
= ranges_size
- memory_limit_
;
619 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName() << ": Before GC"
620 << " ranges_size=" << ranges_size
621 << " ranges_=" << RangesToString(ranges_
)
622 << " memory_limit_=" << memory_limit_
;
624 // Begin deleting after the last appended buffer.
625 int bytes_freed
= FreeBuffersAfterLastAppended(bytes_to_free
);
627 // Begin deleting from the front.
628 if (bytes_to_free
- bytes_freed
> 0)
629 bytes_freed
+= FreeBuffers(bytes_to_free
- bytes_freed
, false);
631 // Begin deleting from the back.
632 if (bytes_to_free
- bytes_freed
> 0)
633 bytes_freed
+= FreeBuffers(bytes_to_free
- bytes_freed
, true);
635 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName() << ": After GC"
636 << " bytes_freed=" << bytes_freed
637 << " ranges_=" << RangesToString(ranges_
);
640 int SourceBufferStream::FreeBuffersAfterLastAppended(int total_bytes_to_free
) {
641 DecodeTimestamp next_buffer_timestamp
= GetNextBufferTimestamp();
642 if (last_appended_buffer_timestamp_
== kNoDecodeTimestamp() ||
643 next_buffer_timestamp
== kNoDecodeTimestamp() ||
644 last_appended_buffer_timestamp_
>= next_buffer_timestamp
) {
648 DecodeTimestamp remove_range_start
= last_appended_buffer_timestamp_
;
649 if (last_appended_buffer_is_keyframe_
)
650 remove_range_start
+= GetMaxInterbufferDistance();
652 DecodeTimestamp remove_range_start_keyframe
= FindKeyframeAfterTimestamp(
654 if (remove_range_start_keyframe
!= kNoDecodeTimestamp())
655 remove_range_start
= remove_range_start_keyframe
;
656 if (remove_range_start
>= next_buffer_timestamp
)
659 DecodeTimestamp remove_range_end
;
660 int bytes_freed
= GetRemovalRange(
661 remove_range_start
, next_buffer_timestamp
, total_bytes_to_free
,
663 if (bytes_freed
> 0) {
664 Remove(remove_range_start
.ToPresentationTime(),
665 remove_range_end
.ToPresentationTime(),
666 next_buffer_timestamp
.ToPresentationTime());
672 int SourceBufferStream::GetRemovalRange(
673 DecodeTimestamp start_timestamp
, DecodeTimestamp end_timestamp
,
674 int total_bytes_to_free
, DecodeTimestamp
* removal_end_timestamp
) {
675 DCHECK(start_timestamp
>= DecodeTimestamp()) << start_timestamp
.InSecondsF();
676 DCHECK(start_timestamp
< end_timestamp
)
677 << "start " << start_timestamp
.InSecondsF()
678 << ", end " << end_timestamp
.InSecondsF();
680 int bytes_to_free
= total_bytes_to_free
;
683 for (RangeList::iterator itr
= ranges_
.begin();
684 itr
!= ranges_
.end() && bytes_to_free
> 0; ++itr
) {
685 SourceBufferRange
* range
= *itr
;
686 if (range
->GetStartTimestamp() >= end_timestamp
)
688 if (range
->GetEndTimestamp() < start_timestamp
)
691 int bytes_removed
= range
->GetRemovalGOP(
692 start_timestamp
, end_timestamp
, bytes_to_free
, removal_end_timestamp
);
693 bytes_to_free
-= bytes_removed
;
694 bytes_freed
+= bytes_removed
;
699 int SourceBufferStream::FreeBuffers(int total_bytes_to_free
,
700 bool reverse_direction
) {
701 TRACE_EVENT2("media", "SourceBufferStream::FreeBuffers",
702 "total bytes to free", total_bytes_to_free
,
703 "reverse direction", reverse_direction
);
705 DCHECK_GT(total_bytes_to_free
, 0);
706 int bytes_to_free
= total_bytes_to_free
;
709 // This range will save the last GOP appended to |range_for_next_append_|
710 // if the buffers surrounding it get deleted during garbage collection.
711 SourceBufferRange
* new_range_for_append
= NULL
;
713 while (!ranges_
.empty() && bytes_to_free
> 0) {
714 SourceBufferRange
* current_range
= NULL
;
716 int bytes_deleted
= 0;
718 if (reverse_direction
) {
719 current_range
= ranges_
.back();
720 if (current_range
->LastGOPContainsNextBufferPosition()) {
721 DCHECK_EQ(current_range
, selected_range_
);
724 bytes_deleted
= current_range
->DeleteGOPFromBack(&buffers
);
726 current_range
= ranges_
.front();
727 if (current_range
->FirstGOPContainsNextBufferPosition()) {
728 DCHECK_EQ(current_range
, selected_range_
);
731 bytes_deleted
= current_range
->DeleteGOPFromFront(&buffers
);
734 // Check to see if we've just deleted the GOP that was last appended.
735 DecodeTimestamp end_timestamp
= buffers
.back()->GetDecodeTimestamp();
736 if (end_timestamp
== last_appended_buffer_timestamp_
) {
737 DCHECK(last_appended_buffer_timestamp_
!= kNoDecodeTimestamp());
738 DCHECK(!new_range_for_append
);
739 // Create a new range containing these buffers.
740 new_range_for_append
= new SourceBufferRange(
741 TypeToGapPolicy(GetType()),
742 buffers
, kNoDecodeTimestamp(),
743 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance
,
744 base::Unretained(this)));
745 range_for_next_append_
= ranges_
.end();
747 bytes_to_free
-= bytes_deleted
;
748 bytes_freed
+= bytes_deleted
;
751 if (current_range
->size_in_bytes() == 0) {
752 DCHECK_NE(current_range
, selected_range_
);
753 DCHECK(range_for_next_append_
== ranges_
.end() ||
754 *range_for_next_append_
!= current_range
);
755 delete current_range
;
756 reverse_direction
? ranges_
.pop_back() : ranges_
.pop_front();
760 // Insert |new_range_for_append| into |ranges_|, if applicable.
761 if (new_range_for_append
) {
762 range_for_next_append_
= AddToRanges(new_range_for_append
);
763 DCHECK(range_for_next_append_
!= ranges_
.end());
765 // Check to see if we need to merge |new_range_for_append| with the range
766 // before or after it. |new_range_for_append| is created whenever the last
767 // GOP appended is encountered, regardless of whether any buffers after it
768 // are ultimately deleted. Merging is necessary if there were no buffers
769 // (or very few buffers) deleted after creating |new_range_for_append|.
770 if (range_for_next_append_
!= ranges_
.begin()) {
771 RangeList::iterator range_before_next
= range_for_next_append_
;
773 MergeWithAdjacentRangeIfNecessary(range_before_next
);
775 MergeWithAdjacentRangeIfNecessary(range_for_next_append_
);
780 void SourceBufferStream::PrepareRangesForNextAppend(
781 const BufferQueue
& new_buffers
, BufferQueue
* deleted_buffers
) {
782 DCHECK(deleted_buffers
);
784 bool temporarily_select_range
= false;
785 if (!track_buffer_
.empty()) {
786 DecodeTimestamp tb_timestamp
= track_buffer_
.back()->GetDecodeTimestamp();
787 DecodeTimestamp seek_timestamp
= FindKeyframeAfterTimestamp(tb_timestamp
);
788 if (seek_timestamp
!= kNoDecodeTimestamp() &&
789 seek_timestamp
< new_buffers
.front()->GetDecodeTimestamp() &&
790 range_for_next_append_
!= ranges_
.end() &&
791 (*range_for_next_append_
)->BelongsToRange(seek_timestamp
)) {
792 DCHECK(tb_timestamp
< seek_timestamp
);
793 DCHECK(!selected_range_
);
794 DCHECK(!(*range_for_next_append_
)->HasNextBufferPosition());
796 // If there are GOPs between the end of the track buffer and the
797 // beginning of the new buffers, then temporarily seek the range
798 // so that the buffers between these two times will be deposited in
799 // |deleted_buffers| as if they were part of the current playback
801 // TODO(acolwell): Figure out a more elegant way to do this.
802 SeekAndSetSelectedRange(*range_for_next_append_
, seek_timestamp
);
803 temporarily_select_range
= true;
807 // Handle splices between the existing buffers and the new buffers. If a
808 // splice is generated the timestamp and duration of the first buffer in
809 // |new_buffers| will be modified.
810 if (splice_frames_enabled_
)
811 GenerateSpliceFrame(new_buffers
);
813 DecodeTimestamp prev_timestamp
= last_appended_buffer_timestamp_
;
814 bool prev_is_keyframe
= last_appended_buffer_is_keyframe_
;
815 DecodeTimestamp next_timestamp
= new_buffers
.front()->GetDecodeTimestamp();
816 bool next_is_keyframe
= new_buffers
.front()->is_key_frame();
818 if (prev_timestamp
!= kNoDecodeTimestamp() &&
819 prev_timestamp
!= next_timestamp
) {
820 // Clean up the old buffers between the last appended buffer and the
821 // beginning of |new_buffers|.
822 RemoveInternal(prev_timestamp
, next_timestamp
, true, deleted_buffers
);
825 // Make the delete range exclusive if we are dealing with an allowed same
826 // timestamp situation. This prevents the first buffer in the current append
827 // from deleting the last buffer in the previous append if both buffers
828 // have the same timestamp.
830 // The delete range should never be exclusive if a splice frame was generated
831 // because we don't generate splice frames for same timestamp situations.
832 DCHECK(new_buffers
.front()->splice_timestamp() !=
833 new_buffers
.front()->timestamp());
834 const bool exclude_start
=
835 new_buffers
.front()->splice_buffers().empty() &&
836 prev_timestamp
== next_timestamp
&&
837 SourceBufferRange::AllowSameTimestamp(prev_is_keyframe
, next_is_keyframe
);
839 // Delete the buffers that |new_buffers| overlaps.
840 DecodeTimestamp start
= new_buffers
.front()->GetDecodeTimestamp();
841 DecodeTimestamp end
= new_buffers
.back()->GetDecodeTimestamp();
842 base::TimeDelta duration
= new_buffers
.back()->duration();
844 // Set end time for remove to include the duration of last buffer. If the
845 // duration is estimated, use 1 microsecond instead to ensure frames are not
846 // accidentally removed due to over-estimation.
847 if (duration
!= kNoTimestamp() && duration
> base::TimeDelta() &&
848 !new_buffers
.back()->is_duration_estimated()) {
851 // TODO(chcunningham): Emit warning when 0ms durations are not expected.
852 // http://crbug.com/312836
853 end
+= base::TimeDelta::FromInternalValue(1);
856 RemoveInternal(start
, end
, exclude_start
, deleted_buffers
);
858 // Restore the range seek state if necessary.
859 if (temporarily_select_range
)
860 SetSelectedRange(NULL
);
863 bool SourceBufferStream::AreAdjacentInSequence(
864 DecodeTimestamp first_timestamp
, DecodeTimestamp second_timestamp
) const {
865 return first_timestamp
< second_timestamp
&&
867 first_timestamp
+ ComputeFudgeRoom(GetMaxInterbufferDistance());
870 void SourceBufferStream::PruneTrackBuffer(const DecodeTimestamp timestamp
) {
871 // If we don't have the next timestamp, we don't have anything to delete.
872 if (timestamp
== kNoDecodeTimestamp())
875 while (!track_buffer_
.empty() &&
876 track_buffer_
.back()->GetDecodeTimestamp() >= timestamp
) {
877 track_buffer_
.pop_back();
881 void SourceBufferStream::MergeWithAdjacentRangeIfNecessary(
882 const RangeList::iterator
& range_with_new_buffers_itr
) {
883 DCHECK(range_with_new_buffers_itr
!= ranges_
.end());
885 SourceBufferRange
* range_with_new_buffers
= *range_with_new_buffers_itr
;
886 RangeList::iterator next_range_itr
= range_with_new_buffers_itr
;
889 if (next_range_itr
== ranges_
.end() ||
890 !range_with_new_buffers
->CanAppendRangeToEnd(**next_range_itr
)) {
894 bool transfer_current_position
= selected_range_
== *next_range_itr
;
895 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
896 << " merging " << RangeToString(*range_with_new_buffers
)
897 << " into " << RangeToString(**next_range_itr
);
898 range_with_new_buffers
->AppendRangeToEnd(**next_range_itr
,
899 transfer_current_position
);
900 // Update |selected_range_| pointer if |range| has become selected after
902 if (transfer_current_position
)
903 SetSelectedRange(range_with_new_buffers
);
905 if (next_range_itr
== range_for_next_append_
)
906 range_for_next_append_
= range_with_new_buffers_itr
;
908 DeleteAndRemoveRange(&next_range_itr
);
911 void SourceBufferStream::Seek(base::TimeDelta timestamp
) {
912 DCHECK(timestamp
>= base::TimeDelta());
913 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
914 << " (" << timestamp
.InSecondsF() << ")";
917 seek_buffer_timestamp_
= timestamp
;
918 seek_pending_
= true;
920 if (ShouldSeekToStartOfBuffered(timestamp
)) {
921 ranges_
.front()->SeekToStart();
922 SetSelectedRange(ranges_
.front());
923 seek_pending_
= false;
927 DecodeTimestamp seek_dts
= DecodeTimestamp::FromPresentationTime(timestamp
);
929 RangeList::iterator itr
= ranges_
.end();
930 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
931 if ((*itr
)->CanSeekTo(seek_dts
))
935 if (itr
== ranges_
.end())
938 SeekAndSetSelectedRange(*itr
, seek_dts
);
939 seek_pending_
= false;
942 bool SourceBufferStream::IsSeekPending() const {
943 return seek_pending_
&& !IsEndOfStreamReached();
946 void SourceBufferStream::OnSetDuration(base::TimeDelta duration
) {
947 DecodeTimestamp duration_dts
=
948 DecodeTimestamp::FromPresentationTime(duration
);
949 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
950 << " (" << duration
.InSecondsF() << ")";
952 RangeList::iterator itr
= ranges_
.end();
953 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
954 if ((*itr
)->GetEndTimestamp() > duration_dts
)
957 if (itr
== ranges_
.end())
960 // Need to partially truncate this range.
961 if ((*itr
)->GetStartTimestamp() < duration_dts
) {
962 bool delete_range
= (*itr
)->TruncateAt(duration_dts
, NULL
, false);
963 if ((*itr
== selected_range_
) && !selected_range_
->HasNextBufferPosition())
964 SetSelectedRange(NULL
);
967 DeleteAndRemoveRange(&itr
);
973 // Delete all ranges that begin after |duration_dts|.
974 while (itr
!= ranges_
.end()) {
975 // If we're about to delete the selected range, also reset the seek state.
976 DCHECK((*itr
)->GetStartTimestamp() >= duration_dts
);
977 if (*itr
== selected_range_
)
979 DeleteAndRemoveRange(&itr
);
983 SourceBufferStream::Status
SourceBufferStream::GetNextBuffer(
984 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
985 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName();
986 if (!pending_buffer_
.get()) {
987 const SourceBufferStream::Status status
= GetNextBufferInternal(out_buffer
);
988 if (status
!= SourceBufferStream::kSuccess
||
989 !SetPendingBuffer(out_buffer
)) {
990 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
991 << ": no pending buffer, returning status " << status
;
996 if (!pending_buffer_
->splice_buffers().empty()) {
997 const SourceBufferStream::Status status
=
998 HandleNextBufferWithSplice(out_buffer
);
999 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1000 << ": handled next buffer with splice, returning status "
1005 DCHECK(pending_buffer_
->preroll_buffer().get());
1007 const SourceBufferStream::Status status
=
1008 HandleNextBufferWithPreroll(out_buffer
);
1009 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1010 << ": handled next buffer with preroll, returning status "
1015 SourceBufferStream::Status
SourceBufferStream::HandleNextBufferWithSplice(
1016 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1017 const BufferQueue
& splice_buffers
= pending_buffer_
->splice_buffers();
1018 const size_t last_splice_buffer_index
= splice_buffers
.size() - 1;
1020 // Are there any splice buffers left to hand out? The last buffer should be
1021 // handed out separately since it represents the first post-splice buffer.
1022 if (splice_buffers_index_
< last_splice_buffer_index
) {
1023 // Account for config changes which occur between fade out buffers.
1024 if (current_config_index_
!=
1025 splice_buffers
[splice_buffers_index_
]->GetConfigId()) {
1026 config_change_pending_
= true;
1027 DVLOG(1) << "Config change (splice buffer config ID does not match).";
1028 return SourceBufferStream::kConfigChange
;
1031 // Every pre splice buffer must have the same splice_timestamp().
1032 DCHECK(pending_buffer_
->splice_timestamp() ==
1033 splice_buffers
[splice_buffers_index_
]->splice_timestamp());
1035 // No pre splice buffers should have preroll.
1036 DCHECK(!splice_buffers
[splice_buffers_index_
]->preroll_buffer().get());
1038 *out_buffer
= splice_buffers
[splice_buffers_index_
++];
1039 return SourceBufferStream::kSuccess
;
1042 // Did we hand out the last pre-splice buffer on the previous call?
1043 if (!pending_buffers_complete_
) {
1044 DCHECK_EQ(splice_buffers_index_
, last_splice_buffer_index
);
1045 pending_buffers_complete_
= true;
1046 config_change_pending_
= true;
1047 DVLOG(1) << "Config change (forced for fade in of splice frame).";
1048 return SourceBufferStream::kConfigChange
;
1051 // All pre-splice buffers have been handed out and a config change completed,
1052 // so hand out the final buffer for fade in. Because a config change is
1053 // always issued prior to handing out this buffer, any changes in config id
1054 // have been inherently handled.
1055 DCHECK(pending_buffers_complete_
);
1056 DCHECK_EQ(splice_buffers_index_
, splice_buffers
.size() - 1);
1057 DCHECK(splice_buffers
.back()->splice_timestamp() == kNoTimestamp());
1058 *out_buffer
= splice_buffers
.back();
1059 pending_buffer_
= NULL
;
1061 // If the last splice buffer has preroll, hand off to the preroll handler.
1062 return SetPendingBuffer(out_buffer
) ? HandleNextBufferWithPreroll(out_buffer
)
1063 : SourceBufferStream::kSuccess
;
1066 SourceBufferStream::Status
SourceBufferStream::HandleNextBufferWithPreroll(
1067 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1068 // Any config change should have already been handled.
1069 DCHECK_EQ(current_config_index_
, pending_buffer_
->GetConfigId());
1071 // Check if the preroll buffer has already been handed out.
1072 if (!pending_buffers_complete_
) {
1073 pending_buffers_complete_
= true;
1074 *out_buffer
= pending_buffer_
->preroll_buffer();
1075 return SourceBufferStream::kSuccess
;
1078 // Preroll complete, hand out the final buffer.
1079 *out_buffer
= pending_buffer_
;
1080 pending_buffer_
= NULL
;
1081 return SourceBufferStream::kSuccess
;
1084 SourceBufferStream::Status
SourceBufferStream::GetNextBufferInternal(
1085 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1086 CHECK(!config_change_pending_
);
1088 if (!track_buffer_
.empty()) {
1089 DCHECK(!selected_range_
);
1090 scoped_refptr
<StreamParserBuffer
>& next_buffer
= track_buffer_
.front();
1092 // If the next buffer is an audio splice frame, the next effective config id
1093 // comes from the first splice buffer.
1094 if (next_buffer
->GetSpliceBufferConfigId(0) != current_config_index_
) {
1095 config_change_pending_
= true;
1096 DVLOG(1) << "Config change (track buffer config ID does not match).";
1097 return kConfigChange
;
1100 DVLOG(3) << __FUNCTION__
<< " Next buffer coming from track_buffer_";
1101 *out_buffer
= next_buffer
;
1102 track_buffer_
.pop_front();
1103 last_output_buffer_timestamp_
= (*out_buffer
)->GetDecodeTimestamp();
1105 // If the track buffer becomes empty, then try to set the selected range
1106 // based on the timestamp of this buffer being returned.
1107 if (track_buffer_
.empty())
1108 SetSelectedRangeIfNeeded(last_output_buffer_timestamp_
);
1113 DCHECK(track_buffer_
.empty());
1114 if (!selected_range_
|| !selected_range_
->HasNextBuffer()) {
1115 if (IsEndOfStreamReached()) {
1116 return kEndOfStream
;
1118 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
1119 << ": returning kNeedBuffer "
1120 << (selected_range_
? "(selected range has no next buffer)"
1121 : "(no selected range)");
1125 if (selected_range_
->GetNextConfigId() != current_config_index_
) {
1126 config_change_pending_
= true;
1127 DVLOG(1) << "Config change (selected range config ID does not match).";
1128 return kConfigChange
;
1131 CHECK(selected_range_
->GetNextBuffer(out_buffer
));
1132 last_output_buffer_timestamp_
= (*out_buffer
)->GetDecodeTimestamp();
1136 DecodeTimestamp
SourceBufferStream::GetNextBufferTimestamp() {
1137 if (!track_buffer_
.empty())
1138 return track_buffer_
.front()->GetDecodeTimestamp();
1140 if (!selected_range_
)
1141 return kNoDecodeTimestamp();
1143 DCHECK(selected_range_
->HasNextBufferPosition());
1144 return selected_range_
->GetNextTimestamp();
1147 SourceBufferStream::RangeList::iterator
1148 SourceBufferStream::FindExistingRangeFor(DecodeTimestamp start_timestamp
) {
1149 for (RangeList::iterator itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1150 if ((*itr
)->BelongsToRange(start_timestamp
))
1153 return ranges_
.end();
1156 SourceBufferStream::RangeList::iterator
1157 SourceBufferStream::AddToRanges(SourceBufferRange
* new_range
) {
1158 DecodeTimestamp start_timestamp
= new_range
->GetStartTimestamp();
1159 RangeList::iterator itr
= ranges_
.end();
1160 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1161 if ((*itr
)->GetStartTimestamp() > start_timestamp
)
1164 return ranges_
.insert(itr
, new_range
);
1167 SourceBufferStream::RangeList::iterator
1168 SourceBufferStream::GetSelectedRangeItr() {
1169 DCHECK(selected_range_
);
1170 RangeList::iterator itr
= ranges_
.end();
1171 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1172 if (*itr
== selected_range_
)
1175 DCHECK(itr
!= ranges_
.end());
1179 void SourceBufferStream::SeekAndSetSelectedRange(
1180 SourceBufferRange
* range
, DecodeTimestamp seek_timestamp
) {
1182 range
->Seek(seek_timestamp
);
1183 SetSelectedRange(range
);
1186 void SourceBufferStream::SetSelectedRange(SourceBufferRange
* range
) {
1187 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
1188 << ": " << selected_range_
<< " -> " << range
;
1189 if (selected_range_
)
1190 selected_range_
->ResetNextBufferPosition();
1191 DCHECK(!range
|| range
->HasNextBufferPosition());
1192 selected_range_
= range
;
1195 Ranges
<base::TimeDelta
> SourceBufferStream::GetBufferedTime() const {
1196 Ranges
<base::TimeDelta
> ranges
;
1197 for (RangeList::const_iterator itr
= ranges_
.begin();
1198 itr
!= ranges_
.end(); ++itr
) {
1199 ranges
.Add((*itr
)->GetStartTimestamp().ToPresentationTime(),
1200 (*itr
)->GetBufferedEndTimestamp().ToPresentationTime());
1205 base::TimeDelta
SourceBufferStream::GetBufferedDuration() const {
1206 if (ranges_
.empty())
1207 return base::TimeDelta();
1209 return ranges_
.back()->GetBufferedEndTimestamp().ToPresentationTime();
1212 void SourceBufferStream::MarkEndOfStream() {
1213 DCHECK(!end_of_stream_
);
1214 end_of_stream_
= true;
1217 void SourceBufferStream::UnmarkEndOfStream() {
1218 DCHECK(end_of_stream_
);
1219 end_of_stream_
= false;
1222 bool SourceBufferStream::IsEndOfStreamReached() const {
1223 if (!end_of_stream_
|| !track_buffer_
.empty())
1226 if (ranges_
.empty())
1229 if (seek_pending_
) {
1230 base::TimeDelta last_range_end_time
=
1231 ranges_
.back()->GetBufferedEndTimestamp().ToPresentationTime();
1232 return seek_buffer_timestamp_
>= last_range_end_time
;
1235 if (!selected_range_
)
1238 return selected_range_
== ranges_
.back();
1241 const AudioDecoderConfig
& SourceBufferStream::GetCurrentAudioDecoderConfig() {
1242 if (config_change_pending_
)
1243 CompleteConfigChange();
1244 return audio_configs_
[current_config_index_
];
1247 const VideoDecoderConfig
& SourceBufferStream::GetCurrentVideoDecoderConfig() {
1248 if (config_change_pending_
)
1249 CompleteConfigChange();
1250 return video_configs_
[current_config_index_
];
1253 const TextTrackConfig
& SourceBufferStream::GetCurrentTextTrackConfig() {
1254 return text_track_config_
;
1257 base::TimeDelta
SourceBufferStream::GetMaxInterbufferDistance() const {
1258 if (max_interbuffer_distance_
== kNoTimestamp())
1259 return base::TimeDelta::FromMilliseconds(kDefaultBufferDurationInMs
);
1260 return max_interbuffer_distance_
;
1263 bool SourceBufferStream::UpdateAudioConfig(const AudioDecoderConfig
& config
) {
1264 DCHECK(!audio_configs_
.empty());
1265 DCHECK(video_configs_
.empty());
1266 DVLOG(3) << "UpdateAudioConfig.";
1268 if (audio_configs_
[0].codec() != config
.codec()) {
1269 MEDIA_LOG(ERROR
, log_cb_
) << "Audio codec changes not allowed.";
1273 if (audio_configs_
[0].is_encrypted() != config
.is_encrypted()) {
1274 MEDIA_LOG(ERROR
, log_cb_
) << "Audio encryption changes not allowed.";
1278 // Check to see if the new config matches an existing one.
1279 for (size_t i
= 0; i
< audio_configs_
.size(); ++i
) {
1280 if (config
.Matches(audio_configs_
[i
])) {
1281 append_config_index_
= i
;
1286 // No matches found so let's add this one to the list.
1287 append_config_index_
= audio_configs_
.size();
1288 DVLOG(2) << "New audio config - index: " << append_config_index_
;
1289 audio_configs_
.resize(audio_configs_
.size() + 1);
1290 audio_configs_
[append_config_index_
] = config
;
1294 bool SourceBufferStream::UpdateVideoConfig(const VideoDecoderConfig
& config
) {
1295 DCHECK(!video_configs_
.empty());
1296 DCHECK(audio_configs_
.empty());
1297 DVLOG(3) << "UpdateVideoConfig.";
1299 if (video_configs_
[0].codec() != config
.codec()) {
1300 MEDIA_LOG(ERROR
, log_cb_
) << "Video codec changes not allowed.";
1304 if (video_configs_
[0].is_encrypted() != config
.is_encrypted()) {
1305 MEDIA_LOG(ERROR
, log_cb_
) << "Video encryption changes not allowed.";
1309 // Check to see if the new config matches an existing one.
1310 for (size_t i
= 0; i
< video_configs_
.size(); ++i
) {
1311 if (config
.Matches(video_configs_
[i
])) {
1312 append_config_index_
= i
;
1317 // No matches found so let's add this one to the list.
1318 append_config_index_
= video_configs_
.size();
1319 DVLOG(2) << "New video config - index: " << append_config_index_
;
1320 video_configs_
.resize(video_configs_
.size() + 1);
1321 video_configs_
[append_config_index_
] = config
;
1325 void SourceBufferStream::CompleteConfigChange() {
1326 config_change_pending_
= false;
1328 if (pending_buffer_
.get()) {
1329 current_config_index_
=
1330 pending_buffer_
->GetSpliceBufferConfigId(splice_buffers_index_
);
1334 if (!track_buffer_
.empty()) {
1335 current_config_index_
= track_buffer_
.front()->GetSpliceBufferConfigId(0);
1339 if (selected_range_
&& selected_range_
->HasNextBuffer())
1340 current_config_index_
= selected_range_
->GetNextConfigId();
1343 void SourceBufferStream::SetSelectedRangeIfNeeded(
1344 const DecodeTimestamp timestamp
) {
1345 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1346 << "(" << timestamp
.InSecondsF() << ")";
1348 if (selected_range_
) {
1349 DCHECK(track_buffer_
.empty());
1353 if (!track_buffer_
.empty()) {
1354 DCHECK(!selected_range_
);
1358 DecodeTimestamp start_timestamp
= timestamp
;
1360 // If the next buffer timestamp is not known then use a timestamp just after
1361 // the timestamp on the last buffer returned by GetNextBuffer().
1362 if (start_timestamp
== kNoDecodeTimestamp()) {
1363 if (last_output_buffer_timestamp_
== kNoDecodeTimestamp()) {
1364 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1365 << " no previous output timestamp";
1369 start_timestamp
= last_output_buffer_timestamp_
+
1370 base::TimeDelta::FromInternalValue(1);
1373 DecodeTimestamp seek_timestamp
=
1374 FindNewSelectedRangeSeekTimestamp(start_timestamp
);
1376 // If we don't have buffered data to seek to, then return.
1377 if (seek_timestamp
== kNoDecodeTimestamp()) {
1378 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1379 << " couldn't find new selected range seek timestamp";
1383 DCHECK(track_buffer_
.empty());
1384 SeekAndSetSelectedRange(*FindExistingRangeFor(seek_timestamp
),
1388 DecodeTimestamp
SourceBufferStream::FindNewSelectedRangeSeekTimestamp(
1389 const DecodeTimestamp start_timestamp
) {
1390 DCHECK(start_timestamp
!= kNoDecodeTimestamp());
1391 DCHECK(start_timestamp
>= DecodeTimestamp());
1393 RangeList::iterator itr
= ranges_
.begin();
1395 for (; itr
!= ranges_
.end(); ++itr
) {
1396 if ((*itr
)->GetEndTimestamp() >= start_timestamp
) {
1401 if (itr
== ranges_
.end()) {
1402 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1403 << " no buffered data for dts=" << start_timestamp
.InSecondsF();
1404 return kNoDecodeTimestamp();
1407 // First check for a keyframe timestamp >= |start_timestamp|
1408 // in the current range.
1409 DecodeTimestamp keyframe_timestamp
=
1410 (*itr
)->NextKeyframeTimestamp(start_timestamp
);
1412 if (keyframe_timestamp
!= kNoDecodeTimestamp())
1413 return keyframe_timestamp
;
1415 // If a keyframe was not found then look for a keyframe that is
1416 // "close enough" in the current or next range.
1417 DecodeTimestamp end_timestamp
=
1418 start_timestamp
+ ComputeFudgeRoom(GetMaxInterbufferDistance());
1419 DCHECK(start_timestamp
< end_timestamp
);
1421 // Make sure the current range doesn't start beyond |end_timestamp|.
1422 if ((*itr
)->GetStartTimestamp() >= end_timestamp
)
1423 return kNoDecodeTimestamp();
1425 keyframe_timestamp
= (*itr
)->KeyframeBeforeTimestamp(end_timestamp
);
1427 // Check to see if the keyframe is within the acceptable range
1428 // (|start_timestamp|, |end_timestamp|].
1429 if (keyframe_timestamp
!= kNoDecodeTimestamp() &&
1430 start_timestamp
< keyframe_timestamp
&&
1431 keyframe_timestamp
<= end_timestamp
) {
1432 return keyframe_timestamp
;
1435 // If |end_timestamp| is within this range, then no other checks are
1437 if (end_timestamp
<= (*itr
)->GetEndTimestamp())
1438 return kNoDecodeTimestamp();
1440 // Move on to the next range.
1443 // Return early if the next range does not contain |end_timestamp|.
1444 if (itr
== ranges_
.end() || (*itr
)->GetStartTimestamp() >= end_timestamp
)
1445 return kNoDecodeTimestamp();
1447 keyframe_timestamp
= (*itr
)->KeyframeBeforeTimestamp(end_timestamp
);
1449 // Check to see if the keyframe is within the acceptable range
1450 // (|start_timestamp|, |end_timestamp|].
1451 if (keyframe_timestamp
!= kNoDecodeTimestamp() &&
1452 start_timestamp
< keyframe_timestamp
&&
1453 keyframe_timestamp
<= end_timestamp
) {
1454 return keyframe_timestamp
;
1457 return kNoDecodeTimestamp();
1460 DecodeTimestamp
SourceBufferStream::FindKeyframeAfterTimestamp(
1461 const DecodeTimestamp timestamp
) {
1462 DCHECK(timestamp
!= kNoDecodeTimestamp());
1464 RangeList::iterator itr
= FindExistingRangeFor(timestamp
);
1466 if (itr
== ranges_
.end())
1467 return kNoDecodeTimestamp();
1469 // First check for a keyframe timestamp >= |timestamp|
1470 // in the current range.
1471 return (*itr
)->NextKeyframeTimestamp(timestamp
);
1474 std::string
SourceBufferStream::GetStreamTypeName() const {
1475 switch (GetType()) {
1487 SourceBufferStream::Type
SourceBufferStream::GetType() const {
1488 if (!audio_configs_
.empty())
1490 if (!video_configs_
.empty())
1492 DCHECK_NE(text_track_config_
.kind(), kTextNone
);
1496 void SourceBufferStream::DeleteAndRemoveRange(RangeList::iterator
* itr
) {
1497 DVLOG(1) << __FUNCTION__
;
1499 DCHECK(*itr
!= ranges_
.end());
1500 if (**itr
== selected_range_
) {
1501 DVLOG(1) << __FUNCTION__
<< " deleting selected range.";
1502 SetSelectedRange(NULL
);
1505 if (*itr
== range_for_next_append_
) {
1506 DVLOG(1) << __FUNCTION__
<< " deleting range_for_next_append_.";
1507 range_for_next_append_
= ranges_
.end();
1508 last_appended_buffer_timestamp_
= kNoDecodeTimestamp();
1509 last_appended_buffer_is_keyframe_
= false;
1513 *itr
= ranges_
.erase(*itr
);
1516 void SourceBufferStream::GenerateSpliceFrame(const BufferQueue
& new_buffers
) {
1517 DCHECK(!new_buffers
.empty());
1519 // Splice frames are only supported for audio.
1520 if (GetType() != kAudio
)
1523 // Find the overlapped range (if any).
1524 const base::TimeDelta splice_timestamp
= new_buffers
.front()->timestamp();
1525 const DecodeTimestamp splice_dts
=
1526 DecodeTimestamp::FromPresentationTime(splice_timestamp
);
1527 RangeList::iterator range_itr
= FindExistingRangeFor(splice_dts
);
1528 if (range_itr
== ranges_
.end())
1531 const DecodeTimestamp max_splice_end_dts
=
1532 splice_dts
+ base::TimeDelta::FromMilliseconds(
1533 AudioSplicer::kCrossfadeDurationInMilliseconds
);
1535 // Find all buffers involved before the splice point.
1536 BufferQueue pre_splice_buffers
;
1537 if (!(*range_itr
)->GetBuffersInRange(
1538 splice_dts
, max_splice_end_dts
, &pre_splice_buffers
)) {
1542 // If there are gaps in the timeline, it's possible that we only find buffers
1543 // after the splice point but within the splice range. For simplicity, we do
1544 // not generate splice frames in this case.
1546 // We also do not want to generate splices if the first new buffer replaces an
1547 // existing buffer exactly.
1548 if (pre_splice_buffers
.front()->timestamp() >= splice_timestamp
)
1551 // If any |pre_splice_buffers| are already splices or preroll, do not generate
1553 for (size_t i
= 0; i
< pre_splice_buffers
.size(); ++i
) {
1554 const BufferQueue
& original_splice_buffers
=
1555 pre_splice_buffers
[i
]->splice_buffers();
1556 if (!original_splice_buffers
.empty()) {
1557 DVLOG(1) << "Can't generate splice: overlapped buffers contain a "
1558 "pre-existing splice.";
1562 if (pre_splice_buffers
[i
]->preroll_buffer().get()) {
1563 DVLOG(1) << "Can't generate splice: overlapped buffers contain preroll.";
1568 // Don't generate splice frames which represent less than a millisecond (which
1569 // is frequently the extent of timestamp resolution for poorly encoded media)
1570 // or less than two frames (need at least two to crossfade).
1571 const base::TimeDelta splice_duration
=
1572 pre_splice_buffers
.back()->timestamp() +
1573 pre_splice_buffers
.back()->duration() - splice_timestamp
;
1574 const base::TimeDelta minimum_splice_duration
= std::max(
1575 base::TimeDelta::FromMilliseconds(1),
1576 base::TimeDelta::FromSecondsD(
1577 2.0 / audio_configs_
[append_config_index_
].samples_per_second()));
1578 if (splice_duration
< minimum_splice_duration
) {
1579 DVLOG(1) << "Can't generate splice: not enough samples for crossfade; have "
1580 << splice_duration
.InMicroseconds() << " us, but need "
1581 << minimum_splice_duration
.InMicroseconds() << " us.";
1585 DVLOG(1) << "Generating splice frame @ " << new_buffers
.front()->timestamp()
1586 << ", splice duration: " << splice_duration
.InMicroseconds()
1588 new_buffers
.front()->ConvertToSpliceBuffer(pre_splice_buffers
);
1591 bool SourceBufferStream::SetPendingBuffer(
1592 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1593 DCHECK(out_buffer
->get());
1594 DCHECK(!pending_buffer_
.get());
1596 const bool have_splice_buffers
= !(*out_buffer
)->splice_buffers().empty();
1597 const bool have_preroll_buffer
= !!(*out_buffer
)->preroll_buffer().get();
1599 if (!have_splice_buffers
&& !have_preroll_buffer
)
1602 DCHECK_NE(have_splice_buffers
, have_preroll_buffer
);
1603 splice_buffers_index_
= 0;
1604 pending_buffer_
.swap(*out_buffer
);
1605 pending_buffers_complete_
= false;
1609 } // namespace media