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"
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
),
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();
54 DCHECK((*itr
)->GetDecodeTimestamp() != kNoDecodeTimestamp());
55 buffers_
.push_back(*itr
);
56 size_in_bytes_
+= (*itr
)->data_size();
58 if ((*itr
)->is_key_frame()) {
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;
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())
118 // Remove the data beginning at |keyframe_index| from |buffers_| and save it
119 // into |removed_buffers|.
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();
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(),
162 CompareTimeDeltaToStreamParserBuffer
)
163 : std::lower_bound(buffers_
.begin(),
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
183 if (result
!= keyframe_map_
.begin() &&
184 (result
== keyframe_map_
.end() || result
->first
!= timestamp
)) {
190 void SourceBufferRange::DeleteAll(BufferQueue
* removed_buffers
) {
191 TruncateAt(buffers_
.begin(), removed_buffers
);
194 bool SourceBufferRange::TruncateAt(
195 DecodeTimestamp timestamp
, BufferQueue
* removed_buffers
,
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
218 int end_index
= keyframe_map_
.size() > 0 ?
219 keyframe_map_
.begin()->second
- keyframe_map_index_base_
:
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();
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
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);
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
271 deleted_buffers
->push_front(buffers_
.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())
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
)
299 while (gop_itr
!= gop_end
&& bytes_to_free
> 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())
323 // If there is only one GOP, it must contain the next buffer position.
324 if (keyframe_map_
.size() == 1u)
327 KeyframeMap::const_iterator second_gop
= keyframe_map_
.begin();
329 return next_buffer_index_
< second_gop
->second
- keyframe_map_index_base_
;
332 bool SourceBufferRange::LastGOPContainsNextBufferPosition() const {
333 if (!HasNextBufferPosition())
336 // If there is only one GOP, it must contain the next buffer position.
337 if (keyframe_map_
.size() == 1u)
340 KeyframeMap::const_iterator last_gop
= keyframe_map_
.end();
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
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())
396 *out_buffer
= buffers_
[next_buffer_index_
];
397 next_buffer_index_
++;
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
) {
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())) {
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
,
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())
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();
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()) {
579 if (buffer
->end_of_stream() ||
580 buffer
->timestamp() >= end
.ToPresentationTime()) {
584 if (buffer
->timestamp() + buffer
->duration() <= start
.ToPresentationTime())
586 buffers
->push_back(buffer
);
588 return previous_size
< buffers
->size();