1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/filters/source_buffer_stream.h"
10 #include "base/bind.h"
11 #include "base/debug/trace_event.h"
12 #include "base/logging.h"
13 #include "media/base/audio_splicer.h"
14 #include "media/filters/source_buffer_platform.h"
18 typedef StreamParser::BufferQueue BufferQueue
;
20 // Buffers with the same timestamp are only allowed under certain conditions.
21 // More precisely, it is allowed in all situations except when the previous
22 // frame is not a key frame and the current is a key frame.
23 // Examples of situations where DTS of two consecutive frames can be equal:
24 // - Video: VP8 Alt-Ref frames.
25 // - Video: IPBPBP...: DTS for I frame and for P frame can be equal.
26 // - Text track cues that start at same time.
27 // Returns true if |prev_is_keyframe| and |current_is_keyframe| indicate a
28 // same timestamp situation that is allowed. False is returned otherwise.
29 static bool AllowSameTimestamp(
30 bool prev_is_keyframe
, bool current_is_keyframe
,
31 SourceBufferStream::Type type
) {
32 return prev_is_keyframe
|| !current_is_keyframe
;
35 // Returns the config ID of |buffer| if |buffer| has no splice buffers or
36 // |index| is out of range. Otherwise returns the config ID for the fade out
37 // preroll buffer at position |index|.
38 static int GetConfigId(StreamParserBuffer
* buffer
, size_t index
) {
39 return index
< buffer
->splice_buffers().size()
40 ? buffer
->splice_buffers()[index
]->GetConfigId()
41 : buffer
->GetConfigId();
44 // Helper class representing a range of buffered data. All buffers in a
45 // SourceBufferRange are ordered sequentially in presentation order with no
47 class SourceBufferRange
{
49 // Returns the maximum distance in time between any buffer seen in this
50 // stream. Used to estimate the duration of a buffer if its duration is not
52 typedef base::Callback
<base::TimeDelta()> InterbufferDistanceCB
;
54 // Creates a source buffer range with |new_buffers|. |new_buffers| cannot be
55 // empty and the front of |new_buffers| must be a keyframe.
56 // |media_segment_start_time| refers to the starting timestamp for the media
57 // segment to which these buffers belong.
58 SourceBufferRange(SourceBufferStream::Type type
,
59 const BufferQueue
& new_buffers
,
60 base::TimeDelta media_segment_start_time
,
61 const InterbufferDistanceCB
& interbuffer_distance_cb
);
63 // Appends |buffers| to the end of the range and updates |keyframe_map_| as
64 // it encounters new keyframes. Assumes |buffers| belongs at the end of the
66 void AppendBuffersToEnd(const BufferQueue
& buffers
);
67 bool CanAppendBuffersToEnd(const BufferQueue
& buffers
) const;
69 // Appends the buffers from |range| into this range.
70 // The first buffer in |range| must come directly after the last buffer
72 // If |transfer_current_position| is true, |range|'s |next_buffer_index_|
73 // is transfered to this SourceBufferRange.
74 void AppendRangeToEnd(const SourceBufferRange
& range
,
75 bool transfer_current_position
);
76 bool CanAppendRangeToEnd(const SourceBufferRange
& range
) const;
78 // Updates |next_buffer_index_| to point to the Buffer containing |timestamp|.
79 // Assumes |timestamp| is valid and in this range.
80 void Seek(base::TimeDelta timestamp
);
82 // Updates |next_buffer_index_| to point to next keyframe after or equal to
84 void SeekAheadTo(base::TimeDelta timestamp
);
86 // Updates |next_buffer_index_| to point to next keyframe strictly after
88 void SeekAheadPast(base::TimeDelta timestamp
);
90 // Seeks to the beginning of the range.
93 // Finds the next keyframe from |buffers_| after |timestamp| (or at
94 // |timestamp| if |is_exclusive| is false) and creates and returns a new
95 // SourceBufferRange with the buffers from that keyframe onward.
96 // The buffers in the new SourceBufferRange are moved out of this range. If
97 // there is no keyframe after |timestamp|, SplitRange() returns null and this
98 // range is unmodified.
99 SourceBufferRange
* SplitRange(base::TimeDelta timestamp
, bool is_exclusive
);
101 // Deletes the buffers from this range starting at |timestamp|, exclusive if
102 // |is_exclusive| is true, inclusive otherwise.
103 // Resets |next_buffer_index_| if the buffer at |next_buffer_index_| was
104 // deleted, and deletes the |keyframe_map_| entries for the buffers that
106 // |deleted_buffers| contains the buffers that were deleted from this range,
107 // starting at the buffer that had been at |next_buffer_index_|.
108 // Returns true if everything in the range was deleted. Otherwise
110 bool TruncateAt(base::TimeDelta timestamp
,
111 BufferQueue
* deleted_buffers
, bool is_exclusive
);
112 // Deletes all buffers in range.
113 void DeleteAll(BufferQueue
* deleted_buffers
);
115 // Deletes a GOP from the front or back of the range and moves these
116 // buffers into |deleted_buffers|. Returns the number of bytes deleted from
117 // the range (i.e. the size in bytes of |deleted_buffers|).
118 int DeleteGOPFromFront(BufferQueue
* deleted_buffers
);
119 int DeleteGOPFromBack(BufferQueue
* deleted_buffers
);
121 // Gets the range of GOP to secure at least |bytes_to_free| from
122 // [|start_timestamp|, |end_timestamp|).
123 // Returns the size of the buffers to secure if the buffers of
124 // [|start_timestamp|, |end_removal_timestamp|) is removed.
125 // Will not update |end_removal_timestamp| if the returned size is 0.
127 base::TimeDelta start_timestamp
, base::TimeDelta end_timestamp
,
128 int bytes_to_free
, base::TimeDelta
* end_removal_timestamp
);
130 // Indicates whether the GOP at the beginning or end of the range contains the
131 // next buffer position.
132 bool FirstGOPContainsNextBufferPosition() const;
133 bool LastGOPContainsNextBufferPosition() const;
135 // Updates |out_buffer| with the next buffer in presentation order. Seek()
136 // must be called before calls to GetNextBuffer(), and buffers are returned
137 // in order from the last call to Seek(). Returns true if |out_buffer| is
138 // filled with a valid buffer, false if there is not enough data to fulfill
140 bool GetNextBuffer(scoped_refptr
<StreamParserBuffer
>* out_buffer
);
141 bool HasNextBuffer() const;
143 // Returns the config ID for the buffer that will be returned by
145 int GetNextConfigId() const;
147 // Returns true if the range knows the position of the next buffer it should
148 // return, i.e. it has been Seek()ed. This does not necessarily mean that it
149 // has the next buffer yet.
150 bool HasNextBufferPosition() const;
152 // Resets this range to an "unseeked" state.
153 void ResetNextBufferPosition();
155 // Returns the timestamp of the next buffer that will be returned from
156 // GetNextBuffer(), or kNoTimestamp() if the timestamp is unknown.
157 base::TimeDelta
GetNextTimestamp() const;
159 // Returns the start timestamp of the range.
160 base::TimeDelta
GetStartTimestamp() const;
162 // Returns the timestamp of the last buffer in the range.
163 base::TimeDelta
GetEndTimestamp() const;
165 // Returns the timestamp for the end of the buffered region in this range.
166 // This is an approximation if the duration for the last buffer in the range
168 base::TimeDelta
GetBufferedEndTimestamp() const;
170 // Gets the timestamp for the keyframe that is after |timestamp|. If
171 // there isn't a keyframe in the range after |timestamp| then kNoTimestamp()
172 // is returned. If |timestamp| is in the "gap" between the value returned by
173 // GetStartTimestamp() and the timestamp on the first buffer in |buffers_|,
174 // then |timestamp| is returned.
175 base::TimeDelta
NextKeyframeTimestamp(base::TimeDelta timestamp
);
177 // Gets the timestamp for the closest keyframe that is <= |timestamp|. If
178 // there isn't a keyframe before |timestamp| or |timestamp| is outside
179 // this range, then kNoTimestamp() is returned.
180 base::TimeDelta
KeyframeBeforeTimestamp(base::TimeDelta timestamp
);
182 // Returns whether a buffer with a starting timestamp of |timestamp| would
183 // belong in this range. This includes a buffer that would be appended to
184 // the end of the range.
185 bool BelongsToRange(base::TimeDelta timestamp
) const;
187 // Returns true if the range has enough data to seek to the specified
188 // |timestamp|, false otherwise.
189 bool CanSeekTo(base::TimeDelta timestamp
) const;
191 // Returns true if this range's buffered timespan completely overlaps the
192 // buffered timespan of |range|.
193 bool CompletelyOverlaps(const SourceBufferRange
& range
) const;
195 // Returns true if the end of this range contains buffers that overlaps with
196 // the beginning of |range|.
197 bool EndOverlaps(const SourceBufferRange
& range
) const;
199 // Returns true if |timestamp| is the timestamp of the next buffer in
200 // sequence after |buffers_.back()|, false otherwise.
201 bool IsNextInSequence(base::TimeDelta timestamp
, bool is_keyframe
) const;
203 // Adds all buffers which overlap [start, end) to the end of |buffers|. If
204 // no buffers exist in the range returns false, true otherwise.
205 bool GetBuffersInRange(base::TimeDelta start
, base::TimeDelta end
,
206 BufferQueue
* buffers
);
208 int size_in_bytes() const { return size_in_bytes_
; }
211 typedef std::map
<base::TimeDelta
, int> KeyframeMap
;
213 // Seeks the range to the next keyframe after |timestamp|. If
214 // |skip_given_timestamp| is true, the seek will go to a keyframe with a
215 // timestamp strictly greater than |timestamp|.
216 void SeekAhead(base::TimeDelta timestamp
, bool skip_given_timestamp
);
218 // Returns an iterator in |buffers_| pointing to the buffer at |timestamp|.
219 // If |skip_given_timestamp| is true, this returns the first buffer with
220 // timestamp greater than |timestamp|.
221 BufferQueue::iterator
GetBufferItrAt(
222 base::TimeDelta timestamp
, bool skip_given_timestamp
);
224 // Returns an iterator in |keyframe_map_| pointing to the next keyframe after
225 // |timestamp|. If |skip_given_timestamp| is true, this returns the first
226 // keyframe with a timestamp strictly greater than |timestamp|.
227 KeyframeMap::iterator
GetFirstKeyframeAt(
228 base::TimeDelta timestamp
, bool skip_given_timestamp
);
230 // Returns an iterator in |keyframe_map_| pointing to the first keyframe
231 // before or at |timestamp|.
232 KeyframeMap::iterator
GetFirstKeyframeBefore(base::TimeDelta timestamp
);
234 // Helper method to delete buffers in |buffers_| starting at
235 // |starting_point|, an iterator in |buffers_|.
236 // Returns true if everything in the range was removed. Returns
237 // false if the range still contains buffers.
238 bool TruncateAt(const BufferQueue::iterator
& starting_point
,
239 BufferQueue
* deleted_buffers
);
241 // Frees the buffers in |buffers_| from [|start_point|,|ending_point|) and
242 // updates the |size_in_bytes_| accordingly. Does not update |keyframe_map_|.
243 void FreeBufferRange(const BufferQueue::iterator
& starting_point
,
244 const BufferQueue::iterator
& ending_point
);
246 // Returns the distance in time estimating how far from the beginning or end
247 // of this range a buffer can be to considered in the range.
248 base::TimeDelta
GetFudgeRoom() const;
250 // Returns the approximate duration of a buffer in this range.
251 base::TimeDelta
GetApproximateDuration() const;
253 // Type of this stream.
254 const SourceBufferStream::Type type_
;
256 // An ordered list of buffers in this range.
257 BufferQueue buffers_
;
259 // Maps keyframe timestamps to its index position in |buffers_|.
260 KeyframeMap keyframe_map_
;
262 // Index base of all positions in |keyframe_map_|. In other words, the
263 // real position of entry |k| of |keyframe_map_| in the range is:
264 // keyframe_map_[k] - keyframe_map_index_base_
265 int keyframe_map_index_base_
;
267 // Index into |buffers_| for the next buffer to be returned by
268 // GetNextBuffer(), set to -1 before Seek().
269 int next_buffer_index_
;
271 // If the first buffer in this range is the beginning of a media segment,
272 // |media_segment_start_time_| is the time when the media segment begins.
273 // |media_segment_start_time_| may be <= the timestamp of the first buffer in
274 // |buffers_|. |media_segment_start_time_| is kNoTimestamp() if this range
275 // does not start at the beginning of a media segment, which can only happen
276 // garbage collection or after an end overlap that results in a split range
277 // (we don't have a way of knowing the media segment timestamp for the new
279 base::TimeDelta media_segment_start_time_
;
281 // Called to get the largest interbuffer distance seen so far in the stream.
282 InterbufferDistanceCB interbuffer_distance_cb_
;
284 // Stores the amount of memory taken up by the data in |buffers_|.
287 DISALLOW_COPY_AND_ASSIGN(SourceBufferRange
);
292 // Helper method that returns true if |ranges| is sorted in increasing order,
294 static bool IsRangeListSorted(
295 const std::list
<media::SourceBufferRange
*>& ranges
) {
296 base::TimeDelta prev
= media::kNoTimestamp();
297 for (std::list
<media::SourceBufferRange
*>::const_iterator itr
=
298 ranges
.begin(); itr
!= ranges
.end(); ++itr
) {
299 if (prev
!= media::kNoTimestamp() && prev
>= (*itr
)->GetStartTimestamp())
301 prev
= (*itr
)->GetEndTimestamp();
306 // Comparison operators for std::upper_bound() and std::lower_bound().
307 static bool CompareTimeDeltaToStreamParserBuffer(
308 const base::TimeDelta
& decode_timestamp
,
309 const scoped_refptr
<media::StreamParserBuffer
>& buffer
) {
310 return decode_timestamp
< buffer
->GetDecodeTimestamp();
312 static bool CompareStreamParserBufferToTimeDelta(
313 const scoped_refptr
<media::StreamParserBuffer
>& buffer
,
314 const base::TimeDelta
& decode_timestamp
) {
315 return buffer
->GetDecodeTimestamp() < decode_timestamp
;
318 // Returns an estimate of how far from the beginning or end of a range a buffer
319 // can be to still be considered in the range, given the |approximate_duration|
320 // of a buffer in the stream.
321 static base::TimeDelta
ComputeFudgeRoom(base::TimeDelta approximate_duration
) {
322 // Because we do not know exactly when is the next timestamp, any buffer
323 // that starts within 2x the approximate duration of a buffer is considered
324 // within this range.
325 return 2 * approximate_duration
;
328 // An arbitrarily-chosen number to estimate the duration of a buffer if none
329 // is set and there's not enough information to get a better estimate.
330 static int kDefaultBufferDurationInMs
= 125;
332 // The amount of time the beginning of the buffered data can differ from the
333 // start time in order to still be considered the start of stream.
334 static base::TimeDelta
kSeekToStartFudgeRoom() {
335 return base::TimeDelta::FromMilliseconds(1000);
340 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig
& audio_config
,
342 bool splice_frames_enabled
)
344 current_config_index_(0),
345 append_config_index_(0),
346 seek_pending_(false),
347 end_of_stream_(false),
348 seek_buffer_timestamp_(kNoTimestamp()),
349 selected_range_(NULL
),
350 media_segment_start_time_(kNoTimestamp()),
351 range_for_next_append_(ranges_
.end()),
352 new_media_segment_(false),
353 last_appended_buffer_timestamp_(kNoTimestamp()),
354 last_appended_buffer_is_keyframe_(false),
355 last_output_buffer_timestamp_(kNoTimestamp()),
356 max_interbuffer_distance_(kNoTimestamp()),
357 memory_limit_(kSourceBufferAudioMemoryLimit
),
358 config_change_pending_(false),
359 splice_buffers_index_(0),
360 pending_buffers_complete_(false),
361 splice_frames_enabled_(splice_frames_enabled
) {
362 DCHECK(audio_config
.IsValidConfig());
363 audio_configs_
.push_back(audio_config
);
366 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig
& video_config
,
368 bool splice_frames_enabled
)
370 current_config_index_(0),
371 append_config_index_(0),
372 seek_pending_(false),
373 end_of_stream_(false),
374 seek_buffer_timestamp_(kNoTimestamp()),
375 selected_range_(NULL
),
376 media_segment_start_time_(kNoTimestamp()),
377 range_for_next_append_(ranges_
.end()),
378 new_media_segment_(false),
379 last_appended_buffer_timestamp_(kNoTimestamp()),
380 last_appended_buffer_is_keyframe_(false),
381 last_output_buffer_timestamp_(kNoTimestamp()),
382 max_interbuffer_distance_(kNoTimestamp()),
383 memory_limit_(kSourceBufferVideoMemoryLimit
),
384 config_change_pending_(false),
385 splice_buffers_index_(0),
386 pending_buffers_complete_(false),
387 splice_frames_enabled_(splice_frames_enabled
) {
388 DCHECK(video_config
.IsValidConfig());
389 video_configs_
.push_back(video_config
);
392 SourceBufferStream::SourceBufferStream(const TextTrackConfig
& text_config
,
394 bool splice_frames_enabled
)
396 current_config_index_(0),
397 append_config_index_(0),
398 text_track_config_(text_config
),
399 seek_pending_(false),
400 end_of_stream_(false),
401 seek_buffer_timestamp_(kNoTimestamp()),
402 selected_range_(NULL
),
403 media_segment_start_time_(kNoTimestamp()),
404 range_for_next_append_(ranges_
.end()),
405 new_media_segment_(false),
406 last_appended_buffer_timestamp_(kNoTimestamp()),
407 last_appended_buffer_is_keyframe_(false),
408 last_output_buffer_timestamp_(kNoTimestamp()),
409 max_interbuffer_distance_(kNoTimestamp()),
410 memory_limit_(kSourceBufferAudioMemoryLimit
),
411 config_change_pending_(false),
412 splice_buffers_index_(0),
413 pending_buffers_complete_(false),
414 splice_frames_enabled_(splice_frames_enabled
) {}
416 SourceBufferStream::~SourceBufferStream() {
417 while (!ranges_
.empty()) {
418 delete ranges_
.front();
423 void SourceBufferStream::OnNewMediaSegment(
424 base::TimeDelta media_segment_start_time
) {
425 DCHECK(!end_of_stream_
);
426 media_segment_start_time_
= media_segment_start_time
;
427 new_media_segment_
= true;
429 RangeList::iterator last_range
= range_for_next_append_
;
430 range_for_next_append_
= FindExistingRangeFor(media_segment_start_time
);
432 // Only reset |last_appended_buffer_timestamp_| if this new media segment is
433 // not adjacent to the previous media segment appended to the stream.
434 if (range_for_next_append_
== ranges_
.end() ||
435 !AreAdjacentInSequence(last_appended_buffer_timestamp_
,
436 media_segment_start_time
)) {
437 last_appended_buffer_timestamp_
= kNoTimestamp();
438 last_appended_buffer_is_keyframe_
= false;
439 } else if (last_range
!= ranges_
.end()) {
440 DCHECK(last_range
== range_for_next_append_
);
444 bool SourceBufferStream::Append(const BufferQueue
& buffers
) {
445 TRACE_EVENT2("media", "SourceBufferStream::Append",
446 "stream type", GetStreamTypeName(),
447 "buffers to append", buffers
.size());
449 DCHECK(!buffers
.empty());
450 DCHECK(media_segment_start_time_
!= kNoTimestamp());
451 DCHECK(media_segment_start_time_
<= buffers
.front()->GetDecodeTimestamp());
452 DCHECK(!end_of_stream_
);
454 // New media segments must begin with a keyframe.
455 if (new_media_segment_
&& !buffers
.front()->IsKeyframe()) {
456 MEDIA_LOG(log_cb_
) << "Media segment did not begin with keyframe.";
460 // Buffers within a media segment should be monotonically increasing.
461 if (!IsMonotonicallyIncreasing(buffers
))
464 if (media_segment_start_time_
< base::TimeDelta() ||
465 buffers
.front()->GetDecodeTimestamp() < base::TimeDelta()) {
467 << "Cannot append a media segment with negative timestamps.";
471 if (!IsNextTimestampValid(buffers
.front()->GetDecodeTimestamp(),
472 buffers
.front()->IsKeyframe())) {
473 MEDIA_LOG(log_cb_
) << "Invalid same timestamp construct detected at time "
474 << buffers
.front()->GetDecodeTimestamp().InSecondsF();
479 UpdateMaxInterbufferDistance(buffers
);
480 SetConfigIds(buffers
);
482 // Save a snapshot of stream state before range modifications are made.
483 base::TimeDelta next_buffer_timestamp
= GetNextBufferTimestamp();
484 BufferQueue deleted_buffers
;
486 PrepareRangesForNextAppend(buffers
, &deleted_buffers
);
488 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise,
489 // create a new range with |buffers|.
490 if (range_for_next_append_
!= ranges_
.end()) {
491 (*range_for_next_append_
)->AppendBuffersToEnd(buffers
);
492 last_appended_buffer_timestamp_
= buffers
.back()->GetDecodeTimestamp();
493 last_appended_buffer_is_keyframe_
= buffers
.back()->IsKeyframe();
495 base::TimeDelta new_range_start_time
= std::min(
496 media_segment_start_time_
, buffers
.front()->GetDecodeTimestamp());
497 const BufferQueue
* buffers_for_new_range
= &buffers
;
498 BufferQueue trimmed_buffers
;
500 // If the new range is not being created because of a new media
501 // segment, then we must make sure that we start with a keyframe.
502 // This can happen if the GOP in the previous append gets destroyed
503 // by a Remove() call.
504 if (!new_media_segment_
) {
505 BufferQueue::const_iterator itr
= buffers
.begin();
507 // Scan past all the non-keyframes.
508 while (itr
!= buffers
.end() && !(*itr
)->IsKeyframe()) {
512 // If we didn't find a keyframe, then update the last appended
513 // buffer state and return.
514 if (itr
== buffers
.end()) {
515 last_appended_buffer_timestamp_
= buffers
.back()->GetDecodeTimestamp();
516 last_appended_buffer_is_keyframe_
= buffers
.back()->IsKeyframe();
518 } else if (itr
!= buffers
.begin()) {
519 // Copy the first keyframe and everything after it into
520 // |trimmed_buffers|.
521 trimmed_buffers
.assign(itr
, buffers
.end());
522 buffers_for_new_range
= &trimmed_buffers
;
525 new_range_start_time
=
526 buffers_for_new_range
->front()->GetDecodeTimestamp();
529 range_for_next_append_
=
530 AddToRanges(new SourceBufferRange(
531 GetType(), *buffers_for_new_range
, new_range_start_time
,
532 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance
,
533 base::Unretained(this))));
534 last_appended_buffer_timestamp_
=
535 buffers_for_new_range
->back()->GetDecodeTimestamp();
536 last_appended_buffer_is_keyframe_
=
537 buffers_for_new_range
->back()->IsKeyframe();
540 new_media_segment_
= false;
542 MergeWithAdjacentRangeIfNecessary(range_for_next_append_
);
544 // Seek to try to fulfill a previous call to Seek().
546 DCHECK(!selected_range_
);
547 DCHECK(deleted_buffers
.empty());
548 Seek(seek_buffer_timestamp_
);
551 if (!deleted_buffers
.empty()) {
552 base::TimeDelta start_of_deleted
=
553 deleted_buffers
.front()->GetDecodeTimestamp();
555 DCHECK(track_buffer_
.empty() ||
556 track_buffer_
.back()->GetDecodeTimestamp() < start_of_deleted
)
557 << "decode timestamp "
558 << track_buffer_
.back()->GetDecodeTimestamp().InSecondsF() << " sec"
559 << ", start_of_deleted " << start_of_deleted
.InSecondsF()<< " sec";
561 track_buffer_
.insert(track_buffer_
.end(), deleted_buffers
.begin(),
562 deleted_buffers
.end());
565 // Prune any extra buffers in |track_buffer_| if new keyframes
566 // are appended to the range covered by |track_buffer_|.
567 if (!track_buffer_
.empty()) {
568 base::TimeDelta keyframe_timestamp
=
569 FindKeyframeAfterTimestamp(track_buffer_
.front()->GetDecodeTimestamp());
570 if (keyframe_timestamp
!= kNoTimestamp())
571 PruneTrackBuffer(keyframe_timestamp
);
574 SetSelectedRangeIfNeeded(next_buffer_timestamp
);
576 GarbageCollectIfNeeded();
578 DCHECK(IsRangeListSorted(ranges_
));
579 DCHECK(OnlySelectedRangeIsSeeked());
583 void SourceBufferStream::Remove(base::TimeDelta start
, base::TimeDelta end
,
584 base::TimeDelta duration
) {
585 DVLOG(1) << __FUNCTION__
<< "(" << start
.InSecondsF()
586 << ", " << end
.InSecondsF()
587 << ", " << duration
.InSecondsF() << ")";
588 DCHECK(start
>= base::TimeDelta()) << start
.InSecondsF();
589 DCHECK(start
< end
) << "start " << start
.InSecondsF()
590 << " end " << end
.InSecondsF();
591 DCHECK(duration
!= kNoTimestamp());
593 base::TimeDelta remove_end_timestamp
= duration
;
594 base::TimeDelta keyframe_timestamp
= FindKeyframeAfterTimestamp(end
);
595 if (keyframe_timestamp
!= kNoTimestamp()) {
596 remove_end_timestamp
= keyframe_timestamp
;
597 } else if (end
< remove_end_timestamp
) {
598 remove_end_timestamp
= end
;
601 BufferQueue deleted_buffers
;
602 RemoveInternal(start
, remove_end_timestamp
, false, &deleted_buffers
);
604 if (!deleted_buffers
.empty())
605 SetSelectedRangeIfNeeded(deleted_buffers
.front()->GetDecodeTimestamp());
608 void SourceBufferStream::RemoveInternal(
609 base::TimeDelta start
, base::TimeDelta end
, bool is_exclusive
,
610 BufferQueue
* deleted_buffers
) {
611 DVLOG(1) << __FUNCTION__
<< "(" << start
.InSecondsF()
612 << ", " << end
.InSecondsF()
613 << ", " << is_exclusive
<< ")";
615 DCHECK(start
>= base::TimeDelta());
616 DCHECK(start
< end
) << "start " << start
.InSecondsF()
617 << " end " << end
.InSecondsF();
618 DCHECK(deleted_buffers
);
620 RangeList::iterator itr
= ranges_
.begin();
622 while (itr
!= ranges_
.end()) {
623 SourceBufferRange
* range
= *itr
;
624 if (range
->GetStartTimestamp() >= end
)
627 // Split off any remaining end piece and add it to |ranges_|.
628 SourceBufferRange
* new_range
= range
->SplitRange(end
, is_exclusive
);
630 itr
= ranges_
.insert(++itr
, new_range
);
633 // Update the selected range if the next buffer position was transferred
635 if (new_range
->HasNextBufferPosition())
636 SetSelectedRange(new_range
);
639 // Truncate the current range so that it only contains data before
640 // the removal range.
641 BufferQueue saved_buffers
;
642 bool delete_range
= range
->TruncateAt(start
, &saved_buffers
, is_exclusive
);
644 // Check to see if the current playback position was removed and
645 // update the selected range appropriately.
646 if (!saved_buffers
.empty()) {
647 DCHECK(!range
->HasNextBufferPosition());
648 DCHECK(deleted_buffers
->empty());
650 *deleted_buffers
= saved_buffers
;
653 if (range
== selected_range_
&& !range
->HasNextBufferPosition())
654 SetSelectedRange(NULL
);
656 // If the current range now is completely covered by the removal
657 // range then delete it and move on.
659 DeleteAndRemoveRange(&itr
);
663 // Clear |range_for_next_append_| if we determine that the removal
664 // operation makes it impossible for the next append to be added
665 // to the current range.
666 if (range_for_next_append_
!= ranges_
.end() &&
667 *range_for_next_append_
== range
&&
668 last_appended_buffer_timestamp_
!= kNoTimestamp()) {
669 base::TimeDelta potential_next_append_timestamp
=
670 last_appended_buffer_timestamp_
+
671 base::TimeDelta::FromInternalValue(1);
673 if (!range
->BelongsToRange(potential_next_append_timestamp
)) {
674 DVLOG(1) << "Resetting range_for_next_append_ since the next append"
675 << " can't add to the current range.";
676 range_for_next_append_
=
677 FindExistingRangeFor(potential_next_append_timestamp
);
681 // Move on to the next range.
685 DCHECK(IsRangeListSorted(ranges_
));
686 DCHECK(OnlySelectedRangeIsSeeked());
687 DVLOG(1) << __FUNCTION__
<< " : done";
690 void SourceBufferStream::ResetSeekState() {
691 SetSelectedRange(NULL
);
692 track_buffer_
.clear();
693 config_change_pending_
= false;
694 last_output_buffer_timestamp_
= kNoTimestamp();
695 splice_buffers_index_
= 0;
696 pending_buffer_
= NULL
;
697 pending_buffers_complete_
= false;
700 bool SourceBufferStream::ShouldSeekToStartOfBuffered(
701 base::TimeDelta seek_timestamp
) const {
704 base::TimeDelta beginning_of_buffered
=
705 ranges_
.front()->GetStartTimestamp();
706 return (seek_timestamp
<= beginning_of_buffered
&&
707 beginning_of_buffered
< kSeekToStartFudgeRoom());
710 bool SourceBufferStream::IsMonotonicallyIncreasing(
711 const BufferQueue
& buffers
) const {
712 DCHECK(!buffers
.empty());
713 base::TimeDelta prev_timestamp
= last_appended_buffer_timestamp_
;
714 bool prev_is_keyframe
= last_appended_buffer_is_keyframe_
;
715 for (BufferQueue::const_iterator itr
= buffers
.begin();
716 itr
!= buffers
.end(); ++itr
) {
717 base::TimeDelta current_timestamp
= (*itr
)->GetDecodeTimestamp();
718 bool current_is_keyframe
= (*itr
)->IsKeyframe();
719 DCHECK(current_timestamp
!= kNoTimestamp());
721 if (prev_timestamp
!= kNoTimestamp()) {
722 if (current_timestamp
< prev_timestamp
) {
723 MEDIA_LOG(log_cb_
) << "Buffers were not monotonically increasing.";
727 if (current_timestamp
== prev_timestamp
&&
728 !AllowSameTimestamp(prev_is_keyframe
, current_is_keyframe
,
730 MEDIA_LOG(log_cb_
) << "Unexpected combination of buffers with the"
731 << " same timestamp detected at "
732 << current_timestamp
.InSecondsF();
737 prev_timestamp
= current_timestamp
;
738 prev_is_keyframe
= current_is_keyframe
;
743 bool SourceBufferStream::IsNextTimestampValid(
744 base::TimeDelta next_timestamp
, bool next_is_keyframe
) const {
745 return (last_appended_buffer_timestamp_
!= next_timestamp
) ||
746 new_media_segment_
||
747 AllowSameTimestamp(last_appended_buffer_is_keyframe_
, next_is_keyframe
,
752 bool SourceBufferStream::OnlySelectedRangeIsSeeked() const {
753 for (RangeList::const_iterator itr
= ranges_
.begin();
754 itr
!= ranges_
.end(); ++itr
) {
755 if ((*itr
)->HasNextBufferPosition() && (*itr
) != selected_range_
)
758 return !selected_range_
|| selected_range_
->HasNextBufferPosition();
761 void SourceBufferStream::UpdateMaxInterbufferDistance(
762 const BufferQueue
& buffers
) {
763 DCHECK(!buffers
.empty());
764 base::TimeDelta prev_timestamp
= last_appended_buffer_timestamp_
;
765 for (BufferQueue::const_iterator itr
= buffers
.begin();
766 itr
!= buffers
.end(); ++itr
) {
767 base::TimeDelta current_timestamp
= (*itr
)->GetDecodeTimestamp();
768 DCHECK(current_timestamp
!= kNoTimestamp());
770 if (prev_timestamp
!= kNoTimestamp()) {
771 base::TimeDelta interbuffer_distance
= current_timestamp
- prev_timestamp
;
772 if (max_interbuffer_distance_
== kNoTimestamp()) {
773 max_interbuffer_distance_
= interbuffer_distance
;
775 max_interbuffer_distance_
=
776 std::max(max_interbuffer_distance_
, interbuffer_distance
);
779 prev_timestamp
= current_timestamp
;
783 void SourceBufferStream::SetConfigIds(const BufferQueue
& buffers
) {
784 for (BufferQueue::const_iterator itr
= buffers
.begin();
785 itr
!= buffers
.end(); ++itr
) {
786 (*itr
)->SetConfigId(append_config_index_
);
790 void SourceBufferStream::GarbageCollectIfNeeded() {
791 // Compute size of |ranges_|.
793 for (RangeList::iterator itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
)
794 ranges_size
+= (*itr
)->size_in_bytes();
796 // Return if we're under or at the memory limit.
797 if (ranges_size
<= memory_limit_
)
800 int bytes_to_free
= ranges_size
- memory_limit_
;
802 // Begin deleting after the last appended buffer.
803 int bytes_freed
= FreeBuffersAfterLastAppended(bytes_to_free
);
805 // Begin deleting from the front.
806 if (bytes_to_free
- bytes_freed
> 0)
807 bytes_freed
+= FreeBuffers(bytes_to_free
- bytes_freed
, false);
809 // Begin deleting from the back.
810 if (bytes_to_free
- bytes_freed
> 0)
811 FreeBuffers(bytes_to_free
- bytes_freed
, true);
814 int SourceBufferStream::FreeBuffersAfterLastAppended(int total_bytes_to_free
) {
815 base::TimeDelta next_buffer_timestamp
= GetNextBufferTimestamp();
816 if (last_appended_buffer_timestamp_
== kNoTimestamp() ||
817 next_buffer_timestamp
== kNoTimestamp() ||
818 last_appended_buffer_timestamp_
>= next_buffer_timestamp
) {
822 base::TimeDelta remove_range_start
= last_appended_buffer_timestamp_
;
823 if (last_appended_buffer_is_keyframe_
)
824 remove_range_start
+= GetMaxInterbufferDistance();
826 base::TimeDelta remove_range_start_keyframe
= FindKeyframeAfterTimestamp(
828 if (remove_range_start_keyframe
!= kNoTimestamp())
829 remove_range_start
= remove_range_start_keyframe
;
830 if (remove_range_start
>= next_buffer_timestamp
)
833 base::TimeDelta remove_range_end
;
834 int bytes_freed
= GetRemovalRange(
835 remove_range_start
, next_buffer_timestamp
, total_bytes_to_free
,
838 Remove(remove_range_start
, remove_range_end
, next_buffer_timestamp
);
842 int SourceBufferStream::GetRemovalRange(
843 base::TimeDelta start_timestamp
, base::TimeDelta end_timestamp
,
844 int total_bytes_to_free
, base::TimeDelta
* removal_end_timestamp
) {
845 DCHECK(start_timestamp
>= base::TimeDelta()) << start_timestamp
.InSecondsF();
846 DCHECK(start_timestamp
< end_timestamp
)
847 << "start " << start_timestamp
.InSecondsF()
848 << ", end " << end_timestamp
.InSecondsF();
850 int bytes_to_free
= total_bytes_to_free
;
853 for (RangeList::iterator itr
= ranges_
.begin();
854 itr
!= ranges_
.end() && bytes_to_free
> 0; ++itr
) {
855 SourceBufferRange
* range
= *itr
;
856 if (range
->GetStartTimestamp() >= end_timestamp
)
858 if (range
->GetEndTimestamp() < start_timestamp
)
861 int bytes_removed
= range
->GetRemovalGOP(
862 start_timestamp
, end_timestamp
, bytes_to_free
, removal_end_timestamp
);
863 bytes_to_free
-= bytes_removed
;
864 bytes_freed
+= bytes_removed
;
869 int SourceBufferStream::FreeBuffers(int total_bytes_to_free
,
870 bool reverse_direction
) {
871 TRACE_EVENT2("media", "SourceBufferStream::FreeBuffers",
872 "total bytes to free", total_bytes_to_free
,
873 "reverse direction", reverse_direction
);
875 DCHECK_GT(total_bytes_to_free
, 0);
876 int bytes_to_free
= total_bytes_to_free
;
879 // This range will save the last GOP appended to |range_for_next_append_|
880 // if the buffers surrounding it get deleted during garbage collection.
881 SourceBufferRange
* new_range_for_append
= NULL
;
883 while (!ranges_
.empty() && bytes_to_free
> 0) {
884 SourceBufferRange
* current_range
= NULL
;
886 int bytes_deleted
= 0;
888 if (reverse_direction
) {
889 current_range
= ranges_
.back();
890 if (current_range
->LastGOPContainsNextBufferPosition()) {
891 DCHECK_EQ(current_range
, selected_range_
);
894 bytes_deleted
= current_range
->DeleteGOPFromBack(&buffers
);
896 current_range
= ranges_
.front();
897 if (current_range
->FirstGOPContainsNextBufferPosition()) {
898 DCHECK_EQ(current_range
, selected_range_
);
901 bytes_deleted
= current_range
->DeleteGOPFromFront(&buffers
);
904 // Check to see if we've just deleted the GOP that was last appended.
905 base::TimeDelta end_timestamp
= buffers
.back()->GetDecodeTimestamp();
906 if (end_timestamp
== last_appended_buffer_timestamp_
) {
907 DCHECK(last_appended_buffer_timestamp_
!= kNoTimestamp());
908 DCHECK(!new_range_for_append
);
909 // Create a new range containing these buffers.
910 new_range_for_append
= new SourceBufferRange(
911 GetType(), buffers
, kNoTimestamp(),
912 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance
,
913 base::Unretained(this)));
914 range_for_next_append_
= ranges_
.end();
916 bytes_to_free
-= bytes_deleted
;
917 bytes_freed
+= bytes_deleted
;
920 if (current_range
->size_in_bytes() == 0) {
921 DCHECK_NE(current_range
, selected_range_
);
922 DCHECK(range_for_next_append_
== ranges_
.end() ||
923 *range_for_next_append_
!= current_range
);
924 delete current_range
;
925 reverse_direction
? ranges_
.pop_back() : ranges_
.pop_front();
929 // Insert |new_range_for_append| into |ranges_|, if applicable.
930 if (new_range_for_append
) {
931 range_for_next_append_
= AddToRanges(new_range_for_append
);
932 DCHECK(range_for_next_append_
!= ranges_
.end());
934 // Check to see if we need to merge |new_range_for_append| with the range
935 // before or after it. |new_range_for_append| is created whenever the last
936 // GOP appended is encountered, regardless of whether any buffers after it
937 // are ultimately deleted. Merging is necessary if there were no buffers
938 // (or very few buffers) deleted after creating |new_range_for_append|.
939 if (range_for_next_append_
!= ranges_
.begin()) {
940 RangeList::iterator range_before_next
= range_for_next_append_
;
942 MergeWithAdjacentRangeIfNecessary(range_before_next
);
944 MergeWithAdjacentRangeIfNecessary(range_for_next_append_
);
949 void SourceBufferStream::PrepareRangesForNextAppend(
950 const BufferQueue
& new_buffers
, BufferQueue
* deleted_buffers
) {
951 DCHECK(deleted_buffers
);
953 bool temporarily_select_range
= false;
954 if (!track_buffer_
.empty()) {
955 base::TimeDelta tb_timestamp
= track_buffer_
.back()->GetDecodeTimestamp();
956 base::TimeDelta seek_timestamp
= FindKeyframeAfterTimestamp(tb_timestamp
);
957 if (seek_timestamp
!= kNoTimestamp() &&
958 seek_timestamp
< new_buffers
.front()->GetDecodeTimestamp() &&
959 range_for_next_append_
!= ranges_
.end() &&
960 (*range_for_next_append_
)->BelongsToRange(seek_timestamp
)) {
961 DCHECK(tb_timestamp
< seek_timestamp
);
962 DCHECK(!selected_range_
);
963 DCHECK(!(*range_for_next_append_
)->HasNextBufferPosition());
965 // If there are GOPs between the end of the track buffer and the
966 // beginning of the new buffers, then temporarily seek the range
967 // so that the buffers between these two times will be deposited in
968 // |deleted_buffers| as if they were part of the current playback
970 // TODO(acolwell): Figure out a more elegant way to do this.
971 SeekAndSetSelectedRange(*range_for_next_append_
, seek_timestamp
);
972 temporarily_select_range
= true;
976 // Handle splices between the existing buffers and the new buffers. If a
977 // splice is generated the timestamp and duration of the first buffer in
978 // |new_buffers| will be modified.
979 if (splice_frames_enabled_
)
980 GenerateSpliceFrame(new_buffers
);
982 base::TimeDelta prev_timestamp
= last_appended_buffer_timestamp_
;
983 bool prev_is_keyframe
= last_appended_buffer_is_keyframe_
;
984 base::TimeDelta next_timestamp
= new_buffers
.front()->GetDecodeTimestamp();
985 bool next_is_keyframe
= new_buffers
.front()->IsKeyframe();
987 if (prev_timestamp
!= kNoTimestamp() && prev_timestamp
!= next_timestamp
) {
988 // Clean up the old buffers between the last appended buffer and the
989 // beginning of |new_buffers|.
990 RemoveInternal(prev_timestamp
, next_timestamp
, true, deleted_buffers
);
993 // Make the delete range exclusive if we are dealing with an allowed same
994 // timestamp situation. This prevents the first buffer in the current append
995 // from deleting the last buffer in the previous append if both buffers
996 // have the same timestamp.
998 // The delete range should never be exclusive if a splice frame was generated
999 // because we don't generate splice frames for same timestamp situations.
1000 DCHECK(new_buffers
.front()->splice_timestamp() !=
1001 new_buffers
.front()->timestamp());
1002 const bool is_exclusive
=
1003 new_buffers
.front()->splice_buffers().empty() &&
1004 prev_timestamp
== next_timestamp
&&
1005 AllowSameTimestamp(prev_is_keyframe
, next_is_keyframe
, GetType());
1007 // Delete the buffers that |new_buffers| overlaps.
1008 base::TimeDelta start
= new_buffers
.front()->GetDecodeTimestamp();
1009 base::TimeDelta end
= new_buffers
.back()->GetDecodeTimestamp();
1010 base::TimeDelta duration
= new_buffers
.back()->duration();
1012 if (duration
!= kNoTimestamp() && duration
> base::TimeDelta()) {
1015 // TODO(acolwell): Ensure all buffers actually have proper
1016 // duration info so that this hack isn't needed.
1017 // http://crbug.com/312836
1018 end
+= base::TimeDelta::FromInternalValue(1);
1021 RemoveInternal(start
, end
, is_exclusive
, deleted_buffers
);
1023 // Restore the range seek state if necessary.
1024 if (temporarily_select_range
)
1025 SetSelectedRange(NULL
);
1028 bool SourceBufferStream::AreAdjacentInSequence(
1029 base::TimeDelta first_timestamp
, base::TimeDelta second_timestamp
) const {
1030 return first_timestamp
< second_timestamp
&&
1032 first_timestamp
+ ComputeFudgeRoom(GetMaxInterbufferDistance());
1035 void SourceBufferStream::PruneTrackBuffer(const base::TimeDelta timestamp
) {
1036 // If we don't have the next timestamp, we don't have anything to delete.
1037 if (timestamp
== kNoTimestamp())
1040 while (!track_buffer_
.empty() &&
1041 track_buffer_
.back()->GetDecodeTimestamp() >= timestamp
) {
1042 track_buffer_
.pop_back();
1046 void SourceBufferStream::MergeWithAdjacentRangeIfNecessary(
1047 const RangeList::iterator
& range_with_new_buffers_itr
) {
1048 DCHECK(range_with_new_buffers_itr
!= ranges_
.end());
1050 SourceBufferRange
* range_with_new_buffers
= *range_with_new_buffers_itr
;
1051 RangeList::iterator next_range_itr
= range_with_new_buffers_itr
;
1054 if (next_range_itr
== ranges_
.end() ||
1055 !range_with_new_buffers
->CanAppendRangeToEnd(**next_range_itr
)) {
1059 bool transfer_current_position
= selected_range_
== *next_range_itr
;
1060 range_with_new_buffers
->AppendRangeToEnd(**next_range_itr
,
1061 transfer_current_position
);
1062 // Update |selected_range_| pointer if |range| has become selected after
1064 if (transfer_current_position
)
1065 SetSelectedRange(range_with_new_buffers
);
1067 if (next_range_itr
== range_for_next_append_
)
1068 range_for_next_append_
= range_with_new_buffers_itr
;
1070 DeleteAndRemoveRange(&next_range_itr
);
1073 void SourceBufferStream::Seek(base::TimeDelta timestamp
) {
1074 DCHECK(timestamp
>= base::TimeDelta());
1077 if (ShouldSeekToStartOfBuffered(timestamp
)) {
1078 ranges_
.front()->SeekToStart();
1079 SetSelectedRange(ranges_
.front());
1080 seek_pending_
= false;
1084 seek_buffer_timestamp_
= timestamp
;
1085 seek_pending_
= true;
1087 RangeList::iterator itr
= ranges_
.end();
1088 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1089 if ((*itr
)->CanSeekTo(timestamp
))
1093 if (itr
== ranges_
.end())
1096 SeekAndSetSelectedRange(*itr
, timestamp
);
1097 seek_pending_
= false;
1100 bool SourceBufferStream::IsSeekPending() const {
1101 return !(end_of_stream_
&& IsEndSelected()) && seek_pending_
;
1104 void SourceBufferStream::OnSetDuration(base::TimeDelta duration
) {
1105 RangeList::iterator itr
= ranges_
.end();
1106 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1107 if ((*itr
)->GetEndTimestamp() > duration
)
1110 if (itr
== ranges_
.end())
1113 // Need to partially truncate this range.
1114 if ((*itr
)->GetStartTimestamp() < duration
) {
1115 bool delete_range
= (*itr
)->TruncateAt(duration
, NULL
, false);
1116 if ((*itr
== selected_range_
) && !selected_range_
->HasNextBufferPosition())
1117 SetSelectedRange(NULL
);
1120 DeleteAndRemoveRange(&itr
);
1126 // Delete all ranges that begin after |duration|.
1127 while (itr
!= ranges_
.end()) {
1128 // If we're about to delete the selected range, also reset the seek state.
1129 DCHECK((*itr
)->GetStartTimestamp() >= duration
);
1130 if (*itr
== selected_range_
)
1132 DeleteAndRemoveRange(&itr
);
1136 SourceBufferStream::Status
SourceBufferStream::GetNextBuffer(
1137 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1138 if (!pending_buffer_
) {
1139 const SourceBufferStream::Status status
= GetNextBufferInternal(out_buffer
);
1140 if (status
!= SourceBufferStream::kSuccess
|| !SetPendingBuffer(out_buffer
))
1144 if (!pending_buffer_
->splice_buffers().empty())
1145 return HandleNextBufferWithSplice(out_buffer
);
1147 DCHECK(pending_buffer_
->preroll_buffer());
1148 return HandleNextBufferWithPreroll(out_buffer
);
1151 SourceBufferStream::Status
SourceBufferStream::HandleNextBufferWithSplice(
1152 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1153 const BufferQueue
& splice_buffers
= pending_buffer_
->splice_buffers();
1154 const size_t last_splice_buffer_index
= splice_buffers
.size() - 1;
1156 // Are there any splice buffers left to hand out? The last buffer should be
1157 // handed out separately since it represents the first post-splice buffer.
1158 if (splice_buffers_index_
< last_splice_buffer_index
) {
1159 // Account for config changes which occur between fade out buffers.
1160 if (current_config_index_
!=
1161 splice_buffers
[splice_buffers_index_
]->GetConfigId()) {
1162 config_change_pending_
= true;
1163 DVLOG(1) << "Config change (splice buffer config ID does not match).";
1164 return SourceBufferStream::kConfigChange
;
1167 // Every pre splice buffer must have the same splice_timestamp().
1168 DCHECK(pending_buffer_
->splice_timestamp() ==
1169 splice_buffers
[splice_buffers_index_
]->splice_timestamp());
1171 // No pre splice buffers should have preroll.
1172 DCHECK(!splice_buffers
[splice_buffers_index_
]->preroll_buffer());
1174 *out_buffer
= splice_buffers
[splice_buffers_index_
++];
1175 return SourceBufferStream::kSuccess
;
1178 // Did we hand out the last pre-splice buffer on the previous call?
1179 if (!pending_buffers_complete_
) {
1180 DCHECK_EQ(splice_buffers_index_
, last_splice_buffer_index
);
1181 pending_buffers_complete_
= true;
1182 config_change_pending_
= true;
1183 DVLOG(1) << "Config change (forced for fade in of splice frame).";
1184 return SourceBufferStream::kConfigChange
;
1187 // All pre-splice buffers have been handed out and a config change completed,
1188 // so hand out the final buffer for fade in. Because a config change is
1189 // always issued prior to handing out this buffer, any changes in config id
1190 // have been inherently handled.
1191 DCHECK(pending_buffers_complete_
);
1192 DCHECK_EQ(splice_buffers_index_
, splice_buffers
.size() - 1);
1193 DCHECK(splice_buffers
.back()->splice_timestamp() == kNoTimestamp());
1194 *out_buffer
= splice_buffers
.back();
1195 pending_buffer_
= NULL
;
1197 // If the last splice buffer has preroll, hand off to the preroll handler.
1198 return SetPendingBuffer(out_buffer
) ? HandleNextBufferWithPreroll(out_buffer
)
1199 : SourceBufferStream::kSuccess
;
1202 SourceBufferStream::Status
SourceBufferStream::HandleNextBufferWithPreroll(
1203 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1204 // Any config change should have already been handled.
1205 DCHECK_EQ(current_config_index_
, pending_buffer_
->GetConfigId());
1207 // Check if the preroll buffer has already been handed out.
1208 if (!pending_buffers_complete_
) {
1209 pending_buffers_complete_
= true;
1210 *out_buffer
= pending_buffer_
->preroll_buffer();
1211 return SourceBufferStream::kSuccess
;
1214 // Preroll complete, hand out the final buffer.
1215 *out_buffer
= pending_buffer_
;
1216 pending_buffer_
= NULL
;
1217 return SourceBufferStream::kSuccess
;
1220 SourceBufferStream::Status
SourceBufferStream::GetNextBufferInternal(
1221 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1222 CHECK(!config_change_pending_
);
1224 if (!track_buffer_
.empty()) {
1225 DCHECK(!selected_range_
);
1226 scoped_refptr
<StreamParserBuffer
>& next_buffer
= track_buffer_
.front();
1228 // If the next buffer is an audio splice frame, the next effective config id
1229 // comes from the first splice buffer.
1230 if (GetConfigId(next_buffer
, 0) != current_config_index_
) {
1231 config_change_pending_
= true;
1232 DVLOG(1) << "Config change (track buffer config ID does not match).";
1233 return kConfigChange
;
1236 *out_buffer
= next_buffer
;
1237 track_buffer_
.pop_front();
1238 last_output_buffer_timestamp_
= (*out_buffer
)->GetDecodeTimestamp();
1240 // If the track buffer becomes empty, then try to set the selected range
1241 // based on the timestamp of this buffer being returned.
1242 if (track_buffer_
.empty())
1243 SetSelectedRangeIfNeeded(last_output_buffer_timestamp_
);
1248 if (!selected_range_
|| !selected_range_
->HasNextBuffer()) {
1249 if (end_of_stream_
&& IsEndSelected())
1250 return kEndOfStream
;
1254 if (selected_range_
->GetNextConfigId() != current_config_index_
) {
1255 config_change_pending_
= true;
1256 DVLOG(1) << "Config change (selected range config ID does not match).";
1257 return kConfigChange
;
1260 CHECK(selected_range_
->GetNextBuffer(out_buffer
));
1261 last_output_buffer_timestamp_
= (*out_buffer
)->GetDecodeTimestamp();
1265 base::TimeDelta
SourceBufferStream::GetNextBufferTimestamp() {
1266 if (!track_buffer_
.empty())
1267 return track_buffer_
.front()->GetDecodeTimestamp();
1269 if (!selected_range_
)
1270 return kNoTimestamp();
1272 DCHECK(selected_range_
->HasNextBufferPosition());
1273 return selected_range_
->GetNextTimestamp();
1276 base::TimeDelta
SourceBufferStream::GetEndBufferTimestamp() {
1277 if (!selected_range_
)
1278 return kNoTimestamp();
1279 return selected_range_
->GetEndTimestamp();
1282 SourceBufferStream::RangeList::iterator
1283 SourceBufferStream::FindExistingRangeFor(base::TimeDelta start_timestamp
) {
1284 for (RangeList::iterator itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1285 if ((*itr
)->BelongsToRange(start_timestamp
))
1288 return ranges_
.end();
1291 SourceBufferStream::RangeList::iterator
1292 SourceBufferStream::AddToRanges(SourceBufferRange
* new_range
) {
1293 base::TimeDelta start_timestamp
= new_range
->GetStartTimestamp();
1294 RangeList::iterator itr
= ranges_
.end();
1295 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1296 if ((*itr
)->GetStartTimestamp() > start_timestamp
)
1299 return ranges_
.insert(itr
, new_range
);
1302 SourceBufferStream::RangeList::iterator
1303 SourceBufferStream::GetSelectedRangeItr() {
1304 DCHECK(selected_range_
);
1305 RangeList::iterator itr
= ranges_
.end();
1306 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1307 if (*itr
== selected_range_
)
1310 DCHECK(itr
!= ranges_
.end());
1314 void SourceBufferStream::SeekAndSetSelectedRange(
1315 SourceBufferRange
* range
, base::TimeDelta seek_timestamp
) {
1317 range
->Seek(seek_timestamp
);
1318 SetSelectedRange(range
);
1321 void SourceBufferStream::SetSelectedRange(SourceBufferRange
* range
) {
1322 DVLOG(1) << __FUNCTION__
<< " : " << selected_range_
<< " -> " << range
;
1323 if (selected_range_
)
1324 selected_range_
->ResetNextBufferPosition();
1325 DCHECK(!range
|| range
->HasNextBufferPosition());
1326 selected_range_
= range
;
1329 Ranges
<base::TimeDelta
> SourceBufferStream::GetBufferedTime() const {
1330 Ranges
<base::TimeDelta
> ranges
;
1331 for (RangeList::const_iterator itr
= ranges_
.begin();
1332 itr
!= ranges_
.end(); ++itr
) {
1333 ranges
.Add((*itr
)->GetStartTimestamp(), (*itr
)->GetBufferedEndTimestamp());
1338 base::TimeDelta
SourceBufferStream::GetBufferedDuration() const {
1339 if (ranges_
.empty())
1340 return base::TimeDelta();
1342 return ranges_
.back()->GetBufferedEndTimestamp();
1345 void SourceBufferStream::MarkEndOfStream() {
1346 DCHECK(!end_of_stream_
);
1347 end_of_stream_
= true;
1350 void SourceBufferStream::UnmarkEndOfStream() {
1351 DCHECK(end_of_stream_
);
1352 end_of_stream_
= false;
1355 bool SourceBufferStream::IsEndSelected() const {
1356 if (ranges_
.empty())
1360 return seek_buffer_timestamp_
>= ranges_
.back()->GetBufferedEndTimestamp();
1362 return selected_range_
== ranges_
.back();
1365 const AudioDecoderConfig
& SourceBufferStream::GetCurrentAudioDecoderConfig() {
1366 if (config_change_pending_
)
1367 CompleteConfigChange();
1368 return audio_configs_
[current_config_index_
];
1371 const VideoDecoderConfig
& SourceBufferStream::GetCurrentVideoDecoderConfig() {
1372 if (config_change_pending_
)
1373 CompleteConfigChange();
1374 return video_configs_
[current_config_index_
];
1377 const TextTrackConfig
& SourceBufferStream::GetCurrentTextTrackConfig() {
1378 return text_track_config_
;
1381 base::TimeDelta
SourceBufferStream::GetMaxInterbufferDistance() const {
1382 if (max_interbuffer_distance_
== kNoTimestamp())
1383 return base::TimeDelta::FromMilliseconds(kDefaultBufferDurationInMs
);
1384 return max_interbuffer_distance_
;
1387 bool SourceBufferStream::UpdateAudioConfig(const AudioDecoderConfig
& config
) {
1388 DCHECK(!audio_configs_
.empty());
1389 DCHECK(video_configs_
.empty());
1390 DVLOG(3) << "UpdateAudioConfig.";
1392 if (audio_configs_
[0].codec() != config
.codec()) {
1393 MEDIA_LOG(log_cb_
) << "Audio codec changes not allowed.";
1397 if (audio_configs_
[0].is_encrypted() != config
.is_encrypted()) {
1398 MEDIA_LOG(log_cb_
) << "Audio encryption changes not allowed.";
1402 // Check to see if the new config matches an existing one.
1403 for (size_t i
= 0; i
< audio_configs_
.size(); ++i
) {
1404 if (config
.Matches(audio_configs_
[i
])) {
1405 append_config_index_
= i
;
1410 // No matches found so let's add this one to the list.
1411 append_config_index_
= audio_configs_
.size();
1412 DVLOG(2) << "New audio config - index: " << append_config_index_
;
1413 audio_configs_
.resize(audio_configs_
.size() + 1);
1414 audio_configs_
[append_config_index_
] = config
;
1418 bool SourceBufferStream::UpdateVideoConfig(const VideoDecoderConfig
& config
) {
1419 DCHECK(!video_configs_
.empty());
1420 DCHECK(audio_configs_
.empty());
1421 DVLOG(3) << "UpdateVideoConfig.";
1423 if (video_configs_
[0].codec() != config
.codec()) {
1424 MEDIA_LOG(log_cb_
) << "Video codec changes not allowed.";
1428 if (video_configs_
[0].is_encrypted() != config
.is_encrypted()) {
1429 MEDIA_LOG(log_cb_
) << "Video encryption changes not allowed.";
1433 // Check to see if the new config matches an existing one.
1434 for (size_t i
= 0; i
< video_configs_
.size(); ++i
) {
1435 if (config
.Matches(video_configs_
[i
])) {
1436 append_config_index_
= i
;
1441 // No matches found so let's add this one to the list.
1442 append_config_index_
= video_configs_
.size();
1443 DVLOG(2) << "New video config - index: " << append_config_index_
;
1444 video_configs_
.resize(video_configs_
.size() + 1);
1445 video_configs_
[append_config_index_
] = config
;
1449 void SourceBufferStream::CompleteConfigChange() {
1450 config_change_pending_
= false;
1452 if (pending_buffer_
) {
1453 current_config_index_
=
1454 GetConfigId(pending_buffer_
, splice_buffers_index_
);
1458 if (!track_buffer_
.empty()) {
1459 current_config_index_
= GetConfigId(track_buffer_
.front(), 0);
1463 if (selected_range_
&& selected_range_
->HasNextBuffer())
1464 current_config_index_
= selected_range_
->GetNextConfigId();
1467 void SourceBufferStream::SetSelectedRangeIfNeeded(
1468 const base::TimeDelta timestamp
) {
1469 DVLOG(1) << __FUNCTION__
<< "(" << timestamp
.InSecondsF() << ")";
1471 if (selected_range_
) {
1472 DCHECK(track_buffer_
.empty());
1476 if (!track_buffer_
.empty()) {
1477 DCHECK(!selected_range_
);
1481 base::TimeDelta start_timestamp
= timestamp
;
1483 // If the next buffer timestamp is not known then use a timestamp just after
1484 // the timestamp on the last buffer returned by GetNextBuffer().
1485 if (start_timestamp
== kNoTimestamp()) {
1486 if (last_output_buffer_timestamp_
== kNoTimestamp())
1489 start_timestamp
= last_output_buffer_timestamp_
+
1490 base::TimeDelta::FromInternalValue(1);
1493 base::TimeDelta seek_timestamp
=
1494 FindNewSelectedRangeSeekTimestamp(start_timestamp
);
1496 // If we don't have buffered data to seek to, then return.
1497 if (seek_timestamp
== kNoTimestamp())
1500 DCHECK(track_buffer_
.empty());
1501 SeekAndSetSelectedRange(*FindExistingRangeFor(seek_timestamp
),
1505 base::TimeDelta
SourceBufferStream::FindNewSelectedRangeSeekTimestamp(
1506 const base::TimeDelta start_timestamp
) {
1507 DCHECK(start_timestamp
!= kNoTimestamp());
1508 DCHECK(start_timestamp
>= base::TimeDelta());
1510 RangeList::iterator itr
= ranges_
.begin();
1512 for (; itr
!= ranges_
.end(); ++itr
) {
1513 if ((*itr
)->GetEndTimestamp() >= start_timestamp
) {
1518 if (itr
== ranges_
.end())
1519 return kNoTimestamp();
1521 // First check for a keyframe timestamp >= |start_timestamp|
1522 // in the current range.
1523 base::TimeDelta keyframe_timestamp
=
1524 (*itr
)->NextKeyframeTimestamp(start_timestamp
);
1526 if (keyframe_timestamp
!= kNoTimestamp())
1527 return keyframe_timestamp
;
1529 // If a keyframe was not found then look for a keyframe that is
1530 // "close enough" in the current or next range.
1531 base::TimeDelta end_timestamp
=
1532 start_timestamp
+ ComputeFudgeRoom(GetMaxInterbufferDistance());
1533 DCHECK(start_timestamp
< end_timestamp
);
1535 // Make sure the current range doesn't start beyond |end_timestamp|.
1536 if ((*itr
)->GetStartTimestamp() >= end_timestamp
)
1537 return kNoTimestamp();
1539 keyframe_timestamp
= (*itr
)->KeyframeBeforeTimestamp(end_timestamp
);
1541 // Check to see if the keyframe is within the acceptable range
1542 // (|start_timestamp|, |end_timestamp|].
1543 if (keyframe_timestamp
!= kNoTimestamp() &&
1544 start_timestamp
< keyframe_timestamp
&&
1545 keyframe_timestamp
<= end_timestamp
) {
1546 return keyframe_timestamp
;
1549 // If |end_timestamp| is within this range, then no other checks are
1551 if (end_timestamp
<= (*itr
)->GetEndTimestamp())
1552 return kNoTimestamp();
1554 // Move on to the next range.
1557 // Return early if the next range does not contain |end_timestamp|.
1558 if (itr
== ranges_
.end() || (*itr
)->GetStartTimestamp() >= end_timestamp
)
1559 return kNoTimestamp();
1561 keyframe_timestamp
= (*itr
)->KeyframeBeforeTimestamp(end_timestamp
);
1563 // Check to see if the keyframe is within the acceptable range
1564 // (|start_timestamp|, |end_timestamp|].
1565 if (keyframe_timestamp
!= kNoTimestamp() &&
1566 start_timestamp
< keyframe_timestamp
&&
1567 keyframe_timestamp
<= end_timestamp
) {
1568 return keyframe_timestamp
;
1571 return kNoTimestamp();
1574 base::TimeDelta
SourceBufferStream::FindKeyframeAfterTimestamp(
1575 const base::TimeDelta timestamp
) {
1576 DCHECK(timestamp
!= kNoTimestamp());
1578 RangeList::iterator itr
= FindExistingRangeFor(timestamp
);
1580 if (itr
== ranges_
.end())
1581 return kNoTimestamp();
1583 // First check for a keyframe timestamp >= |timestamp|
1584 // in the current range.
1585 return (*itr
)->NextKeyframeTimestamp(timestamp
);
1588 std::string
SourceBufferStream::GetStreamTypeName() const {
1589 switch (GetType()) {
1601 SourceBufferStream::Type
SourceBufferStream::GetType() const {
1602 if (!audio_configs_
.empty())
1604 if (!video_configs_
.empty())
1606 DCHECK_NE(text_track_config_
.kind(), kTextNone
);
1610 void SourceBufferStream::DeleteAndRemoveRange(RangeList::iterator
* itr
) {
1611 DVLOG(1) << __FUNCTION__
;
1613 DCHECK(*itr
!= ranges_
.end());
1614 if (**itr
== selected_range_
) {
1615 DVLOG(1) << __FUNCTION__
<< " deleting selected range.";
1616 SetSelectedRange(NULL
);
1619 if (*itr
== range_for_next_append_
) {
1620 DVLOG(1) << __FUNCTION__
<< " deleting range_for_next_append_.";
1621 range_for_next_append_
= ranges_
.end();
1622 last_appended_buffer_timestamp_
= kNoTimestamp();
1623 last_appended_buffer_is_keyframe_
= false;
1627 *itr
= ranges_
.erase(*itr
);
1630 void SourceBufferStream::GenerateSpliceFrame(const BufferQueue
& new_buffers
) {
1631 DCHECK(!new_buffers
.empty());
1633 // Splice frames are only supported for audio.
1634 if (GetType() != kAudio
)
1637 // Find the overlapped range (if any).
1638 const base::TimeDelta splice_timestamp
= new_buffers
.front()->timestamp();
1639 RangeList::iterator range_itr
= FindExistingRangeFor(splice_timestamp
);
1640 if (range_itr
== ranges_
.end())
1643 const base::TimeDelta max_splice_end_timestamp
=
1644 splice_timestamp
+ base::TimeDelta::FromMilliseconds(
1645 AudioSplicer::kCrossfadeDurationInMilliseconds
);
1647 // Find all buffers involved before the splice point.
1648 BufferQueue pre_splice_buffers
;
1649 if (!(*range_itr
)->GetBuffersInRange(
1650 splice_timestamp
, max_splice_end_timestamp
, &pre_splice_buffers
)) {
1654 // If there are gaps in the timeline, it's possible that we only find buffers
1655 // after the splice point but within the splice range. For simplicity, we do
1656 // not generate splice frames in this case.
1658 // We also do not want to generate splices if the first new buffer replaces an
1659 // existing buffer exactly.
1660 if (pre_splice_buffers
.front()->timestamp() >= splice_timestamp
)
1663 // If any |pre_splice_buffers| are already splices or preroll, do not generate
1665 for (size_t i
= 0; i
< pre_splice_buffers
.size(); ++i
) {
1666 const BufferQueue
& original_splice_buffers
=
1667 pre_splice_buffers
[i
]->splice_buffers();
1668 if (!original_splice_buffers
.empty()) {
1669 DVLOG(1) << "Can't generate splice: overlapped buffers contain a "
1670 "pre-existing splice.";
1674 if (pre_splice_buffers
[i
]->preroll_buffer()) {
1675 DVLOG(1) << "Can't generate splice: overlapped buffers contain preroll.";
1680 // Don't generate splice frames which represent less than two frames, since we
1681 // need at least that much to generate a crossfade. Per the spec, make this
1682 // check using the sample rate of the overlapping buffers.
1683 const base::TimeDelta splice_duration
=
1684 pre_splice_buffers
.back()->timestamp() +
1685 pre_splice_buffers
.back()->duration() - splice_timestamp
;
1686 const base::TimeDelta minimum_splice_duration
= base::TimeDelta::FromSecondsD(
1687 2.0 / audio_configs_
[append_config_index_
].samples_per_second());
1688 if (splice_duration
< minimum_splice_duration
) {
1689 DVLOG(1) << "Can't generate splice: not enough samples for crossfade; have "
1690 << splice_duration
.InMicroseconds() << " us, but need "
1691 << minimum_splice_duration
.InMicroseconds() << " us.";
1695 new_buffers
.front()->ConvertToSpliceBuffer(pre_splice_buffers
);
1698 SourceBufferRange::SourceBufferRange(
1699 SourceBufferStream::Type type
, const BufferQueue
& new_buffers
,
1700 base::TimeDelta media_segment_start_time
,
1701 const InterbufferDistanceCB
& interbuffer_distance_cb
)
1703 keyframe_map_index_base_(0),
1704 next_buffer_index_(-1),
1705 media_segment_start_time_(media_segment_start_time
),
1706 interbuffer_distance_cb_(interbuffer_distance_cb
),
1708 CHECK(!new_buffers
.empty());
1709 DCHECK(new_buffers
.front()->IsKeyframe());
1710 DCHECK(!interbuffer_distance_cb
.is_null());
1711 AppendBuffersToEnd(new_buffers
);
1714 void SourceBufferRange::AppendBuffersToEnd(const BufferQueue
& new_buffers
) {
1715 DCHECK(buffers_
.empty() || CanAppendBuffersToEnd(new_buffers
));
1716 DCHECK(media_segment_start_time_
== kNoTimestamp() ||
1717 media_segment_start_time_
<=
1718 new_buffers
.front()->GetDecodeTimestamp());
1719 for (BufferQueue::const_iterator itr
= new_buffers
.begin();
1720 itr
!= new_buffers
.end();
1722 DCHECK((*itr
)->GetDecodeTimestamp() != kNoTimestamp());
1723 buffers_
.push_back(*itr
);
1724 size_in_bytes_
+= (*itr
)->data_size();
1726 if ((*itr
)->IsKeyframe()) {
1727 keyframe_map_
.insert(
1728 std::make_pair((*itr
)->GetDecodeTimestamp(),
1729 buffers_
.size() - 1 + keyframe_map_index_base_
));
1734 void SourceBufferRange::Seek(base::TimeDelta timestamp
) {
1735 DCHECK(CanSeekTo(timestamp
));
1736 DCHECK(!keyframe_map_
.empty());
1738 KeyframeMap::iterator result
= GetFirstKeyframeBefore(timestamp
);
1739 next_buffer_index_
= result
->second
- keyframe_map_index_base_
;
1740 DCHECK_LT(next_buffer_index_
, static_cast<int>(buffers_
.size()));
1743 void SourceBufferRange::SeekAheadTo(base::TimeDelta timestamp
) {
1744 SeekAhead(timestamp
, false);
1747 void SourceBufferRange::SeekAheadPast(base::TimeDelta timestamp
) {
1748 SeekAhead(timestamp
, true);
1751 void SourceBufferRange::SeekAhead(base::TimeDelta timestamp
,
1752 bool skip_given_timestamp
) {
1753 DCHECK(!keyframe_map_
.empty());
1755 KeyframeMap::iterator result
=
1756 GetFirstKeyframeAt(timestamp
, skip_given_timestamp
);
1758 // If there isn't a keyframe after |timestamp|, then seek to end and return
1759 // kNoTimestamp to signal such.
1760 if (result
== keyframe_map_
.end()) {
1761 next_buffer_index_
= -1;
1764 next_buffer_index_
= result
->second
- keyframe_map_index_base_
;
1765 DCHECK_LT(next_buffer_index_
, static_cast<int>(buffers_
.size()));
1768 void SourceBufferRange::SeekToStart() {
1769 DCHECK(!buffers_
.empty());
1770 next_buffer_index_
= 0;
1773 SourceBufferRange
* SourceBufferRange::SplitRange(
1774 base::TimeDelta timestamp
, bool is_exclusive
) {
1775 CHECK(!buffers_
.empty());
1777 // Find the first keyframe after |timestamp|. If |is_exclusive|, do not
1778 // include keyframes at |timestamp|.
1779 KeyframeMap::iterator new_beginning_keyframe
=
1780 GetFirstKeyframeAt(timestamp
, is_exclusive
);
1782 // If there is no keyframe after |timestamp|, we can't split the range.
1783 if (new_beginning_keyframe
== keyframe_map_
.end())
1786 // Remove the data beginning at |keyframe_index| from |buffers_| and save it
1787 // into |removed_buffers|.
1788 int keyframe_index
=
1789 new_beginning_keyframe
->second
- keyframe_map_index_base_
;
1790 DCHECK_LT(keyframe_index
, static_cast<int>(buffers_
.size()));
1791 BufferQueue::iterator starting_point
= buffers_
.begin() + keyframe_index
;
1792 BufferQueue
removed_buffers(starting_point
, buffers_
.end());
1794 base::TimeDelta new_range_start_timestamp
= kNoTimestamp();
1795 if (GetStartTimestamp() < buffers_
.front()->GetDecodeTimestamp() &&
1796 timestamp
< removed_buffers
.front()->GetDecodeTimestamp()) {
1797 // The split is in the gap between |media_segment_start_time_| and
1798 // the first buffer of the new range so we should set the start
1799 // time of the new range to |timestamp| so we preserve part of the
1800 // gap in the new range.
1801 new_range_start_timestamp
= timestamp
;
1804 keyframe_map_
.erase(new_beginning_keyframe
, keyframe_map_
.end());
1805 FreeBufferRange(starting_point
, buffers_
.end());
1807 // Create a new range with |removed_buffers|.
1808 SourceBufferRange
* split_range
=
1809 new SourceBufferRange(
1810 type_
, removed_buffers
, new_range_start_timestamp
,
1811 interbuffer_distance_cb_
);
1813 // If the next buffer position is now in |split_range|, update the state of
1814 // this range and |split_range| accordingly.
1815 if (next_buffer_index_
>= static_cast<int>(buffers_
.size())) {
1816 split_range
->next_buffer_index_
= next_buffer_index_
- keyframe_index
;
1817 ResetNextBufferPosition();
1823 BufferQueue::iterator
SourceBufferRange::GetBufferItrAt(
1824 base::TimeDelta timestamp
,
1825 bool skip_given_timestamp
) {
1826 return skip_given_timestamp
1827 ? std::upper_bound(buffers_
.begin(),
1830 CompareTimeDeltaToStreamParserBuffer
)
1831 : std::lower_bound(buffers_
.begin(),
1834 CompareStreamParserBufferToTimeDelta
);
1837 SourceBufferRange::KeyframeMap::iterator
1838 SourceBufferRange::GetFirstKeyframeAt(base::TimeDelta timestamp
,
1839 bool skip_given_timestamp
) {
1840 return skip_given_timestamp
?
1841 keyframe_map_
.upper_bound(timestamp
) :
1842 keyframe_map_
.lower_bound(timestamp
);
1845 SourceBufferRange::KeyframeMap::iterator
1846 SourceBufferRange::GetFirstKeyframeBefore(base::TimeDelta timestamp
) {
1847 KeyframeMap::iterator result
= keyframe_map_
.lower_bound(timestamp
);
1848 // lower_bound() returns the first element >= |timestamp|, so we want the
1849 // previous element if it did not return the element exactly equal to
1851 if (result
!= keyframe_map_
.begin() &&
1852 (result
== keyframe_map_
.end() || result
->first
!= timestamp
)) {
1858 void SourceBufferRange::DeleteAll(BufferQueue
* removed_buffers
) {
1859 TruncateAt(buffers_
.begin(), removed_buffers
);
1862 bool SourceBufferRange::TruncateAt(
1863 base::TimeDelta timestamp
, BufferQueue
* removed_buffers
,
1864 bool is_exclusive
) {
1865 // Find the place in |buffers_| where we will begin deleting data.
1866 BufferQueue::iterator starting_point
=
1867 GetBufferItrAt(timestamp
, is_exclusive
);
1868 return TruncateAt(starting_point
, removed_buffers
);
1871 int SourceBufferRange::DeleteGOPFromFront(BufferQueue
* deleted_buffers
) {
1872 DCHECK(!FirstGOPContainsNextBufferPosition());
1873 DCHECK(deleted_buffers
);
1875 int buffers_deleted
= 0;
1876 int total_bytes_deleted
= 0;
1878 KeyframeMap::iterator front
= keyframe_map_
.begin();
1879 DCHECK(front
!= keyframe_map_
.end());
1881 // Delete the keyframe at the start of |keyframe_map_|.
1882 keyframe_map_
.erase(front
);
1884 // Now we need to delete all the buffers that depend on the keyframe we've
1886 int end_index
= keyframe_map_
.size() > 0 ?
1887 keyframe_map_
.begin()->second
- keyframe_map_index_base_
:
1890 // Delete buffers from the beginning of the buffered range up until (but not
1891 // including) the next keyframe.
1892 for (int i
= 0; i
< end_index
; i
++) {
1893 int bytes_deleted
= buffers_
.front()->data_size();
1894 size_in_bytes_
-= bytes_deleted
;
1895 total_bytes_deleted
+= bytes_deleted
;
1896 deleted_buffers
->push_back(buffers_
.front());
1897 buffers_
.pop_front();
1901 // Update |keyframe_map_index_base_| to account for the deleted buffers.
1902 keyframe_map_index_base_
+= buffers_deleted
;
1904 if (next_buffer_index_
> -1) {
1905 next_buffer_index_
-= buffers_deleted
;
1906 DCHECK_GE(next_buffer_index_
, 0);
1909 // Invalidate media segment start time if we've deleted the first buffer of
1911 if (buffers_deleted
> 0)
1912 media_segment_start_time_
= kNoTimestamp();
1914 return total_bytes_deleted
;
1917 int SourceBufferRange::DeleteGOPFromBack(BufferQueue
* deleted_buffers
) {
1918 DCHECK(!LastGOPContainsNextBufferPosition());
1919 DCHECK(deleted_buffers
);
1921 // Remove the last GOP's keyframe from the |keyframe_map_|.
1922 KeyframeMap::iterator back
= keyframe_map_
.end();
1923 DCHECK_GT(keyframe_map_
.size(), 0u);
1926 // The index of the first buffer in the last GOP is equal to the new size of
1927 // |buffers_| after that GOP is deleted.
1928 size_t goal_size
= back
->second
- keyframe_map_index_base_
;
1929 keyframe_map_
.erase(back
);
1931 int total_bytes_deleted
= 0;
1932 while (buffers_
.size() != goal_size
) {
1933 int bytes_deleted
= buffers_
.back()->data_size();
1934 size_in_bytes_
-= bytes_deleted
;
1935 total_bytes_deleted
+= bytes_deleted
;
1936 // We're removing buffers from the back, so push each removed buffer to the
1937 // front of |deleted_buffers| so that |deleted_buffers| are in nondecreasing
1939 deleted_buffers
->push_front(buffers_
.back());
1940 buffers_
.pop_back();
1943 return total_bytes_deleted
;
1946 int SourceBufferRange::GetRemovalGOP(
1947 base::TimeDelta start_timestamp
, base::TimeDelta end_timestamp
,
1948 int total_bytes_to_free
, base::TimeDelta
* removal_end_timestamp
) {
1949 int bytes_to_free
= total_bytes_to_free
;
1950 int bytes_removed
= 0;
1952 KeyframeMap::iterator gop_itr
= GetFirstKeyframeAt(start_timestamp
, false);
1953 if (gop_itr
== keyframe_map_
.end())
1955 int keyframe_index
= gop_itr
->second
- keyframe_map_index_base_
;
1956 BufferQueue::iterator buffer_itr
= buffers_
.begin() + keyframe_index
;
1957 KeyframeMap::iterator gop_end
= keyframe_map_
.end();
1958 if (end_timestamp
< GetBufferedEndTimestamp())
1959 gop_end
= GetFirstKeyframeBefore(end_timestamp
);
1961 // Check if the removal range is within a GOP and skip the loop if so.
1962 // [keyframe]...[start_timestamp]...[end_timestamp]...[keyframe]
1963 KeyframeMap::iterator gop_itr_prev
= gop_itr
;
1964 if (gop_itr_prev
!= keyframe_map_
.begin() && --gop_itr_prev
== gop_end
)
1967 while (gop_itr
!= gop_end
&& bytes_to_free
> 0) {
1971 int next_gop_index
= gop_itr
== keyframe_map_
.end() ?
1972 buffers_
.size() : gop_itr
->second
- keyframe_map_index_base_
;
1973 BufferQueue::iterator next_gop_start
= buffers_
.begin() + next_gop_index
;
1974 for (; buffer_itr
!= next_gop_start
; ++buffer_itr
)
1975 gop_size
+= (*buffer_itr
)->data_size();
1977 bytes_removed
+= gop_size
;
1978 bytes_to_free
-= gop_size
;
1980 if (bytes_removed
> 0) {
1981 *removal_end_timestamp
= gop_itr
== keyframe_map_
.end() ?
1982 GetBufferedEndTimestamp() : gop_itr
->first
;
1984 return bytes_removed
;
1987 bool SourceBufferRange::FirstGOPContainsNextBufferPosition() const {
1988 if (!HasNextBufferPosition())
1991 // If there is only one GOP, it must contain the next buffer position.
1992 if (keyframe_map_
.size() == 1u)
1995 KeyframeMap::const_iterator second_gop
= keyframe_map_
.begin();
1997 return next_buffer_index_
< second_gop
->second
- keyframe_map_index_base_
;
2000 bool SourceBufferRange::LastGOPContainsNextBufferPosition() const {
2001 if (!HasNextBufferPosition())
2004 // If there is only one GOP, it must contain the next buffer position.
2005 if (keyframe_map_
.size() == 1u)
2008 KeyframeMap::const_iterator last_gop
= keyframe_map_
.end();
2010 return last_gop
->second
- keyframe_map_index_base_
<= next_buffer_index_
;
2013 void SourceBufferRange::FreeBufferRange(
2014 const BufferQueue::iterator
& starting_point
,
2015 const BufferQueue::iterator
& ending_point
) {
2016 for (BufferQueue::iterator itr
= starting_point
;
2017 itr
!= ending_point
; ++itr
) {
2018 size_in_bytes_
-= (*itr
)->data_size();
2019 DCHECK_GE(size_in_bytes_
, 0);
2021 buffers_
.erase(starting_point
, ending_point
);
2024 bool SourceBufferRange::TruncateAt(
2025 const BufferQueue::iterator
& starting_point
, BufferQueue
* removed_buffers
) {
2026 DCHECK(!removed_buffers
|| removed_buffers
->empty());
2028 // Return if we're not deleting anything.
2029 if (starting_point
== buffers_
.end())
2030 return buffers_
.empty();
2032 // Reset the next buffer index if we will be deleting the buffer that's next
2034 if (HasNextBufferPosition()) {
2035 base::TimeDelta next_buffer_timestamp
= GetNextTimestamp();
2036 if (next_buffer_timestamp
== kNoTimestamp() ||
2037 next_buffer_timestamp
>= (*starting_point
)->GetDecodeTimestamp()) {
2038 if (HasNextBuffer() && removed_buffers
) {
2039 int starting_offset
= starting_point
- buffers_
.begin();
2040 int next_buffer_offset
= next_buffer_index_
- starting_offset
;
2041 DCHECK_GE(next_buffer_offset
, 0);
2042 BufferQueue
saved(starting_point
+ next_buffer_offset
, buffers_
.end());
2043 removed_buffers
->swap(saved
);
2045 ResetNextBufferPosition();
2049 // Remove keyframes from |starting_point| onward.
2050 KeyframeMap::iterator starting_point_keyframe
=
2051 keyframe_map_
.lower_bound((*starting_point
)->GetDecodeTimestamp());
2052 keyframe_map_
.erase(starting_point_keyframe
, keyframe_map_
.end());
2054 // Remove everything from |starting_point| onward.
2055 FreeBufferRange(starting_point
, buffers_
.end());
2056 return buffers_
.empty();
2059 bool SourceBufferRange::GetNextBuffer(
2060 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
2061 if (!HasNextBuffer())
2064 *out_buffer
= buffers_
[next_buffer_index_
];
2065 next_buffer_index_
++;
2069 bool SourceBufferRange::HasNextBuffer() const {
2070 return next_buffer_index_
>= 0 &&
2071 next_buffer_index_
< static_cast<int>(buffers_
.size());
2074 int SourceBufferRange::GetNextConfigId() const {
2075 DCHECK(HasNextBuffer());
2076 // If the next buffer is an audio splice frame, the next effective config id
2077 // comes from the first fade out preroll buffer.
2078 return GetConfigId(buffers_
[next_buffer_index_
], 0);
2081 base::TimeDelta
SourceBufferRange::GetNextTimestamp() const {
2082 DCHECK(!buffers_
.empty());
2083 DCHECK(HasNextBufferPosition());
2085 if (next_buffer_index_
>= static_cast<int>(buffers_
.size())) {
2086 return kNoTimestamp();
2089 return buffers_
[next_buffer_index_
]->GetDecodeTimestamp();
2092 bool SourceBufferRange::HasNextBufferPosition() const {
2093 return next_buffer_index_
>= 0;
2096 void SourceBufferRange::ResetNextBufferPosition() {
2097 next_buffer_index_
= -1;
2100 void SourceBufferRange::AppendRangeToEnd(const SourceBufferRange
& range
,
2101 bool transfer_current_position
) {
2102 DCHECK(CanAppendRangeToEnd(range
));
2103 DCHECK(!buffers_
.empty());
2105 if (transfer_current_position
&& range
.next_buffer_index_
>= 0)
2106 next_buffer_index_
= range
.next_buffer_index_
+ buffers_
.size();
2108 AppendBuffersToEnd(range
.buffers_
);
2111 bool SourceBufferRange::CanAppendRangeToEnd(
2112 const SourceBufferRange
& range
) const {
2113 return CanAppendBuffersToEnd(range
.buffers_
);
2116 bool SourceBufferRange::CanAppendBuffersToEnd(
2117 const BufferQueue
& buffers
) const {
2118 DCHECK(!buffers_
.empty());
2119 return IsNextInSequence(buffers
.front()->GetDecodeTimestamp(),
2120 buffers
.front()->IsKeyframe());
2123 bool SourceBufferRange::BelongsToRange(base::TimeDelta timestamp
) const {
2124 DCHECK(!buffers_
.empty());
2126 return (IsNextInSequence(timestamp
, false) ||
2127 (GetStartTimestamp() <= timestamp
&& timestamp
<= GetEndTimestamp()));
2130 bool SourceBufferRange::CanSeekTo(base::TimeDelta timestamp
) const {
2131 base::TimeDelta start_timestamp
=
2132 std::max(base::TimeDelta(), GetStartTimestamp() - GetFudgeRoom());
2133 return !keyframe_map_
.empty() && start_timestamp
<= timestamp
&&
2134 timestamp
< GetBufferedEndTimestamp();
2137 bool SourceBufferRange::CompletelyOverlaps(
2138 const SourceBufferRange
& range
) const {
2139 return GetStartTimestamp() <= range
.GetStartTimestamp() &&
2140 GetEndTimestamp() >= range
.GetEndTimestamp();
2143 bool SourceBufferRange::EndOverlaps(const SourceBufferRange
& range
) const {
2144 return range
.GetStartTimestamp() <= GetEndTimestamp() &&
2145 GetEndTimestamp() < range
.GetEndTimestamp();
2148 base::TimeDelta
SourceBufferRange::GetStartTimestamp() const {
2149 DCHECK(!buffers_
.empty());
2150 base::TimeDelta start_timestamp
= media_segment_start_time_
;
2151 if (start_timestamp
== kNoTimestamp())
2152 start_timestamp
= buffers_
.front()->GetDecodeTimestamp();
2153 return start_timestamp
;
2156 base::TimeDelta
SourceBufferRange::GetEndTimestamp() const {
2157 DCHECK(!buffers_
.empty());
2158 return buffers_
.back()->GetDecodeTimestamp();
2161 base::TimeDelta
SourceBufferRange::GetBufferedEndTimestamp() const {
2162 DCHECK(!buffers_
.empty());
2163 base::TimeDelta duration
= buffers_
.back()->duration();
2164 if (duration
== kNoTimestamp() || duration
== base::TimeDelta())
2165 duration
= GetApproximateDuration();
2166 return GetEndTimestamp() + duration
;
2169 base::TimeDelta
SourceBufferRange::NextKeyframeTimestamp(
2170 base::TimeDelta timestamp
) {
2171 DCHECK(!keyframe_map_
.empty());
2173 if (timestamp
< GetStartTimestamp() || timestamp
>= GetBufferedEndTimestamp())
2174 return kNoTimestamp();
2176 KeyframeMap::iterator itr
= GetFirstKeyframeAt(timestamp
, false);
2177 if (itr
== keyframe_map_
.end())
2178 return kNoTimestamp();
2180 // If the timestamp is inside the gap between the start of the media
2181 // segment and the first buffer, then just pretend there is a
2182 // keyframe at the specified timestamp.
2183 if (itr
== keyframe_map_
.begin() &&
2184 timestamp
> media_segment_start_time_
&&
2185 timestamp
< itr
->first
) {
2192 base::TimeDelta
SourceBufferRange::KeyframeBeforeTimestamp(
2193 base::TimeDelta timestamp
) {
2194 DCHECK(!keyframe_map_
.empty());
2196 if (timestamp
< GetStartTimestamp() || timestamp
>= GetBufferedEndTimestamp())
2197 return kNoTimestamp();
2199 return GetFirstKeyframeBefore(timestamp
)->first
;
2202 bool SourceBufferRange::IsNextInSequence(
2203 base::TimeDelta timestamp
, bool is_keyframe
) const {
2204 base::TimeDelta end
= buffers_
.back()->GetDecodeTimestamp();
2205 if (end
< timestamp
&&
2206 (type_
== SourceBufferStream::kText
||
2207 timestamp
<= end
+ GetFudgeRoom())) {
2211 return timestamp
== end
&& AllowSameTimestamp(
2212 buffers_
.back()->IsKeyframe(), is_keyframe
, type_
);
2215 base::TimeDelta
SourceBufferRange::GetFudgeRoom() const {
2216 return ComputeFudgeRoom(GetApproximateDuration());
2219 base::TimeDelta
SourceBufferRange::GetApproximateDuration() const {
2220 base::TimeDelta max_interbuffer_distance
= interbuffer_distance_cb_
.Run();
2221 DCHECK(max_interbuffer_distance
!= kNoTimestamp());
2222 return max_interbuffer_distance
;
2225 bool SourceBufferRange::GetBuffersInRange(base::TimeDelta start
,
2226 base::TimeDelta end
,
2227 BufferQueue
* buffers
) {
2228 // Find the nearest buffer with a decode timestamp <= start.
2229 const base::TimeDelta first_timestamp
= KeyframeBeforeTimestamp(start
);
2230 if (first_timestamp
== kNoTimestamp())
2233 // Find all buffers involved in the range.
2234 const size_t previous_size
= buffers
->size();
2235 for (BufferQueue::iterator it
= GetBufferItrAt(first_timestamp
, false);
2236 it
!= buffers_
.end();
2238 const scoped_refptr
<StreamParserBuffer
>& buffer
= *it
;
2239 // Buffers without duration are not supported, so bail if we encounter any.
2240 if (buffer
->duration() == kNoTimestamp() ||
2241 buffer
->duration() <= base::TimeDelta()) {
2244 if (buffer
->end_of_stream() || buffer
->timestamp() >= end
)
2246 if (buffer
->timestamp() + buffer
->duration() <= start
)
2248 buffers
->push_back(buffer
);
2250 return previous_size
< buffers
->size();
2253 bool SourceBufferStream::SetPendingBuffer(
2254 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
2255 DCHECK(*out_buffer
);
2256 DCHECK(!pending_buffer_
);
2258 const bool have_splice_buffers
= !(*out_buffer
)->splice_buffers().empty();
2259 const bool have_preroll_buffer
= !!(*out_buffer
)->preroll_buffer();
2261 if (!have_splice_buffers
&& !have_preroll_buffer
)
2264 DCHECK_NE(have_splice_buffers
, have_preroll_buffer
);
2265 splice_buffers_index_
= 0;
2266 pending_buffer_
.swap(*out_buffer
);
2267 pending_buffers_complete_
= false;
2271 } // namespace media