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"
22 // An arbitrarily-chosen number to estimate the duration of a buffer if none is
23 // set and there's not enough information to get a better estimate.
24 const int kDefaultBufferDurationInMs
= 125;
26 // Limit the number of MEDIA_LOG() logs for splice buffer generation warnings
27 // and successes. Though these values are high enough to possibly exhaust the
28 // media internals event cache (along with other events), these logs are
29 // important for debugging splice generation.
30 const int kMaxSpliceGenerationWarningLogs
= 50;
31 const int kMaxSpliceGenerationSuccessLogs
= 20;
33 // Limit the number of MEDIA_LOG() logs for track buffer time gaps.
34 const int kMaxTrackBufferGapWarningLogs
= 20;
36 // Helper method that returns true if |ranges| is sorted in increasing order,
38 bool IsRangeListSorted(const std::list
<media::SourceBufferRange
*>& ranges
) {
39 DecodeTimestamp prev
= kNoDecodeTimestamp();
40 for (std::list
<SourceBufferRange
*>::const_iterator itr
=
41 ranges
.begin(); itr
!= ranges
.end(); ++itr
) {
42 if (prev
!= kNoDecodeTimestamp() && prev
>= (*itr
)->GetStartTimestamp())
44 prev
= (*itr
)->GetEndTimestamp();
49 // Returns an estimate of how far from the beginning or end of a range a buffer
50 // can be to still be considered in the range, given the |approximate_duration|
51 // of a buffer in the stream.
52 // TODO(wolenetz): Once all stream parsers emit accurate frame durations, use
53 // logic like FrameProcessor (2*last_frame_duration + last_decode_timestamp)
54 // instead of an overall maximum interbuffer delta for range discontinuity
55 // detection, and adjust similarly for splice frame discontinuity detection.
56 // See http://crbug.com/351489 and http://crbug.com/351166.
57 base::TimeDelta
ComputeFudgeRoom(base::TimeDelta approximate_duration
) {
58 // Because we do not know exactly when is the next timestamp, any buffer
59 // that starts within 2x the approximate duration of a buffer is considered
61 return 2 * approximate_duration
;
64 // The amount of time the beginning of the buffered data can differ from the
65 // start time in order to still be considered the start of stream.
66 base::TimeDelta
kSeekToStartFudgeRoom() {
67 return base::TimeDelta::FromMilliseconds(1000);
70 // Helper method for logging, converts a range into a readable string.
71 std::string
RangeToString(const SourceBufferRange
& range
) {
73 ss
<< "[" << range
.GetStartTimestamp().InSecondsF()
74 << ";" << range
.GetEndTimestamp().InSecondsF()
75 << "(" << range
.GetBufferedEndTimestamp().InSecondsF() << ")]";
79 // Helper method for logging, converts a set of ranges into a readable string.
80 std::string
RangesToString(const SourceBufferStream::RangeList
& ranges
) {
85 for (const auto* range_ptr
: ranges
) {
86 if (range_ptr
!= ranges
.front())
88 ss
<< RangeToString(*range_ptr
);
93 std::string
BufferQueueToLogString(
94 const SourceBufferStream::BufferQueue
& buffers
) {
95 std::stringstream result
;
96 if (buffers
.front()->GetDecodeTimestamp().InMicroseconds() ==
97 buffers
.front()->timestamp().InMicroseconds() &&
98 buffers
.back()->GetDecodeTimestamp().InMicroseconds() ==
99 buffers
.back()->timestamp().InMicroseconds()) {
100 result
<< "dts/pts=[" << buffers
.front()->timestamp().InSecondsF() << ";"
101 << buffers
.back()->timestamp().InSecondsF() << "(last frame dur="
102 << buffers
.back()->duration().InSecondsF() << ")]";
104 result
<< "dts=[" << buffers
.front()->GetDecodeTimestamp().InSecondsF()
105 << ";" << buffers
.back()->GetDecodeTimestamp().InSecondsF()
106 << "] pts=[" << buffers
.front()->timestamp().InSecondsF() << ";"
107 << buffers
.back()->timestamp().InSecondsF() << "(last frame dur="
108 << buffers
.back()->duration().InSecondsF() << ")]";
113 SourceBufferRange::GapPolicy
TypeToGapPolicy(SourceBufferStream::Type type
) {
115 case SourceBufferStream::kAudio
:
116 case SourceBufferStream::kVideo
:
117 return SourceBufferRange::NO_GAPS_ALLOWED
;
118 case SourceBufferStream::kText
:
119 return SourceBufferRange::ALLOW_GAPS
;
123 return SourceBufferRange::NO_GAPS_ALLOWED
;
128 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig
& audio_config
,
129 const scoped_refptr
<MediaLog
>& media_log
,
130 bool splice_frames_enabled
)
131 : media_log_(media_log
),
132 current_config_index_(0),
133 append_config_index_(0),
134 seek_pending_(false),
135 end_of_stream_(false),
136 seek_buffer_timestamp_(kNoTimestamp()),
137 selected_range_(NULL
),
138 just_exhausted_track_buffer_(false),
139 media_segment_start_time_(kNoDecodeTimestamp()),
140 range_for_next_append_(ranges_
.end()),
141 new_media_segment_(false),
142 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
143 last_appended_buffer_is_keyframe_(false),
144 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
145 max_interbuffer_distance_(kNoTimestamp()),
146 memory_limit_(kSourceBufferAudioMemoryLimit
),
147 config_change_pending_(false),
148 splice_buffers_index_(0),
149 pending_buffers_complete_(false),
150 splice_frames_enabled_(splice_frames_enabled
),
151 num_splice_generation_warning_logs_(0),
152 num_splice_generation_success_logs_(0),
153 num_track_buffer_gap_warning_logs_(0) {
154 DCHECK(audio_config
.IsValidConfig());
155 audio_configs_
.push_back(audio_config
);
158 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig
& video_config
,
159 const scoped_refptr
<MediaLog
>& media_log
,
160 bool splice_frames_enabled
)
161 : media_log_(media_log
),
162 current_config_index_(0),
163 append_config_index_(0),
164 seek_pending_(false),
165 end_of_stream_(false),
166 seek_buffer_timestamp_(kNoTimestamp()),
167 selected_range_(NULL
),
168 just_exhausted_track_buffer_(false),
169 media_segment_start_time_(kNoDecodeTimestamp()),
170 range_for_next_append_(ranges_
.end()),
171 new_media_segment_(false),
172 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
173 last_appended_buffer_is_keyframe_(false),
174 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
175 max_interbuffer_distance_(kNoTimestamp()),
176 memory_limit_(kSourceBufferVideoMemoryLimit
),
177 config_change_pending_(false),
178 splice_buffers_index_(0),
179 pending_buffers_complete_(false),
180 splice_frames_enabled_(splice_frames_enabled
),
181 num_splice_generation_warning_logs_(0),
182 num_splice_generation_success_logs_(0),
183 num_track_buffer_gap_warning_logs_(0) {
184 DCHECK(video_config
.IsValidConfig());
185 video_configs_
.push_back(video_config
);
188 SourceBufferStream::SourceBufferStream(const TextTrackConfig
& text_config
,
189 const scoped_refptr
<MediaLog
>& media_log
,
190 bool splice_frames_enabled
)
191 : media_log_(media_log
),
192 current_config_index_(0),
193 append_config_index_(0),
194 text_track_config_(text_config
),
195 seek_pending_(false),
196 end_of_stream_(false),
197 seek_buffer_timestamp_(kNoTimestamp()),
198 selected_range_(NULL
),
199 just_exhausted_track_buffer_(false),
200 media_segment_start_time_(kNoDecodeTimestamp()),
201 range_for_next_append_(ranges_
.end()),
202 new_media_segment_(false),
203 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
204 last_appended_buffer_is_keyframe_(false),
205 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
206 max_interbuffer_distance_(kNoTimestamp()),
207 memory_limit_(kSourceBufferAudioMemoryLimit
),
208 config_change_pending_(false),
209 splice_buffers_index_(0),
210 pending_buffers_complete_(false),
211 splice_frames_enabled_(splice_frames_enabled
),
212 num_splice_generation_warning_logs_(0),
213 num_splice_generation_success_logs_(0),
214 num_track_buffer_gap_warning_logs_(0) {}
216 SourceBufferStream::~SourceBufferStream() {
217 while (!ranges_
.empty()) {
218 delete ranges_
.front();
223 void SourceBufferStream::OnNewMediaSegment(
224 DecodeTimestamp media_segment_start_time
) {
225 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
226 << " (" << media_segment_start_time
.InSecondsF() << ")";
227 DCHECK(!end_of_stream_
);
228 media_segment_start_time_
= media_segment_start_time
;
229 new_media_segment_
= true;
231 RangeList::iterator last_range
= range_for_next_append_
;
232 range_for_next_append_
= FindExistingRangeFor(media_segment_start_time
);
234 // Only reset |last_appended_buffer_timestamp_| if this new media segment is
235 // not adjacent to the previous media segment appended to the stream.
236 if (range_for_next_append_
== ranges_
.end() ||
237 !AreAdjacentInSequence(last_appended_buffer_timestamp_
,
238 media_segment_start_time
)) {
239 last_appended_buffer_timestamp_
= kNoDecodeTimestamp();
240 last_appended_buffer_is_keyframe_
= false;
241 DVLOG(3) << __FUNCTION__
<< " next appended buffers will be in a new range";
242 } else if (last_range
!= ranges_
.end()) {
243 DCHECK(last_range
== range_for_next_append_
);
244 DVLOG(3) << __FUNCTION__
<< " next appended buffers will continue range "
245 << "unless intervening remove makes discontinuity";
249 bool SourceBufferStream::Append(const BufferQueue
& buffers
) {
250 TRACE_EVENT2("media", "SourceBufferStream::Append",
251 "stream type", GetStreamTypeName(),
252 "buffers to append", buffers
.size());
254 DCHECK(!buffers
.empty());
255 DCHECK(media_segment_start_time_
!= kNoDecodeTimestamp());
256 DCHECK(media_segment_start_time_
<= buffers
.front()->GetDecodeTimestamp());
257 DCHECK(!end_of_stream_
);
259 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
260 << ": buffers " << BufferQueueToLogString(buffers
);
262 // New media segments must begin with a keyframe.
263 // TODO(wolenetz): Relax this requirement. See http://crbug.com/229412.
264 if (new_media_segment_
&& !buffers
.front()->is_key_frame()) {
265 MEDIA_LOG(ERROR
, media_log_
) << "Media segment did not begin with key "
266 "frame. Support for such segments will be "
267 "available in a future version. Please see "
268 "https://crbug.com/229412.";
272 // Buffers within a media segment should be monotonically increasing.
273 if (!IsMonotonicallyIncreasing(buffers
))
276 if (media_segment_start_time_
< DecodeTimestamp() ||
277 buffers
.front()->GetDecodeTimestamp() < DecodeTimestamp()) {
278 MEDIA_LOG(ERROR
, media_log_
)
279 << "Cannot append a media segment with negative timestamps.";
283 if (!IsNextTimestampValid(buffers
.front()->GetDecodeTimestamp(),
284 buffers
.front()->is_key_frame())) {
285 const DecodeTimestamp
& dts
= buffers
.front()->GetDecodeTimestamp();
286 MEDIA_LOG(ERROR
, media_log_
)
287 << "Invalid same timestamp construct detected at"
288 << " time " << dts
.InSecondsF();
293 UpdateMaxInterbufferDistance(buffers
);
294 SetConfigIds(buffers
);
296 // Save a snapshot of stream state before range modifications are made.
297 DecodeTimestamp next_buffer_timestamp
= GetNextBufferTimestamp();
298 BufferQueue deleted_buffers
;
300 PrepareRangesForNextAppend(buffers
, &deleted_buffers
);
302 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise,
303 // create a new range with |buffers|.
304 if (range_for_next_append_
!= ranges_
.end()) {
305 (*range_for_next_append_
)->AppendBuffersToEnd(buffers
);
306 last_appended_buffer_timestamp_
= buffers
.back()->GetDecodeTimestamp();
307 last_appended_buffer_is_keyframe_
= buffers
.back()->is_key_frame();
309 DecodeTimestamp new_range_start_time
= std::min(
310 media_segment_start_time_
, buffers
.front()->GetDecodeTimestamp());
311 const BufferQueue
* buffers_for_new_range
= &buffers
;
312 BufferQueue trimmed_buffers
;
314 // If the new range is not being created because of a new media
315 // segment, then we must make sure that we start with a key frame.
316 // This can happen if the GOP in the previous append gets destroyed
317 // by a Remove() call.
318 if (!new_media_segment_
) {
319 BufferQueue::const_iterator itr
= buffers
.begin();
321 // Scan past all the non-key-frames.
322 while (itr
!= buffers
.end() && !(*itr
)->is_key_frame()) {
326 // If we didn't find a key frame, then update the last appended
327 // buffer state and return.
328 if (itr
== buffers
.end()) {
329 last_appended_buffer_timestamp_
= buffers
.back()->GetDecodeTimestamp();
330 last_appended_buffer_is_keyframe_
= buffers
.back()->is_key_frame();
331 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
332 << ": new buffers in the middle of media segment depend on"
333 "keyframe that has been removed, and contain no keyframes."
334 "Skipping further processing.";
335 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
336 << ": done. ranges_=" << RangesToString(ranges_
);
338 } else if (itr
!= buffers
.begin()) {
339 // Copy the first key frame and everything after it into
340 // |trimmed_buffers|.
341 trimmed_buffers
.assign(itr
, buffers
.end());
342 buffers_for_new_range
= &trimmed_buffers
;
345 new_range_start_time
=
346 buffers_for_new_range
->front()->GetDecodeTimestamp();
349 range_for_next_append_
=
350 AddToRanges(new SourceBufferRange(
351 TypeToGapPolicy(GetType()),
352 *buffers_for_new_range
, new_range_start_time
,
353 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance
,
354 base::Unretained(this))));
355 last_appended_buffer_timestamp_
=
356 buffers_for_new_range
->back()->GetDecodeTimestamp();
357 last_appended_buffer_is_keyframe_
=
358 buffers_for_new_range
->back()->is_key_frame();
361 new_media_segment_
= false;
363 MergeWithAdjacentRangeIfNecessary(range_for_next_append_
);
365 // Seek to try to fulfill a previous call to Seek().
367 DCHECK(!selected_range_
);
368 DCHECK(deleted_buffers
.empty());
369 Seek(seek_buffer_timestamp_
);
372 if (!deleted_buffers
.empty()) {
373 DecodeTimestamp start_of_deleted
=
374 deleted_buffers
.front()->GetDecodeTimestamp();
376 DCHECK(track_buffer_
.empty() ||
377 track_buffer_
.back()->GetDecodeTimestamp() < start_of_deleted
)
378 << "decode timestamp "
379 << track_buffer_
.back()->GetDecodeTimestamp().InSecondsF() << " sec"
380 << ", start_of_deleted " << start_of_deleted
.InSecondsF()<< " sec";
382 track_buffer_
.insert(track_buffer_
.end(), deleted_buffers
.begin(),
383 deleted_buffers
.end());
384 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName() << " Added "
385 << deleted_buffers
.size()
386 << " buffers to track buffer. TB size is now "
387 << track_buffer_
.size();
389 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
390 << " No deleted buffers for track buffer";
393 // Prune any extra buffers in |track_buffer_| if new keyframes
394 // are appended to the range covered by |track_buffer_|.
395 if (!track_buffer_
.empty()) {
396 DecodeTimestamp keyframe_timestamp
=
397 FindKeyframeAfterTimestamp(track_buffer_
.front()->GetDecodeTimestamp());
398 if (keyframe_timestamp
!= kNoDecodeTimestamp())
399 PruneTrackBuffer(keyframe_timestamp
);
402 SetSelectedRangeIfNeeded(next_buffer_timestamp
);
404 GarbageCollectIfNeeded();
406 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
407 << ": done. ranges_=" << RangesToString(ranges_
);
408 DCHECK(IsRangeListSorted(ranges_
));
409 DCHECK(OnlySelectedRangeIsSeeked());
413 void SourceBufferStream::Remove(base::TimeDelta start
, base::TimeDelta end
,
414 base::TimeDelta duration
) {
415 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
416 << " (" << start
.InSecondsF() << ", " << end
.InSecondsF()
417 << ", " << duration
.InSecondsF() << ")";
418 DCHECK(start
>= base::TimeDelta()) << start
.InSecondsF();
419 DCHECK(start
< end
) << "start " << start
.InSecondsF()
420 << " end " << end
.InSecondsF();
421 DCHECK(duration
!= kNoTimestamp());
423 DecodeTimestamp start_dts
= DecodeTimestamp::FromPresentationTime(start
);
424 DecodeTimestamp end_dts
= DecodeTimestamp::FromPresentationTime(end
);
425 DecodeTimestamp remove_end_timestamp
=
426 DecodeTimestamp::FromPresentationTime(duration
);
427 DecodeTimestamp keyframe_timestamp
= FindKeyframeAfterTimestamp(end_dts
);
428 if (keyframe_timestamp
!= kNoDecodeTimestamp()) {
429 remove_end_timestamp
= keyframe_timestamp
;
430 } else if (end_dts
< remove_end_timestamp
) {
431 remove_end_timestamp
= end_dts
;
434 BufferQueue deleted_buffers
;
435 RemoveInternal(start_dts
, remove_end_timestamp
, false, &deleted_buffers
);
437 if (!deleted_buffers
.empty()) {
438 // Buffers for the current position have been removed.
439 SetSelectedRangeIfNeeded(deleted_buffers
.front()->GetDecodeTimestamp());
440 if (last_output_buffer_timestamp_
== kNoDecodeTimestamp()) {
441 // We just removed buffers for the current playback position for this
442 // stream, yet we also had output no buffer since the last Seek.
443 // Re-seek to prevent stall.
444 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
445 << ": re-seeking to " << seek_buffer_timestamp_
446 << " to prevent stall if this time becomes buffered again";
447 Seek(seek_buffer_timestamp_
);
452 void SourceBufferStream::RemoveInternal(DecodeTimestamp start
,
455 BufferQueue
* deleted_buffers
) {
456 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName() << " ("
457 << start
.InSecondsF() << ", " << end
.InSecondsF() << ", "
458 << exclude_start
<< ")";
459 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
460 << ": before remove ranges_=" << RangesToString(ranges_
);
462 DCHECK(start
>= DecodeTimestamp());
463 DCHECK(start
< end
) << "start " << start
.InSecondsF()
464 << " end " << end
.InSecondsF();
465 DCHECK(deleted_buffers
);
467 RangeList::iterator itr
= ranges_
.begin();
469 while (itr
!= ranges_
.end()) {
470 SourceBufferRange
* range
= *itr
;
471 if (range
->GetStartTimestamp() >= end
)
474 // Split off any remaining GOPs starting at or after |end| and add it to
476 SourceBufferRange
* new_range
= range
->SplitRange(end
);
478 itr
= ranges_
.insert(++itr
, new_range
);
481 // Update the selected range if the next buffer position was transferred
483 if (new_range
->HasNextBufferPosition())
484 SetSelectedRange(new_range
);
487 // Truncate the current range so that it only contains data before
488 // the removal range.
489 BufferQueue saved_buffers
;
490 bool delete_range
= range
->TruncateAt(start
, &saved_buffers
, exclude_start
);
492 // Check to see if the current playback position was removed and
493 // update the selected range appropriately.
494 if (!saved_buffers
.empty()) {
495 DCHECK(!range
->HasNextBufferPosition());
496 DCHECK(deleted_buffers
->empty());
498 *deleted_buffers
= saved_buffers
;
501 if (range
== selected_range_
&& !range
->HasNextBufferPosition())
502 SetSelectedRange(NULL
);
504 // If the current range now is completely covered by the removal
505 // range then delete it and move on.
507 DeleteAndRemoveRange(&itr
);
511 // Clear |range_for_next_append_| if we determine that the removal
512 // operation makes it impossible for the next append to be added
513 // to the current range.
514 if (range_for_next_append_
!= ranges_
.end() &&
515 *range_for_next_append_
== range
&&
516 last_appended_buffer_timestamp_
!= kNoDecodeTimestamp()) {
517 DecodeTimestamp potential_next_append_timestamp
=
518 last_appended_buffer_timestamp_
+
519 base::TimeDelta::FromInternalValue(1);
521 if (!range
->BelongsToRange(potential_next_append_timestamp
)) {
522 DVLOG(1) << "Resetting range_for_next_append_ since the next append"
523 << " can't add to the current range.";
524 range_for_next_append_
=
525 FindExistingRangeFor(potential_next_append_timestamp
);
529 // Move on to the next range.
533 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
534 << ": after remove ranges_=" << RangesToString(ranges_
);
536 DCHECK(IsRangeListSorted(ranges_
));
537 DCHECK(OnlySelectedRangeIsSeeked());
540 void SourceBufferStream::ResetSeekState() {
541 SetSelectedRange(NULL
);
542 track_buffer_
.clear();
543 config_change_pending_
= false;
544 last_output_buffer_timestamp_
= kNoDecodeTimestamp();
545 just_exhausted_track_buffer_
= false;
546 splice_buffers_index_
= 0;
547 pending_buffer_
= NULL
;
548 pending_buffers_complete_
= false;
551 bool SourceBufferStream::ShouldSeekToStartOfBuffered(
552 base::TimeDelta seek_timestamp
) const {
555 base::TimeDelta beginning_of_buffered
=
556 ranges_
.front()->GetStartTimestamp().ToPresentationTime();
557 return (seek_timestamp
<= beginning_of_buffered
&&
558 beginning_of_buffered
< kSeekToStartFudgeRoom());
561 bool SourceBufferStream::IsMonotonicallyIncreasing(
562 const BufferQueue
& buffers
) const {
563 DCHECK(!buffers
.empty());
564 DecodeTimestamp prev_timestamp
= last_appended_buffer_timestamp_
;
565 bool prev_is_keyframe
= last_appended_buffer_is_keyframe_
;
566 for (BufferQueue::const_iterator itr
= buffers
.begin();
567 itr
!= buffers
.end(); ++itr
) {
568 DecodeTimestamp current_timestamp
= (*itr
)->GetDecodeTimestamp();
569 bool current_is_keyframe
= (*itr
)->is_key_frame();
570 DCHECK(current_timestamp
!= kNoDecodeTimestamp());
571 DCHECK((*itr
)->duration() >= base::TimeDelta())
572 << "Packet with invalid duration."
573 << " pts " << (*itr
)->timestamp().InSecondsF()
574 << " dts " << (*itr
)->GetDecodeTimestamp().InSecondsF()
575 << " dur " << (*itr
)->duration().InSecondsF();
577 if (prev_timestamp
!= kNoDecodeTimestamp()) {
578 if (current_timestamp
< prev_timestamp
) {
579 MEDIA_LOG(ERROR
, media_log_
)
580 << "Buffers did not monotonically increase.";
584 if (current_timestamp
== prev_timestamp
&&
585 !SourceBufferRange::AllowSameTimestamp(prev_is_keyframe
,
586 current_is_keyframe
)) {
587 MEDIA_LOG(ERROR
, media_log_
) << "Unexpected combination of buffers with"
588 << " the same timestamp detected at "
589 << current_timestamp
.InSecondsF();
594 prev_timestamp
= current_timestamp
;
595 prev_is_keyframe
= current_is_keyframe
;
600 bool SourceBufferStream::IsNextTimestampValid(
601 DecodeTimestamp next_timestamp
, bool next_is_keyframe
) const {
602 return (last_appended_buffer_timestamp_
!= next_timestamp
) ||
603 new_media_segment_
||
604 SourceBufferRange::AllowSameTimestamp(last_appended_buffer_is_keyframe_
,
609 bool SourceBufferStream::OnlySelectedRangeIsSeeked() const {
610 for (RangeList::const_iterator itr
= ranges_
.begin();
611 itr
!= ranges_
.end(); ++itr
) {
612 if ((*itr
)->HasNextBufferPosition() && (*itr
) != selected_range_
)
615 return !selected_range_
|| selected_range_
->HasNextBufferPosition();
618 void SourceBufferStream::UpdateMaxInterbufferDistance(
619 const BufferQueue
& buffers
) {
620 DCHECK(!buffers
.empty());
621 DecodeTimestamp prev_timestamp
= last_appended_buffer_timestamp_
;
622 for (BufferQueue::const_iterator itr
= buffers
.begin();
623 itr
!= buffers
.end(); ++itr
) {
624 DecodeTimestamp current_timestamp
= (*itr
)->GetDecodeTimestamp();
625 DCHECK(current_timestamp
!= kNoDecodeTimestamp());
627 base::TimeDelta interbuffer_distance
= (*itr
)->duration();
628 DCHECK(interbuffer_distance
>= base::TimeDelta());
630 if (prev_timestamp
!= kNoDecodeTimestamp()) {
631 interbuffer_distance
=
632 std::max(current_timestamp
- prev_timestamp
, interbuffer_distance
);
635 if (interbuffer_distance
> base::TimeDelta()) {
636 if (max_interbuffer_distance_
== kNoTimestamp()) {
637 max_interbuffer_distance_
= interbuffer_distance
;
639 max_interbuffer_distance_
=
640 std::max(max_interbuffer_distance_
, interbuffer_distance
);
643 prev_timestamp
= current_timestamp
;
647 void SourceBufferStream::SetConfigIds(const BufferQueue
& buffers
) {
648 for (BufferQueue::const_iterator itr
= buffers
.begin();
649 itr
!= buffers
.end(); ++itr
) {
650 (*itr
)->SetConfigId(append_config_index_
);
654 void SourceBufferStream::GarbageCollectIfNeeded() {
655 // Compute size of |ranges_|.
656 size_t ranges_size
= 0;
657 for (RangeList::iterator itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
)
658 ranges_size
+= (*itr
)->size_in_bytes();
660 // Return if we're under or at the memory limit.
661 if (ranges_size
<= memory_limit_
)
664 size_t bytes_to_free
= ranges_size
- memory_limit_
;
666 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName() << ": Before GC"
667 << " ranges_size=" << ranges_size
668 << " ranges_=" << RangesToString(ranges_
)
669 << " memory_limit_=" << memory_limit_
;
671 // Begin deleting after the last appended buffer.
672 size_t bytes_freed
= FreeBuffersAfterLastAppended(bytes_to_free
);
674 // Begin deleting from the front.
675 if (bytes_freed
< bytes_to_free
)
676 bytes_freed
+= FreeBuffers(bytes_to_free
- bytes_freed
, false);
678 // Begin deleting from the back.
679 if (bytes_freed
< bytes_to_free
)
680 bytes_freed
+= FreeBuffers(bytes_to_free
- bytes_freed
, true);
682 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName() << ": After GC"
683 << " bytes_freed=" << bytes_freed
684 << " ranges_=" << RangesToString(ranges_
);
687 size_t SourceBufferStream::FreeBuffersAfterLastAppended(
688 size_t total_bytes_to_free
) {
689 DecodeTimestamp next_buffer_timestamp
= GetNextBufferTimestamp();
690 if (last_appended_buffer_timestamp_
== kNoDecodeTimestamp() ||
691 next_buffer_timestamp
== kNoDecodeTimestamp() ||
692 last_appended_buffer_timestamp_
>= next_buffer_timestamp
) {
696 DecodeTimestamp remove_range_start
= last_appended_buffer_timestamp_
;
697 if (last_appended_buffer_is_keyframe_
)
698 remove_range_start
+= GetMaxInterbufferDistance();
700 DecodeTimestamp remove_range_start_keyframe
= FindKeyframeAfterTimestamp(
702 if (remove_range_start_keyframe
!= kNoDecodeTimestamp())
703 remove_range_start
= remove_range_start_keyframe
;
704 if (remove_range_start
>= next_buffer_timestamp
)
707 DecodeTimestamp remove_range_end
;
708 size_t bytes_freed
= GetRemovalRange(remove_range_start
,
709 next_buffer_timestamp
,
712 if (bytes_freed
> 0) {
713 Remove(remove_range_start
.ToPresentationTime(),
714 remove_range_end
.ToPresentationTime(),
715 next_buffer_timestamp
.ToPresentationTime());
721 size_t SourceBufferStream::GetRemovalRange(
722 DecodeTimestamp start_timestamp
, DecodeTimestamp end_timestamp
,
723 size_t total_bytes_to_free
, DecodeTimestamp
* removal_end_timestamp
) {
724 DCHECK(start_timestamp
>= DecodeTimestamp()) << start_timestamp
.InSecondsF();
725 DCHECK(start_timestamp
< end_timestamp
)
726 << "start " << start_timestamp
.InSecondsF()
727 << ", end " << end_timestamp
.InSecondsF();
729 size_t bytes_freed
= 0;
731 for (RangeList::iterator itr
= ranges_
.begin();
732 itr
!= ranges_
.end() && bytes_freed
< total_bytes_to_free
; ++itr
) {
733 SourceBufferRange
* range
= *itr
;
734 if (range
->GetStartTimestamp() >= end_timestamp
)
736 if (range
->GetEndTimestamp() < start_timestamp
)
739 size_t bytes_to_free
= total_bytes_to_free
- bytes_freed
;
740 size_t bytes_removed
= range
->GetRemovalGOP(
741 start_timestamp
, end_timestamp
, bytes_to_free
, removal_end_timestamp
);
742 bytes_freed
+= bytes_removed
;
747 size_t SourceBufferStream::FreeBuffers(size_t total_bytes_to_free
,
748 bool reverse_direction
) {
749 TRACE_EVENT2("media", "SourceBufferStream::FreeBuffers",
750 "total bytes to free", total_bytes_to_free
,
751 "reverse direction", reverse_direction
);
753 DCHECK_GT(total_bytes_to_free
, 0u);
754 size_t bytes_freed
= 0;
756 // This range will save the last GOP appended to |range_for_next_append_|
757 // if the buffers surrounding it get deleted during garbage collection.
758 SourceBufferRange
* new_range_for_append
= NULL
;
760 while (!ranges_
.empty() && bytes_freed
< total_bytes_to_free
) {
761 SourceBufferRange
* current_range
= NULL
;
763 size_t bytes_deleted
= 0;
765 if (reverse_direction
) {
766 current_range
= ranges_
.back();
767 if (current_range
->LastGOPContainsNextBufferPosition()) {
768 DCHECK_EQ(current_range
, selected_range_
);
771 bytes_deleted
= current_range
->DeleteGOPFromBack(&buffers
);
773 current_range
= ranges_
.front();
774 if (current_range
->FirstGOPContainsNextBufferPosition()) {
775 DCHECK_EQ(current_range
, selected_range_
);
778 bytes_deleted
= current_range
->DeleteGOPFromFront(&buffers
);
781 // Check to see if we've just deleted the GOP that was last appended.
782 DecodeTimestamp end_timestamp
= buffers
.back()->GetDecodeTimestamp();
783 if (end_timestamp
== last_appended_buffer_timestamp_
) {
784 DCHECK(last_appended_buffer_timestamp_
!= kNoDecodeTimestamp());
785 DCHECK(!new_range_for_append
);
786 // Create a new range containing these buffers.
787 new_range_for_append
= new SourceBufferRange(
788 TypeToGapPolicy(GetType()),
789 buffers
, kNoDecodeTimestamp(),
790 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance
,
791 base::Unretained(this)));
792 range_for_next_append_
= ranges_
.end();
794 bytes_freed
+= bytes_deleted
;
797 if (current_range
->size_in_bytes() == 0) {
798 DCHECK_NE(current_range
, selected_range_
);
799 DCHECK(range_for_next_append_
== ranges_
.end() ||
800 *range_for_next_append_
!= current_range
);
801 delete current_range
;
802 reverse_direction
? ranges_
.pop_back() : ranges_
.pop_front();
806 // Insert |new_range_for_append| into |ranges_|, if applicable.
807 if (new_range_for_append
) {
808 range_for_next_append_
= AddToRanges(new_range_for_append
);
809 DCHECK(range_for_next_append_
!= ranges_
.end());
811 // Check to see if we need to merge |new_range_for_append| with the range
812 // before or after it. |new_range_for_append| is created whenever the last
813 // GOP appended is encountered, regardless of whether any buffers after it
814 // are ultimately deleted. Merging is necessary if there were no buffers
815 // (or very few buffers) deleted after creating |new_range_for_append|.
816 if (range_for_next_append_
!= ranges_
.begin()) {
817 RangeList::iterator range_before_next
= range_for_next_append_
;
819 MergeWithAdjacentRangeIfNecessary(range_before_next
);
821 MergeWithAdjacentRangeIfNecessary(range_for_next_append_
);
826 void SourceBufferStream::PrepareRangesForNextAppend(
827 const BufferQueue
& new_buffers
, BufferQueue
* deleted_buffers
) {
828 DCHECK(deleted_buffers
);
830 bool temporarily_select_range
= false;
831 if (!track_buffer_
.empty()) {
832 DecodeTimestamp tb_timestamp
= track_buffer_
.back()->GetDecodeTimestamp();
833 DecodeTimestamp seek_timestamp
= FindKeyframeAfterTimestamp(tb_timestamp
);
834 if (seek_timestamp
!= kNoDecodeTimestamp() &&
835 seek_timestamp
< new_buffers
.front()->GetDecodeTimestamp() &&
836 range_for_next_append_
!= ranges_
.end() &&
837 (*range_for_next_append_
)->BelongsToRange(seek_timestamp
)) {
838 DCHECK(tb_timestamp
< seek_timestamp
);
839 DCHECK(!selected_range_
);
840 DCHECK(!(*range_for_next_append_
)->HasNextBufferPosition());
842 // If there are GOPs between the end of the track buffer and the
843 // beginning of the new buffers, then temporarily seek the range
844 // so that the buffers between these two times will be deposited in
845 // |deleted_buffers| as if they were part of the current playback
847 // TODO(acolwell): Figure out a more elegant way to do this.
848 SeekAndSetSelectedRange(*range_for_next_append_
, seek_timestamp
);
849 temporarily_select_range
= true;
853 // Handle splices between the existing buffers and the new buffers. If a
854 // splice is generated the timestamp and duration of the first buffer in
855 // |new_buffers| will be modified.
856 if (splice_frames_enabled_
)
857 GenerateSpliceFrame(new_buffers
);
859 DecodeTimestamp prev_timestamp
= last_appended_buffer_timestamp_
;
860 bool prev_is_keyframe
= last_appended_buffer_is_keyframe_
;
861 DecodeTimestamp next_timestamp
= new_buffers
.front()->GetDecodeTimestamp();
862 bool next_is_keyframe
= new_buffers
.front()->is_key_frame();
864 if (prev_timestamp
!= kNoDecodeTimestamp() &&
865 prev_timestamp
!= next_timestamp
) {
866 // Clean up the old buffers between the last appended buffer and the
867 // beginning of |new_buffers|.
868 RemoveInternal(prev_timestamp
, next_timestamp
, true, deleted_buffers
);
871 // Make the delete range exclusive if we are dealing with an allowed same
872 // timestamp situation. This prevents the first buffer in the current append
873 // from deleting the last buffer in the previous append if both buffers
874 // have the same timestamp.
876 // The delete range should never be exclusive if a splice frame was generated
877 // because we don't generate splice frames for same timestamp situations.
878 DCHECK(new_buffers
.front()->splice_timestamp() !=
879 new_buffers
.front()->timestamp());
880 const bool exclude_start
=
881 new_buffers
.front()->splice_buffers().empty() &&
882 prev_timestamp
== next_timestamp
&&
883 SourceBufferRange::AllowSameTimestamp(prev_is_keyframe
, next_is_keyframe
);
885 // Delete the buffers that |new_buffers| overlaps.
886 DecodeTimestamp start
= new_buffers
.front()->GetDecodeTimestamp();
887 DecodeTimestamp end
= new_buffers
.back()->GetDecodeTimestamp();
888 base::TimeDelta duration
= new_buffers
.back()->duration();
890 // Set end time for remove to include the duration of last buffer. If the
891 // duration is estimated, use 1 microsecond instead to ensure frames are not
892 // accidentally removed due to over-estimation.
893 if (duration
!= kNoTimestamp() && duration
> base::TimeDelta() &&
894 !new_buffers
.back()->is_duration_estimated()) {
897 // TODO(chcunningham): Emit warning when 0ms durations are not expected.
898 // http://crbug.com/312836
899 end
+= base::TimeDelta::FromInternalValue(1);
902 RemoveInternal(start
, end
, exclude_start
, deleted_buffers
);
904 // Restore the range seek state if necessary.
905 if (temporarily_select_range
)
906 SetSelectedRange(NULL
);
909 bool SourceBufferStream::AreAdjacentInSequence(
910 DecodeTimestamp first_timestamp
, DecodeTimestamp second_timestamp
) const {
911 return first_timestamp
< second_timestamp
&&
913 first_timestamp
+ ComputeFudgeRoom(GetMaxInterbufferDistance());
916 void SourceBufferStream::PruneTrackBuffer(const DecodeTimestamp timestamp
) {
917 // If we don't have the next timestamp, we don't have anything to delete.
918 if (timestamp
== kNoDecodeTimestamp())
921 while (!track_buffer_
.empty() &&
922 track_buffer_
.back()->GetDecodeTimestamp() >= timestamp
) {
923 track_buffer_
.pop_back();
925 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
926 << " Removed all buffers with DTS >= " << timestamp
.InSecondsF()
927 << ". New track buffer size:" << track_buffer_
.size();
930 void SourceBufferStream::MergeWithAdjacentRangeIfNecessary(
931 const RangeList::iterator
& range_with_new_buffers_itr
) {
932 DCHECK(range_with_new_buffers_itr
!= ranges_
.end());
934 SourceBufferRange
* range_with_new_buffers
= *range_with_new_buffers_itr
;
935 RangeList::iterator next_range_itr
= range_with_new_buffers_itr
;
938 if (next_range_itr
== ranges_
.end() ||
939 !range_with_new_buffers
->CanAppendRangeToEnd(**next_range_itr
)) {
943 bool transfer_current_position
= selected_range_
== *next_range_itr
;
944 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
945 << " merging " << RangeToString(*range_with_new_buffers
)
946 << " into " << RangeToString(**next_range_itr
);
947 range_with_new_buffers
->AppendRangeToEnd(**next_range_itr
,
948 transfer_current_position
);
949 // Update |selected_range_| pointer if |range| has become selected after
951 if (transfer_current_position
)
952 SetSelectedRange(range_with_new_buffers
);
954 if (next_range_itr
== range_for_next_append_
)
955 range_for_next_append_
= range_with_new_buffers_itr
;
957 DeleteAndRemoveRange(&next_range_itr
);
960 void SourceBufferStream::Seek(base::TimeDelta timestamp
) {
961 DCHECK(timestamp
>= base::TimeDelta());
962 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
963 << " (" << timestamp
.InSecondsF() << ")";
966 seek_buffer_timestamp_
= timestamp
;
967 seek_pending_
= true;
969 if (ShouldSeekToStartOfBuffered(timestamp
)) {
970 ranges_
.front()->SeekToStart();
971 SetSelectedRange(ranges_
.front());
972 seek_pending_
= false;
976 DecodeTimestamp seek_dts
= DecodeTimestamp::FromPresentationTime(timestamp
);
978 RangeList::iterator itr
= ranges_
.end();
979 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
980 if ((*itr
)->CanSeekTo(seek_dts
))
984 if (itr
== ranges_
.end())
987 SeekAndSetSelectedRange(*itr
, seek_dts
);
988 seek_pending_
= false;
991 bool SourceBufferStream::IsSeekPending() const {
992 return seek_pending_
&& !IsEndOfStreamReached();
995 void SourceBufferStream::OnSetDuration(base::TimeDelta duration
) {
996 DecodeTimestamp duration_dts
=
997 DecodeTimestamp::FromPresentationTime(duration
);
998 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
999 << " (" << duration
.InSecondsF() << ")";
1001 RangeList::iterator itr
= ranges_
.end();
1002 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1003 if ((*itr
)->GetEndTimestamp() > duration_dts
)
1006 if (itr
== ranges_
.end())
1009 // Need to partially truncate this range.
1010 if ((*itr
)->GetStartTimestamp() < duration_dts
) {
1011 bool delete_range
= (*itr
)->TruncateAt(duration_dts
, NULL
, false);
1012 if ((*itr
== selected_range_
) && !selected_range_
->HasNextBufferPosition())
1013 SetSelectedRange(NULL
);
1016 DeleteAndRemoveRange(&itr
);
1022 // Delete all ranges that begin after |duration_dts|.
1023 while (itr
!= ranges_
.end()) {
1024 // If we're about to delete the selected range, also reset the seek state.
1025 DCHECK((*itr
)->GetStartTimestamp() >= duration_dts
);
1026 if (*itr
== selected_range_
)
1028 DeleteAndRemoveRange(&itr
);
1032 SourceBufferStream::Status
SourceBufferStream::GetNextBuffer(
1033 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1034 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName();
1035 if (!pending_buffer_
.get()) {
1036 const SourceBufferStream::Status status
= GetNextBufferInternal(out_buffer
);
1037 if (status
!= SourceBufferStream::kSuccess
||
1038 !SetPendingBuffer(out_buffer
)) {
1039 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1040 << ": no pending buffer, returning status " << status
;
1045 if (!pending_buffer_
->splice_buffers().empty()) {
1046 const SourceBufferStream::Status status
=
1047 HandleNextBufferWithSplice(out_buffer
);
1048 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1049 << ": handled next buffer with splice, returning status "
1054 DCHECK(pending_buffer_
->preroll_buffer().get());
1056 const SourceBufferStream::Status status
=
1057 HandleNextBufferWithPreroll(out_buffer
);
1058 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1059 << ": handled next buffer with preroll, returning status "
1064 SourceBufferStream::Status
SourceBufferStream::HandleNextBufferWithSplice(
1065 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1066 const BufferQueue
& splice_buffers
= pending_buffer_
->splice_buffers();
1067 const size_t last_splice_buffer_index
= splice_buffers
.size() - 1;
1069 // Are there any splice buffers left to hand out? The last buffer should be
1070 // handed out separately since it represents the first post-splice buffer.
1071 if (splice_buffers_index_
< last_splice_buffer_index
) {
1072 // Account for config changes which occur between fade out buffers.
1073 if (current_config_index_
!=
1074 splice_buffers
[splice_buffers_index_
]->GetConfigId()) {
1075 config_change_pending_
= true;
1076 DVLOG(1) << "Config change (splice buffer config ID does not match).";
1077 return SourceBufferStream::kConfigChange
;
1080 // Every pre splice buffer must have the same splice_timestamp().
1081 DCHECK(pending_buffer_
->splice_timestamp() ==
1082 splice_buffers
[splice_buffers_index_
]->splice_timestamp());
1084 // No pre splice buffers should have preroll.
1085 DCHECK(!splice_buffers
[splice_buffers_index_
]->preroll_buffer().get());
1087 *out_buffer
= splice_buffers
[splice_buffers_index_
++];
1088 return SourceBufferStream::kSuccess
;
1091 // Did we hand out the last pre-splice buffer on the previous call?
1092 if (!pending_buffers_complete_
) {
1093 DCHECK_EQ(splice_buffers_index_
, last_splice_buffer_index
);
1094 pending_buffers_complete_
= true;
1095 config_change_pending_
= true;
1096 DVLOG(1) << "Config change (forced for fade in of splice frame).";
1097 return SourceBufferStream::kConfigChange
;
1100 // All pre-splice buffers have been handed out and a config change completed,
1101 // so hand out the final buffer for fade in. Because a config change is
1102 // always issued prior to handing out this buffer, any changes in config id
1103 // have been inherently handled.
1104 DCHECK(pending_buffers_complete_
);
1105 DCHECK_EQ(splice_buffers_index_
, splice_buffers
.size() - 1);
1106 DCHECK(splice_buffers
.back()->splice_timestamp() == kNoTimestamp());
1107 *out_buffer
= splice_buffers
.back();
1108 pending_buffer_
= NULL
;
1110 // If the last splice buffer has preroll, hand off to the preroll handler.
1111 return SetPendingBuffer(out_buffer
) ? HandleNextBufferWithPreroll(out_buffer
)
1112 : SourceBufferStream::kSuccess
;
1115 SourceBufferStream::Status
SourceBufferStream::HandleNextBufferWithPreroll(
1116 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1117 // Any config change should have already been handled.
1118 DCHECK_EQ(current_config_index_
, pending_buffer_
->GetConfigId());
1120 // Check if the preroll buffer has already been handed out.
1121 if (!pending_buffers_complete_
) {
1122 pending_buffers_complete_
= true;
1123 *out_buffer
= pending_buffer_
->preroll_buffer();
1124 return SourceBufferStream::kSuccess
;
1127 // Preroll complete, hand out the final buffer.
1128 *out_buffer
= pending_buffer_
;
1129 pending_buffer_
= NULL
;
1130 return SourceBufferStream::kSuccess
;
1133 SourceBufferStream::Status
SourceBufferStream::GetNextBufferInternal(
1134 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1135 CHECK(!config_change_pending_
);
1137 if (!track_buffer_
.empty()) {
1138 DCHECK(!selected_range_
);
1139 scoped_refptr
<StreamParserBuffer
>& next_buffer
= track_buffer_
.front();
1141 // If the next buffer is an audio splice frame, the next effective config id
1142 // comes from the first splice buffer.
1143 if (next_buffer
->GetSpliceBufferConfigId(0) != current_config_index_
) {
1144 config_change_pending_
= true;
1145 DVLOG(1) << "Config change (track buffer config ID does not match).";
1146 return kConfigChange
;
1149 DVLOG(3) << __FUNCTION__
<< " Next buffer coming from track_buffer_";
1150 *out_buffer
= next_buffer
;
1151 track_buffer_
.pop_front();
1152 WarnIfTrackBufferExhaustionSkipsForward(*out_buffer
);
1153 last_output_buffer_timestamp_
= (*out_buffer
)->GetDecodeTimestamp();
1155 // If the track buffer becomes empty, then try to set the selected range
1156 // based on the timestamp of this buffer being returned.
1157 if (track_buffer_
.empty()) {
1158 just_exhausted_track_buffer_
= true;
1159 SetSelectedRangeIfNeeded(last_output_buffer_timestamp_
);
1165 DCHECK(track_buffer_
.empty());
1166 if (!selected_range_
|| !selected_range_
->HasNextBuffer()) {
1167 if (IsEndOfStreamReached()) {
1168 return kEndOfStream
;
1170 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
1171 << ": returning kNeedBuffer "
1172 << (selected_range_
? "(selected range has no next buffer)"
1173 : "(no selected range)");
1177 if (selected_range_
->GetNextConfigId() != current_config_index_
) {
1178 config_change_pending_
= true;
1179 DVLOG(1) << "Config change (selected range config ID does not match).";
1180 return kConfigChange
;
1183 CHECK(selected_range_
->GetNextBuffer(out_buffer
));
1184 WarnIfTrackBufferExhaustionSkipsForward(*out_buffer
);
1185 last_output_buffer_timestamp_
= (*out_buffer
)->GetDecodeTimestamp();
1189 void SourceBufferStream::WarnIfTrackBufferExhaustionSkipsForward(
1190 const scoped_refptr
<StreamParserBuffer
>& next_buffer
) {
1191 if (!just_exhausted_track_buffer_
)
1194 just_exhausted_track_buffer_
= false;
1195 DCHECK(next_buffer
->is_key_frame());
1196 DecodeTimestamp next_output_buffer_timestamp
=
1197 next_buffer
->GetDecodeTimestamp();
1198 base::TimeDelta delta
=
1199 next_output_buffer_timestamp
- last_output_buffer_timestamp_
;
1200 DCHECK_GE(delta
, base::TimeDelta());
1201 if (delta
> GetMaxInterbufferDistance()) {
1202 LIMITED_MEDIA_LOG(DEBUG
, media_log_
, num_track_buffer_gap_warning_logs_
,
1203 kMaxTrackBufferGapWarningLogs
)
1204 << "Media append that overlapped current playback position caused time "
1206 << GetStreamTypeName() << " stream because the next keyframe is "
1207 << delta
.InMilliseconds() << "ms beyond last overlapped frame. Media "
1208 "may appear temporarily frozen.";
1212 DecodeTimestamp
SourceBufferStream::GetNextBufferTimestamp() {
1213 if (!track_buffer_
.empty())
1214 return track_buffer_
.front()->GetDecodeTimestamp();
1216 if (!selected_range_
)
1217 return kNoDecodeTimestamp();
1219 DCHECK(selected_range_
->HasNextBufferPosition());
1220 return selected_range_
->GetNextTimestamp();
1223 SourceBufferStream::RangeList::iterator
1224 SourceBufferStream::FindExistingRangeFor(DecodeTimestamp start_timestamp
) {
1225 for (RangeList::iterator itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1226 if ((*itr
)->BelongsToRange(start_timestamp
))
1229 return ranges_
.end();
1232 SourceBufferStream::RangeList::iterator
1233 SourceBufferStream::AddToRanges(SourceBufferRange
* new_range
) {
1234 DecodeTimestamp start_timestamp
= new_range
->GetStartTimestamp();
1235 RangeList::iterator itr
= ranges_
.end();
1236 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1237 if ((*itr
)->GetStartTimestamp() > start_timestamp
)
1240 return ranges_
.insert(itr
, new_range
);
1243 SourceBufferStream::RangeList::iterator
1244 SourceBufferStream::GetSelectedRangeItr() {
1245 DCHECK(selected_range_
);
1246 RangeList::iterator itr
= ranges_
.end();
1247 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1248 if (*itr
== selected_range_
)
1251 DCHECK(itr
!= ranges_
.end());
1255 void SourceBufferStream::SeekAndSetSelectedRange(
1256 SourceBufferRange
* range
, DecodeTimestamp seek_timestamp
) {
1258 range
->Seek(seek_timestamp
);
1259 SetSelectedRange(range
);
1262 void SourceBufferStream::SetSelectedRange(SourceBufferRange
* range
) {
1263 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
1264 << ": " << selected_range_
<< " -> " << range
;
1265 if (selected_range_
)
1266 selected_range_
->ResetNextBufferPosition();
1267 DCHECK(!range
|| range
->HasNextBufferPosition());
1268 selected_range_
= range
;
1271 Ranges
<base::TimeDelta
> SourceBufferStream::GetBufferedTime() const {
1272 Ranges
<base::TimeDelta
> ranges
;
1273 for (RangeList::const_iterator itr
= ranges_
.begin();
1274 itr
!= ranges_
.end(); ++itr
) {
1275 ranges
.Add((*itr
)->GetStartTimestamp().ToPresentationTime(),
1276 (*itr
)->GetBufferedEndTimestamp().ToPresentationTime());
1281 base::TimeDelta
SourceBufferStream::GetBufferedDuration() const {
1282 if (ranges_
.empty())
1283 return base::TimeDelta();
1285 return ranges_
.back()->GetBufferedEndTimestamp().ToPresentationTime();
1288 void SourceBufferStream::MarkEndOfStream() {
1289 DCHECK(!end_of_stream_
);
1290 end_of_stream_
= true;
1293 void SourceBufferStream::UnmarkEndOfStream() {
1294 DCHECK(end_of_stream_
);
1295 end_of_stream_
= false;
1298 bool SourceBufferStream::IsEndOfStreamReached() const {
1299 if (!end_of_stream_
|| !track_buffer_
.empty())
1302 if (ranges_
.empty())
1305 if (seek_pending_
) {
1306 base::TimeDelta last_range_end_time
=
1307 ranges_
.back()->GetBufferedEndTimestamp().ToPresentationTime();
1308 return seek_buffer_timestamp_
>= last_range_end_time
;
1311 if (!selected_range_
)
1314 return selected_range_
== ranges_
.back();
1317 const AudioDecoderConfig
& SourceBufferStream::GetCurrentAudioDecoderConfig() {
1318 if (config_change_pending_
)
1319 CompleteConfigChange();
1320 return audio_configs_
[current_config_index_
];
1323 const VideoDecoderConfig
& SourceBufferStream::GetCurrentVideoDecoderConfig() {
1324 if (config_change_pending_
)
1325 CompleteConfigChange();
1326 return video_configs_
[current_config_index_
];
1329 const TextTrackConfig
& SourceBufferStream::GetCurrentTextTrackConfig() {
1330 return text_track_config_
;
1333 base::TimeDelta
SourceBufferStream::GetMaxInterbufferDistance() const {
1334 if (max_interbuffer_distance_
== kNoTimestamp())
1335 return base::TimeDelta::FromMilliseconds(kDefaultBufferDurationInMs
);
1336 return max_interbuffer_distance_
;
1339 bool SourceBufferStream::UpdateAudioConfig(const AudioDecoderConfig
& config
) {
1340 DCHECK(!audio_configs_
.empty());
1341 DCHECK(video_configs_
.empty());
1342 DVLOG(3) << "UpdateAudioConfig.";
1344 if (audio_configs_
[0].codec() != config
.codec()) {
1345 MEDIA_LOG(ERROR
, media_log_
) << "Audio codec changes not allowed.";
1349 if (audio_configs_
[0].is_encrypted() != config
.is_encrypted()) {
1350 MEDIA_LOG(ERROR
, media_log_
) << "Audio encryption changes not allowed.";
1354 // Check to see if the new config matches an existing one.
1355 for (size_t i
= 0; i
< audio_configs_
.size(); ++i
) {
1356 if (config
.Matches(audio_configs_
[i
])) {
1357 append_config_index_
= i
;
1362 // No matches found so let's add this one to the list.
1363 append_config_index_
= audio_configs_
.size();
1364 DVLOG(2) << "New audio config - index: " << append_config_index_
;
1365 audio_configs_
.resize(audio_configs_
.size() + 1);
1366 audio_configs_
[append_config_index_
] = config
;
1370 bool SourceBufferStream::UpdateVideoConfig(const VideoDecoderConfig
& config
) {
1371 DCHECK(!video_configs_
.empty());
1372 DCHECK(audio_configs_
.empty());
1373 DVLOG(3) << "UpdateVideoConfig.";
1375 if (video_configs_
[0].codec() != config
.codec()) {
1376 MEDIA_LOG(ERROR
, media_log_
) << "Video codec changes not allowed.";
1380 if (video_configs_
[0].is_encrypted() != config
.is_encrypted()) {
1381 MEDIA_LOG(ERROR
, media_log_
) << "Video encryption changes not allowed.";
1385 // Check to see if the new config matches an existing one.
1386 for (size_t i
= 0; i
< video_configs_
.size(); ++i
) {
1387 if (config
.Matches(video_configs_
[i
])) {
1388 append_config_index_
= i
;
1393 // No matches found so let's add this one to the list.
1394 append_config_index_
= video_configs_
.size();
1395 DVLOG(2) << "New video config - index: " << append_config_index_
;
1396 video_configs_
.resize(video_configs_
.size() + 1);
1397 video_configs_
[append_config_index_
] = config
;
1401 void SourceBufferStream::CompleteConfigChange() {
1402 config_change_pending_
= false;
1404 if (pending_buffer_
.get()) {
1405 current_config_index_
=
1406 pending_buffer_
->GetSpliceBufferConfigId(splice_buffers_index_
);
1410 if (!track_buffer_
.empty()) {
1411 current_config_index_
= track_buffer_
.front()->GetSpliceBufferConfigId(0);
1415 if (selected_range_
&& selected_range_
->HasNextBuffer())
1416 current_config_index_
= selected_range_
->GetNextConfigId();
1419 void SourceBufferStream::SetSelectedRangeIfNeeded(
1420 const DecodeTimestamp timestamp
) {
1421 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1422 << "(" << timestamp
.InSecondsF() << ")";
1424 if (selected_range_
) {
1425 DCHECK(track_buffer_
.empty());
1429 if (!track_buffer_
.empty()) {
1430 DCHECK(!selected_range_
);
1434 DecodeTimestamp start_timestamp
= timestamp
;
1436 // If the next buffer timestamp is not known then use a timestamp just after
1437 // the timestamp on the last buffer returned by GetNextBuffer().
1438 if (start_timestamp
== kNoDecodeTimestamp()) {
1439 if (last_output_buffer_timestamp_
== kNoDecodeTimestamp()) {
1440 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1441 << " no previous output timestamp";
1445 start_timestamp
= last_output_buffer_timestamp_
+
1446 base::TimeDelta::FromInternalValue(1);
1449 DecodeTimestamp seek_timestamp
=
1450 FindNewSelectedRangeSeekTimestamp(start_timestamp
);
1452 // If we don't have buffered data to seek to, then return.
1453 if (seek_timestamp
== kNoDecodeTimestamp()) {
1454 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1455 << " couldn't find new selected range seek timestamp";
1459 DCHECK(track_buffer_
.empty());
1460 SeekAndSetSelectedRange(*FindExistingRangeFor(seek_timestamp
),
1464 DecodeTimestamp
SourceBufferStream::FindNewSelectedRangeSeekTimestamp(
1465 const DecodeTimestamp start_timestamp
) {
1466 DCHECK(start_timestamp
!= kNoDecodeTimestamp());
1467 DCHECK(start_timestamp
>= DecodeTimestamp());
1469 RangeList::iterator itr
= ranges_
.begin();
1471 for (; itr
!= ranges_
.end(); ++itr
) {
1472 if ((*itr
)->GetEndTimestamp() >= start_timestamp
) {
1477 if (itr
== ranges_
.end()) {
1478 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1479 << " no buffered data for dts=" << start_timestamp
.InSecondsF();
1480 return kNoDecodeTimestamp();
1483 // First check for a keyframe timestamp >= |start_timestamp|
1484 // in the current range.
1485 DecodeTimestamp keyframe_timestamp
=
1486 (*itr
)->NextKeyframeTimestamp(start_timestamp
);
1488 if (keyframe_timestamp
!= kNoDecodeTimestamp())
1489 return keyframe_timestamp
;
1491 // If a keyframe was not found then look for a keyframe that is
1492 // "close enough" in the current or next range.
1493 DecodeTimestamp end_timestamp
=
1494 start_timestamp
+ ComputeFudgeRoom(GetMaxInterbufferDistance());
1495 DCHECK(start_timestamp
< end_timestamp
);
1497 // Make sure the current range doesn't start beyond |end_timestamp|.
1498 if ((*itr
)->GetStartTimestamp() >= end_timestamp
)
1499 return kNoDecodeTimestamp();
1501 keyframe_timestamp
= (*itr
)->KeyframeBeforeTimestamp(end_timestamp
);
1503 // Check to see if the keyframe is within the acceptable range
1504 // (|start_timestamp|, |end_timestamp|].
1505 if (keyframe_timestamp
!= kNoDecodeTimestamp() &&
1506 start_timestamp
< keyframe_timestamp
&&
1507 keyframe_timestamp
<= end_timestamp
) {
1508 return keyframe_timestamp
;
1511 // If |end_timestamp| is within this range, then no other checks are
1513 if (end_timestamp
<= (*itr
)->GetEndTimestamp())
1514 return kNoDecodeTimestamp();
1516 // Move on to the next range.
1519 // Return early if the next range does not contain |end_timestamp|.
1520 if (itr
== ranges_
.end() || (*itr
)->GetStartTimestamp() >= end_timestamp
)
1521 return kNoDecodeTimestamp();
1523 keyframe_timestamp
= (*itr
)->KeyframeBeforeTimestamp(end_timestamp
);
1525 // Check to see if the keyframe is within the acceptable range
1526 // (|start_timestamp|, |end_timestamp|].
1527 if (keyframe_timestamp
!= kNoDecodeTimestamp() &&
1528 start_timestamp
< keyframe_timestamp
&&
1529 keyframe_timestamp
<= end_timestamp
) {
1530 return keyframe_timestamp
;
1533 return kNoDecodeTimestamp();
1536 DecodeTimestamp
SourceBufferStream::FindKeyframeAfterTimestamp(
1537 const DecodeTimestamp timestamp
) {
1538 DCHECK(timestamp
!= kNoDecodeTimestamp());
1540 RangeList::iterator itr
= FindExistingRangeFor(timestamp
);
1542 if (itr
== ranges_
.end())
1543 return kNoDecodeTimestamp();
1545 // First check for a keyframe timestamp >= |timestamp|
1546 // in the current range.
1547 return (*itr
)->NextKeyframeTimestamp(timestamp
);
1550 std::string
SourceBufferStream::GetStreamTypeName() const {
1551 switch (GetType()) {
1563 SourceBufferStream::Type
SourceBufferStream::GetType() const {
1564 if (!audio_configs_
.empty())
1566 if (!video_configs_
.empty())
1568 DCHECK_NE(text_track_config_
.kind(), kTextNone
);
1572 void SourceBufferStream::DeleteAndRemoveRange(RangeList::iterator
* itr
) {
1573 DVLOG(1) << __FUNCTION__
;
1575 DCHECK(*itr
!= ranges_
.end());
1576 if (**itr
== selected_range_
) {
1577 DVLOG(1) << __FUNCTION__
<< " deleting selected range.";
1578 SetSelectedRange(NULL
);
1581 if (*itr
== range_for_next_append_
) {
1582 DVLOG(1) << __FUNCTION__
<< " deleting range_for_next_append_.";
1583 range_for_next_append_
= ranges_
.end();
1584 last_appended_buffer_timestamp_
= kNoDecodeTimestamp();
1585 last_appended_buffer_is_keyframe_
= false;
1589 *itr
= ranges_
.erase(*itr
);
1592 void SourceBufferStream::GenerateSpliceFrame(const BufferQueue
& new_buffers
) {
1593 DCHECK(!new_buffers
.empty());
1595 // Splice frames are only supported for audio.
1596 if (GetType() != kAudio
)
1599 // Find the overlapped range (if any).
1600 const base::TimeDelta splice_timestamp
= new_buffers
.front()->timestamp();
1601 const DecodeTimestamp splice_dts
=
1602 DecodeTimestamp::FromPresentationTime(splice_timestamp
);
1603 RangeList::iterator range_itr
= FindExistingRangeFor(splice_dts
);
1604 if (range_itr
== ranges_
.end())
1607 const DecodeTimestamp max_splice_end_dts
=
1608 splice_dts
+ base::TimeDelta::FromMilliseconds(
1609 AudioSplicer::kCrossfadeDurationInMilliseconds
);
1611 // Find all buffers involved before the splice point.
1612 BufferQueue pre_splice_buffers
;
1613 if (!(*range_itr
)->GetBuffersInRange(
1614 splice_dts
, max_splice_end_dts
, &pre_splice_buffers
)) {
1618 // If there are gaps in the timeline, it's possible that we only find buffers
1619 // after the splice point but within the splice range. For simplicity, we do
1620 // not generate splice frames in this case.
1622 // We also do not want to generate splices if the first new buffer replaces an
1623 // existing buffer exactly.
1624 if (pre_splice_buffers
.front()->timestamp() >= splice_timestamp
) {
1625 LIMITED_MEDIA_LOG(DEBUG
, media_log_
, num_splice_generation_warning_logs_
,
1626 kMaxSpliceGenerationWarningLogs
)
1627 << "Skipping splice frame generation: first new buffer at "
1628 << splice_timestamp
.InMicroseconds()
1629 << "us begins at or before existing buffer at "
1630 << pre_splice_buffers
.front()->timestamp().InMicroseconds() << "us.";
1631 DVLOG(1) << "Skipping splice: overlapped buffers begin at or after the "
1632 "first new buffer.";
1636 // If any |pre_splice_buffers| are already splices or preroll, do not generate
1638 for (size_t i
= 0; i
< pre_splice_buffers
.size(); ++i
) {
1639 const BufferQueue
& original_splice_buffers
=
1640 pre_splice_buffers
[i
]->splice_buffers();
1641 if (!original_splice_buffers
.empty()) {
1642 LIMITED_MEDIA_LOG(DEBUG
, media_log_
, num_splice_generation_warning_logs_
,
1643 kMaxSpliceGenerationWarningLogs
)
1644 << "Skipping splice frame generation: overlapped buffers at "
1645 << pre_splice_buffers
[i
]->timestamp().InMicroseconds()
1646 << "us are in a previously buffered splice.";
1647 DVLOG(1) << "Can't generate splice: overlapped buffers contain a "
1648 "pre-existing splice.";
1652 if (pre_splice_buffers
[i
]->preroll_buffer().get()) {
1653 LIMITED_MEDIA_LOG(DEBUG
, media_log_
, num_splice_generation_warning_logs_
,
1654 kMaxSpliceGenerationWarningLogs
)
1655 << "Skipping splice frame generation: overlapped buffers at "
1656 << pre_splice_buffers
[i
]->timestamp().InMicroseconds()
1657 << "us contain preroll.";
1658 DVLOG(1) << "Can't generate splice: overlapped buffers contain preroll.";
1663 // Don't generate splice frames which represent less than a millisecond (which
1664 // is frequently the extent of timestamp resolution for poorly encoded media)
1665 // or less than two samples (need at least two to crossfade).
1666 const base::TimeDelta splice_duration
=
1667 pre_splice_buffers
.back()->timestamp() +
1668 pre_splice_buffers
.back()->duration() - splice_timestamp
;
1669 const base::TimeDelta minimum_splice_duration
= std::max(
1670 base::TimeDelta::FromMilliseconds(1),
1671 base::TimeDelta::FromSecondsD(
1672 2.0 / audio_configs_
[append_config_index_
].samples_per_second()));
1673 if (splice_duration
< minimum_splice_duration
) {
1674 LIMITED_MEDIA_LOG(DEBUG
, media_log_
, num_splice_generation_warning_logs_
,
1675 kMaxSpliceGenerationWarningLogs
)
1676 << "Skipping splice frame generation: not enough samples for splicing "
1678 << splice_timestamp
.InMicroseconds() << "us. Have "
1679 << splice_duration
.InMicroseconds() << "us, but need "
1680 << minimum_splice_duration
.InMicroseconds() << "us.";
1681 DVLOG(1) << "Can't generate splice: not enough samples for crossfade; have "
1682 << splice_duration
.InMicroseconds() << "us, but need "
1683 << minimum_splice_duration
.InMicroseconds() << "us.";
1687 DVLOG(1) << "Generating splice frame @ " << new_buffers
.front()->timestamp()
1688 << ", splice duration: " << splice_duration
.InMicroseconds()
1690 LIMITED_MEDIA_LOG(DEBUG
, media_log_
, num_splice_generation_success_logs_
,
1691 kMaxSpliceGenerationSuccessLogs
)
1692 << "Generated splice of overlap duration "
1693 << splice_duration
.InMicroseconds() << "us into new buffer at "
1694 << splice_timestamp
.InMicroseconds() << "us.";
1695 new_buffers
.front()->ConvertToSpliceBuffer(pre_splice_buffers
);
1698 bool SourceBufferStream::SetPendingBuffer(
1699 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1700 DCHECK(out_buffer
->get());
1701 DCHECK(!pending_buffer_
.get());
1703 const bool have_splice_buffers
= !(*out_buffer
)->splice_buffers().empty();
1704 const bool have_preroll_buffer
= !!(*out_buffer
)->preroll_buffer().get();
1706 if (!have_splice_buffers
&& !have_preroll_buffer
)
1709 DCHECK_NE(have_splice_buffers
, have_preroll_buffer
);
1710 splice_buffers_index_
= 0;
1711 pending_buffer_
.swap(*out_buffer
);
1712 pending_buffers_complete_
= false;
1716 } // namespace media