1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/filters/source_buffer_stream.h"
11 #include "base/bind.h"
12 #include "base/logging.h"
13 #include "base/trace_event/trace_event.h"
14 #include "media/base/audio_splicer.h"
15 #include "media/filters/source_buffer_platform.h"
16 #include "media/filters/source_buffer_range.h"
23 // An arbitrarily-chosen number to estimate the duration of a buffer if none
24 // is set and there's not enough information to get a better estimate.
25 kDefaultBufferDurationInMs
= 125,
27 // Limit the number of MEDIA_LOG() logs for splice buffer generation warnings
28 // and successes. Though these values are high enough to possibly exhaust the
29 // media internals event cache (along with other events), these logs are
30 // important for debugging splice generation.
31 kMaxSpliceGenerationWarningLogs
= 50,
32 kMaxSpliceGenerationSuccessLogs
= 20,
35 // Helper method that returns true if |ranges| is sorted in increasing order,
37 bool IsRangeListSorted(const std::list
<media::SourceBufferRange
*>& ranges
) {
38 DecodeTimestamp prev
= kNoDecodeTimestamp();
39 for (std::list
<SourceBufferRange
*>::const_iterator itr
=
40 ranges
.begin(); itr
!= ranges
.end(); ++itr
) {
41 if (prev
!= kNoDecodeTimestamp() && prev
>= (*itr
)->GetStartTimestamp())
43 prev
= (*itr
)->GetEndTimestamp();
48 // Returns an estimate of how far from the beginning or end of a range a buffer
49 // can be to still be considered in the range, given the |approximate_duration|
50 // of a buffer in the stream.
51 // TODO(wolenetz): Once all stream parsers emit accurate frame durations, use
52 // logic like FrameProcessor (2*last_frame_duration + last_decode_timestamp)
53 // instead of an overall maximum interbuffer delta for range discontinuity
54 // detection, and adjust similarly for splice frame discontinuity detection.
55 // See http://crbug.com/351489 and http://crbug.com/351166.
56 base::TimeDelta
ComputeFudgeRoom(base::TimeDelta approximate_duration
) {
57 // Because we do not know exactly when is the next timestamp, any buffer
58 // that starts within 2x the approximate duration of a buffer is considered
60 return 2 * approximate_duration
;
63 // The amount of time the beginning of the buffered data can differ from the
64 // start time in order to still be considered the start of stream.
65 base::TimeDelta
kSeekToStartFudgeRoom() {
66 return base::TimeDelta::FromMilliseconds(1000);
69 // Helper method for logging, converts a range into a readable string.
70 std::string
RangeToString(const SourceBufferRange
& range
) {
72 ss
<< "[" << range
.GetStartTimestamp().InSecondsF()
73 << ";" << range
.GetEndTimestamp().InSecondsF()
74 << "(" << range
.GetBufferedEndTimestamp().InSecondsF() << ")]";
78 // Helper method for logging, converts a set of ranges into a readable string.
79 std::string
RangesToString(const SourceBufferStream::RangeList
& ranges
) {
84 for (const auto* range_ptr
: ranges
) {
85 if (range_ptr
!= ranges
.front())
87 ss
<< RangeToString(*range_ptr
);
92 std::string
BufferQueueToLogString(
93 const SourceBufferStream::BufferQueue
& buffers
) {
94 std::stringstream result
;
95 if (buffers
.front()->GetDecodeTimestamp().InMicroseconds() ==
96 buffers
.front()->timestamp().InMicroseconds() &&
97 buffers
.back()->GetDecodeTimestamp().InMicroseconds() ==
98 buffers
.back()->timestamp().InMicroseconds()) {
99 result
<< "dts/pts=[" << buffers
.front()->timestamp().InSecondsF() << ";"
100 << buffers
.back()->timestamp().InSecondsF() << "(last frame dur="
101 << buffers
.back()->duration().InSecondsF() << ")]";
103 result
<< "dts=[" << buffers
.front()->GetDecodeTimestamp().InSecondsF()
104 << ";" << buffers
.back()->GetDecodeTimestamp().InSecondsF()
105 << "] pts=[" << buffers
.front()->timestamp().InSecondsF() << ";"
106 << buffers
.back()->timestamp().InSecondsF() << "(last frame dur="
107 << buffers
.back()->duration().InSecondsF() << ")]";
112 SourceBufferRange::GapPolicy
TypeToGapPolicy(SourceBufferStream::Type type
) {
114 case SourceBufferStream::kAudio
:
115 case SourceBufferStream::kVideo
:
116 return SourceBufferRange::NO_GAPS_ALLOWED
;
117 case SourceBufferStream::kText
:
118 return SourceBufferRange::ALLOW_GAPS
;
122 return SourceBufferRange::NO_GAPS_ALLOWED
;
127 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig
& audio_config
,
128 const scoped_refptr
<MediaLog
>& media_log
,
129 bool splice_frames_enabled
)
130 : media_log_(media_log
),
131 current_config_index_(0),
132 append_config_index_(0),
133 seek_pending_(false),
134 end_of_stream_(false),
135 seek_buffer_timestamp_(kNoTimestamp()),
136 selected_range_(NULL
),
137 media_segment_start_time_(kNoDecodeTimestamp()),
138 range_for_next_append_(ranges_
.end()),
139 new_media_segment_(false),
140 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
141 last_appended_buffer_is_keyframe_(false),
142 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
143 max_interbuffer_distance_(kNoTimestamp()),
144 memory_limit_(kSourceBufferAudioMemoryLimit
),
145 config_change_pending_(false),
146 splice_buffers_index_(0),
147 pending_buffers_complete_(false),
148 splice_frames_enabled_(splice_frames_enabled
),
149 num_splice_generation_warning_logs_(0),
150 num_splice_generation_success_logs_(0) {
151 DCHECK(audio_config
.IsValidConfig());
152 audio_configs_
.push_back(audio_config
);
155 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig
& video_config
,
156 const scoped_refptr
<MediaLog
>& media_log
,
157 bool splice_frames_enabled
)
158 : media_log_(media_log
),
159 current_config_index_(0),
160 append_config_index_(0),
161 seek_pending_(false),
162 end_of_stream_(false),
163 seek_buffer_timestamp_(kNoTimestamp()),
164 selected_range_(NULL
),
165 media_segment_start_time_(kNoDecodeTimestamp()),
166 range_for_next_append_(ranges_
.end()),
167 new_media_segment_(false),
168 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
169 last_appended_buffer_is_keyframe_(false),
170 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
171 max_interbuffer_distance_(kNoTimestamp()),
172 memory_limit_(kSourceBufferVideoMemoryLimit
),
173 config_change_pending_(false),
174 splice_buffers_index_(0),
175 pending_buffers_complete_(false),
176 splice_frames_enabled_(splice_frames_enabled
),
177 num_splice_generation_warning_logs_(0),
178 num_splice_generation_success_logs_(0) {
179 DCHECK(video_config
.IsValidConfig());
180 video_configs_
.push_back(video_config
);
183 SourceBufferStream::SourceBufferStream(const TextTrackConfig
& text_config
,
184 const scoped_refptr
<MediaLog
>& media_log
,
185 bool splice_frames_enabled
)
186 : media_log_(media_log
),
187 current_config_index_(0),
188 append_config_index_(0),
189 text_track_config_(text_config
),
190 seek_pending_(false),
191 end_of_stream_(false),
192 seek_buffer_timestamp_(kNoTimestamp()),
193 selected_range_(NULL
),
194 media_segment_start_time_(kNoDecodeTimestamp()),
195 range_for_next_append_(ranges_
.end()),
196 new_media_segment_(false),
197 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
198 last_appended_buffer_is_keyframe_(false),
199 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
200 max_interbuffer_distance_(kNoTimestamp()),
201 memory_limit_(kSourceBufferAudioMemoryLimit
),
202 config_change_pending_(false),
203 splice_buffers_index_(0),
204 pending_buffers_complete_(false),
205 splice_frames_enabled_(splice_frames_enabled
),
206 num_splice_generation_warning_logs_(0),
207 num_splice_generation_success_logs_(0) {}
209 SourceBufferStream::~SourceBufferStream() {
210 while (!ranges_
.empty()) {
211 delete ranges_
.front();
216 void SourceBufferStream::OnNewMediaSegment(
217 DecodeTimestamp media_segment_start_time
) {
218 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
219 << " (" << media_segment_start_time
.InSecondsF() << ")";
220 DCHECK(!end_of_stream_
);
221 media_segment_start_time_
= media_segment_start_time
;
222 new_media_segment_
= true;
224 RangeList::iterator last_range
= range_for_next_append_
;
225 range_for_next_append_
= FindExistingRangeFor(media_segment_start_time
);
227 // Only reset |last_appended_buffer_timestamp_| if this new media segment is
228 // not adjacent to the previous media segment appended to the stream.
229 if (range_for_next_append_
== ranges_
.end() ||
230 !AreAdjacentInSequence(last_appended_buffer_timestamp_
,
231 media_segment_start_time
)) {
232 last_appended_buffer_timestamp_
= kNoDecodeTimestamp();
233 last_appended_buffer_is_keyframe_
= false;
234 DVLOG(3) << __FUNCTION__
<< " next appended buffers will be in a new range";
235 } else if (last_range
!= ranges_
.end()) {
236 DCHECK(last_range
== range_for_next_append_
);
237 DVLOG(3) << __FUNCTION__
<< " next appended buffers will continue range "
238 << "unless intervening remove makes discontinuity";
242 bool SourceBufferStream::Append(const BufferQueue
& buffers
) {
243 TRACE_EVENT2("media", "SourceBufferStream::Append",
244 "stream type", GetStreamTypeName(),
245 "buffers to append", buffers
.size());
247 DCHECK(!buffers
.empty());
248 DCHECK(media_segment_start_time_
!= kNoDecodeTimestamp());
249 DCHECK(media_segment_start_time_
<= buffers
.front()->GetDecodeTimestamp());
250 DCHECK(!end_of_stream_
);
252 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
253 << ": buffers " << BufferQueueToLogString(buffers
);
255 // New media segments must begin with a keyframe.
256 // TODO(wolenetz): Relax this requirement. See http://crbug.com/229412.
257 if (new_media_segment_
&& !buffers
.front()->is_key_frame()) {
258 MEDIA_LOG(ERROR
, media_log_
) << "Media segment did not begin with key "
259 "frame. Support for such segments will be "
260 "available in a future version. Please see "
261 "https://crbug.com/229412.";
265 // Buffers within a media segment should be monotonically increasing.
266 if (!IsMonotonicallyIncreasing(buffers
))
269 if (media_segment_start_time_
< DecodeTimestamp() ||
270 buffers
.front()->GetDecodeTimestamp() < DecodeTimestamp()) {
271 MEDIA_LOG(ERROR
, media_log_
)
272 << "Cannot append a media segment with negative timestamps.";
276 if (!IsNextTimestampValid(buffers
.front()->GetDecodeTimestamp(),
277 buffers
.front()->is_key_frame())) {
278 const DecodeTimestamp
& dts
= buffers
.front()->GetDecodeTimestamp();
279 MEDIA_LOG(ERROR
, media_log_
)
280 << "Invalid same timestamp construct detected at"
281 << " time " << dts
.InSecondsF();
286 UpdateMaxInterbufferDistance(buffers
);
287 SetConfigIds(buffers
);
289 // Save a snapshot of stream state before range modifications are made.
290 DecodeTimestamp next_buffer_timestamp
= GetNextBufferTimestamp();
291 BufferQueue deleted_buffers
;
293 PrepareRangesForNextAppend(buffers
, &deleted_buffers
);
295 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise,
296 // create a new range with |buffers|.
297 if (range_for_next_append_
!= ranges_
.end()) {
298 (*range_for_next_append_
)->AppendBuffersToEnd(buffers
);
299 last_appended_buffer_timestamp_
= buffers
.back()->GetDecodeTimestamp();
300 last_appended_buffer_is_keyframe_
= buffers
.back()->is_key_frame();
302 DecodeTimestamp new_range_start_time
= std::min(
303 media_segment_start_time_
, buffers
.front()->GetDecodeTimestamp());
304 const BufferQueue
* buffers_for_new_range
= &buffers
;
305 BufferQueue trimmed_buffers
;
307 // If the new range is not being created because of a new media
308 // segment, then we must make sure that we start with a key frame.
309 // This can happen if the GOP in the previous append gets destroyed
310 // by a Remove() call.
311 if (!new_media_segment_
) {
312 BufferQueue::const_iterator itr
= buffers
.begin();
314 // Scan past all the non-key-frames.
315 while (itr
!= buffers
.end() && !(*itr
)->is_key_frame()) {
319 // If we didn't find a key frame, then update the last appended
320 // buffer state and return.
321 if (itr
== buffers
.end()) {
322 last_appended_buffer_timestamp_
= buffers
.back()->GetDecodeTimestamp();
323 last_appended_buffer_is_keyframe_
= buffers
.back()->is_key_frame();
324 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
325 << ": new buffers in the middle of media segment depend on"
326 "keyframe that has been removed, and contain no keyframes."
327 "Skipping further processing.";
328 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
329 << ": done. ranges_=" << RangesToString(ranges_
);
331 } else if (itr
!= buffers
.begin()) {
332 // Copy the first key frame and everything after it into
333 // |trimmed_buffers|.
334 trimmed_buffers
.assign(itr
, buffers
.end());
335 buffers_for_new_range
= &trimmed_buffers
;
338 new_range_start_time
=
339 buffers_for_new_range
->front()->GetDecodeTimestamp();
342 range_for_next_append_
=
343 AddToRanges(new SourceBufferRange(
344 TypeToGapPolicy(GetType()),
345 *buffers_for_new_range
, new_range_start_time
,
346 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance
,
347 base::Unretained(this))));
348 last_appended_buffer_timestamp_
=
349 buffers_for_new_range
->back()->GetDecodeTimestamp();
350 last_appended_buffer_is_keyframe_
=
351 buffers_for_new_range
->back()->is_key_frame();
354 new_media_segment_
= false;
356 MergeWithAdjacentRangeIfNecessary(range_for_next_append_
);
358 // Seek to try to fulfill a previous call to Seek().
360 DCHECK(!selected_range_
);
361 DCHECK(deleted_buffers
.empty());
362 Seek(seek_buffer_timestamp_
);
365 if (!deleted_buffers
.empty()) {
366 DecodeTimestamp start_of_deleted
=
367 deleted_buffers
.front()->GetDecodeTimestamp();
369 DCHECK(track_buffer_
.empty() ||
370 track_buffer_
.back()->GetDecodeTimestamp() < start_of_deleted
)
371 << "decode timestamp "
372 << track_buffer_
.back()->GetDecodeTimestamp().InSecondsF() << " sec"
373 << ", start_of_deleted " << start_of_deleted
.InSecondsF()<< " sec";
375 track_buffer_
.insert(track_buffer_
.end(), deleted_buffers
.begin(),
376 deleted_buffers
.end());
377 DVLOG(3) << __FUNCTION__
<< " Added " << deleted_buffers
.size()
378 << " deleted buffers to track buffer. TB size is now "
379 << track_buffer_
.size();
381 DVLOG(3) << __FUNCTION__
<< " No deleted buffers for track buffer";
384 // Prune any extra buffers in |track_buffer_| if new keyframes
385 // are appended to the range covered by |track_buffer_|.
386 if (!track_buffer_
.empty()) {
387 DecodeTimestamp keyframe_timestamp
=
388 FindKeyframeAfterTimestamp(track_buffer_
.front()->GetDecodeTimestamp());
389 if (keyframe_timestamp
!= kNoDecodeTimestamp())
390 PruneTrackBuffer(keyframe_timestamp
);
393 SetSelectedRangeIfNeeded(next_buffer_timestamp
);
395 GarbageCollectIfNeeded();
397 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
398 << ": done. ranges_=" << RangesToString(ranges_
);
399 DCHECK(IsRangeListSorted(ranges_
));
400 DCHECK(OnlySelectedRangeIsSeeked());
404 void SourceBufferStream::Remove(base::TimeDelta start
, base::TimeDelta end
,
405 base::TimeDelta duration
) {
406 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
407 << " (" << start
.InSecondsF() << ", " << end
.InSecondsF()
408 << ", " << duration
.InSecondsF() << ")";
409 DCHECK(start
>= base::TimeDelta()) << start
.InSecondsF();
410 DCHECK(start
< end
) << "start " << start
.InSecondsF()
411 << " end " << end
.InSecondsF();
412 DCHECK(duration
!= kNoTimestamp());
414 DecodeTimestamp start_dts
= DecodeTimestamp::FromPresentationTime(start
);
415 DecodeTimestamp end_dts
= DecodeTimestamp::FromPresentationTime(end
);
416 DecodeTimestamp remove_end_timestamp
=
417 DecodeTimestamp::FromPresentationTime(duration
);
418 DecodeTimestamp keyframe_timestamp
= FindKeyframeAfterTimestamp(end_dts
);
419 if (keyframe_timestamp
!= kNoDecodeTimestamp()) {
420 remove_end_timestamp
= keyframe_timestamp
;
421 } else if (end_dts
< remove_end_timestamp
) {
422 remove_end_timestamp
= end_dts
;
425 BufferQueue deleted_buffers
;
426 RemoveInternal(start_dts
, remove_end_timestamp
, false, &deleted_buffers
);
428 if (!deleted_buffers
.empty()) {
429 // Buffers for the current position have been removed.
430 SetSelectedRangeIfNeeded(deleted_buffers
.front()->GetDecodeTimestamp());
431 if (last_output_buffer_timestamp_
== kNoDecodeTimestamp()) {
432 // We just removed buffers for the current playback position for this
433 // stream, yet we also had output no buffer since the last Seek.
434 // Re-seek to prevent stall.
435 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
436 << ": re-seeking to " << seek_buffer_timestamp_
437 << " to prevent stall if this time becomes buffered again";
438 Seek(seek_buffer_timestamp_
);
443 void SourceBufferStream::RemoveInternal(DecodeTimestamp start
,
446 BufferQueue
* deleted_buffers
) {
447 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName() << " ("
448 << start
.InSecondsF() << ", " << end
.InSecondsF() << ", "
449 << exclude_start
<< ")";
450 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
451 << ": before remove ranges_=" << RangesToString(ranges_
);
453 DCHECK(start
>= DecodeTimestamp());
454 DCHECK(start
< end
) << "start " << start
.InSecondsF()
455 << " end " << end
.InSecondsF();
456 DCHECK(deleted_buffers
);
458 RangeList::iterator itr
= ranges_
.begin();
460 while (itr
!= ranges_
.end()) {
461 SourceBufferRange
* range
= *itr
;
462 if (range
->GetStartTimestamp() >= end
)
465 // Split off any remaining GOPs starting at or after |end| and add it to
467 SourceBufferRange
* new_range
= range
->SplitRange(end
);
469 itr
= ranges_
.insert(++itr
, new_range
);
472 // Update the selected range if the next buffer position was transferred
474 if (new_range
->HasNextBufferPosition())
475 SetSelectedRange(new_range
);
478 // Truncate the current range so that it only contains data before
479 // the removal range.
480 BufferQueue saved_buffers
;
481 bool delete_range
= range
->TruncateAt(start
, &saved_buffers
, exclude_start
);
483 // Check to see if the current playback position was removed and
484 // update the selected range appropriately.
485 if (!saved_buffers
.empty()) {
486 DCHECK(!range
->HasNextBufferPosition());
487 DCHECK(deleted_buffers
->empty());
489 *deleted_buffers
= saved_buffers
;
492 if (range
== selected_range_
&& !range
->HasNextBufferPosition())
493 SetSelectedRange(NULL
);
495 // If the current range now is completely covered by the removal
496 // range then delete it and move on.
498 DeleteAndRemoveRange(&itr
);
502 // Clear |range_for_next_append_| if we determine that the removal
503 // operation makes it impossible for the next append to be added
504 // to the current range.
505 if (range_for_next_append_
!= ranges_
.end() &&
506 *range_for_next_append_
== range
&&
507 last_appended_buffer_timestamp_
!= kNoDecodeTimestamp()) {
508 DecodeTimestamp potential_next_append_timestamp
=
509 last_appended_buffer_timestamp_
+
510 base::TimeDelta::FromInternalValue(1);
512 if (!range
->BelongsToRange(potential_next_append_timestamp
)) {
513 DVLOG(1) << "Resetting range_for_next_append_ since the next append"
514 << " can't add to the current range.";
515 range_for_next_append_
=
516 FindExistingRangeFor(potential_next_append_timestamp
);
520 // Move on to the next range.
524 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
525 << ": after remove ranges_=" << RangesToString(ranges_
);
527 DCHECK(IsRangeListSorted(ranges_
));
528 DCHECK(OnlySelectedRangeIsSeeked());
531 void SourceBufferStream::ResetSeekState() {
532 SetSelectedRange(NULL
);
533 track_buffer_
.clear();
534 config_change_pending_
= false;
535 last_output_buffer_timestamp_
= kNoDecodeTimestamp();
536 splice_buffers_index_
= 0;
537 pending_buffer_
= NULL
;
538 pending_buffers_complete_
= false;
541 bool SourceBufferStream::ShouldSeekToStartOfBuffered(
542 base::TimeDelta seek_timestamp
) const {
545 base::TimeDelta beginning_of_buffered
=
546 ranges_
.front()->GetStartTimestamp().ToPresentationTime();
547 return (seek_timestamp
<= beginning_of_buffered
&&
548 beginning_of_buffered
< kSeekToStartFudgeRoom());
551 bool SourceBufferStream::IsMonotonicallyIncreasing(
552 const BufferQueue
& buffers
) const {
553 DCHECK(!buffers
.empty());
554 DecodeTimestamp prev_timestamp
= last_appended_buffer_timestamp_
;
555 bool prev_is_keyframe
= last_appended_buffer_is_keyframe_
;
556 for (BufferQueue::const_iterator itr
= buffers
.begin();
557 itr
!= buffers
.end(); ++itr
) {
558 DecodeTimestamp current_timestamp
= (*itr
)->GetDecodeTimestamp();
559 bool current_is_keyframe
= (*itr
)->is_key_frame();
560 DCHECK(current_timestamp
!= kNoDecodeTimestamp());
561 DCHECK((*itr
)->duration() >= base::TimeDelta())
562 << "Packet with invalid duration."
563 << " pts " << (*itr
)->timestamp().InSecondsF()
564 << " dts " << (*itr
)->GetDecodeTimestamp().InSecondsF()
565 << " dur " << (*itr
)->duration().InSecondsF();
567 if (prev_timestamp
!= kNoDecodeTimestamp()) {
568 if (current_timestamp
< prev_timestamp
) {
569 MEDIA_LOG(ERROR
, media_log_
)
570 << "Buffers did not monotonically increase.";
574 if (current_timestamp
== prev_timestamp
&&
575 !SourceBufferRange::AllowSameTimestamp(prev_is_keyframe
,
576 current_is_keyframe
)) {
577 MEDIA_LOG(ERROR
, media_log_
) << "Unexpected combination of buffers with"
578 << " the same timestamp detected at "
579 << current_timestamp
.InSecondsF();
584 prev_timestamp
= current_timestamp
;
585 prev_is_keyframe
= current_is_keyframe
;
590 bool SourceBufferStream::IsNextTimestampValid(
591 DecodeTimestamp next_timestamp
, bool next_is_keyframe
) const {
592 return (last_appended_buffer_timestamp_
!= next_timestamp
) ||
593 new_media_segment_
||
594 SourceBufferRange::AllowSameTimestamp(last_appended_buffer_is_keyframe_
,
599 bool SourceBufferStream::OnlySelectedRangeIsSeeked() const {
600 for (RangeList::const_iterator itr
= ranges_
.begin();
601 itr
!= ranges_
.end(); ++itr
) {
602 if ((*itr
)->HasNextBufferPosition() && (*itr
) != selected_range_
)
605 return !selected_range_
|| selected_range_
->HasNextBufferPosition();
608 void SourceBufferStream::UpdateMaxInterbufferDistance(
609 const BufferQueue
& buffers
) {
610 DCHECK(!buffers
.empty());
611 DecodeTimestamp prev_timestamp
= last_appended_buffer_timestamp_
;
612 for (BufferQueue::const_iterator itr
= buffers
.begin();
613 itr
!= buffers
.end(); ++itr
) {
614 DecodeTimestamp current_timestamp
= (*itr
)->GetDecodeTimestamp();
615 DCHECK(current_timestamp
!= kNoDecodeTimestamp());
617 base::TimeDelta interbuffer_distance
= (*itr
)->duration();
618 DCHECK(interbuffer_distance
>= base::TimeDelta());
620 if (prev_timestamp
!= kNoDecodeTimestamp()) {
621 interbuffer_distance
=
622 std::max(current_timestamp
- prev_timestamp
, interbuffer_distance
);
625 if (interbuffer_distance
> base::TimeDelta()) {
626 if (max_interbuffer_distance_
== kNoTimestamp()) {
627 max_interbuffer_distance_
= interbuffer_distance
;
629 max_interbuffer_distance_
=
630 std::max(max_interbuffer_distance_
, interbuffer_distance
);
633 prev_timestamp
= current_timestamp
;
637 void SourceBufferStream::SetConfigIds(const BufferQueue
& buffers
) {
638 for (BufferQueue::const_iterator itr
= buffers
.begin();
639 itr
!= buffers
.end(); ++itr
) {
640 (*itr
)->SetConfigId(append_config_index_
);
644 void SourceBufferStream::GarbageCollectIfNeeded() {
645 // Compute size of |ranges_|.
646 size_t ranges_size
= 0;
647 for (RangeList::iterator itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
)
648 ranges_size
+= (*itr
)->size_in_bytes();
650 // Return if we're under or at the memory limit.
651 if (ranges_size
<= memory_limit_
)
654 size_t bytes_to_free
= ranges_size
- memory_limit_
;
656 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName() << ": Before GC"
657 << " ranges_size=" << ranges_size
658 << " ranges_=" << RangesToString(ranges_
)
659 << " memory_limit_=" << memory_limit_
;
661 // Begin deleting after the last appended buffer.
662 size_t bytes_freed
= FreeBuffersAfterLastAppended(bytes_to_free
);
664 // Begin deleting from the front.
665 if (bytes_freed
< bytes_to_free
)
666 bytes_freed
+= FreeBuffers(bytes_to_free
- bytes_freed
, false);
668 // Begin deleting from the back.
669 if (bytes_freed
< bytes_to_free
)
670 bytes_freed
+= FreeBuffers(bytes_to_free
- bytes_freed
, true);
672 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName() << ": After GC"
673 << " bytes_freed=" << bytes_freed
674 << " ranges_=" << RangesToString(ranges_
);
677 size_t SourceBufferStream::FreeBuffersAfterLastAppended(
678 size_t total_bytes_to_free
) {
679 DecodeTimestamp next_buffer_timestamp
= GetNextBufferTimestamp();
680 if (last_appended_buffer_timestamp_
== kNoDecodeTimestamp() ||
681 next_buffer_timestamp
== kNoDecodeTimestamp() ||
682 last_appended_buffer_timestamp_
>= next_buffer_timestamp
) {
686 DecodeTimestamp remove_range_start
= last_appended_buffer_timestamp_
;
687 if (last_appended_buffer_is_keyframe_
)
688 remove_range_start
+= GetMaxInterbufferDistance();
690 DecodeTimestamp remove_range_start_keyframe
= FindKeyframeAfterTimestamp(
692 if (remove_range_start_keyframe
!= kNoDecodeTimestamp())
693 remove_range_start
= remove_range_start_keyframe
;
694 if (remove_range_start
>= next_buffer_timestamp
)
697 DecodeTimestamp remove_range_end
;
698 size_t bytes_freed
= GetRemovalRange(remove_range_start
,
699 next_buffer_timestamp
,
702 if (bytes_freed
> 0) {
703 Remove(remove_range_start
.ToPresentationTime(),
704 remove_range_end
.ToPresentationTime(),
705 next_buffer_timestamp
.ToPresentationTime());
711 size_t SourceBufferStream::GetRemovalRange(
712 DecodeTimestamp start_timestamp
, DecodeTimestamp end_timestamp
,
713 size_t total_bytes_to_free
, DecodeTimestamp
* removal_end_timestamp
) {
714 DCHECK(start_timestamp
>= DecodeTimestamp()) << start_timestamp
.InSecondsF();
715 DCHECK(start_timestamp
< end_timestamp
)
716 << "start " << start_timestamp
.InSecondsF()
717 << ", end " << end_timestamp
.InSecondsF();
719 size_t bytes_freed
= 0;
721 for (RangeList::iterator itr
= ranges_
.begin();
722 itr
!= ranges_
.end() && bytes_freed
< total_bytes_to_free
; ++itr
) {
723 SourceBufferRange
* range
= *itr
;
724 if (range
->GetStartTimestamp() >= end_timestamp
)
726 if (range
->GetEndTimestamp() < start_timestamp
)
729 size_t bytes_to_free
= total_bytes_to_free
- bytes_freed
;
730 size_t bytes_removed
= range
->GetRemovalGOP(
731 start_timestamp
, end_timestamp
, bytes_to_free
, removal_end_timestamp
);
732 bytes_freed
+= bytes_removed
;
737 size_t SourceBufferStream::FreeBuffers(size_t total_bytes_to_free
,
738 bool reverse_direction
) {
739 TRACE_EVENT2("media", "SourceBufferStream::FreeBuffers",
740 "total bytes to free", total_bytes_to_free
,
741 "reverse direction", reverse_direction
);
743 DCHECK_GT(total_bytes_to_free
, 0u);
744 size_t bytes_freed
= 0;
746 // This range will save the last GOP appended to |range_for_next_append_|
747 // if the buffers surrounding it get deleted during garbage collection.
748 SourceBufferRange
* new_range_for_append
= NULL
;
750 while (!ranges_
.empty() && bytes_freed
< total_bytes_to_free
) {
751 SourceBufferRange
* current_range
= NULL
;
753 size_t bytes_deleted
= 0;
755 if (reverse_direction
) {
756 current_range
= ranges_
.back();
757 if (current_range
->LastGOPContainsNextBufferPosition()) {
758 DCHECK_EQ(current_range
, selected_range_
);
761 bytes_deleted
= current_range
->DeleteGOPFromBack(&buffers
);
763 current_range
= ranges_
.front();
764 if (current_range
->FirstGOPContainsNextBufferPosition()) {
765 DCHECK_EQ(current_range
, selected_range_
);
768 bytes_deleted
= current_range
->DeleteGOPFromFront(&buffers
);
771 // Check to see if we've just deleted the GOP that was last appended.
772 DecodeTimestamp end_timestamp
= buffers
.back()->GetDecodeTimestamp();
773 if (end_timestamp
== last_appended_buffer_timestamp_
) {
774 DCHECK(last_appended_buffer_timestamp_
!= kNoDecodeTimestamp());
775 DCHECK(!new_range_for_append
);
776 // Create a new range containing these buffers.
777 new_range_for_append
= new SourceBufferRange(
778 TypeToGapPolicy(GetType()),
779 buffers
, kNoDecodeTimestamp(),
780 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance
,
781 base::Unretained(this)));
782 range_for_next_append_
= ranges_
.end();
784 bytes_freed
+= bytes_deleted
;
787 if (current_range
->size_in_bytes() == 0) {
788 DCHECK_NE(current_range
, selected_range_
);
789 DCHECK(range_for_next_append_
== ranges_
.end() ||
790 *range_for_next_append_
!= current_range
);
791 delete current_range
;
792 reverse_direction
? ranges_
.pop_back() : ranges_
.pop_front();
796 // Insert |new_range_for_append| into |ranges_|, if applicable.
797 if (new_range_for_append
) {
798 range_for_next_append_
= AddToRanges(new_range_for_append
);
799 DCHECK(range_for_next_append_
!= ranges_
.end());
801 // Check to see if we need to merge |new_range_for_append| with the range
802 // before or after it. |new_range_for_append| is created whenever the last
803 // GOP appended is encountered, regardless of whether any buffers after it
804 // are ultimately deleted. Merging is necessary if there were no buffers
805 // (or very few buffers) deleted after creating |new_range_for_append|.
806 if (range_for_next_append_
!= ranges_
.begin()) {
807 RangeList::iterator range_before_next
= range_for_next_append_
;
809 MergeWithAdjacentRangeIfNecessary(range_before_next
);
811 MergeWithAdjacentRangeIfNecessary(range_for_next_append_
);
816 void SourceBufferStream::PrepareRangesForNextAppend(
817 const BufferQueue
& new_buffers
, BufferQueue
* deleted_buffers
) {
818 DCHECK(deleted_buffers
);
820 bool temporarily_select_range
= false;
821 if (!track_buffer_
.empty()) {
822 DecodeTimestamp tb_timestamp
= track_buffer_
.back()->GetDecodeTimestamp();
823 DecodeTimestamp seek_timestamp
= FindKeyframeAfterTimestamp(tb_timestamp
);
824 if (seek_timestamp
!= kNoDecodeTimestamp() &&
825 seek_timestamp
< new_buffers
.front()->GetDecodeTimestamp() &&
826 range_for_next_append_
!= ranges_
.end() &&
827 (*range_for_next_append_
)->BelongsToRange(seek_timestamp
)) {
828 DCHECK(tb_timestamp
< seek_timestamp
);
829 DCHECK(!selected_range_
);
830 DCHECK(!(*range_for_next_append_
)->HasNextBufferPosition());
832 // If there are GOPs between the end of the track buffer and the
833 // beginning of the new buffers, then temporarily seek the range
834 // so that the buffers between these two times will be deposited in
835 // |deleted_buffers| as if they were part of the current playback
837 // TODO(acolwell): Figure out a more elegant way to do this.
838 SeekAndSetSelectedRange(*range_for_next_append_
, seek_timestamp
);
839 temporarily_select_range
= true;
843 // Handle splices between the existing buffers and the new buffers. If a
844 // splice is generated the timestamp and duration of the first buffer in
845 // |new_buffers| will be modified.
846 if (splice_frames_enabled_
)
847 GenerateSpliceFrame(new_buffers
);
849 DecodeTimestamp prev_timestamp
= last_appended_buffer_timestamp_
;
850 bool prev_is_keyframe
= last_appended_buffer_is_keyframe_
;
851 DecodeTimestamp next_timestamp
= new_buffers
.front()->GetDecodeTimestamp();
852 bool next_is_keyframe
= new_buffers
.front()->is_key_frame();
854 if (prev_timestamp
!= kNoDecodeTimestamp() &&
855 prev_timestamp
!= next_timestamp
) {
856 // Clean up the old buffers between the last appended buffer and the
857 // beginning of |new_buffers|.
858 RemoveInternal(prev_timestamp
, next_timestamp
, true, deleted_buffers
);
861 // Make the delete range exclusive if we are dealing with an allowed same
862 // timestamp situation. This prevents the first buffer in the current append
863 // from deleting the last buffer in the previous append if both buffers
864 // have the same timestamp.
866 // The delete range should never be exclusive if a splice frame was generated
867 // because we don't generate splice frames for same timestamp situations.
868 DCHECK(new_buffers
.front()->splice_timestamp() !=
869 new_buffers
.front()->timestamp());
870 const bool exclude_start
=
871 new_buffers
.front()->splice_buffers().empty() &&
872 prev_timestamp
== next_timestamp
&&
873 SourceBufferRange::AllowSameTimestamp(prev_is_keyframe
, next_is_keyframe
);
875 // Delete the buffers that |new_buffers| overlaps.
876 DecodeTimestamp start
= new_buffers
.front()->GetDecodeTimestamp();
877 DecodeTimestamp end
= new_buffers
.back()->GetDecodeTimestamp();
878 base::TimeDelta duration
= new_buffers
.back()->duration();
880 // Set end time for remove to include the duration of last buffer. If the
881 // duration is estimated, use 1 microsecond instead to ensure frames are not
882 // accidentally removed due to over-estimation.
883 if (duration
!= kNoTimestamp() && duration
> base::TimeDelta() &&
884 !new_buffers
.back()->is_duration_estimated()) {
887 // TODO(chcunningham): Emit warning when 0ms durations are not expected.
888 // http://crbug.com/312836
889 end
+= base::TimeDelta::FromInternalValue(1);
892 RemoveInternal(start
, end
, exclude_start
, deleted_buffers
);
894 // Restore the range seek state if necessary.
895 if (temporarily_select_range
)
896 SetSelectedRange(NULL
);
899 bool SourceBufferStream::AreAdjacentInSequence(
900 DecodeTimestamp first_timestamp
, DecodeTimestamp second_timestamp
) const {
901 return first_timestamp
< second_timestamp
&&
903 first_timestamp
+ ComputeFudgeRoom(GetMaxInterbufferDistance());
906 void SourceBufferStream::PruneTrackBuffer(const DecodeTimestamp timestamp
) {
907 // If we don't have the next timestamp, we don't have anything to delete.
908 if (timestamp
== kNoDecodeTimestamp())
911 while (!track_buffer_
.empty() &&
912 track_buffer_
.back()->GetDecodeTimestamp() >= timestamp
) {
913 track_buffer_
.pop_back();
917 void SourceBufferStream::MergeWithAdjacentRangeIfNecessary(
918 const RangeList::iterator
& range_with_new_buffers_itr
) {
919 DCHECK(range_with_new_buffers_itr
!= ranges_
.end());
921 SourceBufferRange
* range_with_new_buffers
= *range_with_new_buffers_itr
;
922 RangeList::iterator next_range_itr
= range_with_new_buffers_itr
;
925 if (next_range_itr
== ranges_
.end() ||
926 !range_with_new_buffers
->CanAppendRangeToEnd(**next_range_itr
)) {
930 bool transfer_current_position
= selected_range_
== *next_range_itr
;
931 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
932 << " merging " << RangeToString(*range_with_new_buffers
)
933 << " into " << RangeToString(**next_range_itr
);
934 range_with_new_buffers
->AppendRangeToEnd(**next_range_itr
,
935 transfer_current_position
);
936 // Update |selected_range_| pointer if |range| has become selected after
938 if (transfer_current_position
)
939 SetSelectedRange(range_with_new_buffers
);
941 if (next_range_itr
== range_for_next_append_
)
942 range_for_next_append_
= range_with_new_buffers_itr
;
944 DeleteAndRemoveRange(&next_range_itr
);
947 void SourceBufferStream::Seek(base::TimeDelta timestamp
) {
948 DCHECK(timestamp
>= base::TimeDelta());
949 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
950 << " (" << timestamp
.InSecondsF() << ")";
953 seek_buffer_timestamp_
= timestamp
;
954 seek_pending_
= true;
956 if (ShouldSeekToStartOfBuffered(timestamp
)) {
957 ranges_
.front()->SeekToStart();
958 SetSelectedRange(ranges_
.front());
959 seek_pending_
= false;
963 DecodeTimestamp seek_dts
= DecodeTimestamp::FromPresentationTime(timestamp
);
965 RangeList::iterator itr
= ranges_
.end();
966 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
967 if ((*itr
)->CanSeekTo(seek_dts
))
971 if (itr
== ranges_
.end())
974 SeekAndSetSelectedRange(*itr
, seek_dts
);
975 seek_pending_
= false;
978 bool SourceBufferStream::IsSeekPending() const {
979 return seek_pending_
&& !IsEndOfStreamReached();
982 void SourceBufferStream::OnSetDuration(base::TimeDelta duration
) {
983 DecodeTimestamp duration_dts
=
984 DecodeTimestamp::FromPresentationTime(duration
);
985 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
986 << " (" << duration
.InSecondsF() << ")";
988 RangeList::iterator itr
= ranges_
.end();
989 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
990 if ((*itr
)->GetEndTimestamp() > duration_dts
)
993 if (itr
== ranges_
.end())
996 // Need to partially truncate this range.
997 if ((*itr
)->GetStartTimestamp() < duration_dts
) {
998 bool delete_range
= (*itr
)->TruncateAt(duration_dts
, NULL
, false);
999 if ((*itr
== selected_range_
) && !selected_range_
->HasNextBufferPosition())
1000 SetSelectedRange(NULL
);
1003 DeleteAndRemoveRange(&itr
);
1009 // Delete all ranges that begin after |duration_dts|.
1010 while (itr
!= ranges_
.end()) {
1011 // If we're about to delete the selected range, also reset the seek state.
1012 DCHECK((*itr
)->GetStartTimestamp() >= duration_dts
);
1013 if (*itr
== selected_range_
)
1015 DeleteAndRemoveRange(&itr
);
1019 SourceBufferStream::Status
SourceBufferStream::GetNextBuffer(
1020 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1021 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName();
1022 if (!pending_buffer_
.get()) {
1023 const SourceBufferStream::Status status
= GetNextBufferInternal(out_buffer
);
1024 if (status
!= SourceBufferStream::kSuccess
||
1025 !SetPendingBuffer(out_buffer
)) {
1026 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1027 << ": no pending buffer, returning status " << status
;
1032 if (!pending_buffer_
->splice_buffers().empty()) {
1033 const SourceBufferStream::Status status
=
1034 HandleNextBufferWithSplice(out_buffer
);
1035 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1036 << ": handled next buffer with splice, returning status "
1041 DCHECK(pending_buffer_
->preroll_buffer().get());
1043 const SourceBufferStream::Status status
=
1044 HandleNextBufferWithPreroll(out_buffer
);
1045 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1046 << ": handled next buffer with preroll, returning status "
1051 SourceBufferStream::Status
SourceBufferStream::HandleNextBufferWithSplice(
1052 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1053 const BufferQueue
& splice_buffers
= pending_buffer_
->splice_buffers();
1054 const size_t last_splice_buffer_index
= splice_buffers
.size() - 1;
1056 // Are there any splice buffers left to hand out? The last buffer should be
1057 // handed out separately since it represents the first post-splice buffer.
1058 if (splice_buffers_index_
< last_splice_buffer_index
) {
1059 // Account for config changes which occur between fade out buffers.
1060 if (current_config_index_
!=
1061 splice_buffers
[splice_buffers_index_
]->GetConfigId()) {
1062 config_change_pending_
= true;
1063 DVLOG(1) << "Config change (splice buffer config ID does not match).";
1064 return SourceBufferStream::kConfigChange
;
1067 // Every pre splice buffer must have the same splice_timestamp().
1068 DCHECK(pending_buffer_
->splice_timestamp() ==
1069 splice_buffers
[splice_buffers_index_
]->splice_timestamp());
1071 // No pre splice buffers should have preroll.
1072 DCHECK(!splice_buffers
[splice_buffers_index_
]->preroll_buffer().get());
1074 *out_buffer
= splice_buffers
[splice_buffers_index_
++];
1075 return SourceBufferStream::kSuccess
;
1078 // Did we hand out the last pre-splice buffer on the previous call?
1079 if (!pending_buffers_complete_
) {
1080 DCHECK_EQ(splice_buffers_index_
, last_splice_buffer_index
);
1081 pending_buffers_complete_
= true;
1082 config_change_pending_
= true;
1083 DVLOG(1) << "Config change (forced for fade in of splice frame).";
1084 return SourceBufferStream::kConfigChange
;
1087 // All pre-splice buffers have been handed out and a config change completed,
1088 // so hand out the final buffer for fade in. Because a config change is
1089 // always issued prior to handing out this buffer, any changes in config id
1090 // have been inherently handled.
1091 DCHECK(pending_buffers_complete_
);
1092 DCHECK_EQ(splice_buffers_index_
, splice_buffers
.size() - 1);
1093 DCHECK(splice_buffers
.back()->splice_timestamp() == kNoTimestamp());
1094 *out_buffer
= splice_buffers
.back();
1095 pending_buffer_
= NULL
;
1097 // If the last splice buffer has preroll, hand off to the preroll handler.
1098 return SetPendingBuffer(out_buffer
) ? HandleNextBufferWithPreroll(out_buffer
)
1099 : SourceBufferStream::kSuccess
;
1102 SourceBufferStream::Status
SourceBufferStream::HandleNextBufferWithPreroll(
1103 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1104 // Any config change should have already been handled.
1105 DCHECK_EQ(current_config_index_
, pending_buffer_
->GetConfigId());
1107 // Check if the preroll buffer has already been handed out.
1108 if (!pending_buffers_complete_
) {
1109 pending_buffers_complete_
= true;
1110 *out_buffer
= pending_buffer_
->preroll_buffer();
1111 return SourceBufferStream::kSuccess
;
1114 // Preroll complete, hand out the final buffer.
1115 *out_buffer
= pending_buffer_
;
1116 pending_buffer_
= NULL
;
1117 return SourceBufferStream::kSuccess
;
1120 SourceBufferStream::Status
SourceBufferStream::GetNextBufferInternal(
1121 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1122 CHECK(!config_change_pending_
);
1124 if (!track_buffer_
.empty()) {
1125 DCHECK(!selected_range_
);
1126 scoped_refptr
<StreamParserBuffer
>& next_buffer
= track_buffer_
.front();
1128 // If the next buffer is an audio splice frame, the next effective config id
1129 // comes from the first splice buffer.
1130 if (next_buffer
->GetSpliceBufferConfigId(0) != current_config_index_
) {
1131 config_change_pending_
= true;
1132 DVLOG(1) << "Config change (track buffer config ID does not match).";
1133 return kConfigChange
;
1136 DVLOG(3) << __FUNCTION__
<< " Next buffer coming from track_buffer_";
1137 *out_buffer
= next_buffer
;
1138 track_buffer_
.pop_front();
1139 last_output_buffer_timestamp_
= (*out_buffer
)->GetDecodeTimestamp();
1141 // If the track buffer becomes empty, then try to set the selected range
1142 // based on the timestamp of this buffer being returned.
1143 if (track_buffer_
.empty())
1144 SetSelectedRangeIfNeeded(last_output_buffer_timestamp_
);
1149 DCHECK(track_buffer_
.empty());
1150 if (!selected_range_
|| !selected_range_
->HasNextBuffer()) {
1151 if (IsEndOfStreamReached()) {
1152 return kEndOfStream
;
1154 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
1155 << ": returning kNeedBuffer "
1156 << (selected_range_
? "(selected range has no next buffer)"
1157 : "(no selected range)");
1161 if (selected_range_
->GetNextConfigId() != current_config_index_
) {
1162 config_change_pending_
= true;
1163 DVLOG(1) << "Config change (selected range config ID does not match).";
1164 return kConfigChange
;
1167 CHECK(selected_range_
->GetNextBuffer(out_buffer
));
1168 last_output_buffer_timestamp_
= (*out_buffer
)->GetDecodeTimestamp();
1172 DecodeTimestamp
SourceBufferStream::GetNextBufferTimestamp() {
1173 if (!track_buffer_
.empty())
1174 return track_buffer_
.front()->GetDecodeTimestamp();
1176 if (!selected_range_
)
1177 return kNoDecodeTimestamp();
1179 DCHECK(selected_range_
->HasNextBufferPosition());
1180 return selected_range_
->GetNextTimestamp();
1183 SourceBufferStream::RangeList::iterator
1184 SourceBufferStream::FindExistingRangeFor(DecodeTimestamp start_timestamp
) {
1185 for (RangeList::iterator itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1186 if ((*itr
)->BelongsToRange(start_timestamp
))
1189 return ranges_
.end();
1192 SourceBufferStream::RangeList::iterator
1193 SourceBufferStream::AddToRanges(SourceBufferRange
* new_range
) {
1194 DecodeTimestamp start_timestamp
= new_range
->GetStartTimestamp();
1195 RangeList::iterator itr
= ranges_
.end();
1196 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1197 if ((*itr
)->GetStartTimestamp() > start_timestamp
)
1200 return ranges_
.insert(itr
, new_range
);
1203 SourceBufferStream::RangeList::iterator
1204 SourceBufferStream::GetSelectedRangeItr() {
1205 DCHECK(selected_range_
);
1206 RangeList::iterator itr
= ranges_
.end();
1207 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1208 if (*itr
== selected_range_
)
1211 DCHECK(itr
!= ranges_
.end());
1215 void SourceBufferStream::SeekAndSetSelectedRange(
1216 SourceBufferRange
* range
, DecodeTimestamp seek_timestamp
) {
1218 range
->Seek(seek_timestamp
);
1219 SetSelectedRange(range
);
1222 void SourceBufferStream::SetSelectedRange(SourceBufferRange
* range
) {
1223 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
1224 << ": " << selected_range_
<< " -> " << range
;
1225 if (selected_range_
)
1226 selected_range_
->ResetNextBufferPosition();
1227 DCHECK(!range
|| range
->HasNextBufferPosition());
1228 selected_range_
= range
;
1231 Ranges
<base::TimeDelta
> SourceBufferStream::GetBufferedTime() const {
1232 Ranges
<base::TimeDelta
> ranges
;
1233 for (RangeList::const_iterator itr
= ranges_
.begin();
1234 itr
!= ranges_
.end(); ++itr
) {
1235 ranges
.Add((*itr
)->GetStartTimestamp().ToPresentationTime(),
1236 (*itr
)->GetBufferedEndTimestamp().ToPresentationTime());
1241 base::TimeDelta
SourceBufferStream::GetBufferedDuration() const {
1242 if (ranges_
.empty())
1243 return base::TimeDelta();
1245 return ranges_
.back()->GetBufferedEndTimestamp().ToPresentationTime();
1248 void SourceBufferStream::MarkEndOfStream() {
1249 DCHECK(!end_of_stream_
);
1250 end_of_stream_
= true;
1253 void SourceBufferStream::UnmarkEndOfStream() {
1254 DCHECK(end_of_stream_
);
1255 end_of_stream_
= false;
1258 bool SourceBufferStream::IsEndOfStreamReached() const {
1259 if (!end_of_stream_
|| !track_buffer_
.empty())
1262 if (ranges_
.empty())
1265 if (seek_pending_
) {
1266 base::TimeDelta last_range_end_time
=
1267 ranges_
.back()->GetBufferedEndTimestamp().ToPresentationTime();
1268 return seek_buffer_timestamp_
>= last_range_end_time
;
1271 if (!selected_range_
)
1274 return selected_range_
== ranges_
.back();
1277 const AudioDecoderConfig
& SourceBufferStream::GetCurrentAudioDecoderConfig() {
1278 if (config_change_pending_
)
1279 CompleteConfigChange();
1280 return audio_configs_
[current_config_index_
];
1283 const VideoDecoderConfig
& SourceBufferStream::GetCurrentVideoDecoderConfig() {
1284 if (config_change_pending_
)
1285 CompleteConfigChange();
1286 return video_configs_
[current_config_index_
];
1289 const TextTrackConfig
& SourceBufferStream::GetCurrentTextTrackConfig() {
1290 return text_track_config_
;
1293 base::TimeDelta
SourceBufferStream::GetMaxInterbufferDistance() const {
1294 if (max_interbuffer_distance_
== kNoTimestamp())
1295 return base::TimeDelta::FromMilliseconds(kDefaultBufferDurationInMs
);
1296 return max_interbuffer_distance_
;
1299 bool SourceBufferStream::UpdateAudioConfig(const AudioDecoderConfig
& config
) {
1300 DCHECK(!audio_configs_
.empty());
1301 DCHECK(video_configs_
.empty());
1302 DVLOG(3) << "UpdateAudioConfig.";
1304 if (audio_configs_
[0].codec() != config
.codec()) {
1305 MEDIA_LOG(ERROR
, media_log_
) << "Audio codec changes not allowed.";
1309 if (audio_configs_
[0].is_encrypted() != config
.is_encrypted()) {
1310 MEDIA_LOG(ERROR
, media_log_
) << "Audio encryption changes not allowed.";
1314 // Check to see if the new config matches an existing one.
1315 for (size_t i
= 0; i
< audio_configs_
.size(); ++i
) {
1316 if (config
.Matches(audio_configs_
[i
])) {
1317 append_config_index_
= i
;
1322 // No matches found so let's add this one to the list.
1323 append_config_index_
= audio_configs_
.size();
1324 DVLOG(2) << "New audio config - index: " << append_config_index_
;
1325 audio_configs_
.resize(audio_configs_
.size() + 1);
1326 audio_configs_
[append_config_index_
] = config
;
1330 bool SourceBufferStream::UpdateVideoConfig(const VideoDecoderConfig
& config
) {
1331 DCHECK(!video_configs_
.empty());
1332 DCHECK(audio_configs_
.empty());
1333 DVLOG(3) << "UpdateVideoConfig.";
1335 if (video_configs_
[0].codec() != config
.codec()) {
1336 MEDIA_LOG(ERROR
, media_log_
) << "Video codec changes not allowed.";
1340 if (video_configs_
[0].is_encrypted() != config
.is_encrypted()) {
1341 MEDIA_LOG(ERROR
, media_log_
) << "Video encryption changes not allowed.";
1345 // Check to see if the new config matches an existing one.
1346 for (size_t i
= 0; i
< video_configs_
.size(); ++i
) {
1347 if (config
.Matches(video_configs_
[i
])) {
1348 append_config_index_
= i
;
1353 // No matches found so let's add this one to the list.
1354 append_config_index_
= video_configs_
.size();
1355 DVLOG(2) << "New video config - index: " << append_config_index_
;
1356 video_configs_
.resize(video_configs_
.size() + 1);
1357 video_configs_
[append_config_index_
] = config
;
1361 void SourceBufferStream::CompleteConfigChange() {
1362 config_change_pending_
= false;
1364 if (pending_buffer_
.get()) {
1365 current_config_index_
=
1366 pending_buffer_
->GetSpliceBufferConfigId(splice_buffers_index_
);
1370 if (!track_buffer_
.empty()) {
1371 current_config_index_
= track_buffer_
.front()->GetSpliceBufferConfigId(0);
1375 if (selected_range_
&& selected_range_
->HasNextBuffer())
1376 current_config_index_
= selected_range_
->GetNextConfigId();
1379 void SourceBufferStream::SetSelectedRangeIfNeeded(
1380 const DecodeTimestamp timestamp
) {
1381 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1382 << "(" << timestamp
.InSecondsF() << ")";
1384 if (selected_range_
) {
1385 DCHECK(track_buffer_
.empty());
1389 if (!track_buffer_
.empty()) {
1390 DCHECK(!selected_range_
);
1394 DecodeTimestamp start_timestamp
= timestamp
;
1396 // If the next buffer timestamp is not known then use a timestamp just after
1397 // the timestamp on the last buffer returned by GetNextBuffer().
1398 if (start_timestamp
== kNoDecodeTimestamp()) {
1399 if (last_output_buffer_timestamp_
== kNoDecodeTimestamp()) {
1400 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1401 << " no previous output timestamp";
1405 start_timestamp
= last_output_buffer_timestamp_
+
1406 base::TimeDelta::FromInternalValue(1);
1409 DecodeTimestamp seek_timestamp
=
1410 FindNewSelectedRangeSeekTimestamp(start_timestamp
);
1412 // If we don't have buffered data to seek to, then return.
1413 if (seek_timestamp
== kNoDecodeTimestamp()) {
1414 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1415 << " couldn't find new selected range seek timestamp";
1419 DCHECK(track_buffer_
.empty());
1420 SeekAndSetSelectedRange(*FindExistingRangeFor(seek_timestamp
),
1424 DecodeTimestamp
SourceBufferStream::FindNewSelectedRangeSeekTimestamp(
1425 const DecodeTimestamp start_timestamp
) {
1426 DCHECK(start_timestamp
!= kNoDecodeTimestamp());
1427 DCHECK(start_timestamp
>= DecodeTimestamp());
1429 RangeList::iterator itr
= ranges_
.begin();
1431 for (; itr
!= ranges_
.end(); ++itr
) {
1432 if ((*itr
)->GetEndTimestamp() >= start_timestamp
) {
1437 if (itr
== ranges_
.end()) {
1438 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1439 << " no buffered data for dts=" << start_timestamp
.InSecondsF();
1440 return kNoDecodeTimestamp();
1443 // First check for a keyframe timestamp >= |start_timestamp|
1444 // in the current range.
1445 DecodeTimestamp keyframe_timestamp
=
1446 (*itr
)->NextKeyframeTimestamp(start_timestamp
);
1448 if (keyframe_timestamp
!= kNoDecodeTimestamp())
1449 return keyframe_timestamp
;
1451 // If a keyframe was not found then look for a keyframe that is
1452 // "close enough" in the current or next range.
1453 DecodeTimestamp end_timestamp
=
1454 start_timestamp
+ ComputeFudgeRoom(GetMaxInterbufferDistance());
1455 DCHECK(start_timestamp
< end_timestamp
);
1457 // Make sure the current range doesn't start beyond |end_timestamp|.
1458 if ((*itr
)->GetStartTimestamp() >= end_timestamp
)
1459 return kNoDecodeTimestamp();
1461 keyframe_timestamp
= (*itr
)->KeyframeBeforeTimestamp(end_timestamp
);
1463 // Check to see if the keyframe is within the acceptable range
1464 // (|start_timestamp|, |end_timestamp|].
1465 if (keyframe_timestamp
!= kNoDecodeTimestamp() &&
1466 start_timestamp
< keyframe_timestamp
&&
1467 keyframe_timestamp
<= end_timestamp
) {
1468 return keyframe_timestamp
;
1471 // If |end_timestamp| is within this range, then no other checks are
1473 if (end_timestamp
<= (*itr
)->GetEndTimestamp())
1474 return kNoDecodeTimestamp();
1476 // Move on to the next range.
1479 // Return early if the next range does not contain |end_timestamp|.
1480 if (itr
== ranges_
.end() || (*itr
)->GetStartTimestamp() >= end_timestamp
)
1481 return kNoDecodeTimestamp();
1483 keyframe_timestamp
= (*itr
)->KeyframeBeforeTimestamp(end_timestamp
);
1485 // Check to see if the keyframe is within the acceptable range
1486 // (|start_timestamp|, |end_timestamp|].
1487 if (keyframe_timestamp
!= kNoDecodeTimestamp() &&
1488 start_timestamp
< keyframe_timestamp
&&
1489 keyframe_timestamp
<= end_timestamp
) {
1490 return keyframe_timestamp
;
1493 return kNoDecodeTimestamp();
1496 DecodeTimestamp
SourceBufferStream::FindKeyframeAfterTimestamp(
1497 const DecodeTimestamp timestamp
) {
1498 DCHECK(timestamp
!= kNoDecodeTimestamp());
1500 RangeList::iterator itr
= FindExistingRangeFor(timestamp
);
1502 if (itr
== ranges_
.end())
1503 return kNoDecodeTimestamp();
1505 // First check for a keyframe timestamp >= |timestamp|
1506 // in the current range.
1507 return (*itr
)->NextKeyframeTimestamp(timestamp
);
1510 std::string
SourceBufferStream::GetStreamTypeName() const {
1511 switch (GetType()) {
1523 SourceBufferStream::Type
SourceBufferStream::GetType() const {
1524 if (!audio_configs_
.empty())
1526 if (!video_configs_
.empty())
1528 DCHECK_NE(text_track_config_
.kind(), kTextNone
);
1532 void SourceBufferStream::DeleteAndRemoveRange(RangeList::iterator
* itr
) {
1533 DVLOG(1) << __FUNCTION__
;
1535 DCHECK(*itr
!= ranges_
.end());
1536 if (**itr
== selected_range_
) {
1537 DVLOG(1) << __FUNCTION__
<< " deleting selected range.";
1538 SetSelectedRange(NULL
);
1541 if (*itr
== range_for_next_append_
) {
1542 DVLOG(1) << __FUNCTION__
<< " deleting range_for_next_append_.";
1543 range_for_next_append_
= ranges_
.end();
1544 last_appended_buffer_timestamp_
= kNoDecodeTimestamp();
1545 last_appended_buffer_is_keyframe_
= false;
1549 *itr
= ranges_
.erase(*itr
);
1552 void SourceBufferStream::GenerateSpliceFrame(const BufferQueue
& new_buffers
) {
1553 DCHECK(!new_buffers
.empty());
1555 // Splice frames are only supported for audio.
1556 if (GetType() != kAudio
)
1559 // Find the overlapped range (if any).
1560 const base::TimeDelta splice_timestamp
= new_buffers
.front()->timestamp();
1561 const DecodeTimestamp splice_dts
=
1562 DecodeTimestamp::FromPresentationTime(splice_timestamp
);
1563 RangeList::iterator range_itr
= FindExistingRangeFor(splice_dts
);
1564 if (range_itr
== ranges_
.end())
1567 const DecodeTimestamp max_splice_end_dts
=
1568 splice_dts
+ base::TimeDelta::FromMilliseconds(
1569 AudioSplicer::kCrossfadeDurationInMilliseconds
);
1571 // Find all buffers involved before the splice point.
1572 BufferQueue pre_splice_buffers
;
1573 if (!(*range_itr
)->GetBuffersInRange(
1574 splice_dts
, max_splice_end_dts
, &pre_splice_buffers
)) {
1578 // If there are gaps in the timeline, it's possible that we only find buffers
1579 // after the splice point but within the splice range. For simplicity, we do
1580 // not generate splice frames in this case.
1582 // We also do not want to generate splices if the first new buffer replaces an
1583 // existing buffer exactly.
1584 if (pre_splice_buffers
.front()->timestamp() >= splice_timestamp
) {
1585 LIMITED_MEDIA_LOG(DEBUG
, media_log_
, num_splice_generation_warning_logs_
,
1586 kMaxSpliceGenerationWarningLogs
)
1587 << "Skipping splice frame generation: first new buffer at "
1588 << splice_timestamp
.InMicroseconds()
1589 << "us begins at or before existing buffer at "
1590 << pre_splice_buffers
.front()->timestamp().InMicroseconds() << "us.";
1591 DVLOG(1) << "Skipping splice: overlapped buffers begin at or after the "
1592 "first new buffer.";
1596 // If any |pre_splice_buffers| are already splices or preroll, do not generate
1598 for (size_t i
= 0; i
< pre_splice_buffers
.size(); ++i
) {
1599 const BufferQueue
& original_splice_buffers
=
1600 pre_splice_buffers
[i
]->splice_buffers();
1601 if (!original_splice_buffers
.empty()) {
1602 LIMITED_MEDIA_LOG(DEBUG
, media_log_
, num_splice_generation_warning_logs_
,
1603 kMaxSpliceGenerationWarningLogs
)
1604 << "Skipping splice frame generation: overlapped buffers at "
1605 << pre_splice_buffers
[i
]->timestamp().InMicroseconds()
1606 << "us are in a previously buffered splice.";
1607 DVLOG(1) << "Can't generate splice: overlapped buffers contain a "
1608 "pre-existing splice.";
1612 if (pre_splice_buffers
[i
]->preroll_buffer().get()) {
1613 LIMITED_MEDIA_LOG(DEBUG
, media_log_
, num_splice_generation_warning_logs_
,
1614 kMaxSpliceGenerationWarningLogs
)
1615 << "Skipping splice frame generation: overlapped buffers at "
1616 << pre_splice_buffers
[i
]->timestamp().InMicroseconds()
1617 << "us contain preroll.";
1618 DVLOG(1) << "Can't generate splice: overlapped buffers contain preroll.";
1623 // Don't generate splice frames which represent less than a millisecond (which
1624 // is frequently the extent of timestamp resolution for poorly encoded media)
1625 // or less than two samples (need at least two to crossfade).
1626 const base::TimeDelta splice_duration
=
1627 pre_splice_buffers
.back()->timestamp() +
1628 pre_splice_buffers
.back()->duration() - splice_timestamp
;
1629 const base::TimeDelta minimum_splice_duration
= std::max(
1630 base::TimeDelta::FromMilliseconds(1),
1631 base::TimeDelta::FromSecondsD(
1632 2.0 / audio_configs_
[append_config_index_
].samples_per_second()));
1633 if (splice_duration
< minimum_splice_duration
) {
1634 LIMITED_MEDIA_LOG(DEBUG
, media_log_
, num_splice_generation_warning_logs_
,
1635 kMaxSpliceGenerationWarningLogs
)
1636 << "Skipping splice frame generation: not enough samples for splicing "
1638 << splice_timestamp
.InMicroseconds() << "us. Have "
1639 << splice_duration
.InMicroseconds() << "us, but need "
1640 << minimum_splice_duration
.InMicroseconds() << "us.";
1641 DVLOG(1) << "Can't generate splice: not enough samples for crossfade; have "
1642 << splice_duration
.InMicroseconds() << "us, but need "
1643 << minimum_splice_duration
.InMicroseconds() << "us.";
1647 DVLOG(1) << "Generating splice frame @ " << new_buffers
.front()->timestamp()
1648 << ", splice duration: " << splice_duration
.InMicroseconds()
1650 LIMITED_MEDIA_LOG(DEBUG
, media_log_
, num_splice_generation_success_logs_
,
1651 kMaxSpliceGenerationSuccessLogs
)
1652 << "Generated splice of overlap duration "
1653 << splice_duration
.InMicroseconds() << "us into new buffer at "
1654 << splice_timestamp
.InMicroseconds() << "us.";
1655 new_buffers
.front()->ConvertToSpliceBuffer(pre_splice_buffers
);
1658 bool SourceBufferStream::SetPendingBuffer(
1659 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1660 DCHECK(out_buffer
->get());
1661 DCHECK(!pending_buffer_
.get());
1663 const bool have_splice_buffers
= !(*out_buffer
)->splice_buffers().empty();
1664 const bool have_preroll_buffer
= !!(*out_buffer
)->preroll_buffer().get();
1666 if (!have_splice_buffers
&& !have_preroll_buffer
)
1669 DCHECK_NE(have_splice_buffers
, have_preroll_buffer
);
1670 splice_buffers_index_
= 0;
1671 pending_buffer_
.swap(*out_buffer
);
1672 pending_buffers_complete_
= false;
1676 } // namespace media