roll skia to 4057
[chromium-blink-merge.git] / media / filters / source_buffer_stream.cc
blob52ce36ca464d2a3c4f4acdcc310acb521ce1f8fb
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"
7 #include <algorithm>
8 #include <map>
10 #include "base/logging.h"
12 namespace media {
14 // Helper class representing a range of buffered data. All buffers in a
15 // SourceBufferRange are ordered sequentially in presentation order with no
16 // gaps.
17 class SourceBufferRange {
18 public:
19 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue;
21 SourceBufferRange();
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
41 // the request.
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
50 // in this range.
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;
84 private:
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
87 // range.
88 void AppendToEnd(const BufferQueue& buffers);
90 // Returns the start timestamp of the range, or kNoTimestamp if the range is
91 // empty.
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
96 // range is empty.
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);
113 } // namespace media
115 // Helper method that returns true if |ranges| is sorted in increasing order,
116 // false otherwise.
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)
124 return false;
125 prev = buffered.second;
127 return true;
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);
156 namespace media {
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();
168 ranges_.pop_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))) {
182 return false;
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))
199 break;
201 if (range_value == 0) {
202 // Found an existing range into which we can append buffers.
203 range = *itr;
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())
209 return false;
210 waiting_for_keyframe_ = false;
212 break;
216 if (!range) {
217 // Ranges must begin with a keyframe.
218 if (!buffers.front()->IsKeyframe())
219 return false;
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|.
229 itr++;
231 // Resolve overlaps.
232 itr = ResolveCompleteOverlaps(itr, range);
233 itr = ResolveEndOverlaps(itr, range);
234 MergeWithAdjacentRangeIfNecessary(itr, range);
236 // Finally, try to complete pending seek if one exists.
237 if (seek_pending_)
238 Seek(seek_buffer_timestamp_);
240 DCHECK(IsRangeListSorted(ranges_));
241 return true;
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
265 // |track_buffer_|.
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;
275 delete *itr;
276 itr = ranges_.erase(itr);
278 return 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_);
287 delete *itr;
288 itr = ranges_.erase(itr);
290 return 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
299 // merges.
300 if (transfer_current_position)
301 selected_range_ = new_range;
303 delete *itr;
304 ranges_.erase(itr);
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))
319 break;
322 if (itr == ranges_.end())
323 return;
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();
335 return true;
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());
347 return timespans;
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(),
362 new_buffers.front(),
363 BufferComparator);
365 // Remove everything from |starting_point| onward.
366 buffers_.erase(starting_point, buffers_.end());
369 // Append data.
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
393 // |timestamp|.
394 if (result == keyframe_map_.end() || result->first != timestamp) {
395 DCHECK(result != keyframe_map_.begin());
396 result--;
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()))
427 return false;
429 *out_buffer = buffers_.at(next_buffer_index_);
430 next_buffer_index_++;
431 return true;
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())
471 return 1;
473 if (IsNextInSequence(buffers_.back(), timestamp) ||
474 (BufferedEnd() >= timestamp && BufferedStart() <= timestamp)) {
475 return 0;
478 if (BufferedStart() > timestamp)
479 return -1;
481 // |timestamp| must be after this range.
482 return 1;
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();
532 } // namespace media