Revert of Set defaultPageScaleLimits before setIgnoreViewportTagScaleLimits (patchset...
[chromium-blink-merge.git] / media / filters / source_buffer_range.cc
bloba80d629fe8a620d18177e5ecd33aac34811894c9
1 // Copyright 2014 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_range.h"
7 #include <algorithm>
9 namespace media {
11 // Comparison operators for std::upper_bound() and std::lower_bound().
12 static bool CompareTimeDeltaToStreamParserBuffer(
13 const DecodeTimestamp& decode_timestamp,
14 const scoped_refptr<StreamParserBuffer>& buffer) {
15 return decode_timestamp < buffer->GetDecodeTimestamp();
17 static bool CompareStreamParserBufferToTimeDelta(
18 const scoped_refptr<StreamParserBuffer>& buffer,
19 const DecodeTimestamp& decode_timestamp) {
20 return buffer->GetDecodeTimestamp() < decode_timestamp;
23 bool SourceBufferRange::AllowSameTimestamp(
24 bool prev_is_keyframe, bool current_is_keyframe) {
25 return prev_is_keyframe || !current_is_keyframe;
28 SourceBufferRange::SourceBufferRange(
29 GapPolicy gap_policy, const BufferQueue& new_buffers,
30 DecodeTimestamp media_segment_start_time,
31 const InterbufferDistanceCB& interbuffer_distance_cb)
32 : gap_policy_(gap_policy),
33 keyframe_map_index_base_(0),
34 next_buffer_index_(-1),
35 media_segment_start_time_(media_segment_start_time),
36 interbuffer_distance_cb_(interbuffer_distance_cb),
37 size_in_bytes_(0) {
38 CHECK(!new_buffers.empty());
39 DCHECK(new_buffers.front()->is_key_frame());
40 DCHECK(!interbuffer_distance_cb.is_null());
41 AppendBuffersToEnd(new_buffers);
44 SourceBufferRange::~SourceBufferRange() {}
46 void SourceBufferRange::AppendBuffersToEnd(const BufferQueue& new_buffers) {
47 DCHECK(buffers_.empty() || CanAppendBuffersToEnd(new_buffers));
48 DCHECK(media_segment_start_time_ == kNoDecodeTimestamp() ||
49 media_segment_start_time_ <=
50 new_buffers.front()->GetDecodeTimestamp());
51 for (BufferQueue::const_iterator itr = new_buffers.begin();
52 itr != new_buffers.end();
53 ++itr) {
54 DCHECK((*itr)->GetDecodeTimestamp() != kNoDecodeTimestamp());
55 buffers_.push_back(*itr);
56 size_in_bytes_ += (*itr)->data_size();
58 if ((*itr)->is_key_frame()) {
59 keyframe_map_.insert(
60 std::make_pair((*itr)->GetDecodeTimestamp(),
61 buffers_.size() - 1 + keyframe_map_index_base_));
66 void SourceBufferRange::Seek(DecodeTimestamp timestamp) {
67 DCHECK(CanSeekTo(timestamp));
68 DCHECK(!keyframe_map_.empty());
70 KeyframeMap::iterator result = GetFirstKeyframeBefore(timestamp);
71 next_buffer_index_ = result->second - keyframe_map_index_base_;
72 DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size()));
75 void SourceBufferRange::SeekAheadTo(DecodeTimestamp timestamp) {
76 SeekAhead(timestamp, false);
79 void SourceBufferRange::SeekAheadPast(DecodeTimestamp timestamp) {
80 SeekAhead(timestamp, true);
83 void SourceBufferRange::SeekAhead(DecodeTimestamp timestamp,
84 bool skip_given_timestamp) {
85 DCHECK(!keyframe_map_.empty());
87 KeyframeMap::iterator result =
88 GetFirstKeyframeAt(timestamp, skip_given_timestamp);
90 // If there isn't a keyframe after |timestamp|, then seek to end and return
91 // kNoTimestamp to signal such.
92 if (result == keyframe_map_.end()) {
93 next_buffer_index_ = -1;
94 return;
96 next_buffer_index_ = result->second - keyframe_map_index_base_;
97 DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size()));
100 void SourceBufferRange::SeekToStart() {
101 DCHECK(!buffers_.empty());
102 next_buffer_index_ = 0;
105 SourceBufferRange* SourceBufferRange::SplitRange(
106 DecodeTimestamp timestamp, bool is_exclusive) {
107 CHECK(!buffers_.empty());
109 // Find the first keyframe after |timestamp|. If |is_exclusive|, do not
110 // include keyframes at |timestamp|.
111 KeyframeMap::iterator new_beginning_keyframe =
112 GetFirstKeyframeAt(timestamp, is_exclusive);
114 // If there is no keyframe after |timestamp|, we can't split the range.
115 if (new_beginning_keyframe == keyframe_map_.end())
116 return NULL;
118 // Remove the data beginning at |keyframe_index| from |buffers_| and save it
119 // into |removed_buffers|.
120 int keyframe_index =
121 new_beginning_keyframe->second - keyframe_map_index_base_;
122 DCHECK_LT(keyframe_index, static_cast<int>(buffers_.size()));
123 BufferQueue::iterator starting_point = buffers_.begin() + keyframe_index;
124 BufferQueue removed_buffers(starting_point, buffers_.end());
126 DecodeTimestamp new_range_start_timestamp = kNoDecodeTimestamp();
127 if (GetStartTimestamp() < buffers_.front()->GetDecodeTimestamp() &&
128 timestamp < removed_buffers.front()->GetDecodeTimestamp()) {
129 // The split is in the gap between |media_segment_start_time_| and
130 // the first buffer of the new range so we should set the start
131 // time of the new range to |timestamp| so we preserve part of the
132 // gap in the new range.
133 new_range_start_timestamp = timestamp;
136 keyframe_map_.erase(new_beginning_keyframe, keyframe_map_.end());
137 FreeBufferRange(starting_point, buffers_.end());
139 // Create a new range with |removed_buffers|.
140 SourceBufferRange* split_range =
141 new SourceBufferRange(
142 gap_policy_, removed_buffers, new_range_start_timestamp,
143 interbuffer_distance_cb_);
145 // If the next buffer position is now in |split_range|, update the state of
146 // this range and |split_range| accordingly.
147 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) {
148 split_range->next_buffer_index_ = next_buffer_index_ - keyframe_index;
149 ResetNextBufferPosition();
152 return split_range;
155 SourceBufferRange::BufferQueue::iterator SourceBufferRange::GetBufferItrAt(
156 DecodeTimestamp timestamp,
157 bool skip_given_timestamp) {
158 return skip_given_timestamp
159 ? std::upper_bound(buffers_.begin(),
160 buffers_.end(),
161 timestamp,
162 CompareTimeDeltaToStreamParserBuffer)
163 : std::lower_bound(buffers_.begin(),
164 buffers_.end(),
165 timestamp,
166 CompareStreamParserBufferToTimeDelta);
169 SourceBufferRange::KeyframeMap::iterator
170 SourceBufferRange::GetFirstKeyframeAt(DecodeTimestamp timestamp,
171 bool skip_given_timestamp) {
172 return skip_given_timestamp ?
173 keyframe_map_.upper_bound(timestamp) :
174 keyframe_map_.lower_bound(timestamp);
177 SourceBufferRange::KeyframeMap::iterator
178 SourceBufferRange::GetFirstKeyframeBefore(DecodeTimestamp timestamp) {
179 KeyframeMap::iterator result = keyframe_map_.lower_bound(timestamp);
180 // lower_bound() returns the first element >= |timestamp|, so we want the
181 // previous element if it did not return the element exactly equal to
182 // |timestamp|.
183 if (result != keyframe_map_.begin() &&
184 (result == keyframe_map_.end() || result->first != timestamp)) {
185 --result;
187 return result;
190 void SourceBufferRange::DeleteAll(BufferQueue* removed_buffers) {
191 TruncateAt(buffers_.begin(), removed_buffers);
194 bool SourceBufferRange::TruncateAt(
195 DecodeTimestamp timestamp, BufferQueue* removed_buffers,
196 bool is_exclusive) {
197 // Find the place in |buffers_| where we will begin deleting data.
198 BufferQueue::iterator starting_point =
199 GetBufferItrAt(timestamp, is_exclusive);
200 return TruncateAt(starting_point, removed_buffers);
203 int SourceBufferRange::DeleteGOPFromFront(BufferQueue* deleted_buffers) {
204 DCHECK(!FirstGOPContainsNextBufferPosition());
205 DCHECK(deleted_buffers);
207 int buffers_deleted = 0;
208 int total_bytes_deleted = 0;
210 KeyframeMap::iterator front = keyframe_map_.begin();
211 DCHECK(front != keyframe_map_.end());
213 // Delete the keyframe at the start of |keyframe_map_|.
214 keyframe_map_.erase(front);
216 // Now we need to delete all the buffers that depend on the keyframe we've
217 // just deleted.
218 int end_index = keyframe_map_.size() > 0 ?
219 keyframe_map_.begin()->second - keyframe_map_index_base_ :
220 buffers_.size();
222 // Delete buffers from the beginning of the buffered range up until (but not
223 // including) the next keyframe.
224 for (int i = 0; i < end_index; i++) {
225 int bytes_deleted = buffers_.front()->data_size();
226 size_in_bytes_ -= bytes_deleted;
227 total_bytes_deleted += bytes_deleted;
228 deleted_buffers->push_back(buffers_.front());
229 buffers_.pop_front();
230 ++buffers_deleted;
233 // Update |keyframe_map_index_base_| to account for the deleted buffers.
234 keyframe_map_index_base_ += buffers_deleted;
236 if (next_buffer_index_ > -1) {
237 next_buffer_index_ -= buffers_deleted;
238 DCHECK_GE(next_buffer_index_, 0);
241 // Invalidate media segment start time if we've deleted the first buffer of
242 // the range.
243 if (buffers_deleted > 0)
244 media_segment_start_time_ = kNoDecodeTimestamp();
246 return total_bytes_deleted;
249 int SourceBufferRange::DeleteGOPFromBack(BufferQueue* deleted_buffers) {
250 DCHECK(!LastGOPContainsNextBufferPosition());
251 DCHECK(deleted_buffers);
253 // Remove the last GOP's keyframe from the |keyframe_map_|.
254 KeyframeMap::iterator back = keyframe_map_.end();
255 DCHECK_GT(keyframe_map_.size(), 0u);
256 --back;
258 // The index of the first buffer in the last GOP is equal to the new size of
259 // |buffers_| after that GOP is deleted.
260 size_t goal_size = back->second - keyframe_map_index_base_;
261 keyframe_map_.erase(back);
263 int total_bytes_deleted = 0;
264 while (buffers_.size() != goal_size) {
265 int bytes_deleted = buffers_.back()->data_size();
266 size_in_bytes_ -= bytes_deleted;
267 total_bytes_deleted += bytes_deleted;
268 // We're removing buffers from the back, so push each removed buffer to the
269 // front of |deleted_buffers| so that |deleted_buffers| are in nondecreasing
270 // order.
271 deleted_buffers->push_front(buffers_.back());
272 buffers_.pop_back();
275 return total_bytes_deleted;
278 int SourceBufferRange::GetRemovalGOP(
279 DecodeTimestamp start_timestamp, DecodeTimestamp end_timestamp,
280 int total_bytes_to_free, DecodeTimestamp* removal_end_timestamp) {
281 int bytes_to_free = total_bytes_to_free;
282 int bytes_removed = 0;
284 KeyframeMap::iterator gop_itr = GetFirstKeyframeAt(start_timestamp, false);
285 if (gop_itr == keyframe_map_.end())
286 return 0;
287 int keyframe_index = gop_itr->second - keyframe_map_index_base_;
288 BufferQueue::iterator buffer_itr = buffers_.begin() + keyframe_index;
289 KeyframeMap::iterator gop_end = keyframe_map_.end();
290 if (end_timestamp < GetBufferedEndTimestamp())
291 gop_end = GetFirstKeyframeBefore(end_timestamp);
293 // Check if the removal range is within a GOP and skip the loop if so.
294 // [keyframe]...[start_timestamp]...[end_timestamp]...[keyframe]
295 KeyframeMap::iterator gop_itr_prev = gop_itr;
296 if (gop_itr_prev != keyframe_map_.begin() && --gop_itr_prev == gop_end)
297 gop_end = gop_itr;
299 while (gop_itr != gop_end && bytes_to_free > 0) {
300 ++gop_itr;
302 int gop_size = 0;
303 int next_gop_index = gop_itr == keyframe_map_.end() ?
304 buffers_.size() : gop_itr->second - keyframe_map_index_base_;
305 BufferQueue::iterator next_gop_start = buffers_.begin() + next_gop_index;
306 for (; buffer_itr != next_gop_start; ++buffer_itr)
307 gop_size += (*buffer_itr)->data_size();
309 bytes_removed += gop_size;
310 bytes_to_free -= gop_size;
312 if (bytes_removed > 0) {
313 *removal_end_timestamp = gop_itr == keyframe_map_.end() ?
314 GetBufferedEndTimestamp() : gop_itr->first;
316 return bytes_removed;
319 bool SourceBufferRange::FirstGOPContainsNextBufferPosition() const {
320 if (!HasNextBufferPosition())
321 return false;
323 // If there is only one GOP, it must contain the next buffer position.
324 if (keyframe_map_.size() == 1u)
325 return true;
327 KeyframeMap::const_iterator second_gop = keyframe_map_.begin();
328 ++second_gop;
329 return next_buffer_index_ < second_gop->second - keyframe_map_index_base_;
332 bool SourceBufferRange::LastGOPContainsNextBufferPosition() const {
333 if (!HasNextBufferPosition())
334 return false;
336 // If there is only one GOP, it must contain the next buffer position.
337 if (keyframe_map_.size() == 1u)
338 return true;
340 KeyframeMap::const_iterator last_gop = keyframe_map_.end();
341 --last_gop;
342 return last_gop->second - keyframe_map_index_base_ <= next_buffer_index_;
345 void SourceBufferRange::FreeBufferRange(
346 const BufferQueue::iterator& starting_point,
347 const BufferQueue::iterator& ending_point) {
348 for (BufferQueue::iterator itr = starting_point;
349 itr != ending_point; ++itr) {
350 size_in_bytes_ -= (*itr)->data_size();
351 DCHECK_GE(size_in_bytes_, 0);
353 buffers_.erase(starting_point, ending_point);
356 bool SourceBufferRange::TruncateAt(
357 const BufferQueue::iterator& starting_point, BufferQueue* removed_buffers) {
358 DCHECK(!removed_buffers || removed_buffers->empty());
360 // Return if we're not deleting anything.
361 if (starting_point == buffers_.end())
362 return buffers_.empty();
364 // Reset the next buffer index if we will be deleting the buffer that's next
365 // in sequence.
366 if (HasNextBufferPosition()) {
367 DecodeTimestamp next_buffer_timestamp = GetNextTimestamp();
368 if (next_buffer_timestamp == kNoDecodeTimestamp() ||
369 next_buffer_timestamp >= (*starting_point)->GetDecodeTimestamp()) {
370 if (HasNextBuffer() && removed_buffers) {
371 int starting_offset = starting_point - buffers_.begin();
372 int next_buffer_offset = next_buffer_index_ - starting_offset;
373 DCHECK_GE(next_buffer_offset, 0);
374 BufferQueue saved(starting_point + next_buffer_offset, buffers_.end());
375 removed_buffers->swap(saved);
377 ResetNextBufferPosition();
381 // Remove keyframes from |starting_point| onward.
382 KeyframeMap::iterator starting_point_keyframe =
383 keyframe_map_.lower_bound((*starting_point)->GetDecodeTimestamp());
384 keyframe_map_.erase(starting_point_keyframe, keyframe_map_.end());
386 // Remove everything from |starting_point| onward.
387 FreeBufferRange(starting_point, buffers_.end());
388 return buffers_.empty();
391 bool SourceBufferRange::GetNextBuffer(
392 scoped_refptr<StreamParserBuffer>* out_buffer) {
393 if (!HasNextBuffer())
394 return false;
396 *out_buffer = buffers_[next_buffer_index_];
397 next_buffer_index_++;
398 return true;
401 bool SourceBufferRange::HasNextBuffer() const {
402 return next_buffer_index_ >= 0 &&
403 next_buffer_index_ < static_cast<int>(buffers_.size());
406 int SourceBufferRange::GetNextConfigId() const {
407 DCHECK(HasNextBuffer());
408 // If the next buffer is an audio splice frame, the next effective config id
409 // comes from the first fade out preroll buffer.
410 return buffers_[next_buffer_index_]->GetSpliceBufferConfigId(0);
413 DecodeTimestamp SourceBufferRange::GetNextTimestamp() const {
414 DCHECK(!buffers_.empty());
415 DCHECK(HasNextBufferPosition());
417 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) {
418 return kNoDecodeTimestamp();
421 return buffers_[next_buffer_index_]->GetDecodeTimestamp();
424 bool SourceBufferRange::HasNextBufferPosition() const {
425 return next_buffer_index_ >= 0;
428 void SourceBufferRange::ResetNextBufferPosition() {
429 next_buffer_index_ = -1;
432 void SourceBufferRange::AppendRangeToEnd(const SourceBufferRange& range,
433 bool transfer_current_position) {
434 DCHECK(CanAppendRangeToEnd(range));
435 DCHECK(!buffers_.empty());
437 if (transfer_current_position && range.next_buffer_index_ >= 0)
438 next_buffer_index_ = range.next_buffer_index_ + buffers_.size();
440 AppendBuffersToEnd(range.buffers_);
443 bool SourceBufferRange::CanAppendRangeToEnd(
444 const SourceBufferRange& range) const {
445 return CanAppendBuffersToEnd(range.buffers_);
448 bool SourceBufferRange::CanAppendBuffersToEnd(
449 const BufferQueue& buffers) const {
450 DCHECK(!buffers_.empty());
451 return IsNextInSequence(buffers.front()->GetDecodeTimestamp(),
452 buffers.front()->is_key_frame());
455 bool SourceBufferRange::BelongsToRange(DecodeTimestamp timestamp) const {
456 DCHECK(!buffers_.empty());
458 return (IsNextInSequence(timestamp, false) ||
459 (GetStartTimestamp() <= timestamp && timestamp <= GetEndTimestamp()));
462 bool SourceBufferRange::CanSeekTo(DecodeTimestamp timestamp) const {
463 DecodeTimestamp start_timestamp =
464 std::max(DecodeTimestamp(), GetStartTimestamp() - GetFudgeRoom());
465 return !keyframe_map_.empty() && start_timestamp <= timestamp &&
466 timestamp < GetBufferedEndTimestamp();
469 bool SourceBufferRange::CompletelyOverlaps(
470 const SourceBufferRange& range) const {
471 return GetStartTimestamp() <= range.GetStartTimestamp() &&
472 GetEndTimestamp() >= range.GetEndTimestamp();
475 bool SourceBufferRange::EndOverlaps(const SourceBufferRange& range) const {
476 return range.GetStartTimestamp() <= GetEndTimestamp() &&
477 GetEndTimestamp() < range.GetEndTimestamp();
480 DecodeTimestamp SourceBufferRange::GetStartTimestamp() const {
481 DCHECK(!buffers_.empty());
482 DecodeTimestamp start_timestamp = media_segment_start_time_;
483 if (start_timestamp == kNoDecodeTimestamp())
484 start_timestamp = buffers_.front()->GetDecodeTimestamp();
485 return start_timestamp;
488 DecodeTimestamp SourceBufferRange::GetEndTimestamp() const {
489 DCHECK(!buffers_.empty());
490 return buffers_.back()->GetDecodeTimestamp();
493 DecodeTimestamp SourceBufferRange::GetBufferedEndTimestamp() const {
494 DCHECK(!buffers_.empty());
495 base::TimeDelta duration = buffers_.back()->duration();
496 if (duration == kNoTimestamp() || duration == base::TimeDelta())
497 duration = GetApproximateDuration();
498 return GetEndTimestamp() + duration;
501 DecodeTimestamp SourceBufferRange::NextKeyframeTimestamp(
502 DecodeTimestamp timestamp) {
503 DCHECK(!keyframe_map_.empty());
505 if (timestamp < GetStartTimestamp() || timestamp >= GetBufferedEndTimestamp())
506 return kNoDecodeTimestamp();
508 KeyframeMap::iterator itr = GetFirstKeyframeAt(timestamp, false);
509 if (itr == keyframe_map_.end())
510 return kNoDecodeTimestamp();
512 // If the timestamp is inside the gap between the start of the media
513 // segment and the first buffer, then just pretend there is a
514 // keyframe at the specified timestamp.
515 if (itr == keyframe_map_.begin() &&
516 timestamp > media_segment_start_time_ &&
517 timestamp < itr->first) {
518 return timestamp;
521 return itr->first;
524 DecodeTimestamp SourceBufferRange::KeyframeBeforeTimestamp(
525 DecodeTimestamp timestamp) {
526 DCHECK(!keyframe_map_.empty());
528 if (timestamp < GetStartTimestamp() || timestamp >= GetBufferedEndTimestamp())
529 return kNoDecodeTimestamp();
531 return GetFirstKeyframeBefore(timestamp)->first;
534 bool SourceBufferRange::IsNextInSequence(
535 DecodeTimestamp timestamp, bool is_key_frame) const {
536 DecodeTimestamp end = buffers_.back()->GetDecodeTimestamp();
537 if (end < timestamp &&
538 (gap_policy_ == ALLOW_GAPS ||
539 timestamp <= end + GetFudgeRoom())) {
540 return true;
543 return timestamp == end && AllowSameTimestamp(
544 buffers_.back()->is_key_frame(), is_key_frame);
547 base::TimeDelta SourceBufferRange::GetFudgeRoom() const {
548 // Because we do not know exactly when is the next timestamp, any buffer
549 // that starts within 2x the approximate duration of a buffer is considered
550 // within this range.
551 return 2 * GetApproximateDuration();
554 base::TimeDelta SourceBufferRange::GetApproximateDuration() const {
555 base::TimeDelta max_interbuffer_distance = interbuffer_distance_cb_.Run();
556 DCHECK(max_interbuffer_distance != kNoTimestamp());
557 return max_interbuffer_distance;
560 bool SourceBufferRange::GetBuffersInRange(DecodeTimestamp start,
561 DecodeTimestamp end,
562 BufferQueue* buffers) {
563 // Find the nearest buffer with a decode timestamp <= start.
564 const DecodeTimestamp first_timestamp = KeyframeBeforeTimestamp(start);
565 if (first_timestamp == kNoDecodeTimestamp())
566 return false;
568 // Find all buffers involved in the range.
569 const size_t previous_size = buffers->size();
570 for (BufferQueue::iterator it = GetBufferItrAt(first_timestamp, false);
571 it != buffers_.end();
572 ++it) {
573 const scoped_refptr<StreamParserBuffer>& buffer = *it;
574 // Buffers without duration are not supported, so bail if we encounter any.
575 if (buffer->duration() == kNoTimestamp() ||
576 buffer->duration() <= base::TimeDelta()) {
577 return false;
579 if (buffer->end_of_stream() ||
580 buffer->timestamp() >= end.ToPresentationTime()) {
581 break;
584 if (buffer->timestamp() + buffer->duration() <= start.ToPresentationTime())
585 continue;
586 buffers->push_back(buffer);
588 return previous_size < buffers->size();
591 } // namespace media