1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/filters/source_buffer_stream.h"
11 #include "base/bind.h"
12 #include "base/logging.h"
13 #include "base/trace_event/trace_event.h"
14 #include "media/base/audio_splicer.h"
15 #include "media/filters/source_buffer_platform.h"
16 #include "media/filters/source_buffer_range.h"
20 // Helper method that returns true if |ranges| is sorted in increasing order,
22 static bool IsRangeListSorted(
23 const std::list
<media::SourceBufferRange
*>& ranges
) {
24 DecodeTimestamp prev
= kNoDecodeTimestamp();
25 for (std::list
<SourceBufferRange
*>::const_iterator itr
=
26 ranges
.begin(); itr
!= ranges
.end(); ++itr
) {
27 if (prev
!= kNoDecodeTimestamp() && prev
>= (*itr
)->GetStartTimestamp())
29 prev
= (*itr
)->GetEndTimestamp();
34 // Returns an estimate of how far from the beginning or end of a range a buffer
35 // can be to still be considered in the range, given the |approximate_duration|
36 // of a buffer in the stream.
37 // TODO(wolenetz): Once all stream parsers emit accurate frame durations, use
38 // logic like FrameProcessor (2*last_frame_duration + last_decode_timestamp)
39 // instead of an overall maximum interbuffer delta for range discontinuity
40 // detection, and adjust similarly for splice frame discontinuity detection.
41 // See http://crbug.com/351489 and http://crbug.com/351166.
42 static base::TimeDelta
ComputeFudgeRoom(base::TimeDelta approximate_duration
) {
43 // Because we do not know exactly when is the next timestamp, any buffer
44 // that starts within 2x the approximate duration of a buffer is considered
46 return 2 * approximate_duration
;
49 // An arbitrarily-chosen number to estimate the duration of a buffer if none
50 // is set and there's not enough information to get a better estimate.
51 static int kDefaultBufferDurationInMs
= 125;
53 // The amount of time the beginning of the buffered data can differ from the
54 // start time in order to still be considered the start of stream.
55 static base::TimeDelta
kSeekToStartFudgeRoom() {
56 return base::TimeDelta::FromMilliseconds(1000);
59 // Helper method for logging, converts a range into a readable string.
60 static std::string
RangeToString(const SourceBufferRange
& range
) {
62 ss
<< "[" << range
.GetStartTimestamp().InSecondsF()
63 << ";" << range
.GetEndTimestamp().InSecondsF()
64 << "(" << range
.GetBufferedEndTimestamp().InSecondsF() << ")]";
68 // Helper method for logging, converts a set of ranges into a readable string.
69 static std::string
RangesToString(const SourceBufferStream::RangeList
& ranges
) {
74 for (const auto* range_ptr
: ranges
) {
75 if (range_ptr
!= ranges
.front())
77 ss
<< RangeToString(*range_ptr
);
82 static SourceBufferRange::GapPolicy
TypeToGapPolicy(
83 SourceBufferStream::Type type
) {
85 case SourceBufferStream::kAudio
:
86 case SourceBufferStream::kVideo
:
87 return SourceBufferRange::NO_GAPS_ALLOWED
;
88 case SourceBufferStream::kText
:
89 return SourceBufferRange::ALLOW_GAPS
;
93 return SourceBufferRange::NO_GAPS_ALLOWED
;
96 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig
& audio_config
,
98 bool splice_frames_enabled
)
100 current_config_index_(0),
101 append_config_index_(0),
102 seek_pending_(false),
103 end_of_stream_(false),
104 seek_buffer_timestamp_(kNoTimestamp()),
105 selected_range_(NULL
),
106 media_segment_start_time_(kNoDecodeTimestamp()),
107 range_for_next_append_(ranges_
.end()),
108 new_media_segment_(false),
109 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
110 last_appended_buffer_is_keyframe_(false),
111 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
112 max_interbuffer_distance_(kNoTimestamp()),
113 memory_limit_(kSourceBufferAudioMemoryLimit
),
114 config_change_pending_(false),
115 splice_buffers_index_(0),
116 pending_buffers_complete_(false),
117 splice_frames_enabled_(splice_frames_enabled
) {
118 DCHECK(audio_config
.IsValidConfig());
119 audio_configs_
.push_back(audio_config
);
122 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig
& video_config
,
124 bool splice_frames_enabled
)
126 current_config_index_(0),
127 append_config_index_(0),
128 seek_pending_(false),
129 end_of_stream_(false),
130 seek_buffer_timestamp_(kNoTimestamp()),
131 selected_range_(NULL
),
132 media_segment_start_time_(kNoDecodeTimestamp()),
133 range_for_next_append_(ranges_
.end()),
134 new_media_segment_(false),
135 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
136 last_appended_buffer_is_keyframe_(false),
137 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
138 max_interbuffer_distance_(kNoTimestamp()),
139 memory_limit_(kSourceBufferVideoMemoryLimit
),
140 config_change_pending_(false),
141 splice_buffers_index_(0),
142 pending_buffers_complete_(false),
143 splice_frames_enabled_(splice_frames_enabled
) {
144 DCHECK(video_config
.IsValidConfig());
145 video_configs_
.push_back(video_config
);
148 SourceBufferStream::SourceBufferStream(const TextTrackConfig
& text_config
,
150 bool splice_frames_enabled
)
152 current_config_index_(0),
153 append_config_index_(0),
154 text_track_config_(text_config
),
155 seek_pending_(false),
156 end_of_stream_(false),
157 seek_buffer_timestamp_(kNoTimestamp()),
158 selected_range_(NULL
),
159 media_segment_start_time_(kNoDecodeTimestamp()),
160 range_for_next_append_(ranges_
.end()),
161 new_media_segment_(false),
162 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
163 last_appended_buffer_is_keyframe_(false),
164 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
165 max_interbuffer_distance_(kNoTimestamp()),
166 memory_limit_(kSourceBufferAudioMemoryLimit
),
167 config_change_pending_(false),
168 splice_buffers_index_(0),
169 pending_buffers_complete_(false),
170 splice_frames_enabled_(splice_frames_enabled
) {}
172 SourceBufferStream::~SourceBufferStream() {
173 while (!ranges_
.empty()) {
174 delete ranges_
.front();
179 void SourceBufferStream::OnNewMediaSegment(
180 DecodeTimestamp media_segment_start_time
) {
181 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
182 << " (" << media_segment_start_time
.InSecondsF() << ")";
183 DCHECK(!end_of_stream_
);
184 media_segment_start_time_
= media_segment_start_time
;
185 new_media_segment_
= true;
187 RangeList::iterator last_range
= range_for_next_append_
;
188 range_for_next_append_
= FindExistingRangeFor(media_segment_start_time
);
190 // Only reset |last_appended_buffer_timestamp_| if this new media segment is
191 // not adjacent to the previous media segment appended to the stream.
192 if (range_for_next_append_
== ranges_
.end() ||
193 !AreAdjacentInSequence(last_appended_buffer_timestamp_
,
194 media_segment_start_time
)) {
195 last_appended_buffer_timestamp_
= kNoDecodeTimestamp();
196 last_appended_buffer_is_keyframe_
= false;
197 DVLOG(3) << __FUNCTION__
<< " next appended buffers will be in a new range";
198 } else if (last_range
!= ranges_
.end()) {
199 DCHECK(last_range
== range_for_next_append_
);
200 DVLOG(3) << __FUNCTION__
<< " next appended buffers will continue range "
201 << "unless intervening remove makes discontinuity";
205 bool SourceBufferStream::Append(const BufferQueue
& buffers
) {
206 TRACE_EVENT2("media", "SourceBufferStream::Append",
207 "stream type", GetStreamTypeName(),
208 "buffers to append", buffers
.size());
210 DCHECK(!buffers
.empty());
211 DCHECK(media_segment_start_time_
!= kNoDecodeTimestamp());
212 DCHECK(media_segment_start_time_
<= buffers
.front()->GetDecodeTimestamp());
213 DCHECK(!end_of_stream_
);
215 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName() << ": buffers dts=["
216 << buffers
.front()->GetDecodeTimestamp().InSecondsF() << ";"
217 << buffers
.back()->GetDecodeTimestamp().InSecondsF() << "] pts=["
218 << buffers
.front()->timestamp().InSecondsF() << ";"
219 << buffers
.back()->timestamp().InSecondsF() << "(last frame dur="
220 << buffers
.back()->duration().InSecondsF() << ")]";
222 // New media segments must begin with a keyframe.
223 // TODO(wolenetz): Relax this requirement. See http://crbug.com/229412.
224 if (new_media_segment_
&& !buffers
.front()->is_key_frame()) {
225 MEDIA_LOG(ERROR
, log_cb_
) << "Media segment did not begin with key frame.";
229 // Buffers within a media segment should be monotonically increasing.
230 if (!IsMonotonicallyIncreasing(buffers
))
233 if (media_segment_start_time_
< DecodeTimestamp() ||
234 buffers
.front()->GetDecodeTimestamp() < DecodeTimestamp()) {
235 MEDIA_LOG(ERROR
, log_cb_
)
236 << "Cannot append a media segment with negative timestamps.";
240 if (!IsNextTimestampValid(buffers
.front()->GetDecodeTimestamp(),
241 buffers
.front()->is_key_frame())) {
242 const DecodeTimestamp
& dts
= buffers
.front()->GetDecodeTimestamp();
243 MEDIA_LOG(ERROR
, log_cb_
) << "Invalid same timestamp construct detected at"
244 << " time " << dts
.InSecondsF();
249 UpdateMaxInterbufferDistance(buffers
);
250 SetConfigIds(buffers
);
252 // Save a snapshot of stream state before range modifications are made.
253 DecodeTimestamp next_buffer_timestamp
= GetNextBufferTimestamp();
254 BufferQueue deleted_buffers
;
256 PrepareRangesForNextAppend(buffers
, &deleted_buffers
);
258 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise,
259 // create a new range with |buffers|.
260 if (range_for_next_append_
!= ranges_
.end()) {
261 (*range_for_next_append_
)->AppendBuffersToEnd(buffers
);
262 last_appended_buffer_timestamp_
= buffers
.back()->GetDecodeTimestamp();
263 last_appended_buffer_is_keyframe_
= buffers
.back()->is_key_frame();
265 DecodeTimestamp new_range_start_time
= std::min(
266 media_segment_start_time_
, buffers
.front()->GetDecodeTimestamp());
267 const BufferQueue
* buffers_for_new_range
= &buffers
;
268 BufferQueue trimmed_buffers
;
270 // If the new range is not being created because of a new media
271 // segment, then we must make sure that we start with a key frame.
272 // This can happen if the GOP in the previous append gets destroyed
273 // by a Remove() call.
274 if (!new_media_segment_
) {
275 BufferQueue::const_iterator itr
= buffers
.begin();
277 // Scan past all the non-key-frames.
278 while (itr
!= buffers
.end() && !(*itr
)->is_key_frame()) {
282 // If we didn't find a key frame, then update the last appended
283 // buffer state and return.
284 if (itr
== buffers
.end()) {
285 last_appended_buffer_timestamp_
= buffers
.back()->GetDecodeTimestamp();
286 last_appended_buffer_is_keyframe_
= buffers
.back()->is_key_frame();
287 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
288 << ": new buffers in the middle of media segment depend on"
289 "keyframe that has been removed, and contain no keyframes."
290 "Skipping further processing.";
291 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
292 << ": done. ranges_=" << RangesToString(ranges_
);
294 } else if (itr
!= buffers
.begin()) {
295 // Copy the first key frame and everything after it into
296 // |trimmed_buffers|.
297 trimmed_buffers
.assign(itr
, buffers
.end());
298 buffers_for_new_range
= &trimmed_buffers
;
301 new_range_start_time
=
302 buffers_for_new_range
->front()->GetDecodeTimestamp();
305 range_for_next_append_
=
306 AddToRanges(new SourceBufferRange(
307 TypeToGapPolicy(GetType()),
308 *buffers_for_new_range
, new_range_start_time
,
309 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance
,
310 base::Unretained(this))));
311 last_appended_buffer_timestamp_
=
312 buffers_for_new_range
->back()->GetDecodeTimestamp();
313 last_appended_buffer_is_keyframe_
=
314 buffers_for_new_range
->back()->is_key_frame();
317 new_media_segment_
= false;
319 MergeWithAdjacentRangeIfNecessary(range_for_next_append_
);
321 // Seek to try to fulfill a previous call to Seek().
323 DCHECK(!selected_range_
);
324 DCHECK(deleted_buffers
.empty());
325 Seek(seek_buffer_timestamp_
);
328 if (!deleted_buffers
.empty()) {
329 DecodeTimestamp start_of_deleted
=
330 deleted_buffers
.front()->GetDecodeTimestamp();
332 DCHECK(track_buffer_
.empty() ||
333 track_buffer_
.back()->GetDecodeTimestamp() < start_of_deleted
)
334 << "decode timestamp "
335 << track_buffer_
.back()->GetDecodeTimestamp().InSecondsF() << " sec"
336 << ", start_of_deleted " << start_of_deleted
.InSecondsF()<< " sec";
338 track_buffer_
.insert(track_buffer_
.end(), deleted_buffers
.begin(),
339 deleted_buffers
.end());
342 // Prune any extra buffers in |track_buffer_| if new keyframes
343 // are appended to the range covered by |track_buffer_|.
344 if (!track_buffer_
.empty()) {
345 DecodeTimestamp keyframe_timestamp
=
346 FindKeyframeAfterTimestamp(track_buffer_
.front()->GetDecodeTimestamp());
347 if (keyframe_timestamp
!= kNoDecodeTimestamp())
348 PruneTrackBuffer(keyframe_timestamp
);
351 SetSelectedRangeIfNeeded(next_buffer_timestamp
);
353 GarbageCollectIfNeeded();
355 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
356 << ": done. ranges_=" << RangesToString(ranges_
);
357 DCHECK(IsRangeListSorted(ranges_
));
358 DCHECK(OnlySelectedRangeIsSeeked());
362 void SourceBufferStream::Remove(base::TimeDelta start
, base::TimeDelta end
,
363 base::TimeDelta duration
) {
364 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
365 << " (" << start
.InSecondsF() << ", " << end
.InSecondsF()
366 << ", " << duration
.InSecondsF() << ")";
367 DCHECK(start
>= base::TimeDelta()) << start
.InSecondsF();
368 DCHECK(start
< end
) << "start " << start
.InSecondsF()
369 << " end " << end
.InSecondsF();
370 DCHECK(duration
!= kNoTimestamp());
372 DecodeTimestamp start_dts
= DecodeTimestamp::FromPresentationTime(start
);
373 DecodeTimestamp end_dts
= DecodeTimestamp::FromPresentationTime(end
);
374 DecodeTimestamp remove_end_timestamp
=
375 DecodeTimestamp::FromPresentationTime(duration
);
376 DecodeTimestamp keyframe_timestamp
= FindKeyframeAfterTimestamp(end_dts
);
377 if (keyframe_timestamp
!= kNoDecodeTimestamp()) {
378 remove_end_timestamp
= keyframe_timestamp
;
379 } else if (end_dts
< remove_end_timestamp
) {
380 remove_end_timestamp
= end_dts
;
383 BufferQueue deleted_buffers
;
384 RemoveInternal(start_dts
, remove_end_timestamp
, false, &deleted_buffers
);
386 if (!deleted_buffers
.empty())
387 SetSelectedRangeIfNeeded(deleted_buffers
.front()->GetDecodeTimestamp());
390 void SourceBufferStream::RemoveInternal(DecodeTimestamp start
,
393 BufferQueue
* deleted_buffers
) {
394 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName() << " ("
395 << start
.InSecondsF() << ", " << end
.InSecondsF() << ", "
396 << exclude_start
<< ")";
397 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
398 << ": before remove ranges_=" << RangesToString(ranges_
);
400 DCHECK(start
>= DecodeTimestamp());
401 DCHECK(start
< end
) << "start " << start
.InSecondsF()
402 << " end " << end
.InSecondsF();
403 DCHECK(deleted_buffers
);
405 RangeList::iterator itr
= ranges_
.begin();
407 while (itr
!= ranges_
.end()) {
408 SourceBufferRange
* range
= *itr
;
409 if (range
->GetStartTimestamp() >= end
)
412 // Split off any remaining GOPs starting at or after |end| and add it to
414 SourceBufferRange
* new_range
= range
->SplitRange(end
);
416 itr
= ranges_
.insert(++itr
, new_range
);
419 // Update the selected range if the next buffer position was transferred
421 if (new_range
->HasNextBufferPosition())
422 SetSelectedRange(new_range
);
425 // Truncate the current range so that it only contains data before
426 // the removal range.
427 BufferQueue saved_buffers
;
428 bool delete_range
= range
->TruncateAt(start
, &saved_buffers
, exclude_start
);
430 // Check to see if the current playback position was removed and
431 // update the selected range appropriately.
432 if (!saved_buffers
.empty()) {
433 DCHECK(!range
->HasNextBufferPosition());
434 DCHECK(deleted_buffers
->empty());
436 *deleted_buffers
= saved_buffers
;
439 if (range
== selected_range_
&& !range
->HasNextBufferPosition())
440 SetSelectedRange(NULL
);
442 // If the current range now is completely covered by the removal
443 // range then delete it and move on.
445 DeleteAndRemoveRange(&itr
);
449 // Clear |range_for_next_append_| if we determine that the removal
450 // operation makes it impossible for the next append to be added
451 // to the current range.
452 if (range_for_next_append_
!= ranges_
.end() &&
453 *range_for_next_append_
== range
&&
454 last_appended_buffer_timestamp_
!= kNoDecodeTimestamp()) {
455 DecodeTimestamp potential_next_append_timestamp
=
456 last_appended_buffer_timestamp_
+
457 base::TimeDelta::FromInternalValue(1);
459 if (!range
->BelongsToRange(potential_next_append_timestamp
)) {
460 DVLOG(1) << "Resetting range_for_next_append_ since the next append"
461 << " can't add to the current range.";
462 range_for_next_append_
=
463 FindExistingRangeFor(potential_next_append_timestamp
);
467 // Move on to the next range.
471 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
472 << ": after remove ranges_=" << RangesToString(ranges_
);
474 DCHECK(IsRangeListSorted(ranges_
));
475 DCHECK(OnlySelectedRangeIsSeeked());
478 void SourceBufferStream::ResetSeekState() {
479 SetSelectedRange(NULL
);
480 track_buffer_
.clear();
481 config_change_pending_
= false;
482 last_output_buffer_timestamp_
= kNoDecodeTimestamp();
483 splice_buffers_index_
= 0;
484 pending_buffer_
= NULL
;
485 pending_buffers_complete_
= false;
488 bool SourceBufferStream::ShouldSeekToStartOfBuffered(
489 base::TimeDelta seek_timestamp
) const {
492 base::TimeDelta beginning_of_buffered
=
493 ranges_
.front()->GetStartTimestamp().ToPresentationTime();
494 return (seek_timestamp
<= beginning_of_buffered
&&
495 beginning_of_buffered
< kSeekToStartFudgeRoom());
498 bool SourceBufferStream::IsMonotonicallyIncreasing(
499 const BufferQueue
& buffers
) const {
500 DCHECK(!buffers
.empty());
501 DecodeTimestamp prev_timestamp
= last_appended_buffer_timestamp_
;
502 bool prev_is_keyframe
= last_appended_buffer_is_keyframe_
;
503 for (BufferQueue::const_iterator itr
= buffers
.begin();
504 itr
!= buffers
.end(); ++itr
) {
505 DecodeTimestamp current_timestamp
= (*itr
)->GetDecodeTimestamp();
506 bool current_is_keyframe
= (*itr
)->is_key_frame();
507 DCHECK(current_timestamp
!= kNoDecodeTimestamp());
508 DCHECK((*itr
)->duration() >= base::TimeDelta())
509 << "Packet with invalid duration."
510 << " pts " << (*itr
)->timestamp().InSecondsF()
511 << " dts " << (*itr
)->GetDecodeTimestamp().InSecondsF()
512 << " dur " << (*itr
)->duration().InSecondsF();
514 if (prev_timestamp
!= kNoDecodeTimestamp()) {
515 if (current_timestamp
< prev_timestamp
) {
516 MEDIA_LOG(ERROR
, log_cb_
) << "Buffers did not monotonically increase.";
520 if (current_timestamp
== prev_timestamp
&&
521 !SourceBufferRange::AllowSameTimestamp(prev_is_keyframe
,
522 current_is_keyframe
)) {
523 MEDIA_LOG(ERROR
, log_cb_
) << "Unexpected combination of buffers with"
524 << " the same timestamp detected at "
525 << current_timestamp
.InSecondsF();
530 prev_timestamp
= current_timestamp
;
531 prev_is_keyframe
= current_is_keyframe
;
536 bool SourceBufferStream::IsNextTimestampValid(
537 DecodeTimestamp next_timestamp
, bool next_is_keyframe
) const {
538 return (last_appended_buffer_timestamp_
!= next_timestamp
) ||
539 new_media_segment_
||
540 SourceBufferRange::AllowSameTimestamp(last_appended_buffer_is_keyframe_
,
545 bool SourceBufferStream::OnlySelectedRangeIsSeeked() const {
546 for (RangeList::const_iterator itr
= ranges_
.begin();
547 itr
!= ranges_
.end(); ++itr
) {
548 if ((*itr
)->HasNextBufferPosition() && (*itr
) != selected_range_
)
551 return !selected_range_
|| selected_range_
->HasNextBufferPosition();
554 void SourceBufferStream::UpdateMaxInterbufferDistance(
555 const BufferQueue
& buffers
) {
556 DCHECK(!buffers
.empty());
557 DecodeTimestamp prev_timestamp
= last_appended_buffer_timestamp_
;
558 for (BufferQueue::const_iterator itr
= buffers
.begin();
559 itr
!= buffers
.end(); ++itr
) {
560 DecodeTimestamp current_timestamp
= (*itr
)->GetDecodeTimestamp();
561 DCHECK(current_timestamp
!= kNoDecodeTimestamp());
563 base::TimeDelta interbuffer_distance
= (*itr
)->duration();
564 DCHECK(interbuffer_distance
>= base::TimeDelta());
566 if (prev_timestamp
!= kNoDecodeTimestamp()) {
567 interbuffer_distance
=
568 std::max(current_timestamp
- prev_timestamp
, interbuffer_distance
);
571 if (interbuffer_distance
> base::TimeDelta()) {
572 if (max_interbuffer_distance_
== kNoTimestamp()) {
573 max_interbuffer_distance_
= interbuffer_distance
;
575 max_interbuffer_distance_
=
576 std::max(max_interbuffer_distance_
, interbuffer_distance
);
579 prev_timestamp
= current_timestamp
;
583 void SourceBufferStream::SetConfigIds(const BufferQueue
& buffers
) {
584 for (BufferQueue::const_iterator itr
= buffers
.begin();
585 itr
!= buffers
.end(); ++itr
) {
586 (*itr
)->SetConfigId(append_config_index_
);
590 void SourceBufferStream::GarbageCollectIfNeeded() {
591 // Compute size of |ranges_|.
593 for (RangeList::iterator itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
)
594 ranges_size
+= (*itr
)->size_in_bytes();
596 // Return if we're under or at the memory limit.
597 if (ranges_size
<= memory_limit_
)
600 int bytes_to_free
= ranges_size
- memory_limit_
;
602 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName() << ": Before GC"
603 << " ranges_size=" << ranges_size
604 << " ranges_=" << RangesToString(ranges_
)
605 << " memory_limit_=" << memory_limit_
;
607 // Begin deleting after the last appended buffer.
608 int bytes_freed
= FreeBuffersAfterLastAppended(bytes_to_free
);
610 // Begin deleting from the front.
611 if (bytes_to_free
- bytes_freed
> 0)
612 bytes_freed
+= FreeBuffers(bytes_to_free
- bytes_freed
, false);
614 // Begin deleting from the back.
615 if (bytes_to_free
- bytes_freed
> 0)
616 bytes_freed
+= FreeBuffers(bytes_to_free
- bytes_freed
, true);
618 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName() << ": After GC"
619 << " bytes_freed=" << bytes_freed
620 << " ranges_=" << RangesToString(ranges_
);
623 int SourceBufferStream::FreeBuffersAfterLastAppended(int total_bytes_to_free
) {
624 DecodeTimestamp next_buffer_timestamp
= GetNextBufferTimestamp();
625 if (last_appended_buffer_timestamp_
== kNoDecodeTimestamp() ||
626 next_buffer_timestamp
== kNoDecodeTimestamp() ||
627 last_appended_buffer_timestamp_
>= next_buffer_timestamp
) {
631 DecodeTimestamp remove_range_start
= last_appended_buffer_timestamp_
;
632 if (last_appended_buffer_is_keyframe_
)
633 remove_range_start
+= GetMaxInterbufferDistance();
635 DecodeTimestamp remove_range_start_keyframe
= FindKeyframeAfterTimestamp(
637 if (remove_range_start_keyframe
!= kNoDecodeTimestamp())
638 remove_range_start
= remove_range_start_keyframe
;
639 if (remove_range_start
>= next_buffer_timestamp
)
642 DecodeTimestamp remove_range_end
;
643 int bytes_freed
= GetRemovalRange(
644 remove_range_start
, next_buffer_timestamp
, total_bytes_to_free
,
646 if (bytes_freed
> 0) {
647 Remove(remove_range_start
.ToPresentationTime(),
648 remove_range_end
.ToPresentationTime(),
649 next_buffer_timestamp
.ToPresentationTime());
655 int SourceBufferStream::GetRemovalRange(
656 DecodeTimestamp start_timestamp
, DecodeTimestamp end_timestamp
,
657 int total_bytes_to_free
, DecodeTimestamp
* removal_end_timestamp
) {
658 DCHECK(start_timestamp
>= DecodeTimestamp()) << start_timestamp
.InSecondsF();
659 DCHECK(start_timestamp
< end_timestamp
)
660 << "start " << start_timestamp
.InSecondsF()
661 << ", end " << end_timestamp
.InSecondsF();
663 int bytes_to_free
= total_bytes_to_free
;
666 for (RangeList::iterator itr
= ranges_
.begin();
667 itr
!= ranges_
.end() && bytes_to_free
> 0; ++itr
) {
668 SourceBufferRange
* range
= *itr
;
669 if (range
->GetStartTimestamp() >= end_timestamp
)
671 if (range
->GetEndTimestamp() < start_timestamp
)
674 int bytes_removed
= range
->GetRemovalGOP(
675 start_timestamp
, end_timestamp
, bytes_to_free
, removal_end_timestamp
);
676 bytes_to_free
-= bytes_removed
;
677 bytes_freed
+= bytes_removed
;
682 int SourceBufferStream::FreeBuffers(int total_bytes_to_free
,
683 bool reverse_direction
) {
684 TRACE_EVENT2("media", "SourceBufferStream::FreeBuffers",
685 "total bytes to free", total_bytes_to_free
,
686 "reverse direction", reverse_direction
);
688 DCHECK_GT(total_bytes_to_free
, 0);
689 int bytes_to_free
= total_bytes_to_free
;
692 // This range will save the last GOP appended to |range_for_next_append_|
693 // if the buffers surrounding it get deleted during garbage collection.
694 SourceBufferRange
* new_range_for_append
= NULL
;
696 while (!ranges_
.empty() && bytes_to_free
> 0) {
697 SourceBufferRange
* current_range
= NULL
;
699 int bytes_deleted
= 0;
701 if (reverse_direction
) {
702 current_range
= ranges_
.back();
703 if (current_range
->LastGOPContainsNextBufferPosition()) {
704 DCHECK_EQ(current_range
, selected_range_
);
707 bytes_deleted
= current_range
->DeleteGOPFromBack(&buffers
);
709 current_range
= ranges_
.front();
710 if (current_range
->FirstGOPContainsNextBufferPosition()) {
711 DCHECK_EQ(current_range
, selected_range_
);
714 bytes_deleted
= current_range
->DeleteGOPFromFront(&buffers
);
717 // Check to see if we've just deleted the GOP that was last appended.
718 DecodeTimestamp end_timestamp
= buffers
.back()->GetDecodeTimestamp();
719 if (end_timestamp
== last_appended_buffer_timestamp_
) {
720 DCHECK(last_appended_buffer_timestamp_
!= kNoDecodeTimestamp());
721 DCHECK(!new_range_for_append
);
722 // Create a new range containing these buffers.
723 new_range_for_append
= new SourceBufferRange(
724 TypeToGapPolicy(GetType()),
725 buffers
, kNoDecodeTimestamp(),
726 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance
,
727 base::Unretained(this)));
728 range_for_next_append_
= ranges_
.end();
730 bytes_to_free
-= bytes_deleted
;
731 bytes_freed
+= bytes_deleted
;
734 if (current_range
->size_in_bytes() == 0) {
735 DCHECK_NE(current_range
, selected_range_
);
736 DCHECK(range_for_next_append_
== ranges_
.end() ||
737 *range_for_next_append_
!= current_range
);
738 delete current_range
;
739 reverse_direction
? ranges_
.pop_back() : ranges_
.pop_front();
743 // Insert |new_range_for_append| into |ranges_|, if applicable.
744 if (new_range_for_append
) {
745 range_for_next_append_
= AddToRanges(new_range_for_append
);
746 DCHECK(range_for_next_append_
!= ranges_
.end());
748 // Check to see if we need to merge |new_range_for_append| with the range
749 // before or after it. |new_range_for_append| is created whenever the last
750 // GOP appended is encountered, regardless of whether any buffers after it
751 // are ultimately deleted. Merging is necessary if there were no buffers
752 // (or very few buffers) deleted after creating |new_range_for_append|.
753 if (range_for_next_append_
!= ranges_
.begin()) {
754 RangeList::iterator range_before_next
= range_for_next_append_
;
756 MergeWithAdjacentRangeIfNecessary(range_before_next
);
758 MergeWithAdjacentRangeIfNecessary(range_for_next_append_
);
763 void SourceBufferStream::PrepareRangesForNextAppend(
764 const BufferQueue
& new_buffers
, BufferQueue
* deleted_buffers
) {
765 DCHECK(deleted_buffers
);
767 bool temporarily_select_range
= false;
768 if (!track_buffer_
.empty()) {
769 DecodeTimestamp tb_timestamp
= track_buffer_
.back()->GetDecodeTimestamp();
770 DecodeTimestamp seek_timestamp
= FindKeyframeAfterTimestamp(tb_timestamp
);
771 if (seek_timestamp
!= kNoDecodeTimestamp() &&
772 seek_timestamp
< new_buffers
.front()->GetDecodeTimestamp() &&
773 range_for_next_append_
!= ranges_
.end() &&
774 (*range_for_next_append_
)->BelongsToRange(seek_timestamp
)) {
775 DCHECK(tb_timestamp
< seek_timestamp
);
776 DCHECK(!selected_range_
);
777 DCHECK(!(*range_for_next_append_
)->HasNextBufferPosition());
779 // If there are GOPs between the end of the track buffer and the
780 // beginning of the new buffers, then temporarily seek the range
781 // so that the buffers between these two times will be deposited in
782 // |deleted_buffers| as if they were part of the current playback
784 // TODO(acolwell): Figure out a more elegant way to do this.
785 SeekAndSetSelectedRange(*range_for_next_append_
, seek_timestamp
);
786 temporarily_select_range
= true;
790 // Handle splices between the existing buffers and the new buffers. If a
791 // splice is generated the timestamp and duration of the first buffer in
792 // |new_buffers| will be modified.
793 if (splice_frames_enabled_
)
794 GenerateSpliceFrame(new_buffers
);
796 DecodeTimestamp prev_timestamp
= last_appended_buffer_timestamp_
;
797 bool prev_is_keyframe
= last_appended_buffer_is_keyframe_
;
798 DecodeTimestamp next_timestamp
= new_buffers
.front()->GetDecodeTimestamp();
799 bool next_is_keyframe
= new_buffers
.front()->is_key_frame();
801 if (prev_timestamp
!= kNoDecodeTimestamp() &&
802 prev_timestamp
!= next_timestamp
) {
803 // Clean up the old buffers between the last appended buffer and the
804 // beginning of |new_buffers|.
805 RemoveInternal(prev_timestamp
, next_timestamp
, true, deleted_buffers
);
808 // Make the delete range exclusive if we are dealing with an allowed same
809 // timestamp situation. This prevents the first buffer in the current append
810 // from deleting the last buffer in the previous append if both buffers
811 // have the same timestamp.
813 // The delete range should never be exclusive if a splice frame was generated
814 // because we don't generate splice frames for same timestamp situations.
815 DCHECK(new_buffers
.front()->splice_timestamp() !=
816 new_buffers
.front()->timestamp());
817 const bool exclude_start
=
818 new_buffers
.front()->splice_buffers().empty() &&
819 prev_timestamp
== next_timestamp
&&
820 SourceBufferRange::AllowSameTimestamp(prev_is_keyframe
, next_is_keyframe
);
822 // Delete the buffers that |new_buffers| overlaps.
823 DecodeTimestamp start
= new_buffers
.front()->GetDecodeTimestamp();
824 DecodeTimestamp end
= new_buffers
.back()->GetDecodeTimestamp();
825 base::TimeDelta duration
= new_buffers
.back()->duration();
827 if (duration
!= kNoTimestamp() && duration
> base::TimeDelta()) {
830 // TODO(acolwell): Ensure all buffers actually have proper
831 // duration info so that this hack isn't needed.
832 // http://crbug.com/312836
833 end
+= base::TimeDelta::FromInternalValue(1);
836 RemoveInternal(start
, end
, exclude_start
, deleted_buffers
);
838 // Restore the range seek state if necessary.
839 if (temporarily_select_range
)
840 SetSelectedRange(NULL
);
843 bool SourceBufferStream::AreAdjacentInSequence(
844 DecodeTimestamp first_timestamp
, DecodeTimestamp second_timestamp
) const {
845 return first_timestamp
< second_timestamp
&&
847 first_timestamp
+ ComputeFudgeRoom(GetMaxInterbufferDistance());
850 void SourceBufferStream::PruneTrackBuffer(const DecodeTimestamp timestamp
) {
851 // If we don't have the next timestamp, we don't have anything to delete.
852 if (timestamp
== kNoDecodeTimestamp())
855 while (!track_buffer_
.empty() &&
856 track_buffer_
.back()->GetDecodeTimestamp() >= timestamp
) {
857 track_buffer_
.pop_back();
861 void SourceBufferStream::MergeWithAdjacentRangeIfNecessary(
862 const RangeList::iterator
& range_with_new_buffers_itr
) {
863 DCHECK(range_with_new_buffers_itr
!= ranges_
.end());
865 SourceBufferRange
* range_with_new_buffers
= *range_with_new_buffers_itr
;
866 RangeList::iterator next_range_itr
= range_with_new_buffers_itr
;
869 if (next_range_itr
== ranges_
.end() ||
870 !range_with_new_buffers
->CanAppendRangeToEnd(**next_range_itr
)) {
874 bool transfer_current_position
= selected_range_
== *next_range_itr
;
875 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
876 << " merging " << RangeToString(*range_with_new_buffers
)
877 << " into " << RangeToString(**next_range_itr
);
878 range_with_new_buffers
->AppendRangeToEnd(**next_range_itr
,
879 transfer_current_position
);
880 // Update |selected_range_| pointer if |range| has become selected after
882 if (transfer_current_position
)
883 SetSelectedRange(range_with_new_buffers
);
885 if (next_range_itr
== range_for_next_append_
)
886 range_for_next_append_
= range_with_new_buffers_itr
;
888 DeleteAndRemoveRange(&next_range_itr
);
891 void SourceBufferStream::Seek(base::TimeDelta timestamp
) {
892 DCHECK(timestamp
>= base::TimeDelta());
893 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
894 << " (" << timestamp
.InSecondsF() << ")";
897 if (ShouldSeekToStartOfBuffered(timestamp
)) {
898 ranges_
.front()->SeekToStart();
899 SetSelectedRange(ranges_
.front());
900 seek_pending_
= false;
904 seek_buffer_timestamp_
= timestamp
;
905 seek_pending_
= true;
907 DecodeTimestamp seek_dts
= DecodeTimestamp::FromPresentationTime(timestamp
);
909 RangeList::iterator itr
= ranges_
.end();
910 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
911 if ((*itr
)->CanSeekTo(seek_dts
))
915 if (itr
== ranges_
.end())
918 SeekAndSetSelectedRange(*itr
, seek_dts
);
919 seek_pending_
= false;
922 bool SourceBufferStream::IsSeekPending() const {
923 return !(end_of_stream_
&& IsEndSelected()) && seek_pending_
;
926 void SourceBufferStream::OnSetDuration(base::TimeDelta duration
) {
927 DecodeTimestamp duration_dts
=
928 DecodeTimestamp::FromPresentationTime(duration
);
929 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
930 << " (" << duration
.InSecondsF() << ")";
932 RangeList::iterator itr
= ranges_
.end();
933 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
934 if ((*itr
)->GetEndTimestamp() > duration_dts
)
937 if (itr
== ranges_
.end())
940 // Need to partially truncate this range.
941 if ((*itr
)->GetStartTimestamp() < duration_dts
) {
942 bool delete_range
= (*itr
)->TruncateAt(duration_dts
, NULL
, false);
943 if ((*itr
== selected_range_
) && !selected_range_
->HasNextBufferPosition())
944 SetSelectedRange(NULL
);
947 DeleteAndRemoveRange(&itr
);
953 // Delete all ranges that begin after |duration_dts|.
954 while (itr
!= ranges_
.end()) {
955 // If we're about to delete the selected range, also reset the seek state.
956 DCHECK((*itr
)->GetStartTimestamp() >= duration_dts
);
957 if (*itr
== selected_range_
)
959 DeleteAndRemoveRange(&itr
);
963 SourceBufferStream::Status
SourceBufferStream::GetNextBuffer(
964 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
965 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName();
966 if (!pending_buffer_
.get()) {
967 const SourceBufferStream::Status status
= GetNextBufferInternal(out_buffer
);
968 if (status
!= SourceBufferStream::kSuccess
||
969 !SetPendingBuffer(out_buffer
)) {
970 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
971 << ": no pending buffer, returning status " << status
;
976 if (!pending_buffer_
->splice_buffers().empty()) {
977 const SourceBufferStream::Status status
=
978 HandleNextBufferWithSplice(out_buffer
);
979 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
980 << ": handled next buffer with splice, returning status "
985 DCHECK(pending_buffer_
->preroll_buffer().get());
987 const SourceBufferStream::Status status
=
988 HandleNextBufferWithPreroll(out_buffer
);
989 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
990 << ": handled next buffer with preroll, returning status "
995 SourceBufferStream::Status
SourceBufferStream::HandleNextBufferWithSplice(
996 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
997 const BufferQueue
& splice_buffers
= pending_buffer_
->splice_buffers();
998 const size_t last_splice_buffer_index
= splice_buffers
.size() - 1;
1000 // Are there any splice buffers left to hand out? The last buffer should be
1001 // handed out separately since it represents the first post-splice buffer.
1002 if (splice_buffers_index_
< last_splice_buffer_index
) {
1003 // Account for config changes which occur between fade out buffers.
1004 if (current_config_index_
!=
1005 splice_buffers
[splice_buffers_index_
]->GetConfigId()) {
1006 config_change_pending_
= true;
1007 DVLOG(1) << "Config change (splice buffer config ID does not match).";
1008 return SourceBufferStream::kConfigChange
;
1011 // Every pre splice buffer must have the same splice_timestamp().
1012 DCHECK(pending_buffer_
->splice_timestamp() ==
1013 splice_buffers
[splice_buffers_index_
]->splice_timestamp());
1015 // No pre splice buffers should have preroll.
1016 DCHECK(!splice_buffers
[splice_buffers_index_
]->preroll_buffer().get());
1018 *out_buffer
= splice_buffers
[splice_buffers_index_
++];
1019 return SourceBufferStream::kSuccess
;
1022 // Did we hand out the last pre-splice buffer on the previous call?
1023 if (!pending_buffers_complete_
) {
1024 DCHECK_EQ(splice_buffers_index_
, last_splice_buffer_index
);
1025 pending_buffers_complete_
= true;
1026 config_change_pending_
= true;
1027 DVLOG(1) << "Config change (forced for fade in of splice frame).";
1028 return SourceBufferStream::kConfigChange
;
1031 // All pre-splice buffers have been handed out and a config change completed,
1032 // so hand out the final buffer for fade in. Because a config change is
1033 // always issued prior to handing out this buffer, any changes in config id
1034 // have been inherently handled.
1035 DCHECK(pending_buffers_complete_
);
1036 DCHECK_EQ(splice_buffers_index_
, splice_buffers
.size() - 1);
1037 DCHECK(splice_buffers
.back()->splice_timestamp() == kNoTimestamp());
1038 *out_buffer
= splice_buffers
.back();
1039 pending_buffer_
= NULL
;
1041 // If the last splice buffer has preroll, hand off to the preroll handler.
1042 return SetPendingBuffer(out_buffer
) ? HandleNextBufferWithPreroll(out_buffer
)
1043 : SourceBufferStream::kSuccess
;
1046 SourceBufferStream::Status
SourceBufferStream::HandleNextBufferWithPreroll(
1047 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1048 // Any config change should have already been handled.
1049 DCHECK_EQ(current_config_index_
, pending_buffer_
->GetConfigId());
1051 // Check if the preroll buffer has already been handed out.
1052 if (!pending_buffers_complete_
) {
1053 pending_buffers_complete_
= true;
1054 *out_buffer
= pending_buffer_
->preroll_buffer();
1055 return SourceBufferStream::kSuccess
;
1058 // Preroll complete, hand out the final buffer.
1059 *out_buffer
= pending_buffer_
;
1060 pending_buffer_
= NULL
;
1061 return SourceBufferStream::kSuccess
;
1064 SourceBufferStream::Status
SourceBufferStream::GetNextBufferInternal(
1065 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1066 CHECK(!config_change_pending_
);
1068 if (!track_buffer_
.empty()) {
1069 DCHECK(!selected_range_
);
1070 scoped_refptr
<StreamParserBuffer
>& next_buffer
= track_buffer_
.front();
1072 // If the next buffer is an audio splice frame, the next effective config id
1073 // comes from the first splice buffer.
1074 if (next_buffer
->GetSpliceBufferConfigId(0) != current_config_index_
) {
1075 config_change_pending_
= true;
1076 DVLOG(1) << "Config change (track buffer config ID does not match).";
1077 return kConfigChange
;
1080 *out_buffer
= next_buffer
;
1081 track_buffer_
.pop_front();
1082 last_output_buffer_timestamp_
= (*out_buffer
)->GetDecodeTimestamp();
1084 // If the track buffer becomes empty, then try to set the selected range
1085 // based on the timestamp of this buffer being returned.
1086 if (track_buffer_
.empty())
1087 SetSelectedRangeIfNeeded(last_output_buffer_timestamp_
);
1092 if (!selected_range_
|| !selected_range_
->HasNextBuffer()) {
1093 if (end_of_stream_
&& IsEndSelected())
1094 return kEndOfStream
;
1095 DVLOG(3) << __FUNCTION__
<< " " << GetStreamTypeName()
1096 << ": returning kNeedBuffer "
1097 << (selected_range_
? "(selected range has no next buffer)"
1098 : "(no selected range)");
1102 if (selected_range_
->GetNextConfigId() != current_config_index_
) {
1103 config_change_pending_
= true;
1104 DVLOG(1) << "Config change (selected range config ID does not match).";
1105 return kConfigChange
;
1108 CHECK(selected_range_
->GetNextBuffer(out_buffer
));
1109 last_output_buffer_timestamp_
= (*out_buffer
)->GetDecodeTimestamp();
1113 DecodeTimestamp
SourceBufferStream::GetNextBufferTimestamp() {
1114 if (!track_buffer_
.empty())
1115 return track_buffer_
.front()->GetDecodeTimestamp();
1117 if (!selected_range_
)
1118 return kNoDecodeTimestamp();
1120 DCHECK(selected_range_
->HasNextBufferPosition());
1121 return selected_range_
->GetNextTimestamp();
1124 SourceBufferStream::RangeList::iterator
1125 SourceBufferStream::FindExistingRangeFor(DecodeTimestamp start_timestamp
) {
1126 for (RangeList::iterator itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1127 if ((*itr
)->BelongsToRange(start_timestamp
))
1130 return ranges_
.end();
1133 SourceBufferStream::RangeList::iterator
1134 SourceBufferStream::AddToRanges(SourceBufferRange
* new_range
) {
1135 DecodeTimestamp start_timestamp
= new_range
->GetStartTimestamp();
1136 RangeList::iterator itr
= ranges_
.end();
1137 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1138 if ((*itr
)->GetStartTimestamp() > start_timestamp
)
1141 return ranges_
.insert(itr
, new_range
);
1144 SourceBufferStream::RangeList::iterator
1145 SourceBufferStream::GetSelectedRangeItr() {
1146 DCHECK(selected_range_
);
1147 RangeList::iterator itr
= ranges_
.end();
1148 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1149 if (*itr
== selected_range_
)
1152 DCHECK(itr
!= ranges_
.end());
1156 void SourceBufferStream::SeekAndSetSelectedRange(
1157 SourceBufferRange
* range
, DecodeTimestamp seek_timestamp
) {
1159 range
->Seek(seek_timestamp
);
1160 SetSelectedRange(range
);
1163 void SourceBufferStream::SetSelectedRange(SourceBufferRange
* range
) {
1164 DVLOG(1) << __FUNCTION__
<< " " << GetStreamTypeName()
1165 << ": " << selected_range_
<< " -> " << range
;
1166 if (selected_range_
)
1167 selected_range_
->ResetNextBufferPosition();
1168 DCHECK(!range
|| range
->HasNextBufferPosition());
1169 selected_range_
= range
;
1172 Ranges
<base::TimeDelta
> SourceBufferStream::GetBufferedTime() const {
1173 Ranges
<base::TimeDelta
> ranges
;
1174 for (RangeList::const_iterator itr
= ranges_
.begin();
1175 itr
!= ranges_
.end(); ++itr
) {
1176 ranges
.Add((*itr
)->GetStartTimestamp().ToPresentationTime(),
1177 (*itr
)->GetBufferedEndTimestamp().ToPresentationTime());
1182 base::TimeDelta
SourceBufferStream::GetBufferedDuration() const {
1183 if (ranges_
.empty())
1184 return base::TimeDelta();
1186 return ranges_
.back()->GetBufferedEndTimestamp().ToPresentationTime();
1189 void SourceBufferStream::MarkEndOfStream() {
1190 DCHECK(!end_of_stream_
);
1191 end_of_stream_
= true;
1194 void SourceBufferStream::UnmarkEndOfStream() {
1195 DCHECK(end_of_stream_
);
1196 end_of_stream_
= false;
1199 bool SourceBufferStream::IsEndSelected() const {
1200 if (ranges_
.empty())
1203 if (seek_pending_
) {
1204 base::TimeDelta last_range_end_time
=
1205 ranges_
.back()->GetBufferedEndTimestamp().ToPresentationTime();
1206 return seek_buffer_timestamp_
>= last_range_end_time
;
1209 return selected_range_
== ranges_
.back();
1212 const AudioDecoderConfig
& SourceBufferStream::GetCurrentAudioDecoderConfig() {
1213 if (config_change_pending_
)
1214 CompleteConfigChange();
1215 return audio_configs_
[current_config_index_
];
1218 const VideoDecoderConfig
& SourceBufferStream::GetCurrentVideoDecoderConfig() {
1219 if (config_change_pending_
)
1220 CompleteConfigChange();
1221 return video_configs_
[current_config_index_
];
1224 const TextTrackConfig
& SourceBufferStream::GetCurrentTextTrackConfig() {
1225 return text_track_config_
;
1228 base::TimeDelta
SourceBufferStream::GetMaxInterbufferDistance() const {
1229 if (max_interbuffer_distance_
== kNoTimestamp())
1230 return base::TimeDelta::FromMilliseconds(kDefaultBufferDurationInMs
);
1231 return max_interbuffer_distance_
;
1234 bool SourceBufferStream::UpdateAudioConfig(const AudioDecoderConfig
& config
) {
1235 DCHECK(!audio_configs_
.empty());
1236 DCHECK(video_configs_
.empty());
1237 DVLOG(3) << "UpdateAudioConfig.";
1239 if (audio_configs_
[0].codec() != config
.codec()) {
1240 MEDIA_LOG(ERROR
, log_cb_
) << "Audio codec changes not allowed.";
1244 if (audio_configs_
[0].is_encrypted() != config
.is_encrypted()) {
1245 MEDIA_LOG(ERROR
, log_cb_
) << "Audio encryption changes not allowed.";
1249 // Check to see if the new config matches an existing one.
1250 for (size_t i
= 0; i
< audio_configs_
.size(); ++i
) {
1251 if (config
.Matches(audio_configs_
[i
])) {
1252 append_config_index_
= i
;
1257 // No matches found so let's add this one to the list.
1258 append_config_index_
= audio_configs_
.size();
1259 DVLOG(2) << "New audio config - index: " << append_config_index_
;
1260 audio_configs_
.resize(audio_configs_
.size() + 1);
1261 audio_configs_
[append_config_index_
] = config
;
1265 bool SourceBufferStream::UpdateVideoConfig(const VideoDecoderConfig
& config
) {
1266 DCHECK(!video_configs_
.empty());
1267 DCHECK(audio_configs_
.empty());
1268 DVLOG(3) << "UpdateVideoConfig.";
1270 if (video_configs_
[0].codec() != config
.codec()) {
1271 MEDIA_LOG(ERROR
, log_cb_
) << "Video codec changes not allowed.";
1275 if (video_configs_
[0].is_encrypted() != config
.is_encrypted()) {
1276 MEDIA_LOG(ERROR
, log_cb_
) << "Video encryption changes not allowed.";
1280 // Check to see if the new config matches an existing one.
1281 for (size_t i
= 0; i
< video_configs_
.size(); ++i
) {
1282 if (config
.Matches(video_configs_
[i
])) {
1283 append_config_index_
= i
;
1288 // No matches found so let's add this one to the list.
1289 append_config_index_
= video_configs_
.size();
1290 DVLOG(2) << "New video config - index: " << append_config_index_
;
1291 video_configs_
.resize(video_configs_
.size() + 1);
1292 video_configs_
[append_config_index_
] = config
;
1296 void SourceBufferStream::CompleteConfigChange() {
1297 config_change_pending_
= false;
1299 if (pending_buffer_
.get()) {
1300 current_config_index_
=
1301 pending_buffer_
->GetSpliceBufferConfigId(splice_buffers_index_
);
1305 if (!track_buffer_
.empty()) {
1306 current_config_index_
= track_buffer_
.front()->GetSpliceBufferConfigId(0);
1310 if (selected_range_
&& selected_range_
->HasNextBuffer())
1311 current_config_index_
= selected_range_
->GetNextConfigId();
1314 void SourceBufferStream::SetSelectedRangeIfNeeded(
1315 const DecodeTimestamp timestamp
) {
1316 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1317 << "(" << timestamp
.InSecondsF() << ")";
1319 if (selected_range_
) {
1320 DCHECK(track_buffer_
.empty());
1324 if (!track_buffer_
.empty()) {
1325 DCHECK(!selected_range_
);
1329 DecodeTimestamp start_timestamp
= timestamp
;
1331 // If the next buffer timestamp is not known then use a timestamp just after
1332 // the timestamp on the last buffer returned by GetNextBuffer().
1333 if (start_timestamp
== kNoDecodeTimestamp()) {
1334 if (last_output_buffer_timestamp_
== kNoDecodeTimestamp()) {
1335 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1336 << " no previous output timestamp";
1340 start_timestamp
= last_output_buffer_timestamp_
+
1341 base::TimeDelta::FromInternalValue(1);
1344 DecodeTimestamp seek_timestamp
=
1345 FindNewSelectedRangeSeekTimestamp(start_timestamp
);
1347 // If we don't have buffered data to seek to, then return.
1348 if (seek_timestamp
== kNoDecodeTimestamp()) {
1349 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1350 << " couldn't find new selected range seek timestamp";
1354 DCHECK(track_buffer_
.empty());
1355 SeekAndSetSelectedRange(*FindExistingRangeFor(seek_timestamp
),
1359 DecodeTimestamp
SourceBufferStream::FindNewSelectedRangeSeekTimestamp(
1360 const DecodeTimestamp start_timestamp
) {
1361 DCHECK(start_timestamp
!= kNoDecodeTimestamp());
1362 DCHECK(start_timestamp
>= DecodeTimestamp());
1364 RangeList::iterator itr
= ranges_
.begin();
1366 for (; itr
!= ranges_
.end(); ++itr
) {
1367 if ((*itr
)->GetEndTimestamp() >= start_timestamp
) {
1372 if (itr
== ranges_
.end()) {
1373 DVLOG(2) << __FUNCTION__
<< " " << GetStreamTypeName()
1374 << " no buffered data for dts=" << start_timestamp
.InSecondsF();
1375 return kNoDecodeTimestamp();
1378 // First check for a keyframe timestamp >= |start_timestamp|
1379 // in the current range.
1380 DecodeTimestamp keyframe_timestamp
=
1381 (*itr
)->NextKeyframeTimestamp(start_timestamp
);
1383 if (keyframe_timestamp
!= kNoDecodeTimestamp())
1384 return keyframe_timestamp
;
1386 // If a keyframe was not found then look for a keyframe that is
1387 // "close enough" in the current or next range.
1388 DecodeTimestamp end_timestamp
=
1389 start_timestamp
+ ComputeFudgeRoom(GetMaxInterbufferDistance());
1390 DCHECK(start_timestamp
< end_timestamp
);
1392 // Make sure the current range doesn't start beyond |end_timestamp|.
1393 if ((*itr
)->GetStartTimestamp() >= end_timestamp
)
1394 return kNoDecodeTimestamp();
1396 keyframe_timestamp
= (*itr
)->KeyframeBeforeTimestamp(end_timestamp
);
1398 // Check to see if the keyframe is within the acceptable range
1399 // (|start_timestamp|, |end_timestamp|].
1400 if (keyframe_timestamp
!= kNoDecodeTimestamp() &&
1401 start_timestamp
< keyframe_timestamp
&&
1402 keyframe_timestamp
<= end_timestamp
) {
1403 return keyframe_timestamp
;
1406 // If |end_timestamp| is within this range, then no other checks are
1408 if (end_timestamp
<= (*itr
)->GetEndTimestamp())
1409 return kNoDecodeTimestamp();
1411 // Move on to the next range.
1414 // Return early if the next range does not contain |end_timestamp|.
1415 if (itr
== ranges_
.end() || (*itr
)->GetStartTimestamp() >= end_timestamp
)
1416 return kNoDecodeTimestamp();
1418 keyframe_timestamp
= (*itr
)->KeyframeBeforeTimestamp(end_timestamp
);
1420 // Check to see if the keyframe is within the acceptable range
1421 // (|start_timestamp|, |end_timestamp|].
1422 if (keyframe_timestamp
!= kNoDecodeTimestamp() &&
1423 start_timestamp
< keyframe_timestamp
&&
1424 keyframe_timestamp
<= end_timestamp
) {
1425 return keyframe_timestamp
;
1428 return kNoDecodeTimestamp();
1431 DecodeTimestamp
SourceBufferStream::FindKeyframeAfterTimestamp(
1432 const DecodeTimestamp timestamp
) {
1433 DCHECK(timestamp
!= kNoDecodeTimestamp());
1435 RangeList::iterator itr
= FindExistingRangeFor(timestamp
);
1437 if (itr
== ranges_
.end())
1438 return kNoDecodeTimestamp();
1440 // First check for a keyframe timestamp >= |timestamp|
1441 // in the current range.
1442 return (*itr
)->NextKeyframeTimestamp(timestamp
);
1445 std::string
SourceBufferStream::GetStreamTypeName() const {
1446 switch (GetType()) {
1458 SourceBufferStream::Type
SourceBufferStream::GetType() const {
1459 if (!audio_configs_
.empty())
1461 if (!video_configs_
.empty())
1463 DCHECK_NE(text_track_config_
.kind(), kTextNone
);
1467 void SourceBufferStream::DeleteAndRemoveRange(RangeList::iterator
* itr
) {
1468 DVLOG(1) << __FUNCTION__
;
1470 DCHECK(*itr
!= ranges_
.end());
1471 if (**itr
== selected_range_
) {
1472 DVLOG(1) << __FUNCTION__
<< " deleting selected range.";
1473 SetSelectedRange(NULL
);
1476 if (*itr
== range_for_next_append_
) {
1477 DVLOG(1) << __FUNCTION__
<< " deleting range_for_next_append_.";
1478 range_for_next_append_
= ranges_
.end();
1479 last_appended_buffer_timestamp_
= kNoDecodeTimestamp();
1480 last_appended_buffer_is_keyframe_
= false;
1484 *itr
= ranges_
.erase(*itr
);
1487 void SourceBufferStream::GenerateSpliceFrame(const BufferQueue
& new_buffers
) {
1488 DCHECK(!new_buffers
.empty());
1490 // Splice frames are only supported for audio.
1491 if (GetType() != kAudio
)
1494 // Find the overlapped range (if any).
1495 const base::TimeDelta splice_timestamp
= new_buffers
.front()->timestamp();
1496 const DecodeTimestamp splice_dts
=
1497 DecodeTimestamp::FromPresentationTime(splice_timestamp
);
1498 RangeList::iterator range_itr
= FindExistingRangeFor(splice_dts
);
1499 if (range_itr
== ranges_
.end())
1502 const DecodeTimestamp max_splice_end_dts
=
1503 splice_dts
+ base::TimeDelta::FromMilliseconds(
1504 AudioSplicer::kCrossfadeDurationInMilliseconds
);
1506 // Find all buffers involved before the splice point.
1507 BufferQueue pre_splice_buffers
;
1508 if (!(*range_itr
)->GetBuffersInRange(
1509 splice_dts
, max_splice_end_dts
, &pre_splice_buffers
)) {
1513 // If there are gaps in the timeline, it's possible that we only find buffers
1514 // after the splice point but within the splice range. For simplicity, we do
1515 // not generate splice frames in this case.
1517 // We also do not want to generate splices if the first new buffer replaces an
1518 // existing buffer exactly.
1519 if (pre_splice_buffers
.front()->timestamp() >= splice_timestamp
)
1522 // If any |pre_splice_buffers| are already splices or preroll, do not generate
1524 for (size_t i
= 0; i
< pre_splice_buffers
.size(); ++i
) {
1525 const BufferQueue
& original_splice_buffers
=
1526 pre_splice_buffers
[i
]->splice_buffers();
1527 if (!original_splice_buffers
.empty()) {
1528 DVLOG(1) << "Can't generate splice: overlapped buffers contain a "
1529 "pre-existing splice.";
1533 if (pre_splice_buffers
[i
]->preroll_buffer().get()) {
1534 DVLOG(1) << "Can't generate splice: overlapped buffers contain preroll.";
1539 // Don't generate splice frames which represent less than two frames, since we
1540 // need at least that much to generate a crossfade. Per the spec, make this
1541 // check using the sample rate of the overlapping buffers.
1542 const base::TimeDelta splice_duration
=
1543 pre_splice_buffers
.back()->timestamp() +
1544 pre_splice_buffers
.back()->duration() - splice_timestamp
;
1545 const base::TimeDelta minimum_splice_duration
= base::TimeDelta::FromSecondsD(
1546 2.0 / audio_configs_
[append_config_index_
].samples_per_second());
1547 if (splice_duration
< minimum_splice_duration
) {
1548 DVLOG(1) << "Can't generate splice: not enough samples for crossfade; have "
1549 << splice_duration
.InMicroseconds() << " us, but need "
1550 << minimum_splice_duration
.InMicroseconds() << " us.";
1554 new_buffers
.front()->ConvertToSpliceBuffer(pre_splice_buffers
);
1557 bool SourceBufferStream::SetPendingBuffer(
1558 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1559 DCHECK(out_buffer
->get());
1560 DCHECK(!pending_buffer_
.get());
1562 const bool have_splice_buffers
= !(*out_buffer
)->splice_buffers().empty();
1563 const bool have_preroll_buffer
= !!(*out_buffer
)->preroll_buffer().get();
1565 if (!have_splice_buffers
&& !have_preroll_buffer
)
1568 DCHECK_NE(have_splice_buffers
, have_preroll_buffer
);
1569 splice_buffers_index_
= 0;
1570 pending_buffer_
.swap(*out_buffer
);
1571 pending_buffers_complete_
= false;
1575 } // namespace media