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"
16 // Buffers with the same timestamp are only allowed under certain conditions.
17 // Video: Allowed when the previous frame and current frame are NOT keyframes.
18 // This is the situation for VP8 Alt-Ref frames.
19 // Otherwise: Allowed in all situations except where a non-keyframe is followed
21 // Returns true if |prev_is_keyframe| and |current_is_keyframe| indicate a
22 // same timestamp situation that is allowed. False is returned otherwise.
23 static bool AllowSameTimestamp(
24 bool prev_is_keyframe
, bool current_is_keyframe
,
25 SourceBufferStream::Type type
) {
26 if (type
== SourceBufferStream::kVideo
)
27 return !prev_is_keyframe
&& !current_is_keyframe
;
29 return prev_is_keyframe
|| !current_is_keyframe
;
32 // Returns the config ID of |buffer| if |buffer| has no fade out preroll or
33 // |index| is out of range. Otherwise returns the config ID for the fade out
34 // preroll buffer at position |index|.
35 static int GetConfigId(StreamParserBuffer
* buffer
, size_t index
) {
36 return index
< buffer
->GetFadeOutPreroll().size()
37 ? buffer
->GetFadeOutPreroll()[index
]->GetConfigId()
38 : buffer
->GetConfigId();
41 // Helper class representing a range of buffered data. All buffers in a
42 // SourceBufferRange are ordered sequentially in presentation order with no
44 class SourceBufferRange
{
46 typedef std::deque
<scoped_refptr
<StreamParserBuffer
> > BufferQueue
;
48 // Returns the maximum distance in time between any buffer seen in this
49 // stream. Used to estimate the duration of a buffer if its duration is not
51 typedef base::Callback
<base::TimeDelta()> InterbufferDistanceCB
;
53 // Creates a source buffer range with |new_buffers|. |new_buffers| cannot be
54 // empty and the front of |new_buffers| must be a keyframe.
55 // |media_segment_start_time| refers to the starting timestamp for the media
56 // segment to which these buffers belong.
57 SourceBufferRange(SourceBufferStream::Type type
,
58 const BufferQueue
& new_buffers
,
59 base::TimeDelta media_segment_start_time
,
60 const InterbufferDistanceCB
& interbuffer_distance_cb
);
62 // Appends |buffers| to the end of the range and updates |keyframe_map_| as
63 // it encounters new keyframes. Assumes |buffers| belongs at the end of the
65 void AppendBuffersToEnd(const BufferQueue
& buffers
);
66 bool CanAppendBuffersToEnd(const BufferQueue
& buffers
) const;
68 // Appends the buffers from |range| into this range.
69 // The first buffer in |range| must come directly after the last buffer
71 // If |transfer_current_position| is true, |range|'s |next_buffer_index_|
72 // is transfered to this SourceBufferRange.
73 void AppendRangeToEnd(const SourceBufferRange
& range
,
74 bool transfer_current_position
);
75 bool CanAppendRangeToEnd(const SourceBufferRange
& range
) const;
77 // Updates |next_buffer_index_| to point to the Buffer containing |timestamp|.
78 // Assumes |timestamp| is valid and in this range.
79 void Seek(base::TimeDelta timestamp
);
81 // Updates |next_buffer_index_| to point to next keyframe after or equal to
83 void SeekAheadTo(base::TimeDelta timestamp
);
85 // Updates |next_buffer_index_| to point to next keyframe strictly after
87 void SeekAheadPast(base::TimeDelta timestamp
);
89 // Seeks to the beginning of the range.
92 // Finds the next keyframe from |buffers_| after |timestamp| (or at
93 // |timestamp| if |is_exclusive| is false) and creates and returns a new
94 // SourceBufferRange with the buffers from that keyframe onward.
95 // The buffers in the new SourceBufferRange are moved out of this range. If
96 // there is no keyframe after |timestamp|, SplitRange() returns null and this
97 // range is unmodified.
98 SourceBufferRange
* SplitRange(base::TimeDelta timestamp
, bool is_exclusive
);
100 // Deletes the buffers from this range starting at |timestamp|, exclusive if
101 // |is_exclusive| is true, inclusive otherwise.
102 // Resets |next_buffer_index_| if the buffer at |next_buffer_index_| was
103 // deleted, and deletes the |keyframe_map_| entries for the buffers that
105 // |deleted_buffers| contains the buffers that were deleted from this range,
106 // starting at the buffer that had been at |next_buffer_index_|.
107 // Returns true if everything in the range was deleted. Otherwise
109 bool TruncateAt(base::TimeDelta timestamp
,
110 BufferQueue
* deleted_buffers
, bool is_exclusive
);
111 // Deletes all buffers in range.
112 void DeleteAll(BufferQueue
* deleted_buffers
);
114 // Deletes a GOP from the front or back of the range and moves these
115 // buffers into |deleted_buffers|. Returns the number of bytes deleted from
116 // the range (i.e. the size in bytes of |deleted_buffers|).
117 int DeleteGOPFromFront(BufferQueue
* deleted_buffers
);
118 int DeleteGOPFromBack(BufferQueue
* deleted_buffers
);
120 // Gets the range of GOP to secure at least |bytes_to_free| from
121 // [|start_timestamp|, |end_timestamp|).
122 // Returns the size of the buffers to secure if the buffers of
123 // [|start_timestamp|, |end_removal_timestamp|) is removed.
124 // Will not update |end_removal_timestamp| if the returned size is 0.
126 base::TimeDelta start_timestamp
, base::TimeDelta end_timestamp
,
127 int bytes_to_free
, base::TimeDelta
* end_removal_timestamp
);
129 // Indicates whether the GOP at the beginning or end of the range contains the
130 // next buffer position.
131 bool FirstGOPContainsNextBufferPosition() const;
132 bool LastGOPContainsNextBufferPosition() const;
134 // Updates |out_buffer| with the next buffer in presentation order. Seek()
135 // must be called before calls to GetNextBuffer(), and buffers are returned
136 // in order from the last call to Seek(). Returns true if |out_buffer| is
137 // filled with a valid buffer, false if there is not enough data to fulfill
139 bool GetNextBuffer(scoped_refptr
<StreamParserBuffer
>* out_buffer
);
140 bool HasNextBuffer() const;
142 // Returns the config ID for the buffer that will be returned by
144 int GetNextConfigId() const;
146 // Returns true if the range knows the position of the next buffer it should
147 // return, i.e. it has been Seek()ed. This does not necessarily mean that it
148 // has the next buffer yet.
149 bool HasNextBufferPosition() const;
151 // Resets this range to an "unseeked" state.
152 void ResetNextBufferPosition();
154 // Returns the timestamp of the next buffer that will be returned from
155 // GetNextBuffer(), or kNoTimestamp() if the timestamp is unknown.
156 base::TimeDelta
GetNextTimestamp() const;
158 // Returns the start timestamp of the range.
159 base::TimeDelta
GetStartTimestamp() const;
161 // Returns the timestamp of the last buffer in the range.
162 base::TimeDelta
GetEndTimestamp() const;
164 // Returns the timestamp for the end of the buffered region in this range.
165 // This is an approximation if the duration for the last buffer in the range
167 base::TimeDelta
GetBufferedEndTimestamp() const;
169 // Gets the timestamp for the keyframe that is after |timestamp|. If
170 // there isn't a keyframe in the range after |timestamp| then kNoTimestamp()
172 base::TimeDelta
NextKeyframeTimestamp(base::TimeDelta timestamp
);
174 // Gets the timestamp for the closest keyframe that is <= |timestamp|. If
175 // there isn't a keyframe before |timestamp| or |timestamp| is outside
176 // this range, then kNoTimestamp() is returned.
177 base::TimeDelta
KeyframeBeforeTimestamp(base::TimeDelta timestamp
);
179 // Returns whether a buffer with a starting timestamp of |timestamp| would
180 // belong in this range. This includes a buffer that would be appended to
181 // the end of the range.
182 bool BelongsToRange(base::TimeDelta timestamp
) const;
184 // Returns true if the range has enough data to seek to the specified
185 // |timestamp|, false otherwise.
186 bool CanSeekTo(base::TimeDelta timestamp
) const;
188 // Returns true if this range's buffered timespan completely overlaps the
189 // buffered timespan of |range|.
190 bool CompletelyOverlaps(const SourceBufferRange
& range
) const;
192 // Returns true if the end of this range contains buffers that overlaps with
193 // the beginning of |range|.
194 bool EndOverlaps(const SourceBufferRange
& range
) const;
196 // Returns true if |timestamp| is the timestamp of the next buffer in
197 // sequence after |buffers_.back()|, false otherwise.
198 bool IsNextInSequence(base::TimeDelta timestamp
, bool is_keyframe
) const;
200 int size_in_bytes() const { return size_in_bytes_
; }
203 typedef std::map
<base::TimeDelta
, int> KeyframeMap
;
205 // Seeks the range to the next keyframe after |timestamp|. If
206 // |skip_given_timestamp| is true, the seek will go to a keyframe with a
207 // timestamp strictly greater than |timestamp|.
208 void SeekAhead(base::TimeDelta timestamp
, bool skip_given_timestamp
);
210 // Returns an iterator in |buffers_| pointing to the buffer at |timestamp|.
211 // If |skip_given_timestamp| is true, this returns the first buffer with
212 // timestamp greater than |timestamp|.
213 BufferQueue::iterator
GetBufferItrAt(
214 base::TimeDelta timestamp
, bool skip_given_timestamp
);
216 // Returns an iterator in |keyframe_map_| pointing to the next keyframe after
217 // |timestamp|. If |skip_given_timestamp| is true, this returns the first
218 // keyframe with a timestamp strictly greater than |timestamp|.
219 KeyframeMap::iterator
GetFirstKeyframeAt(
220 base::TimeDelta timestamp
, bool skip_given_timestamp
);
222 // Returns an iterator in |keyframe_map_| pointing to the first keyframe
223 // before or at |timestamp|.
224 KeyframeMap::iterator
GetFirstKeyframeBefore(base::TimeDelta timestamp
);
226 // Helper method to delete buffers in |buffers_| starting at
227 // |starting_point|, an iterator in |buffers_|.
228 // Returns true if everything in the range was removed. Returns
229 // false if the range still contains buffers.
230 bool TruncateAt(const BufferQueue::iterator
& starting_point
,
231 BufferQueue
* deleted_buffers
);
233 // Frees the buffers in |buffers_| from [|start_point|,|ending_point|) and
234 // updates the |size_in_bytes_| accordingly. Does not update |keyframe_map_|.
235 void FreeBufferRange(const BufferQueue::iterator
& starting_point
,
236 const BufferQueue::iterator
& ending_point
);
238 // Returns the distance in time estimating how far from the beginning or end
239 // of this range a buffer can be to considered in the range.
240 base::TimeDelta
GetFudgeRoom() const;
242 // Returns the approximate duration of a buffer in this range.
243 base::TimeDelta
GetApproximateDuration() const;
245 // Type of this stream.
246 const SourceBufferStream::Type type_
;
248 // An ordered list of buffers in this range.
249 BufferQueue buffers_
;
251 // Maps keyframe timestamps to its index position in |buffers_|.
252 KeyframeMap keyframe_map_
;
254 // Index base of all positions in |keyframe_map_|. In other words, the
255 // real position of entry |k| of |keyframe_map_| in the range is:
256 // keyframe_map_[k] - keyframe_map_index_base_
257 int keyframe_map_index_base_
;
259 // Index into |buffers_| for the next buffer to be returned by
260 // GetNextBuffer(), set to -1 before Seek().
261 int next_buffer_index_
;
263 // If the first buffer in this range is the beginning of a media segment,
264 // |media_segment_start_time_| is the time when the media segment begins.
265 // |media_segment_start_time_| may be <= the timestamp of the first buffer in
266 // |buffers_|. |media_segment_start_time_| is kNoTimestamp() if this range
267 // does not start at the beginning of a media segment, which can only happen
268 // garbage collection or after an end overlap that results in a split range
269 // (we don't have a way of knowing the media segment timestamp for the new
271 base::TimeDelta media_segment_start_time_
;
273 // Called to get the largest interbuffer distance seen so far in the stream.
274 InterbufferDistanceCB interbuffer_distance_cb_
;
276 // Stores the amount of memory taken up by the data in |buffers_|.
279 DISALLOW_COPY_AND_ASSIGN(SourceBufferRange
);
284 // Helper method that returns true if |ranges| is sorted in increasing order,
286 static bool IsRangeListSorted(
287 const std::list
<media::SourceBufferRange
*>& ranges
) {
288 base::TimeDelta prev
= media::kNoTimestamp();
289 for (std::list
<media::SourceBufferRange
*>::const_iterator itr
=
290 ranges
.begin(); itr
!= ranges
.end(); ++itr
) {
291 if (prev
!= media::kNoTimestamp() && prev
>= (*itr
)->GetStartTimestamp())
293 prev
= (*itr
)->GetEndTimestamp();
298 // Comparison function for two Buffers based on timestamp.
299 static bool BufferComparator(
300 const scoped_refptr
<media::StreamParserBuffer
>& first
,
301 const scoped_refptr
<media::StreamParserBuffer
>& second
) {
302 return first
->GetDecodeTimestamp() < second
->GetDecodeTimestamp();
305 // Returns an estimate of how far from the beginning or end of a range a buffer
306 // can be to still be considered in the range, given the |approximate_duration|
307 // of a buffer in the stream.
308 static base::TimeDelta
ComputeFudgeRoom(base::TimeDelta approximate_duration
) {
309 // Because we do not know exactly when is the next timestamp, any buffer
310 // that starts within 2x the approximate duration of a buffer is considered
311 // within this range.
312 return 2 * approximate_duration
;
315 // An arbitrarily-chosen number to estimate the duration of a buffer if none
316 // is set and there's not enough information to get a better estimate.
317 static int kDefaultBufferDurationInMs
= 125;
319 // The amount of time the beginning of the buffered data can differ from the
320 // start time in order to still be considered the start of stream.
321 static base::TimeDelta
kSeekToStartFudgeRoom() {
322 return base::TimeDelta::FromMilliseconds(1000);
324 // The maximum amount of data in bytes the stream will keep in memory.
325 // 12MB: approximately 5 minutes of 320Kbps content.
326 // 150MB: approximately 5 minutes of 4Mbps content.
327 static int kDefaultAudioMemoryLimit
= 12 * 1024 * 1024;
328 static int kDefaultVideoMemoryLimit
= 150 * 1024 * 1024;
332 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig
& audio_config
,
335 current_config_index_(0),
336 append_config_index_(0),
337 seek_pending_(false),
338 end_of_stream_(false),
339 seek_buffer_timestamp_(kNoTimestamp()),
340 selected_range_(NULL
),
341 media_segment_start_time_(kNoTimestamp()),
342 range_for_next_append_(ranges_
.end()),
343 new_media_segment_(false),
344 last_appended_buffer_timestamp_(kNoTimestamp()),
345 last_appended_buffer_is_keyframe_(false),
346 last_output_buffer_timestamp_(kNoTimestamp()),
347 max_interbuffer_distance_(kNoTimestamp()),
348 memory_limit_(kDefaultAudioMemoryLimit
),
349 config_change_pending_(false),
350 fade_out_preroll_index_(0) {
351 DCHECK(audio_config
.IsValidConfig());
352 audio_configs_
.push_back(audio_config
);
355 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig
& video_config
,
358 current_config_index_(0),
359 append_config_index_(0),
360 seek_pending_(false),
361 end_of_stream_(false),
362 seek_buffer_timestamp_(kNoTimestamp()),
363 selected_range_(NULL
),
364 media_segment_start_time_(kNoTimestamp()),
365 range_for_next_append_(ranges_
.end()),
366 new_media_segment_(false),
367 last_appended_buffer_timestamp_(kNoTimestamp()),
368 last_appended_buffer_is_keyframe_(false),
369 last_output_buffer_timestamp_(kNoTimestamp()),
370 max_interbuffer_distance_(kNoTimestamp()),
371 memory_limit_(kDefaultVideoMemoryLimit
),
372 config_change_pending_(false),
373 fade_out_preroll_index_(0) {
374 DCHECK(video_config
.IsValidConfig());
375 video_configs_
.push_back(video_config
);
378 SourceBufferStream::SourceBufferStream(const TextTrackConfig
& text_config
,
381 current_config_index_(0),
382 append_config_index_(0),
383 text_track_config_(text_config
),
384 seek_pending_(false),
385 end_of_stream_(false),
386 seek_buffer_timestamp_(kNoTimestamp()),
387 selected_range_(NULL
),
388 media_segment_start_time_(kNoTimestamp()),
389 range_for_next_append_(ranges_
.end()),
390 new_media_segment_(false),
391 last_appended_buffer_timestamp_(kNoTimestamp()),
392 last_appended_buffer_is_keyframe_(false),
393 last_output_buffer_timestamp_(kNoTimestamp()),
394 max_interbuffer_distance_(kNoTimestamp()),
395 memory_limit_(kDefaultAudioMemoryLimit
),
396 config_change_pending_(false),
397 fade_out_preroll_index_(0) {
400 SourceBufferStream::~SourceBufferStream() {
401 while (!ranges_
.empty()) {
402 delete ranges_
.front();
407 void SourceBufferStream::OnNewMediaSegment(
408 base::TimeDelta media_segment_start_time
) {
409 DCHECK(!end_of_stream_
);
410 media_segment_start_time_
= media_segment_start_time
;
411 new_media_segment_
= true;
413 RangeList::iterator last_range
= range_for_next_append_
;
414 range_for_next_append_
= FindExistingRangeFor(media_segment_start_time
);
416 // Only reset |last_appended_buffer_timestamp_| if this new media segment is
417 // not adjacent to the previous media segment appended to the stream.
418 if (range_for_next_append_
== ranges_
.end() ||
419 !AreAdjacentInSequence(last_appended_buffer_timestamp_
,
420 media_segment_start_time
)) {
421 last_appended_buffer_timestamp_
= kNoTimestamp();
422 last_appended_buffer_is_keyframe_
= false;
423 } else if (last_range
!= ranges_
.end()) {
424 DCHECK(last_range
== range_for_next_append_
);
428 bool SourceBufferStream::Append(
429 const SourceBufferStream::BufferQueue
& buffers
) {
430 TRACE_EVENT2("media", "SourceBufferStream::Append",
431 "stream type", GetStreamTypeName(),
432 "buffers to append", buffers
.size());
434 DCHECK(!buffers
.empty());
435 DCHECK(media_segment_start_time_
!= kNoTimestamp());
436 DCHECK(!end_of_stream_
);
438 // New media segments must begin with a keyframe.
439 if (new_media_segment_
&& !buffers
.front()->IsKeyframe()) {
440 MEDIA_LOG(log_cb_
) << "Media segment did not begin with keyframe.";
444 // Buffers within a media segment should be monotonically increasing.
445 if (!IsMonotonicallyIncreasing(buffers
))
448 if (media_segment_start_time_
< base::TimeDelta() ||
449 buffers
.front()->GetDecodeTimestamp() < base::TimeDelta()) {
451 << "Cannot append a media segment with negative timestamps.";
455 if (!IsNextTimestampValid(buffers
.front()->GetDecodeTimestamp(),
456 buffers
.front()->IsKeyframe())) {
457 MEDIA_LOG(log_cb_
) << "Invalid same timestamp construct detected at time "
458 << buffers
.front()->GetDecodeTimestamp().InSecondsF();
463 UpdateMaxInterbufferDistance(buffers
);
464 SetConfigIds(buffers
);
466 // Save a snapshot of stream state before range modifications are made.
467 base::TimeDelta next_buffer_timestamp
= GetNextBufferTimestamp();
468 BufferQueue deleted_buffers
;
470 PrepareRangesForNextAppend(buffers
, &deleted_buffers
);
472 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise,
473 // create a new range with |buffers|.
474 if (range_for_next_append_
!= ranges_
.end()) {
475 (*range_for_next_append_
)->AppendBuffersToEnd(buffers
);
476 last_appended_buffer_timestamp_
= buffers
.back()->GetDecodeTimestamp();
477 last_appended_buffer_is_keyframe_
= buffers
.back()->IsKeyframe();
479 base::TimeDelta new_range_start_time
= media_segment_start_time_
;
480 const BufferQueue
* buffers_for_new_range
= &buffers
;
481 BufferQueue trimmed_buffers
;
483 // If the new range is not being created because of a new media
484 // segment, then we must make sure that we start with a keyframe.
485 // This can happen if the GOP in the previous append gets destroyed
486 // by a Remove() call.
487 if (!new_media_segment_
&& !buffers
.front()->IsKeyframe()) {
488 BufferQueue::const_iterator itr
= buffers
.begin();
490 // Scan past all the non-keyframes.
491 while (itr
!= buffers
.end() && !(*itr
)->IsKeyframe()) {
495 // If we didn't find a keyframe, then update the last appended
496 // buffer state and return.
497 if (itr
== buffers
.end()) {
498 last_appended_buffer_timestamp_
= buffers
.back()->GetDecodeTimestamp();
499 last_appended_buffer_is_keyframe_
= buffers
.back()->IsKeyframe();
503 // Copy the first keyframe and everything after it into |trimmed_buffers|.
504 trimmed_buffers
.assign(itr
, buffers
.end());
506 new_range_start_time
= trimmed_buffers
.front()->GetDecodeTimestamp();
507 buffers_for_new_range
= &trimmed_buffers
;
510 range_for_next_append_
=
511 AddToRanges(new SourceBufferRange(
512 GetType(), *buffers_for_new_range
, new_range_start_time
,
513 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance
,
514 base::Unretained(this))));
515 last_appended_buffer_timestamp_
=
516 buffers_for_new_range
->back()->GetDecodeTimestamp();
517 last_appended_buffer_is_keyframe_
=
518 buffers_for_new_range
->back()->IsKeyframe();
521 new_media_segment_
= false;
523 MergeWithAdjacentRangeIfNecessary(range_for_next_append_
);
525 // Seek to try to fulfill a previous call to Seek().
527 DCHECK(!selected_range_
);
528 DCHECK(deleted_buffers
.empty());
529 Seek(seek_buffer_timestamp_
);
532 if (!deleted_buffers
.empty()) {
533 base::TimeDelta start_of_deleted
=
534 deleted_buffers
.front()->GetDecodeTimestamp();
536 DCHECK(track_buffer_
.empty() ||
537 track_buffer_
.back()->GetDecodeTimestamp() < start_of_deleted
)
538 << "decode timestamp "
539 << track_buffer_
.back()->GetDecodeTimestamp().InSecondsF() << " sec"
540 << ", start_of_deleted " << start_of_deleted
.InSecondsF()<< " sec";
542 track_buffer_
.insert(track_buffer_
.end(), deleted_buffers
.begin(),
543 deleted_buffers
.end());
546 // Prune any extra buffers in |track_buffer_| if new keyframes
547 // are appended to the range covered by |track_buffer_|.
548 if (!track_buffer_
.empty()) {
549 base::TimeDelta keyframe_timestamp
=
550 FindKeyframeAfterTimestamp(track_buffer_
.front()->GetDecodeTimestamp());
551 if (keyframe_timestamp
!= kNoTimestamp())
552 PruneTrackBuffer(keyframe_timestamp
);
555 SetSelectedRangeIfNeeded(next_buffer_timestamp
);
557 GarbageCollectIfNeeded();
559 DCHECK(IsRangeListSorted(ranges_
));
560 DCHECK(OnlySelectedRangeIsSeeked());
564 void SourceBufferStream::Remove(base::TimeDelta start
, base::TimeDelta end
,
565 base::TimeDelta duration
) {
566 DVLOG(1) << __FUNCTION__
<< "(" << start
.InSecondsF()
567 << ", " << end
.InSecondsF()
568 << ", " << duration
.InSecondsF() << ")";
569 DCHECK(start
>= base::TimeDelta()) << start
.InSecondsF();
570 DCHECK(start
< end
) << "start " << start
.InSecondsF()
571 << " end " << end
.InSecondsF();
572 DCHECK(duration
!= kNoTimestamp());
574 base::TimeDelta remove_end_timestamp
= duration
;
575 base::TimeDelta keyframe_timestamp
= FindKeyframeAfterTimestamp(end
);
576 if (keyframe_timestamp
!= kNoTimestamp()) {
577 remove_end_timestamp
= keyframe_timestamp
;
578 } else if (end
< remove_end_timestamp
) {
579 remove_end_timestamp
= end
;
582 BufferQueue deleted_buffers
;
583 RemoveInternal(start
, remove_end_timestamp
, false, &deleted_buffers
);
585 if (!deleted_buffers
.empty())
586 SetSelectedRangeIfNeeded(deleted_buffers
.front()->GetDecodeTimestamp());
589 void SourceBufferStream::RemoveInternal(
590 base::TimeDelta start
, base::TimeDelta end
, bool is_exclusive
,
591 BufferQueue
* deleted_buffers
) {
592 DVLOG(1) << __FUNCTION__
<< "(" << start
.InSecondsF()
593 << ", " << end
.InSecondsF()
594 << ", " << is_exclusive
<< ")";
596 DCHECK(start
>= base::TimeDelta());
597 DCHECK(start
< end
) << "start " << start
.InSecondsF()
598 << " end " << end
.InSecondsF();
599 DCHECK(deleted_buffers
);
601 RangeList::iterator itr
= ranges_
.begin();
603 while (itr
!= ranges_
.end()) {
604 SourceBufferRange
* range
= *itr
;
605 if (range
->GetStartTimestamp() >= end
)
608 // Split off any remaining end piece and add it to |ranges_|.
609 SourceBufferRange
* new_range
= range
->SplitRange(end
, is_exclusive
);
611 itr
= ranges_
.insert(++itr
, new_range
);
614 // Update the selected range if the next buffer position was transferred
616 if (new_range
->HasNextBufferPosition())
617 SetSelectedRange(new_range
);
620 // Truncate the current range so that it only contains data before
621 // the removal range.
622 BufferQueue saved_buffers
;
623 bool delete_range
= range
->TruncateAt(start
, &saved_buffers
, is_exclusive
);
625 // Check to see if the current playback position was removed and
626 // update the selected range appropriately.
627 if (!saved_buffers
.empty()) {
628 DCHECK(!range
->HasNextBufferPosition());
629 DCHECK(deleted_buffers
->empty());
631 *deleted_buffers
= saved_buffers
;
634 if (range
== selected_range_
&& !range
->HasNextBufferPosition())
635 SetSelectedRange(NULL
);
637 // If the current range now is completely covered by the removal
638 // range then delete it and move on.
640 DeleteAndRemoveRange(&itr
);
644 // Clear |range_for_next_append_| if we determine that the removal
645 // operation makes it impossible for the next append to be added
646 // to the current range.
647 if (range_for_next_append_
!= ranges_
.end() &&
648 *range_for_next_append_
== range
&&
649 last_appended_buffer_timestamp_
!= kNoTimestamp()) {
650 base::TimeDelta potential_next_append_timestamp
=
651 last_appended_buffer_timestamp_
+
652 base::TimeDelta::FromInternalValue(1);
654 if (!range
->BelongsToRange(potential_next_append_timestamp
)) {
655 DVLOG(1) << "Resetting range_for_next_append_ since the next append"
656 << " can't add to the current range.";
657 range_for_next_append_
=
658 FindExistingRangeFor(potential_next_append_timestamp
);
662 // Move on to the next range.
666 DCHECK(IsRangeListSorted(ranges_
));
667 DCHECK(OnlySelectedRangeIsSeeked());
668 DVLOG(1) << __FUNCTION__
<< " : done";
671 void SourceBufferStream::ResetSeekState() {
672 SetSelectedRange(NULL
);
673 track_buffer_
.clear();
674 config_change_pending_
= false;
675 last_output_buffer_timestamp_
= kNoTimestamp();
676 fade_out_preroll_index_
= 0;
677 fade_in_buffer_
= NULL
;
680 bool SourceBufferStream::ShouldSeekToStartOfBuffered(
681 base::TimeDelta seek_timestamp
) const {
684 base::TimeDelta beginning_of_buffered
=
685 ranges_
.front()->GetStartTimestamp();
686 return (seek_timestamp
<= beginning_of_buffered
&&
687 beginning_of_buffered
< kSeekToStartFudgeRoom());
690 bool SourceBufferStream::IsMonotonicallyIncreasing(
691 const BufferQueue
& buffers
) const {
692 DCHECK(!buffers
.empty());
693 base::TimeDelta prev_timestamp
= last_appended_buffer_timestamp_
;
694 bool prev_is_keyframe
= last_appended_buffer_is_keyframe_
;
695 for (BufferQueue::const_iterator itr
= buffers
.begin();
696 itr
!= buffers
.end(); ++itr
) {
697 base::TimeDelta current_timestamp
= (*itr
)->GetDecodeTimestamp();
698 bool current_is_keyframe
= (*itr
)->IsKeyframe();
699 DCHECK(current_timestamp
!= kNoTimestamp());
701 if (prev_timestamp
!= kNoTimestamp()) {
702 if (current_timestamp
< prev_timestamp
) {
703 MEDIA_LOG(log_cb_
) << "Buffers were not monotonically increasing.";
707 if (current_timestamp
== prev_timestamp
&&
708 !AllowSameTimestamp(prev_is_keyframe
, current_is_keyframe
,
710 MEDIA_LOG(log_cb_
) << "Unexpected combination of buffers with the"
711 << " same timestamp detected at "
712 << current_timestamp
.InSecondsF();
717 prev_timestamp
= current_timestamp
;
718 prev_is_keyframe
= current_is_keyframe
;
723 bool SourceBufferStream::IsNextTimestampValid(
724 base::TimeDelta next_timestamp
, bool next_is_keyframe
) const {
725 return (last_appended_buffer_timestamp_
!= next_timestamp
) ||
726 new_media_segment_
||
727 AllowSameTimestamp(last_appended_buffer_is_keyframe_
, next_is_keyframe
,
732 bool SourceBufferStream::OnlySelectedRangeIsSeeked() const {
733 for (RangeList::const_iterator itr
= ranges_
.begin();
734 itr
!= ranges_
.end(); ++itr
) {
735 if ((*itr
)->HasNextBufferPosition() && (*itr
) != selected_range_
)
738 return !selected_range_
|| selected_range_
->HasNextBufferPosition();
741 void SourceBufferStream::UpdateMaxInterbufferDistance(
742 const BufferQueue
& buffers
) {
743 DCHECK(!buffers
.empty());
744 base::TimeDelta prev_timestamp
= last_appended_buffer_timestamp_
;
745 for (BufferQueue::const_iterator itr
= buffers
.begin();
746 itr
!= buffers
.end(); ++itr
) {
747 base::TimeDelta current_timestamp
= (*itr
)->GetDecodeTimestamp();
748 DCHECK(current_timestamp
!= kNoTimestamp());
750 if (prev_timestamp
!= kNoTimestamp()) {
751 base::TimeDelta interbuffer_distance
= current_timestamp
- prev_timestamp
;
752 if (max_interbuffer_distance_
== kNoTimestamp()) {
753 max_interbuffer_distance_
= interbuffer_distance
;
755 max_interbuffer_distance_
=
756 std::max(max_interbuffer_distance_
, interbuffer_distance
);
759 prev_timestamp
= current_timestamp
;
763 void SourceBufferStream::SetConfigIds(const BufferQueue
& buffers
) {
764 for (BufferQueue::const_iterator itr
= buffers
.begin();
765 itr
!= buffers
.end(); ++itr
) {
766 (*itr
)->SetConfigId(append_config_index_
);
770 void SourceBufferStream::GarbageCollectIfNeeded() {
771 // Compute size of |ranges_|.
773 for (RangeList::iterator itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
)
774 ranges_size
+= (*itr
)->size_in_bytes();
776 // Return if we're under or at the memory limit.
777 if (ranges_size
<= memory_limit_
)
780 int bytes_to_free
= ranges_size
- memory_limit_
;
782 // Begin deleting after the last appended buffer.
783 int bytes_freed
= FreeBuffersAfterLastAppended(bytes_to_free
);
785 // Begin deleting from the front.
786 if (bytes_to_free
- bytes_freed
> 0)
787 bytes_freed
+= FreeBuffers(bytes_to_free
- bytes_freed
, false);
789 // Begin deleting from the back.
790 if (bytes_to_free
- bytes_freed
> 0)
791 FreeBuffers(bytes_to_free
- bytes_freed
, true);
794 int SourceBufferStream::FreeBuffersAfterLastAppended(int total_bytes_to_free
) {
795 base::TimeDelta next_buffer_timestamp
= GetNextBufferTimestamp();
796 if (last_appended_buffer_timestamp_
== kNoTimestamp() ||
797 next_buffer_timestamp
== kNoTimestamp() ||
798 last_appended_buffer_timestamp_
>= next_buffer_timestamp
) {
802 base::TimeDelta remove_range_start
= last_appended_buffer_timestamp_
;
803 if (last_appended_buffer_is_keyframe_
)
804 remove_range_start
+= GetMaxInterbufferDistance();
806 base::TimeDelta remove_range_start_keyframe
= FindKeyframeAfterTimestamp(
808 if (remove_range_start_keyframe
!= kNoTimestamp())
809 remove_range_start
= remove_range_start_keyframe
;
810 if (remove_range_start
>= next_buffer_timestamp
)
813 base::TimeDelta remove_range_end
;
814 int bytes_freed
= GetRemovalRange(
815 remove_range_start
, next_buffer_timestamp
, total_bytes_to_free
,
818 Remove(remove_range_start
, remove_range_end
, next_buffer_timestamp
);
822 int SourceBufferStream::GetRemovalRange(
823 base::TimeDelta start_timestamp
, base::TimeDelta end_timestamp
,
824 int total_bytes_to_free
, base::TimeDelta
* removal_end_timestamp
) {
825 DCHECK(start_timestamp
>= base::TimeDelta()) << start_timestamp
.InSecondsF();
826 DCHECK(start_timestamp
< end_timestamp
)
827 << "start " << start_timestamp
.InSecondsF()
828 << ", end " << end_timestamp
.InSecondsF();
830 int bytes_to_free
= total_bytes_to_free
;
833 for (RangeList::iterator itr
= ranges_
.begin();
834 itr
!= ranges_
.end() && bytes_to_free
> 0; ++itr
) {
835 SourceBufferRange
* range
= *itr
;
836 if (range
->GetStartTimestamp() >= end_timestamp
)
838 if (range
->GetEndTimestamp() < start_timestamp
)
841 int bytes_removed
= range
->GetRemovalGOP(
842 start_timestamp
, end_timestamp
, bytes_to_free
, removal_end_timestamp
);
843 bytes_to_free
-= bytes_removed
;
844 bytes_freed
+= bytes_removed
;
849 int SourceBufferStream::FreeBuffers(int total_bytes_to_free
,
850 bool reverse_direction
) {
851 TRACE_EVENT2("media", "SourceBufferStream::FreeBuffers",
852 "total bytes to free", total_bytes_to_free
,
853 "reverse direction", reverse_direction
);
855 DCHECK_GT(total_bytes_to_free
, 0);
856 int bytes_to_free
= total_bytes_to_free
;
859 // This range will save the last GOP appended to |range_for_next_append_|
860 // if the buffers surrounding it get deleted during garbage collection.
861 SourceBufferRange
* new_range_for_append
= NULL
;
863 while (!ranges_
.empty() && bytes_to_free
> 0) {
864 SourceBufferRange
* current_range
= NULL
;
866 int bytes_deleted
= 0;
868 if (reverse_direction
) {
869 current_range
= ranges_
.back();
870 if (current_range
->LastGOPContainsNextBufferPosition()) {
871 DCHECK_EQ(current_range
, selected_range_
);
874 bytes_deleted
= current_range
->DeleteGOPFromBack(&buffers
);
876 current_range
= ranges_
.front();
877 if (current_range
->FirstGOPContainsNextBufferPosition()) {
878 DCHECK_EQ(current_range
, selected_range_
);
881 bytes_deleted
= current_range
->DeleteGOPFromFront(&buffers
);
884 // Check to see if we've just deleted the GOP that was last appended.
885 base::TimeDelta end_timestamp
= buffers
.back()->GetDecodeTimestamp();
886 if (end_timestamp
== last_appended_buffer_timestamp_
) {
887 DCHECK(last_appended_buffer_timestamp_
!= kNoTimestamp());
888 DCHECK(!new_range_for_append
);
889 // Create a new range containing these buffers.
890 new_range_for_append
= new SourceBufferRange(
891 GetType(), buffers
, kNoTimestamp(),
892 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance
,
893 base::Unretained(this)));
894 range_for_next_append_
= ranges_
.end();
896 bytes_to_free
-= bytes_deleted
;
897 bytes_freed
+= bytes_deleted
;
900 if (current_range
->size_in_bytes() == 0) {
901 DCHECK_NE(current_range
, selected_range_
);
902 DCHECK(range_for_next_append_
== ranges_
.end() ||
903 *range_for_next_append_
!= current_range
);
904 delete current_range
;
905 reverse_direction
? ranges_
.pop_back() : ranges_
.pop_front();
909 // Insert |new_range_for_append| into |ranges_|, if applicable.
910 if (new_range_for_append
) {
911 range_for_next_append_
= AddToRanges(new_range_for_append
);
912 DCHECK(range_for_next_append_
!= ranges_
.end());
914 // Check to see if we need to merge |new_range_for_append| with the range
915 // before or after it. |new_range_for_append| is created whenever the last
916 // GOP appended is encountered, regardless of whether any buffers after it
917 // are ultimately deleted. Merging is necessary if there were no buffers
918 // (or very few buffers) deleted after creating |new_range_for_append|.
919 if (range_for_next_append_
!= ranges_
.begin()) {
920 RangeList::iterator range_before_next
= range_for_next_append_
;
922 MergeWithAdjacentRangeIfNecessary(range_before_next
);
924 MergeWithAdjacentRangeIfNecessary(range_for_next_append_
);
929 void SourceBufferStream::PrepareRangesForNextAppend(
930 const BufferQueue
& new_buffers
, BufferQueue
* deleted_buffers
) {
931 DCHECK(deleted_buffers
);
933 bool temporarily_select_range
= false;
934 if (!track_buffer_
.empty()) {
935 base::TimeDelta tb_timestamp
= track_buffer_
.back()->GetDecodeTimestamp();
936 base::TimeDelta seek_timestamp
= FindKeyframeAfterTimestamp(tb_timestamp
);
937 if (seek_timestamp
!= kNoTimestamp() &&
938 seek_timestamp
< new_buffers
.front()->GetDecodeTimestamp() &&
939 range_for_next_append_
!= ranges_
.end() &&
940 (*range_for_next_append_
)->BelongsToRange(seek_timestamp
)) {
941 DCHECK(tb_timestamp
< seek_timestamp
);
942 DCHECK(!selected_range_
);
943 DCHECK(!(*range_for_next_append_
)->HasNextBufferPosition());
945 // If there are GOPs between the end of the track buffer and the
946 // beginning of the new buffers, then temporarily seek the range
947 // so that the buffers between these two times will be deposited in
948 // |deleted_buffers| as if they were part of the current playback
950 // TODO(acolwell): Figure out a more elegant way to do this.
951 SeekAndSetSelectedRange(*range_for_next_append_
, seek_timestamp
);
952 temporarily_select_range
= true;
956 base::TimeDelta prev_timestamp
= last_appended_buffer_timestamp_
;
957 bool prev_is_keyframe
= last_appended_buffer_is_keyframe_
;
958 base::TimeDelta next_timestamp
= new_buffers
.front()->GetDecodeTimestamp();
959 bool next_is_keyframe
= new_buffers
.front()->IsKeyframe();
961 if (prev_timestamp
!= kNoTimestamp() && prev_timestamp
!= next_timestamp
) {
962 // Clean up the old buffers between the last appended buffer and the
963 // beginning of |new_buffers|.
964 RemoveInternal(prev_timestamp
, next_timestamp
, true, deleted_buffers
);
967 // Make the delete range exclusive if we are dealing with an allowed same
968 // timestamp situation. This prevents the first buffer in the current append
969 // from deleting the last buffer in the previous append if both buffers
970 // have the same timestamp.
971 bool is_exclusive
= (prev_timestamp
== next_timestamp
) &&
972 AllowSameTimestamp(prev_is_keyframe
, next_is_keyframe
, GetType());
974 // Delete the buffers that |new_buffers| overlaps.
975 base::TimeDelta start
= new_buffers
.front()->GetDecodeTimestamp();
976 base::TimeDelta end
= new_buffers
.back()->GetDecodeTimestamp();
977 base::TimeDelta duration
= new_buffers
.back()->duration();
979 if (duration
!= kNoTimestamp() && duration
> base::TimeDelta()) {
982 // TODO(acolwell): Ensure all buffers actually have proper
983 // duration info so that this hack isn't needed.
984 // http://crbug.com/312836
985 end
+= base::TimeDelta::FromInternalValue(1);
988 RemoveInternal(start
, end
, is_exclusive
, deleted_buffers
);
990 // Restore the range seek state if necessary.
991 if (temporarily_select_range
)
992 SetSelectedRange(NULL
);
995 bool SourceBufferStream::AreAdjacentInSequence(
996 base::TimeDelta first_timestamp
, base::TimeDelta second_timestamp
) const {
997 return first_timestamp
< second_timestamp
&&
999 first_timestamp
+ ComputeFudgeRoom(GetMaxInterbufferDistance());
1002 void SourceBufferStream::PruneTrackBuffer(const base::TimeDelta timestamp
) {
1003 // If we don't have the next timestamp, we don't have anything to delete.
1004 if (timestamp
== kNoTimestamp())
1007 while (!track_buffer_
.empty() &&
1008 track_buffer_
.back()->GetDecodeTimestamp() >= timestamp
) {
1009 track_buffer_
.pop_back();
1013 void SourceBufferStream::MergeWithAdjacentRangeIfNecessary(
1014 const RangeList::iterator
& range_with_new_buffers_itr
) {
1015 DCHECK(range_with_new_buffers_itr
!= ranges_
.end());
1017 SourceBufferRange
* range_with_new_buffers
= *range_with_new_buffers_itr
;
1018 RangeList::iterator next_range_itr
= range_with_new_buffers_itr
;
1021 if (next_range_itr
== ranges_
.end() ||
1022 !range_with_new_buffers
->CanAppendRangeToEnd(**next_range_itr
)) {
1026 bool transfer_current_position
= selected_range_
== *next_range_itr
;
1027 range_with_new_buffers
->AppendRangeToEnd(**next_range_itr
,
1028 transfer_current_position
);
1029 // Update |selected_range_| pointer if |range| has become selected after
1031 if (transfer_current_position
)
1032 SetSelectedRange(range_with_new_buffers
);
1034 if (next_range_itr
== range_for_next_append_
)
1035 range_for_next_append_
= range_with_new_buffers_itr
;
1037 DeleteAndRemoveRange(&next_range_itr
);
1040 void SourceBufferStream::Seek(base::TimeDelta timestamp
) {
1041 DCHECK(timestamp
>= base::TimeDelta());
1044 if (ShouldSeekToStartOfBuffered(timestamp
)) {
1045 ranges_
.front()->SeekToStart();
1046 SetSelectedRange(ranges_
.front());
1047 seek_pending_
= false;
1051 seek_buffer_timestamp_
= timestamp
;
1052 seek_pending_
= true;
1054 RangeList::iterator itr
= ranges_
.end();
1055 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1056 if ((*itr
)->CanSeekTo(timestamp
))
1060 if (itr
== ranges_
.end())
1063 SeekAndSetSelectedRange(*itr
, timestamp
);
1064 seek_pending_
= false;
1067 bool SourceBufferStream::IsSeekPending() const {
1068 return !(end_of_stream_
&& IsEndSelected()) && seek_pending_
;
1071 void SourceBufferStream::OnSetDuration(base::TimeDelta duration
) {
1072 RangeList::iterator itr
= ranges_
.end();
1073 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1074 if ((*itr
)->GetEndTimestamp() > duration
)
1077 if (itr
== ranges_
.end())
1080 // Need to partially truncate this range.
1081 if ((*itr
)->GetStartTimestamp() < duration
) {
1082 bool delete_range
= (*itr
)->TruncateAt(duration
, NULL
, false);
1083 if ((*itr
== selected_range_
) && !selected_range_
->HasNextBufferPosition())
1084 SetSelectedRange(NULL
);
1087 DeleteAndRemoveRange(&itr
);
1093 // Delete all ranges that begin after |duration|.
1094 while (itr
!= ranges_
.end()) {
1095 // If we're about to delete the selected range, also reset the seek state.
1096 DCHECK((*itr
)->GetStartTimestamp() >= duration
);
1097 if (*itr
== selected_range_
)
1099 DeleteAndRemoveRange(&itr
);
1103 SourceBufferStream::Status
SourceBufferStream::GetNextBuffer(
1104 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1105 if (!fade_in_buffer_
) {
1106 const SourceBufferStream::Status status
= GetNextBufferInternal(out_buffer
);
1108 // Just return if GetNextBufferInternal() failed or there's no fade out
1109 // preroll, there's nothing else to do.
1110 if (status
!= SourceBufferStream::kSuccess
||
1111 (*out_buffer
)->GetFadeOutPreroll().empty()) {
1115 // Setup fade in buffer and fall through into splice frame buffer handling.
1116 fade_out_preroll_index_
= 0;
1117 fade_in_buffer_
.swap(*out_buffer
);
1120 DCHECK(fade_in_buffer_
);
1121 const std::vector
<scoped_refptr
<StreamParserBuffer
> >& fade_out_preroll
=
1122 fade_in_buffer_
->GetFadeOutPreroll();
1124 // Are there any fade out buffers left to hand out?
1125 if (fade_out_preroll_index_
< fade_out_preroll
.size()) {
1126 // Account for config changes which occur between fade out buffers.
1127 if (current_config_index_
!=
1128 fade_out_preroll
[fade_out_preroll_index_
]->GetConfigId()) {
1129 config_change_pending_
= true;
1130 DVLOG(1) << "Config change (fade out preroll config ID does not match).";
1131 return SourceBufferStream::kConfigChange
;
1134 *out_buffer
= fade_out_preroll
[fade_out_preroll_index_
++];
1135 return SourceBufferStream::kSuccess
;
1138 // Did we hand out the last fade out buffer on the last call?
1139 if (fade_out_preroll_index_
== fade_out_preroll
.size()) {
1140 fade_out_preroll_index_
++;
1141 config_change_pending_
= true;
1142 DVLOG(1) << "Config change (forced for fade in of splice frame).";
1143 return SourceBufferStream::kConfigChange
;
1146 // All fade out buffers have been handed out and a config change completed, so
1147 // hand out the final buffer for fade in. Because a config change is always
1148 // issued prior to handing out this buffer, any changes in config id have been
1149 // inherently handled.
1150 DCHECK_GT(fade_out_preroll_index_
, fade_out_preroll
.size());
1151 out_buffer
->swap(fade_in_buffer_
);
1152 fade_in_buffer_
= NULL
;
1153 fade_out_preroll_index_
= 0;
1154 return SourceBufferStream::kSuccess
;
1157 SourceBufferStream::Status
SourceBufferStream::GetNextBufferInternal(
1158 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1159 CHECK(!config_change_pending_
);
1161 if (!track_buffer_
.empty()) {
1162 DCHECK(!selected_range_
);
1163 scoped_refptr
<StreamParserBuffer
>& next_buffer
= track_buffer_
.front();
1165 // If the next buffer is an audio splice frame, the next effective config id
1166 // comes from the first fade out preroll buffer.
1167 if (GetConfigId(next_buffer
, 0) != current_config_index_
) {
1168 config_change_pending_
= true;
1169 DVLOG(1) << "Config change (track buffer config ID does not match).";
1170 return kConfigChange
;
1173 *out_buffer
= next_buffer
;
1174 track_buffer_
.pop_front();
1175 last_output_buffer_timestamp_
= (*out_buffer
)->GetDecodeTimestamp();
1177 // If the track buffer becomes empty, then try to set the selected range
1178 // based on the timestamp of this buffer being returned.
1179 if (track_buffer_
.empty())
1180 SetSelectedRangeIfNeeded(last_output_buffer_timestamp_
);
1185 if (!selected_range_
|| !selected_range_
->HasNextBuffer()) {
1186 if (end_of_stream_
&& IsEndSelected())
1187 return kEndOfStream
;
1191 if (selected_range_
->GetNextConfigId() != current_config_index_
) {
1192 config_change_pending_
= true;
1193 DVLOG(1) << "Config change (selected range config ID does not match).";
1194 return kConfigChange
;
1197 CHECK(selected_range_
->GetNextBuffer(out_buffer
));
1198 last_output_buffer_timestamp_
= (*out_buffer
)->GetDecodeTimestamp();
1202 base::TimeDelta
SourceBufferStream::GetNextBufferTimestamp() {
1203 if (!track_buffer_
.empty())
1204 return track_buffer_
.front()->GetDecodeTimestamp();
1206 if (!selected_range_
)
1207 return kNoTimestamp();
1209 DCHECK(selected_range_
->HasNextBufferPosition());
1210 return selected_range_
->GetNextTimestamp();
1213 base::TimeDelta
SourceBufferStream::GetEndBufferTimestamp() {
1214 if (!selected_range_
)
1215 return kNoTimestamp();
1216 return selected_range_
->GetEndTimestamp();
1219 SourceBufferStream::RangeList::iterator
1220 SourceBufferStream::FindExistingRangeFor(base::TimeDelta start_timestamp
) {
1221 for (RangeList::iterator itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1222 if ((*itr
)->BelongsToRange(start_timestamp
))
1225 return ranges_
.end();
1228 SourceBufferStream::RangeList::iterator
1229 SourceBufferStream::AddToRanges(SourceBufferRange
* new_range
) {
1230 base::TimeDelta start_timestamp
= new_range
->GetStartTimestamp();
1231 RangeList::iterator itr
= ranges_
.end();
1232 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1233 if ((*itr
)->GetStartTimestamp() > start_timestamp
)
1236 return ranges_
.insert(itr
, new_range
);
1239 SourceBufferStream::RangeList::iterator
1240 SourceBufferStream::GetSelectedRangeItr() {
1241 DCHECK(selected_range_
);
1242 RangeList::iterator itr
= ranges_
.end();
1243 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); ++itr
) {
1244 if (*itr
== selected_range_
)
1247 DCHECK(itr
!= ranges_
.end());
1251 void SourceBufferStream::SeekAndSetSelectedRange(
1252 SourceBufferRange
* range
, base::TimeDelta seek_timestamp
) {
1254 range
->Seek(seek_timestamp
);
1255 SetSelectedRange(range
);
1258 void SourceBufferStream::SetSelectedRange(SourceBufferRange
* range
) {
1259 DVLOG(1) << __FUNCTION__
<< " : " << selected_range_
<< " -> " << range
;
1260 if (selected_range_
)
1261 selected_range_
->ResetNextBufferPosition();
1262 DCHECK(!range
|| range
->HasNextBufferPosition());
1263 selected_range_
= range
;
1266 Ranges
<base::TimeDelta
> SourceBufferStream::GetBufferedTime() const {
1267 Ranges
<base::TimeDelta
> ranges
;
1268 for (RangeList::const_iterator itr
= ranges_
.begin();
1269 itr
!= ranges_
.end(); ++itr
) {
1270 ranges
.Add((*itr
)->GetStartTimestamp(), (*itr
)->GetBufferedEndTimestamp());
1275 base::TimeDelta
SourceBufferStream::GetBufferedDuration() const {
1276 if (ranges_
.empty())
1277 return base::TimeDelta();
1279 return ranges_
.back()->GetBufferedEndTimestamp();
1282 void SourceBufferStream::MarkEndOfStream() {
1283 DCHECK(!end_of_stream_
);
1284 end_of_stream_
= true;
1287 void SourceBufferStream::UnmarkEndOfStream() {
1288 DCHECK(end_of_stream_
);
1289 end_of_stream_
= false;
1292 bool SourceBufferStream::IsEndSelected() const {
1293 if (ranges_
.empty())
1297 return seek_buffer_timestamp_
>= ranges_
.back()->GetBufferedEndTimestamp();
1299 return selected_range_
== ranges_
.back();
1302 const AudioDecoderConfig
& SourceBufferStream::GetCurrentAudioDecoderConfig() {
1303 if (config_change_pending_
)
1304 CompleteConfigChange();
1305 return audio_configs_
[current_config_index_
];
1308 const VideoDecoderConfig
& SourceBufferStream::GetCurrentVideoDecoderConfig() {
1309 if (config_change_pending_
)
1310 CompleteConfigChange();
1311 return video_configs_
[current_config_index_
];
1314 const TextTrackConfig
& SourceBufferStream::GetCurrentTextTrackConfig() {
1315 return text_track_config_
;
1318 base::TimeDelta
SourceBufferStream::GetMaxInterbufferDistance() const {
1319 if (max_interbuffer_distance_
== kNoTimestamp())
1320 return base::TimeDelta::FromMilliseconds(kDefaultBufferDurationInMs
);
1321 return max_interbuffer_distance_
;
1324 bool SourceBufferStream::UpdateAudioConfig(const AudioDecoderConfig
& config
) {
1325 DCHECK(!audio_configs_
.empty());
1326 DCHECK(video_configs_
.empty());
1327 DVLOG(3) << "UpdateAudioConfig.";
1329 if (audio_configs_
[0].codec() != config
.codec()) {
1330 MEDIA_LOG(log_cb_
) << "Audio codec changes not allowed.";
1334 if (audio_configs_
[0].samples_per_second() != config
.samples_per_second()) {
1335 MEDIA_LOG(log_cb_
) << "Audio sample rate changes not allowed.";
1339 if (audio_configs_
[0].channel_layout() != config
.channel_layout()) {
1340 MEDIA_LOG(log_cb_
) << "Audio channel layout changes not allowed.";
1344 if (audio_configs_
[0].bits_per_channel() != config
.bits_per_channel()) {
1345 MEDIA_LOG(log_cb_
) << "Audio bits per channel changes not allowed.";
1349 if (audio_configs_
[0].is_encrypted() != config
.is_encrypted()) {
1350 MEDIA_LOG(log_cb_
) << "Audio encryption changes not allowed.";
1354 // Check to see if the new config matches an existing one.
1355 for (size_t i
= 0; i
< audio_configs_
.size(); ++i
) {
1356 if (config
.Matches(audio_configs_
[i
])) {
1357 append_config_index_
= i
;
1362 // No matches found so let's add this one to the list.
1363 append_config_index_
= audio_configs_
.size();
1364 DVLOG(2) << "New audio config - index: " << append_config_index_
;
1365 audio_configs_
.resize(audio_configs_
.size() + 1);
1366 audio_configs_
[append_config_index_
] = config
;
1370 bool SourceBufferStream::UpdateVideoConfig(const VideoDecoderConfig
& config
) {
1371 DCHECK(!video_configs_
.empty());
1372 DCHECK(audio_configs_
.empty());
1373 DVLOG(3) << "UpdateVideoConfig.";
1375 if (video_configs_
[0].is_encrypted() != config
.is_encrypted()) {
1376 MEDIA_LOG(log_cb_
) << "Video Encryption changes not allowed.";
1380 if (video_configs_
[0].codec() != config
.codec()) {
1381 MEDIA_LOG(log_cb_
) << "Video codec changes not allowed.";
1385 if (video_configs_
[0].is_encrypted() != config
.is_encrypted()) {
1386 MEDIA_LOG(log_cb_
) << "Video encryption changes not allowed.";
1390 // Check to see if the new config matches an existing one.
1391 for (size_t i
= 0; i
< video_configs_
.size(); ++i
) {
1392 if (config
.Matches(video_configs_
[i
])) {
1393 append_config_index_
= i
;
1398 // No matches found so let's add this one to the list.
1399 append_config_index_
= video_configs_
.size();
1400 DVLOG(2) << "New video config - index: " << append_config_index_
;
1401 video_configs_
.resize(video_configs_
.size() + 1);
1402 video_configs_
[append_config_index_
] = config
;
1406 void SourceBufferStream::CompleteConfigChange() {
1407 config_change_pending_
= false;
1409 if (fade_in_buffer_
) {
1410 current_config_index_
=
1411 GetConfigId(fade_in_buffer_
, fade_out_preroll_index_
);
1415 if (!track_buffer_
.empty()) {
1416 current_config_index_
= GetConfigId(track_buffer_
.front(), 0);
1420 if (selected_range_
&& selected_range_
->HasNextBuffer())
1421 current_config_index_
= selected_range_
->GetNextConfigId();
1424 void SourceBufferStream::SetSelectedRangeIfNeeded(
1425 const base::TimeDelta timestamp
) {
1426 DVLOG(1) << __FUNCTION__
<< "(" << timestamp
.InSecondsF() << ")";
1428 if (selected_range_
) {
1429 DCHECK(track_buffer_
.empty());
1433 if (!track_buffer_
.empty()) {
1434 DCHECK(!selected_range_
);
1438 base::TimeDelta start_timestamp
= timestamp
;
1440 // If the next buffer timestamp is not known then use a timestamp just after
1441 // the timestamp on the last buffer returned by GetNextBuffer().
1442 if (start_timestamp
== kNoTimestamp()) {
1443 if (last_output_buffer_timestamp_
== kNoTimestamp())
1446 start_timestamp
= last_output_buffer_timestamp_
+
1447 base::TimeDelta::FromInternalValue(1);
1450 base::TimeDelta seek_timestamp
=
1451 FindNewSelectedRangeSeekTimestamp(start_timestamp
);
1453 // If we don't have buffered data to seek to, then return.
1454 if (seek_timestamp
== kNoTimestamp())
1457 DCHECK(track_buffer_
.empty());
1458 SeekAndSetSelectedRange(*FindExistingRangeFor(seek_timestamp
),
1462 base::TimeDelta
SourceBufferStream::FindNewSelectedRangeSeekTimestamp(
1463 const base::TimeDelta start_timestamp
) {
1464 DCHECK(start_timestamp
!= kNoTimestamp());
1465 DCHECK(start_timestamp
>= base::TimeDelta());
1467 RangeList::iterator itr
= ranges_
.begin();
1469 for (; itr
!= ranges_
.end(); ++itr
) {
1470 if ((*itr
)->GetEndTimestamp() >= start_timestamp
) {
1475 if (itr
== ranges_
.end())
1476 return kNoTimestamp();
1478 // First check for a keyframe timestamp >= |start_timestamp|
1479 // in the current range.
1480 base::TimeDelta keyframe_timestamp
=
1481 (*itr
)->NextKeyframeTimestamp(start_timestamp
);
1483 if (keyframe_timestamp
!= kNoTimestamp())
1484 return keyframe_timestamp
;
1486 // If a keyframe was not found then look for a keyframe that is
1487 // "close enough" in the current or next range.
1488 base::TimeDelta end_timestamp
=
1489 start_timestamp
+ ComputeFudgeRoom(GetMaxInterbufferDistance());
1490 DCHECK(start_timestamp
< end_timestamp
);
1492 // Make sure the current range doesn't start beyond |end_timestamp|.
1493 if ((*itr
)->GetStartTimestamp() >= end_timestamp
)
1494 return kNoTimestamp();
1496 keyframe_timestamp
= (*itr
)->KeyframeBeforeTimestamp(end_timestamp
);
1498 // Check to see if the keyframe is within the acceptable range
1499 // (|start_timestamp|, |end_timestamp|].
1500 if (keyframe_timestamp
!= kNoTimestamp() &&
1501 start_timestamp
< keyframe_timestamp
&&
1502 keyframe_timestamp
<= end_timestamp
) {
1503 return keyframe_timestamp
;
1506 // If |end_timestamp| is within this range, then no other checks are
1508 if (end_timestamp
<= (*itr
)->GetEndTimestamp())
1509 return kNoTimestamp();
1511 // Move on to the next range.
1514 // Return early if the next range does not contain |end_timestamp|.
1515 if (itr
== ranges_
.end() || (*itr
)->GetStartTimestamp() >= end_timestamp
)
1516 return kNoTimestamp();
1518 keyframe_timestamp
= (*itr
)->KeyframeBeforeTimestamp(end_timestamp
);
1520 // Check to see if the keyframe is within the acceptable range
1521 // (|start_timestamp|, |end_timestamp|].
1522 if (keyframe_timestamp
!= kNoTimestamp() &&
1523 start_timestamp
< keyframe_timestamp
&&
1524 keyframe_timestamp
<= end_timestamp
) {
1525 return keyframe_timestamp
;
1528 return kNoTimestamp();
1531 base::TimeDelta
SourceBufferStream::FindKeyframeAfterTimestamp(
1532 const base::TimeDelta timestamp
) {
1533 DCHECK(timestamp
!= kNoTimestamp());
1535 RangeList::iterator itr
= FindExistingRangeFor(timestamp
);
1537 if (itr
== ranges_
.end())
1538 return kNoTimestamp();
1540 // First check for a keyframe timestamp >= |timestamp|
1541 // in the current range.
1542 return (*itr
)->NextKeyframeTimestamp(timestamp
);
1545 std::string
SourceBufferStream::GetStreamTypeName() const {
1546 switch (GetType()) {
1558 SourceBufferStream::Type
SourceBufferStream::GetType() const {
1559 if (!audio_configs_
.empty())
1561 if (!video_configs_
.empty())
1563 DCHECK_NE(text_track_config_
.kind(), kTextNone
);
1567 void SourceBufferStream::DeleteAndRemoveRange(RangeList::iterator
* itr
) {
1568 DVLOG(1) << __FUNCTION__
;
1570 DCHECK(*itr
!= ranges_
.end());
1571 if (**itr
== selected_range_
) {
1572 DVLOG(1) << __FUNCTION__
<< " deleting selected range.";
1573 SetSelectedRange(NULL
);
1576 if (*itr
== range_for_next_append_
) {
1577 DVLOG(1) << __FUNCTION__
<< " deleting range_for_next_append_.";
1578 range_for_next_append_
= ranges_
.end();
1582 *itr
= ranges_
.erase(*itr
);
1585 SourceBufferRange::SourceBufferRange(
1586 SourceBufferStream::Type type
, const BufferQueue
& new_buffers
,
1587 base::TimeDelta media_segment_start_time
,
1588 const InterbufferDistanceCB
& interbuffer_distance_cb
)
1590 keyframe_map_index_base_(0),
1591 next_buffer_index_(-1),
1592 media_segment_start_time_(media_segment_start_time
),
1593 interbuffer_distance_cb_(interbuffer_distance_cb
),
1595 DCHECK(!new_buffers
.empty());
1596 DCHECK(new_buffers
.front()->IsKeyframe());
1597 DCHECK(!interbuffer_distance_cb
.is_null());
1598 AppendBuffersToEnd(new_buffers
);
1601 void SourceBufferRange::AppendBuffersToEnd(const BufferQueue
& new_buffers
) {
1602 DCHECK(buffers_
.empty() || CanAppendBuffersToEnd(new_buffers
));
1604 for (BufferQueue::const_iterator itr
= new_buffers
.begin();
1605 itr
!= new_buffers
.end(); ++itr
) {
1606 DCHECK((*itr
)->GetDecodeTimestamp() != kNoTimestamp());
1607 buffers_
.push_back(*itr
);
1608 size_in_bytes_
+= (*itr
)->data_size();
1610 if ((*itr
)->IsKeyframe()) {
1611 keyframe_map_
.insert(
1612 std::make_pair((*itr
)->GetDecodeTimestamp(),
1613 buffers_
.size() - 1 + keyframe_map_index_base_
));
1618 void SourceBufferRange::Seek(base::TimeDelta timestamp
) {
1619 DCHECK(CanSeekTo(timestamp
));
1620 DCHECK(!keyframe_map_
.empty());
1622 KeyframeMap::iterator result
= GetFirstKeyframeBefore(timestamp
);
1623 next_buffer_index_
= result
->second
- keyframe_map_index_base_
;
1624 DCHECK_LT(next_buffer_index_
, static_cast<int>(buffers_
.size()));
1627 void SourceBufferRange::SeekAheadTo(base::TimeDelta timestamp
) {
1628 SeekAhead(timestamp
, false);
1631 void SourceBufferRange::SeekAheadPast(base::TimeDelta timestamp
) {
1632 SeekAhead(timestamp
, true);
1635 void SourceBufferRange::SeekAhead(base::TimeDelta timestamp
,
1636 bool skip_given_timestamp
) {
1637 DCHECK(!keyframe_map_
.empty());
1639 KeyframeMap::iterator result
=
1640 GetFirstKeyframeAt(timestamp
, skip_given_timestamp
);
1642 // If there isn't a keyframe after |timestamp|, then seek to end and return
1643 // kNoTimestamp to signal such.
1644 if (result
== keyframe_map_
.end()) {
1645 next_buffer_index_
= -1;
1648 next_buffer_index_
= result
->second
- keyframe_map_index_base_
;
1649 DCHECK_LT(next_buffer_index_
, static_cast<int>(buffers_
.size()));
1652 void SourceBufferRange::SeekToStart() {
1653 DCHECK(!buffers_
.empty());
1654 next_buffer_index_
= 0;
1657 SourceBufferRange
* SourceBufferRange::SplitRange(
1658 base::TimeDelta timestamp
, bool is_exclusive
) {
1659 // Find the first keyframe after |timestamp|. If |is_exclusive|, do not
1660 // include keyframes at |timestamp|.
1661 KeyframeMap::iterator new_beginning_keyframe
=
1662 GetFirstKeyframeAt(timestamp
, is_exclusive
);
1664 // If there is no keyframe after |timestamp|, we can't split the range.
1665 if (new_beginning_keyframe
== keyframe_map_
.end())
1668 // Remove the data beginning at |keyframe_index| from |buffers_| and save it
1669 // into |removed_buffers|.
1670 int keyframe_index
=
1671 new_beginning_keyframe
->second
- keyframe_map_index_base_
;
1672 DCHECK_LT(keyframe_index
, static_cast<int>(buffers_
.size()));
1673 BufferQueue::iterator starting_point
= buffers_
.begin() + keyframe_index
;
1674 BufferQueue
removed_buffers(starting_point
, buffers_
.end());
1675 keyframe_map_
.erase(new_beginning_keyframe
, keyframe_map_
.end());
1676 FreeBufferRange(starting_point
, buffers_
.end());
1678 // Create a new range with |removed_buffers|.
1679 SourceBufferRange
* split_range
=
1680 new SourceBufferRange(
1681 type_
, removed_buffers
, kNoTimestamp(), interbuffer_distance_cb_
);
1683 // If the next buffer position is now in |split_range|, update the state of
1684 // this range and |split_range| accordingly.
1685 if (next_buffer_index_
>= static_cast<int>(buffers_
.size())) {
1686 split_range
->next_buffer_index_
= next_buffer_index_
- keyframe_index
;
1687 ResetNextBufferPosition();
1693 SourceBufferRange::BufferQueue::iterator
SourceBufferRange::GetBufferItrAt(
1694 base::TimeDelta timestamp
, bool skip_given_timestamp
) {
1695 // Need to make a dummy buffer with timestamp |timestamp| in order to search
1696 // the |buffers_| container.
1697 scoped_refptr
<StreamParserBuffer
> dummy_buffer
=
1698 StreamParserBuffer::CopyFrom(NULL
, 0, false);
1699 dummy_buffer
->SetDecodeTimestamp(timestamp
);
1701 if (skip_given_timestamp
) {
1702 return std::upper_bound(
1703 buffers_
.begin(), buffers_
.end(), dummy_buffer
, BufferComparator
);
1705 return std::lower_bound(
1706 buffers_
.begin(), buffers_
.end(), dummy_buffer
, BufferComparator
);
1709 SourceBufferRange::KeyframeMap::iterator
1710 SourceBufferRange::GetFirstKeyframeAt(base::TimeDelta timestamp
,
1711 bool skip_given_timestamp
) {
1712 return skip_given_timestamp
?
1713 keyframe_map_
.upper_bound(timestamp
) :
1714 keyframe_map_
.lower_bound(timestamp
);
1717 SourceBufferRange::KeyframeMap::iterator
1718 SourceBufferRange::GetFirstKeyframeBefore(base::TimeDelta timestamp
) {
1719 KeyframeMap::iterator result
= keyframe_map_
.lower_bound(timestamp
);
1720 // lower_bound() returns the first element >= |timestamp|, so we want the
1721 // previous element if it did not return the element exactly equal to
1723 if (result
!= keyframe_map_
.begin() &&
1724 (result
== keyframe_map_
.end() || result
->first
!= timestamp
)) {
1730 void SourceBufferRange::DeleteAll(BufferQueue
* removed_buffers
) {
1731 TruncateAt(buffers_
.begin(), removed_buffers
);
1734 bool SourceBufferRange::TruncateAt(
1735 base::TimeDelta timestamp
, BufferQueue
* removed_buffers
,
1736 bool is_exclusive
) {
1737 // Find the place in |buffers_| where we will begin deleting data.
1738 BufferQueue::iterator starting_point
=
1739 GetBufferItrAt(timestamp
, is_exclusive
);
1740 return TruncateAt(starting_point
, removed_buffers
);
1743 int SourceBufferRange::DeleteGOPFromFront(BufferQueue
* deleted_buffers
) {
1744 DCHECK(!FirstGOPContainsNextBufferPosition());
1745 DCHECK(deleted_buffers
);
1747 int buffers_deleted
= 0;
1748 int total_bytes_deleted
= 0;
1750 KeyframeMap::iterator front
= keyframe_map_
.begin();
1751 DCHECK(front
!= keyframe_map_
.end());
1753 // Delete the keyframe at the start of |keyframe_map_|.
1754 keyframe_map_
.erase(front
);
1756 // Now we need to delete all the buffers that depend on the keyframe we've
1758 int end_index
= keyframe_map_
.size() > 0 ?
1759 keyframe_map_
.begin()->second
- keyframe_map_index_base_
:
1762 // Delete buffers from the beginning of the buffered range up until (but not
1763 // including) the next keyframe.
1764 for (int i
= 0; i
< end_index
; i
++) {
1765 int bytes_deleted
= buffers_
.front()->data_size();
1766 size_in_bytes_
-= bytes_deleted
;
1767 total_bytes_deleted
+= bytes_deleted
;
1768 deleted_buffers
->push_back(buffers_
.front());
1769 buffers_
.pop_front();
1773 // Update |keyframe_map_index_base_| to account for the deleted buffers.
1774 keyframe_map_index_base_
+= buffers_deleted
;
1776 if (next_buffer_index_
> -1) {
1777 next_buffer_index_
-= buffers_deleted
;
1778 DCHECK_GE(next_buffer_index_
, 0);
1781 // Invalidate media segment start time if we've deleted the first buffer of
1783 if (buffers_deleted
> 0)
1784 media_segment_start_time_
= kNoTimestamp();
1786 return total_bytes_deleted
;
1789 int SourceBufferRange::DeleteGOPFromBack(BufferQueue
* deleted_buffers
) {
1790 DCHECK(!LastGOPContainsNextBufferPosition());
1791 DCHECK(deleted_buffers
);
1793 // Remove the last GOP's keyframe from the |keyframe_map_|.
1794 KeyframeMap::iterator back
= keyframe_map_
.end();
1795 DCHECK_GT(keyframe_map_
.size(), 0u);
1798 // The index of the first buffer in the last GOP is equal to the new size of
1799 // |buffers_| after that GOP is deleted.
1800 size_t goal_size
= back
->second
- keyframe_map_index_base_
;
1801 keyframe_map_
.erase(back
);
1803 int total_bytes_deleted
= 0;
1804 while (buffers_
.size() != goal_size
) {
1805 int bytes_deleted
= buffers_
.back()->data_size();
1806 size_in_bytes_
-= bytes_deleted
;
1807 total_bytes_deleted
+= bytes_deleted
;
1808 // We're removing buffers from the back, so push each removed buffer to the
1809 // front of |deleted_buffers| so that |deleted_buffers| are in nondecreasing
1811 deleted_buffers
->push_front(buffers_
.back());
1812 buffers_
.pop_back();
1815 return total_bytes_deleted
;
1818 int SourceBufferRange::GetRemovalGOP(
1819 base::TimeDelta start_timestamp
, base::TimeDelta end_timestamp
,
1820 int total_bytes_to_free
, base::TimeDelta
* removal_end_timestamp
) {
1821 int bytes_to_free
= total_bytes_to_free
;
1822 int bytes_removed
= 0;
1824 KeyframeMap::iterator gop_itr
= GetFirstKeyframeAt(start_timestamp
, false);
1825 if (gop_itr
== keyframe_map_
.end())
1827 int keyframe_index
= gop_itr
->second
- keyframe_map_index_base_
;
1828 BufferQueue::iterator buffer_itr
= buffers_
.begin() + keyframe_index
;
1829 KeyframeMap::iterator gop_end
= keyframe_map_
.end();
1830 if (end_timestamp
< GetBufferedEndTimestamp())
1831 gop_end
= GetFirstKeyframeBefore(end_timestamp
);
1833 // Check if the removal range is within a GOP and skip the loop if so.
1834 // [keyframe]...[start_timestamp]...[end_timestamp]...[keyframe]
1835 KeyframeMap::iterator gop_itr_prev
= gop_itr
;
1836 if (gop_itr_prev
!= keyframe_map_
.begin() && --gop_itr_prev
== gop_end
)
1839 while (gop_itr
!= gop_end
&& bytes_to_free
> 0) {
1843 int next_gop_index
= gop_itr
== keyframe_map_
.end() ?
1844 buffers_
.size() : gop_itr
->second
- keyframe_map_index_base_
;
1845 BufferQueue::iterator next_gop_start
= buffers_
.begin() + next_gop_index
;
1846 for (; buffer_itr
!= next_gop_start
; ++buffer_itr
)
1847 gop_size
+= (*buffer_itr
)->data_size();
1849 bytes_removed
+= gop_size
;
1850 bytes_to_free
-= gop_size
;
1852 if (bytes_removed
> 0) {
1853 *removal_end_timestamp
= gop_itr
== keyframe_map_
.end() ?
1854 GetBufferedEndTimestamp() : gop_itr
->first
;
1856 return bytes_removed
;
1859 bool SourceBufferRange::FirstGOPContainsNextBufferPosition() const {
1860 if (!HasNextBufferPosition())
1863 // If there is only one GOP, it must contain the next buffer position.
1864 if (keyframe_map_
.size() == 1u)
1867 KeyframeMap::const_iterator second_gop
= keyframe_map_
.begin();
1869 return next_buffer_index_
< second_gop
->second
- keyframe_map_index_base_
;
1872 bool SourceBufferRange::LastGOPContainsNextBufferPosition() const {
1873 if (!HasNextBufferPosition())
1876 // If there is only one GOP, it must contain the next buffer position.
1877 if (keyframe_map_
.size() == 1u)
1880 KeyframeMap::const_iterator last_gop
= keyframe_map_
.end();
1882 return last_gop
->second
- keyframe_map_index_base_
<= next_buffer_index_
;
1885 void SourceBufferRange::FreeBufferRange(
1886 const BufferQueue::iterator
& starting_point
,
1887 const BufferQueue::iterator
& ending_point
) {
1888 for (BufferQueue::iterator itr
= starting_point
;
1889 itr
!= ending_point
; ++itr
) {
1890 size_in_bytes_
-= (*itr
)->data_size();
1891 DCHECK_GE(size_in_bytes_
, 0);
1893 buffers_
.erase(starting_point
, ending_point
);
1896 bool SourceBufferRange::TruncateAt(
1897 const BufferQueue::iterator
& starting_point
, BufferQueue
* removed_buffers
) {
1898 DCHECK(!removed_buffers
|| removed_buffers
->empty());
1900 // Return if we're not deleting anything.
1901 if (starting_point
== buffers_
.end())
1904 // Reset the next buffer index if we will be deleting the buffer that's next
1906 if (HasNextBufferPosition()) {
1907 base::TimeDelta next_buffer_timestamp
= GetNextTimestamp();
1908 if (next_buffer_timestamp
== kNoTimestamp() ||
1909 next_buffer_timestamp
>= (*starting_point
)->GetDecodeTimestamp()) {
1910 if (HasNextBuffer() && removed_buffers
) {
1911 int starting_offset
= starting_point
- buffers_
.begin();
1912 int next_buffer_offset
= next_buffer_index_
- starting_offset
;
1913 DCHECK_GE(next_buffer_offset
, 0);
1914 BufferQueue
saved(starting_point
+ next_buffer_offset
, buffers_
.end());
1915 removed_buffers
->swap(saved
);
1917 ResetNextBufferPosition();
1921 // Remove keyframes from |starting_point| onward.
1922 KeyframeMap::iterator starting_point_keyframe
=
1923 keyframe_map_
.lower_bound((*starting_point
)->GetDecodeTimestamp());
1924 keyframe_map_
.erase(starting_point_keyframe
, keyframe_map_
.end());
1926 // Remove everything from |starting_point| onward.
1927 FreeBufferRange(starting_point
, buffers_
.end());
1928 return buffers_
.empty();
1931 bool SourceBufferRange::GetNextBuffer(
1932 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
1933 if (!HasNextBuffer())
1936 *out_buffer
= buffers_
[next_buffer_index_
];
1937 next_buffer_index_
++;
1941 bool SourceBufferRange::HasNextBuffer() const {
1942 return next_buffer_index_
>= 0 &&
1943 next_buffer_index_
< static_cast<int>(buffers_
.size());
1946 int SourceBufferRange::GetNextConfigId() const {
1947 DCHECK(HasNextBuffer());
1948 // If the next buffer is an audio splice frame, the next effective config id
1949 // comes from the first fade out preroll buffer.
1950 return GetConfigId(buffers_
[next_buffer_index_
], 0);
1953 base::TimeDelta
SourceBufferRange::GetNextTimestamp() const {
1954 DCHECK(!buffers_
.empty());
1955 DCHECK(HasNextBufferPosition());
1957 if (next_buffer_index_
>= static_cast<int>(buffers_
.size())) {
1958 return kNoTimestamp();
1961 return buffers_
[next_buffer_index_
]->GetDecodeTimestamp();
1964 bool SourceBufferRange::HasNextBufferPosition() const {
1965 return next_buffer_index_
>= 0;
1968 void SourceBufferRange::ResetNextBufferPosition() {
1969 next_buffer_index_
= -1;
1972 void SourceBufferRange::AppendRangeToEnd(const SourceBufferRange
& range
,
1973 bool transfer_current_position
) {
1974 DCHECK(CanAppendRangeToEnd(range
));
1975 DCHECK(!buffers_
.empty());
1977 if (transfer_current_position
&& range
.next_buffer_index_
>= 0)
1978 next_buffer_index_
= range
.next_buffer_index_
+ buffers_
.size();
1980 AppendBuffersToEnd(range
.buffers_
);
1983 bool SourceBufferRange::CanAppendRangeToEnd(
1984 const SourceBufferRange
& range
) const {
1985 return CanAppendBuffersToEnd(range
.buffers_
);
1988 bool SourceBufferRange::CanAppendBuffersToEnd(
1989 const BufferQueue
& buffers
) const {
1990 DCHECK(!buffers_
.empty());
1991 return IsNextInSequence(buffers
.front()->GetDecodeTimestamp(),
1992 buffers
.front()->IsKeyframe());
1995 bool SourceBufferRange::BelongsToRange(base::TimeDelta timestamp
) const {
1996 DCHECK(!buffers_
.empty());
1998 return (IsNextInSequence(timestamp
, false) ||
1999 (GetStartTimestamp() <= timestamp
&& timestamp
<= GetEndTimestamp()));
2002 bool SourceBufferRange::CanSeekTo(base::TimeDelta timestamp
) const {
2003 base::TimeDelta start_timestamp
=
2004 std::max(base::TimeDelta(), GetStartTimestamp() - GetFudgeRoom());
2005 return !keyframe_map_
.empty() && start_timestamp
<= timestamp
&&
2006 timestamp
< GetBufferedEndTimestamp();
2009 bool SourceBufferRange::CompletelyOverlaps(
2010 const SourceBufferRange
& range
) const {
2011 return GetStartTimestamp() <= range
.GetStartTimestamp() &&
2012 GetEndTimestamp() >= range
.GetEndTimestamp();
2015 bool SourceBufferRange::EndOverlaps(const SourceBufferRange
& range
) const {
2016 return range
.GetStartTimestamp() <= GetEndTimestamp() &&
2017 GetEndTimestamp() < range
.GetEndTimestamp();
2020 base::TimeDelta
SourceBufferRange::GetStartTimestamp() const {
2021 DCHECK(!buffers_
.empty());
2022 base::TimeDelta start_timestamp
= media_segment_start_time_
;
2023 if (start_timestamp
== kNoTimestamp())
2024 start_timestamp
= buffers_
.front()->GetDecodeTimestamp();
2025 return start_timestamp
;
2028 base::TimeDelta
SourceBufferRange::GetEndTimestamp() const {
2029 DCHECK(!buffers_
.empty());
2030 return buffers_
.back()->GetDecodeTimestamp();
2033 base::TimeDelta
SourceBufferRange::GetBufferedEndTimestamp() const {
2034 DCHECK(!buffers_
.empty());
2035 base::TimeDelta duration
= buffers_
.back()->duration();
2036 if (duration
== kNoTimestamp() || duration
== base::TimeDelta())
2037 duration
= GetApproximateDuration();
2038 return GetEndTimestamp() + duration
;
2041 base::TimeDelta
SourceBufferRange::NextKeyframeTimestamp(
2042 base::TimeDelta timestamp
) {
2043 DCHECK(!keyframe_map_
.empty());
2045 if (timestamp
< GetStartTimestamp() || timestamp
>= GetBufferedEndTimestamp())
2046 return kNoTimestamp();
2048 KeyframeMap::iterator itr
= GetFirstKeyframeAt(timestamp
, false);
2049 if (itr
== keyframe_map_
.end())
2050 return kNoTimestamp();
2054 base::TimeDelta
SourceBufferRange::KeyframeBeforeTimestamp(
2055 base::TimeDelta timestamp
) {
2056 DCHECK(!keyframe_map_
.empty());
2058 if (timestamp
< GetStartTimestamp() || timestamp
>= GetBufferedEndTimestamp())
2059 return kNoTimestamp();
2061 return GetFirstKeyframeBefore(timestamp
)->first
;
2064 bool SourceBufferRange::IsNextInSequence(
2065 base::TimeDelta timestamp
, bool is_keyframe
) const {
2066 base::TimeDelta end
= buffers_
.back()->GetDecodeTimestamp();
2067 if (end
< timestamp
&&
2068 (type_
== SourceBufferStream::kText
||
2069 timestamp
<= end
+ GetFudgeRoom())) {
2073 return timestamp
== end
&& AllowSameTimestamp(
2074 buffers_
.back()->IsKeyframe(), is_keyframe
, type_
);
2077 base::TimeDelta
SourceBufferRange::GetFudgeRoom() const {
2078 return ComputeFudgeRoom(GetApproximateDuration());
2081 base::TimeDelta
SourceBufferRange::GetApproximateDuration() const {
2082 base::TimeDelta max_interbuffer_distance
= interbuffer_distance_cb_
.Run();
2083 DCHECK(max_interbuffer_distance
!= kNoTimestamp());
2084 return max_interbuffer_distance
;
2087 } // namespace media