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/logging.h"
14 // Helper class representing a range of buffered data. All buffers in a
15 // SourceBufferRange are ordered sequentially in presentation order with no
17 class SourceBufferRange
{
19 typedef std::deque
<scoped_refptr
<StreamParserBuffer
> > BufferQueue
;
23 // Adds |new_buffers| into this range. |new_buffers| must belong to this
24 // range. Garbage collection may occur after Append().
25 void Append(const BufferQueue
& new_buffers
);
27 // Updates |next_buffer_index_| to point to the Buffer containing |timestamp|.
28 // Assumes |timestamp| is valid and in this range.
29 void Seek(base::TimeDelta timestamp
);
31 // Updates |next_buffer_index_| to point to next keyframe after or equal to
32 // |timestamp|. If there is no such keyframe, then this range will seek to
33 // the end and return kNoTimestamp().
34 // Assumes |timestamp| is valid and in this range.
35 base::TimeDelta
SeekAfter(base::TimeDelta timestamp
);
37 // Updates |out_buffer| with the next buffer in presentation order. Seek()
38 // must be called before calls to GetNextBuffer(), and buffers are returned
39 // in order from the last call to Seek(). Returns true if |out_buffer| is
40 // filled with a valid buffer, false if there is not enough data to fulfill
42 bool GetNextBuffer(scoped_refptr
<StreamParserBuffer
>* out_buffer
);
43 base::TimeDelta
GetNextTimestamp() const;
45 // Returns the Timespan of buffered time in this range.
46 SourceBufferStream::Timespan
GetBufferedTime() const;
48 // Appends the buffers from |range| into this range.
49 // The first buffer in |range| must come directly after the last buffer
51 // If |transfer_current_position| is true, |range|'s |next_buffer_position_|
52 // is transfered to this SourceBufferRange.
53 void AppendToEnd(const SourceBufferRange
& range
,
54 bool transfer_current_position
);
55 bool CanAppendToEnd(const SourceBufferRange
& range
) const;
56 bool CanAppendToEnd(const BufferQueue
& buffers
) const;
58 // Returns whether a buffer with a starting timestamp of |timestamp| would
59 // belong in this range. This includes a buffer that would be appended to
60 // the end of the range.
61 // Returns 0 if |timestamp| is in this range, -1 if |timestamp| appears
62 // before this range, or 1 if |timestamp| appears after this range.
63 int BelongsToRange(base::TimeDelta timestamp
) const;
65 // Returns true if the range has enough data to seek to the specified
66 // |timestamp|, false otherwise.
67 bool CanSeekTo(base::TimeDelta timestamp
) const;
69 // Returns true if this range's buffered timespan completely overlaps the
70 // buffered timespan of |range|.
71 bool CompletelyOverlaps(const SourceBufferRange
& range
) const;
73 // Returns true if the end of this range contains buffers that overlaps with
74 // the beginning of |range|.
75 bool EndOverlaps(const SourceBufferRange
& range
) const;
77 // Functions that tell how |buffers| intersects with this range.
78 // TODO(vrk): These functions should be unnecessary when overlapping the
79 // selected range is implemented properly. (crbug.com/126560)
80 bool IsStartOverlappedBy(const BufferQueue
& buffers
) const;
81 bool IsEndOverlappedBy(const BufferQueue
& buffers
) const;
82 bool IsCompletelyOverlappedBy(const BufferQueue
& buffers
) const;
85 // Appends |buffers| to the end of the range and updates |keyframe_map_| as
86 // it encounters new keyframes. Assumes |buffers| belongs at the end of the
88 void AppendToEnd(const BufferQueue
& buffers
);
90 // Returns the start timestamp of the range, or kNoTimestamp if the range is
92 base::TimeDelta
BufferedStart() const;
94 // Returns the end timestamp of the buffered data. (Note that this is equal to
95 // the last buffer's timestamp + its duration.) Returns kNoTimestamp if the
97 base::TimeDelta
BufferedEnd() const;
99 // An ordered list of buffers in this range.
100 BufferQueue buffers_
;
102 // Maps keyframe timestamps to its index position in |buffers_|.
103 typedef std::map
<base::TimeDelta
, size_t> KeyframeMap
;
104 KeyframeMap keyframe_map_
;
106 // Index into |buffers_| for the next buffer to be returned by
107 // GetBufferedTime(), set to -1 before Seek().
108 int next_buffer_index_
;
110 DISALLOW_COPY_AND_ASSIGN(SourceBufferRange
);
115 // Helper method that returns true if |ranges| is sorted in increasing order,
117 static bool IsRangeListSorted(
118 const std::list
<media::SourceBufferRange
*>& ranges
) {
119 base::TimeDelta prev
= media::kNoTimestamp();
120 for (std::list
<media::SourceBufferRange
*>::const_iterator itr
=
121 ranges
.begin(); itr
!= ranges
.end(); itr
++) {
122 media::SourceBufferStream::Timespan buffered
= (*itr
)->GetBufferedTime();
123 if (prev
!= media::kNoTimestamp() && prev
>= buffered
.first
)
125 prev
= buffered
.second
;
130 // Comparison function for two Buffers based on timestamp.
131 static bool BufferComparator(scoped_refptr
<media::Buffer
> first
,
132 scoped_refptr
<media::Buffer
> second
) {
133 return first
->GetTimestamp() < second
->GetTimestamp();
136 // Returns the upper bound for the starting timestamp for the next buffer
137 // in sequence after |buffer|. Assumes |buffer|'s timestamp and
138 // duration are valid.
139 static base::TimeDelta
MaxNextTimestamp(
140 const scoped_refptr
<media::StreamParserBuffer
>& buffer
) {
141 // Because we do not know exactly when is the next timestamp, any buffer
142 // that starts within 1/3 of the duration past the end of this buffer
143 // is considered the next buffer in the sequence.
144 return buffer
->GetEndTimestamp() + buffer
->GetDuration() / 3;
147 // Returns true if |timestamp| is the timestamp of the next buffer in
148 // sequence after |buffer|, false otherwise.
149 static bool IsNextInSequence(
150 const scoped_refptr
<media::StreamParserBuffer
>& buffer
,
151 base::TimeDelta timestamp
) {
152 return timestamp
>= buffer
->GetEndTimestamp() &&
153 timestamp
<= MaxNextTimestamp(buffer
);
158 SourceBufferStream::SourceBufferStream()
159 : seek_pending_(false),
160 seek_buffer_timestamp_(kNoTimestamp()),
161 selected_range_(NULL
),
162 waiting_for_keyframe_(false) {
165 SourceBufferStream::~SourceBufferStream() {
166 while (!ranges_
.empty()) {
167 delete ranges_
.front();
172 bool SourceBufferStream::Append(
173 const SourceBufferStream::BufferQueue
& buffers
) {
174 DCHECK(!buffers
.empty());
176 // Check to see if |buffers| will overlap the currently |selected_range_|,
177 // and if so, ignore this Append() request.
178 // TODO(vrk): Support overlapping selected range properly. (crbug.com/126560)
179 if (selected_range_
&&
180 (selected_range_
->IsEndOverlappedBy(buffers
) ||
181 selected_range_
->IsStartOverlappedBy(buffers
))) {
185 SourceBufferRange
* range
= NULL
;
186 RangeList::iterator itr
= ranges_
.end();
187 base::TimeDelta start_timestamp
= buffers
.front()->GetTimestamp();
188 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); itr
++) {
189 int range_value
= (*itr
)->BelongsToRange(start_timestamp
);
191 // |start_timestamp| is before the current range in this loop. Because
192 // |ranges_| is sorted, this means that we need to create a new range and it
193 // should be placed before |itr|.
194 // TODO(vrk): We also break out of the loop if |buffers| completely overlaps
195 // the current range. This is to cover the case when |buffers| belongs to
196 // the current range, but also completely overlaps it. This should be
197 // removed when start overlap is handled properly.
198 if (range_value
< 0 || (*itr
)->IsCompletelyOverlappedBy(buffers
))
201 if (range_value
== 0) {
202 // Found an existing range into which we can append buffers.
205 if (range
->CanAppendToEnd(buffers
) && waiting_for_keyframe_
) {
206 // Currently we do not support the case where the next buffer after the
207 // buffers in the track buffer is not a keyframe.
208 if (!buffers
.front()->IsKeyframe())
210 waiting_for_keyframe_
= false;
217 // Ranges must begin with a keyframe.
218 if (!buffers
.front()->IsKeyframe())
221 range
= new SourceBufferRange();
222 itr
= ranges_
.insert(itr
, range
);
225 // Append buffers to the appropriate range.
226 range
->Append(buffers
);
228 // Increment |itr| to be the range after |range|.
232 itr
= ResolveCompleteOverlaps(itr
, range
);
233 itr
= ResolveEndOverlaps(itr
, range
);
234 MergeWithAdjacentRangeIfNecessary(itr
, range
);
236 // Finally, try to complete pending seek if one exists.
238 Seek(seek_buffer_timestamp_
);
240 DCHECK(IsRangeListSorted(ranges_
));
244 SourceBufferStream::RangeList::iterator
245 SourceBufferStream::ResolveCompleteOverlaps(
246 const RangeList::iterator
& range_itr
, SourceBufferRange
* new_range
) {
247 RangeList::iterator itr
= range_itr
;
248 while (itr
!= ranges_
.end() && new_range
->CompletelyOverlaps(**itr
)) {
249 if (*itr
== selected_range_
) {
250 // Get the timestamp for the next buffer in the sequence.
251 base::TimeDelta next_timestamp
= selected_range_
->GetNextTimestamp();
252 // Then seek to the next keyframe after (or equal to) |next_timestamp|.
253 // This will allow us to transition from the old buffers to the new
254 // buffers seamlessly.
255 base::TimeDelta next_keyframe_timestamp
=
256 new_range
->SeekAfter(next_timestamp
);
258 // If there's no keyframe after |next_timestamp|, then set flag to wait
259 // for the next keyframe in this range to be appended.
260 if (next_keyframe_timestamp
== kNoTimestamp())
261 waiting_for_keyframe_
= true;
263 // Add all the old buffers up until |next_keyframe_timestamp| into
264 // |track_buffer_|. If there was no keyframe, then we add all buffers into
266 scoped_refptr
<StreamParserBuffer
> next_buffer
;
267 while (selected_range_
->GetNextBuffer(&next_buffer
) &&
268 (waiting_for_keyframe_
||
269 next_buffer
->GetTimestamp() < next_keyframe_timestamp
)) {
270 track_buffer_
.push_back(next_buffer
);
273 selected_range_
= new_range
;
276 itr
= ranges_
.erase(itr
);
281 SourceBufferStream::RangeList::iterator
282 SourceBufferStream::ResolveEndOverlaps(
283 const RangeList::iterator
& range_itr
, SourceBufferRange
* new_range
) {
284 RangeList::iterator itr
= range_itr
;
285 while (itr
!= ranges_
.end() && new_range
->EndOverlaps(**itr
)) {
286 DCHECK_NE(*itr
, selected_range_
);
288 itr
= ranges_
.erase(itr
);
293 void SourceBufferStream::MergeWithAdjacentRangeIfNecessary(
294 const RangeList::iterator
& itr
, SourceBufferRange
* new_range
) {
295 if (itr
!= ranges_
.end() && new_range
->CanAppendToEnd(**itr
)) {
296 bool transfer_current_position
= selected_range_
== *itr
;
297 new_range
->AppendToEnd(**itr
, transfer_current_position
);
298 // Update |selected_range_| pointer if |range| has become selected after
300 if (transfer_current_position
)
301 selected_range_
= new_range
;
308 void SourceBufferStream::Seek(base::TimeDelta timestamp
) {
309 selected_range_
= NULL
;
310 track_buffer_
.clear();
311 waiting_for_keyframe_
= false;
313 seek_buffer_timestamp_
= timestamp
;
314 seek_pending_
= true;
316 RangeList::iterator itr
= ranges_
.end();
317 for (itr
= ranges_
.begin(); itr
!= ranges_
.end(); itr
++) {
318 if ((*itr
)->CanSeekTo(timestamp
))
322 if (itr
== ranges_
.end())
325 selected_range_
= *itr
;
326 selected_range_
->Seek(timestamp
);
327 seek_pending_
= false;
330 bool SourceBufferStream::GetNextBuffer(
331 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
332 if (!track_buffer_
.empty()) {
333 *out_buffer
= track_buffer_
.front();
334 track_buffer_
.pop_front();
337 return selected_range_
&& selected_range_
->GetNextBuffer(out_buffer
);
340 std::list
<SourceBufferStream::Timespan
>
341 SourceBufferStream::GetBufferedTime() const {
342 std::list
<Timespan
> timespans
;
343 for (RangeList::const_iterator itr
= ranges_
.begin();
344 itr
!= ranges_
.end(); itr
++) {
345 timespans
.push_back((*itr
)->GetBufferedTime());
350 SourceBufferRange::SourceBufferRange()
351 : next_buffer_index_(-1) {
354 void SourceBufferRange::Append(const BufferQueue
& new_buffers
) {
355 base::TimeDelta start_timestamp
= new_buffers
.front()->GetTimestamp();
357 if (!buffers_
.empty() && start_timestamp
< BufferedEnd()) {
358 // We are overwriting existing data, so find the starting point where
359 // things will get overwritten.
360 BufferQueue::iterator starting_point
=
361 std::lower_bound(buffers_
.begin(), buffers_
.end(),
365 // Remove everything from |starting_point| onward.
366 buffers_
.erase(starting_point
, buffers_
.end());
370 AppendToEnd(new_buffers
);
373 void SourceBufferRange::AppendToEnd(const BufferQueue
& new_buffers
) {
374 for (BufferQueue::const_iterator itr
= new_buffers
.begin();
375 itr
!= new_buffers
.end(); itr
++) {
376 DCHECK((*itr
)->GetDuration() > base::TimeDelta());
377 DCHECK((*itr
)->GetTimestamp() != kNoTimestamp());
378 buffers_
.push_back(*itr
);
379 if ((*itr
)->IsKeyframe()) {
380 keyframe_map_
.insert(
381 std::make_pair((*itr
)->GetTimestamp(), buffers_
.size() - 1));
386 void SourceBufferRange::Seek(base::TimeDelta timestamp
) {
387 DCHECK(CanSeekTo(timestamp
));
388 DCHECK(!keyframe_map_
.empty());
390 KeyframeMap::iterator result
= keyframe_map_
.lower_bound(timestamp
);
391 // lower_bound() returns the first element >= |timestamp|, so we want the
392 // previous element if it did not return the element exactly equal to
394 if (result
== keyframe_map_
.end() || result
->first
!= timestamp
) {
395 DCHECK(result
!= keyframe_map_
.begin());
398 next_buffer_index_
= result
->second
;
399 DCHECK_LT(next_buffer_index_
, static_cast<int>(buffers_
.size()));
402 base::TimeDelta
SourceBufferRange::SeekAfter(base::TimeDelta timestamp
) {
403 DCHECK_EQ(BelongsToRange(timestamp
), 0);
404 DCHECK(!keyframe_map_
.empty());
406 // lower_bound() returns the first element >= |timestamp|, so |result| is the
407 // value that we want.
408 KeyframeMap::iterator result
= keyframe_map_
.lower_bound(timestamp
);
410 // If there isn't a keyframe after |timestamp|, then seek to end and return
411 // kNoTimestamp to signal such.
412 if (result
== keyframe_map_
.end()) {
413 next_buffer_index_
= buffers_
.size();
414 return kNoTimestamp();
417 next_buffer_index_
= result
->second
;
418 DCHECK_LT(next_buffer_index_
, static_cast<int>(buffers_
.size()));
419 return result
->first
;
423 bool SourceBufferRange::GetNextBuffer(
424 scoped_refptr
<StreamParserBuffer
>* out_buffer
) {
425 DCHECK_GE(next_buffer_index_
, 0);
426 if (next_buffer_index_
>= static_cast<int>(buffers_
.size()))
429 *out_buffer
= buffers_
.at(next_buffer_index_
);
430 next_buffer_index_
++;
434 base::TimeDelta
SourceBufferRange::GetNextTimestamp() const {
435 DCHECK_GE(next_buffer_index_
, 0);
436 DCHECK(!buffers_
.empty());
438 if (next_buffer_index_
>= static_cast<int>(buffers_
.size()))
439 return buffers_
.back()->GetEndTimestamp();
441 return buffers_
.at(next_buffer_index_
)->GetTimestamp();
444 SourceBufferStream::Timespan
445 SourceBufferRange::GetBufferedTime() const {
446 return std::make_pair(BufferedStart(), BufferedEnd());
449 void SourceBufferRange::AppendToEnd(const SourceBufferRange
& range
,
450 bool transfer_current_position
) {
451 DCHECK(CanAppendToEnd(range
));
452 DCHECK(!buffers_
.empty());
454 if (transfer_current_position
)
455 next_buffer_index_
= range
.next_buffer_index_
+ buffers_
.size();
457 AppendToEnd(range
.buffers_
);
460 bool SourceBufferRange::CanAppendToEnd(const SourceBufferRange
& range
) const {
461 return CanAppendToEnd(range
.buffers_
);
464 bool SourceBufferRange::CanAppendToEnd(const BufferQueue
& buffers
) const {
465 return buffers_
.empty() ||
466 IsNextInSequence(buffers_
.back(), buffers
.front()->GetTimestamp());
469 int SourceBufferRange::BelongsToRange(base::TimeDelta timestamp
) const {
470 if (buffers_
.empty())
473 if (IsNextInSequence(buffers_
.back(), timestamp
) ||
474 (BufferedEnd() >= timestamp
&& BufferedStart() <= timestamp
)) {
478 if (BufferedStart() > timestamp
)
481 // |timestamp| must be after this range.
485 bool SourceBufferRange::CanSeekTo(base::TimeDelta timestamp
) const {
486 return !keyframe_map_
.empty() && BufferedStart() <= timestamp
&&
487 BufferedEnd() > timestamp
;
490 bool SourceBufferRange::CompletelyOverlaps(
491 const SourceBufferRange
& range
) const {
492 return BufferedStart() <= range
.BufferedStart() &&
493 BufferedEnd() >= range
.BufferedEnd();
496 bool SourceBufferRange::EndOverlaps(const SourceBufferRange
& range
) const {
497 return range
.BufferedStart() < BufferedEnd() &&
498 BufferedEnd() < range
.BufferedEnd();
501 bool SourceBufferRange::IsStartOverlappedBy(const BufferQueue
& buffers
) const {
502 base::TimeDelta start_timestamp
= buffers
.front()->GetTimestamp();
503 return BufferedStart() < start_timestamp
&& start_timestamp
< BufferedEnd();
506 bool SourceBufferRange::IsEndOverlappedBy(const BufferQueue
& buffers
) const {
507 base::TimeDelta end_timestamp
= buffers
.back()->GetEndTimestamp();
508 return BufferedStart() < end_timestamp
&& end_timestamp
< BufferedEnd();
511 bool SourceBufferRange::IsCompletelyOverlappedBy(
512 const BufferQueue
& buffers
) const {
513 base::TimeDelta start_timestamp
= buffers
.front()->GetTimestamp();
514 base::TimeDelta end_timestamp
= buffers
.back()->GetEndTimestamp();
515 return start_timestamp
<= BufferedStart() && BufferedEnd() <= end_timestamp
;
518 base::TimeDelta
SourceBufferRange::BufferedStart() const {
519 if (buffers_
.empty())
520 return kNoTimestamp();
522 return buffers_
.front()->GetTimestamp();
525 base::TimeDelta
SourceBufferRange::BufferedEnd() const {
526 if (buffers_
.empty())
527 return kNoTimestamp();
529 return buffers_
.back()->GetEndTimestamp();