1 // Copyright 2014 The Chromium Authors
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"
12 #include "base/logging.h"
13 #include "media/base/stream_parser_buffer.h"
14 #include "media/base/timestamp_constants.h"
18 SourceBufferRange::SourceBufferRange(
20 const BufferQueue& new_buffers,
21 base::TimeDelta range_start_pts,
22 InterbufferDistanceCB interbuffer_distance_cb)
23 : gap_policy_(gap_policy),
24 next_buffer_index_(-1),
25 interbuffer_distance_cb_(std::move(interbuffer_distance_cb)),
27 range_start_pts_(range_start_pts),
28 keyframe_map_index_base_(0) {
30 DCHECK(interbuffer_distance_cb_);
31 CHECK(!new_buffers.empty());
32 DCHECK(new_buffers.front()->is_key_frame());
33 AppendBuffersToEnd(new_buffers, range_start_pts_);
36 SourceBufferRange::~SourceBufferRange() = default;
38 void SourceBufferRange::DeleteAll(BufferQueue* deleted_buffers) {
40 DVLOG(4) << ToStringForDebugging();
42 TruncateAt(0u, deleted_buffers);
45 void SourceBufferRange::SeekToStart() {
46 CHECK(!buffers_.empty());
47 next_buffer_index_ = 0;
50 bool SourceBufferRange::GetNextBuffer(
51 scoped_refptr<StreamParserBuffer>* out_buffer) {
55 *out_buffer = buffers_[next_buffer_index_];
60 bool SourceBufferRange::HasNextBuffer() const {
61 return next_buffer_index_ >= 0 &&
62 next_buffer_index_ < static_cast<int>(buffers_.size());
65 int SourceBufferRange::GetNextConfigId() const {
66 CHECK(HasNextBuffer()) << next_buffer_index_;
67 // If the next buffer is an audio splice frame, the next effective config id
68 // comes from the first fade out preroll buffer.
69 return buffers_[next_buffer_index_]->GetConfigId();
72 bool SourceBufferRange::HasNextBufferPosition() const {
73 return next_buffer_index_ >= 0;
76 void SourceBufferRange::ResetNextBufferPosition() {
77 next_buffer_index_ = -1;
80 void SourceBufferRange::AppendRangeToEnd(const SourceBufferRange& range,
81 bool transfer_current_position) {
83 DVLOG(4) << ToStringForDebugging();
85 DCHECK(CanAppendRangeToEnd(range));
86 DCHECK(!buffers_.empty());
88 if (transfer_current_position && range.next_buffer_index_ >= 0)
89 next_buffer_index_ = range.next_buffer_index_ + buffers_.size();
91 AppendBuffersToEnd(range.buffers_,
92 NextRangeStartTimeForAppendRangeToEnd(range));
95 bool SourceBufferRange::CanAppendRangeToEnd(
96 const SourceBufferRange& range) const {
98 DVLOG(4) << ToStringForDebugging();
100 return CanAppendBuffersToEnd(range.buffers_,
101 NextRangeStartTimeForAppendRangeToEnd(range));
104 void SourceBufferRange::AppendBuffersToEnd(
105 const BufferQueue& new_buffers,
106 base::TimeDelta new_buffers_group_start_pts) {
107 DVLOG(1) << __func__;
108 DVLOG(4) << ToStringForDebugging();
110 CHECK(buffers_.empty() ||
111 CanAppendBuffersToEnd(new_buffers, new_buffers_group_start_pts));
113 DCHECK(new_buffers_group_start_pts == kNoTimestamp ||
114 new_buffers.front()->is_key_frame())
115 << range_start_pts_ << ", " << new_buffers.front()->is_key_frame();
117 AdjustEstimatedDurationForNewAppend(new_buffers);
119 for (BufferQueue::const_iterator itr = new_buffers.begin();
120 itr != new_buffers.end(); ++itr) {
121 DCHECK((*itr)->timestamp() != kNoTimestamp);
122 DCHECK((*itr)->GetDecodeTimestamp() != kNoDecodeTimestamp);
124 buffers_.push_back(*itr);
126 size_in_bytes_ += (*itr)->data_size();
128 if ((*itr)->is_key_frame()) {
129 keyframe_map_.insert(std::make_pair(
130 (*itr)->timestamp(), buffers_.size() - 1 + keyframe_map_index_base_));
134 DVLOG(4) << __func__ << " Result: " << ToStringForDebugging();
137 bool SourceBufferRange::AllowableAppendAfterEstimatedDuration(
138 const BufferQueue& buffers,
139 base::TimeDelta new_buffers_group_start_pts) const {
140 if (buffers_.empty() || !buffers_.back()->is_duration_estimated() ||
141 buffers.empty() || !buffers.front()->is_key_frame()) {
145 if (new_buffers_group_start_pts == kNoTimestamp) {
146 return GetBufferedEndTimestamp() == buffers.front()->timestamp();
149 return GetBufferedEndTimestamp() == new_buffers_group_start_pts;
152 bool SourceBufferRange::CanAppendBuffersToEnd(
153 const BufferQueue& buffers,
154 base::TimeDelta new_buffers_group_start_pts) const {
155 DVLOG(1) << __func__;
156 DVLOG(4) << ToStringForDebugging();
158 DCHECK(!buffers_.empty());
159 if (new_buffers_group_start_pts == kNoTimestamp) {
160 return buffers.front()->is_key_frame()
161 ? (IsNextInPresentationSequence(buffers.front()->timestamp()) ||
162 AllowableAppendAfterEstimatedDuration(
163 buffers, new_buffers_group_start_pts))
164 : IsNextInDecodeSequence(buffers.front()->GetDecodeTimestamp());
166 CHECK(buffers.front()->is_key_frame());
167 DCHECK(new_buffers_group_start_pts >= GetEndTimestamp());
168 DCHECK(buffers.front()->timestamp() >= new_buffers_group_start_pts);
169 return IsNextInPresentationSequence(new_buffers_group_start_pts) ||
170 AllowableAppendAfterEstimatedDuration(buffers,
171 new_buffers_group_start_pts);
174 void SourceBufferRange::Seek(base::TimeDelta timestamp) {
175 DVLOG(1) << __func__;
176 DVLOG(4) << ToStringForDebugging();
178 DCHECK(CanSeekTo(timestamp));
179 DCHECK(!keyframe_map_.empty());
181 auto result = GetFirstKeyframeAtOrBefore(timestamp);
182 next_buffer_index_ = result->second - keyframe_map_index_base_;
183 CHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size()))
184 << next_buffer_index_ << ", size = " << buffers_.size();
186 #if BUILDFLAG(IS_TIZEN_TV)
187 void SourceBufferRange::ModifyFirstFrameForMpeghCodec() {
188 DVLOG(1) << __func__;
189 DVLOG(4) << ToStringForDebugging();
190 // MPEGH codec starting sequence
191 std::vector<uint8_t> start_sequence = {0x01, 0x00, 0x00, 0x00, 0x18,
192 0x00, 0x00, 0x00, 0x00};
194 if (buffers_.size() <= next_buffer_index_)
197 auto old_data_ = buffers_[next_buffer_index_]->data();
198 auto old_data_size = buffers_[next_buffer_index_]->data_size();
200 // This is used to check whether we do not try to add starting sequence to
201 // frame that already had it added while demuxing ie. first uploaded frame
202 bool is_starting_sequence_already_present = true;
203 for (unsigned int i = 0; i < start_sequence.size() && i < old_data_size;
205 if (start_sequence[i] != old_data_[i]) {
206 is_starting_sequence_already_present = false;
211 if (is_starting_sequence_already_present &&
212 old_data_size > start_sequence.size())
215 // New container for old data with added starting sequence
216 std::vector<uint8_t> new_data =
217 std::vector<uint8_t>(old_data_size + start_sequence.size());
219 // Starting sequence inserted in front of new data
220 // new_data.insert(new_data.begin(),start_sequence.begin(),start_sequence.end());
221 for (unsigned int i = 0; i < start_sequence.size(); i++) {
222 new_data[i] = start_sequence[i];
225 // Loop copying old data to new container
226 for (unsigned int i = 0; i < old_data_size; i++) {
227 new_data[i + start_sequence.size()] = old_data_[i];
230 // Creating new buffer based on changed data
231 auto new_buffer = StreamParserBuffer::CopyFrom(
232 &(new_data.front()), new_data.size(),
233 buffers_[next_buffer_index_]->is_key_frame(),
234 buffers_[next_buffer_index_]->type(),
235 buffers_[next_buffer_index_]->track_id());
237 // set side_data/alpha_data for new buffer
238 if (buffers_[next_buffer_index_]->has_side_data()) {
239 auto side_data = buffers_[next_buffer_index_]->side_data();
240 if (!side_data->alpha_data.empty()) {
241 new_buffer->WritableSideData().alpha_data.assign(
242 side_data->alpha_data.data(),
243 side_data->alpha_data.data() + side_data->alpha_data.size());
247 // Setting other necessary data not copied by previous function
248 new_buffer->SetConfigId(buffers_[next_buffer_index_]->GetConfigId());
249 new_buffer->SetDecodeTimestamp(
250 buffers_[next_buffer_index_]->GetDecodeTimestamp());
251 new_buffer->set_is_duration_estimated(
252 buffers_[next_buffer_index_]->is_duration_estimated());
253 new_buffer->set_duration(buffers_[next_buffer_index_]->duration());
254 new_buffer->set_timestamp(buffers_[next_buffer_index_]->timestamp());
256 // Swapping old buffer to new buffer. Old buffer is discarded.
257 buffers_[next_buffer_index_].swap(new_buffer);
261 bool SourceBufferRange::CanSeekTo(base::TimeDelta timestamp) const {
262 DVLOG(1) << __func__;
263 DVLOG(4) << ToStringForDebugging();
265 base::TimeDelta start_timestamp =
266 std::max(base::TimeDelta(), GetStartTimestamp() - GetFudgeRoom());
267 return !keyframe_map_.empty() && start_timestamp <= timestamp &&
268 timestamp < GetBufferedEndTimestamp();
271 int SourceBufferRange::GetConfigIdAtTime(base::TimeDelta timestamp) const {
272 DVLOG(1) << __func__;
273 DVLOG(4) << ToStringForDebugging();
275 DCHECK(CanSeekTo(timestamp));
276 DCHECK(!keyframe_map_.empty());
278 auto result = GetFirstKeyframeAtOrBefore(timestamp);
279 CHECK(result != keyframe_map_.end());
280 size_t buffer_index = result->second - keyframe_map_index_base_;
281 CHECK_LT(buffer_index, buffers_.size())
282 << buffer_index << ", size = " << buffers_.size();
284 return buffers_[buffer_index]->GetConfigId();
287 bool SourceBufferRange::SameConfigThruRange(base::TimeDelta start,
288 base::TimeDelta end) const {
289 DVLOG(1) << __func__;
290 DVLOG(4) << ToStringForDebugging();
292 DCHECK(CanSeekTo(start));
293 DCHECK(CanSeekTo(end));
294 DCHECK(start <= end);
295 DCHECK(!keyframe_map_.empty());
300 auto result = GetFirstKeyframeAtOrBefore(start);
301 CHECK(result != keyframe_map_.end());
302 size_t buffer_index = result->second - keyframe_map_index_base_;
303 CHECK_LT(buffer_index, buffers_.size())
304 << buffer_index << ", size = " << buffers_.size();
306 int start_config = buffers_[buffer_index]->GetConfigId();
308 while (buffer_index < buffers_.size() &&
309 buffers_[buffer_index]->timestamp() <= end) {
310 if (buffers_[buffer_index]->GetConfigId() != start_config)
318 std::unique_ptr<SourceBufferRange> SourceBufferRange::SplitRange(
319 base::TimeDelta timestamp) {
320 DVLOG(1) << __func__;
321 DVLOG(4) << ToStringForDebugging();
323 CHECK(!buffers_.empty());
325 // Find the first keyframe at or after |timestamp|.
326 auto new_beginning_keyframe = GetFirstKeyframeAt(timestamp, false);
328 // If there is no keyframe at or after |timestamp|, we can't split the range.
329 if (new_beginning_keyframe == keyframe_map_.end())
332 // Remove the data beginning at |keyframe_index| from |buffers_| and save it
333 // into |removed_buffers|.
335 new_beginning_keyframe->second - keyframe_map_index_base_;
336 CHECK_LT(keyframe_index, static_cast<int>(buffers_.size()));
337 BufferQueue::iterator starting_point = buffers_.begin() + keyframe_index;
338 BufferQueue removed_buffers(starting_point, buffers_.end());
340 base::TimeDelta new_range_start_pts =
341 std::max(timestamp, GetStartTimestamp());
342 DCHECK(new_range_start_pts <= removed_buffers.front()->timestamp());
344 keyframe_map_.erase(new_beginning_keyframe, keyframe_map_.end());
345 FreeBufferRange(starting_point, buffers_.end());
346 UpdateEndTimeUsingLastGOP();
348 // Create a new range with |removed_buffers|.
349 std::unique_ptr<SourceBufferRange> split_range =
350 std::make_unique<SourceBufferRange>(gap_policy_, removed_buffers,
352 interbuffer_distance_cb_);
354 // If the next buffer position is now in |split_range|, update the state of
355 // this range and |split_range| accordingly.
356 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) {
357 split_range->next_buffer_index_ = next_buffer_index_ - keyframe_index;
359 int split_range_next_buffer_index = split_range->next_buffer_index_;
360 CHECK_GE(split_range_next_buffer_index, 0);
361 // Note that a SourceBufferRange's |next_buffer_index_| can be the index
362 // of a buffer one beyond what is currently in |buffers_|.
363 CHECK_LE(split_range_next_buffer_index,
364 static_cast<int>(split_range->buffers_.size()));
366 ResetNextBufferPosition();
372 bool SourceBufferRange::TruncateAt(base::TimeDelta timestamp,
373 BufferQueue* deleted_buffers,
375 DVLOG(1) << __func__;
376 DVLOG(4) << ToStringForDebugging();
378 // Find the place in |buffers_| where we will begin deleting data, then
379 // truncate from there.
380 return TruncateAt(GetBufferIndexAt(timestamp, is_exclusive), deleted_buffers);
383 size_t SourceBufferRange::DeleteGOPFromFront(BufferQueue* deleted_buffers) {
384 DVLOG(1) << __func__;
385 DVLOG(4) << ToStringForDebugging();
387 DCHECK(!buffers_.empty());
388 DCHECK(!FirstGOPContainsNextBufferPosition());
389 DCHECK(deleted_buffers);
391 int buffers_deleted = 0;
392 size_t total_bytes_deleted = 0;
394 KeyframeMap::const_iterator front = keyframe_map_.begin();
395 DCHECK(front != keyframe_map_.end());
397 // Delete the keyframe at the start of |keyframe_map_|.
398 keyframe_map_.erase(front);
400 // Now we need to delete all the buffers that depend on the keyframe we've
402 int end_index = keyframe_map_.size() > 0
403 ? keyframe_map_.begin()->second - keyframe_map_index_base_
406 // Delete buffers from the beginning of the buffered range up until (but not
407 // including) the next keyframe.
408 for (int i = 0; i < end_index; i++) {
409 size_t bytes_deleted = buffers_.front()->data_size();
410 DCHECK_GE(size_in_bytes_, bytes_deleted);
411 size_in_bytes_ -= bytes_deleted;
412 total_bytes_deleted += bytes_deleted;
413 deleted_buffers->push_back(buffers_.front());
414 buffers_.pop_front();
418 // Update |keyframe_map_index_base_| to account for the deleted buffers.
419 keyframe_map_index_base_ += buffers_deleted;
421 if (next_buffer_index_ > -1) {
422 next_buffer_index_ -= buffers_deleted;
423 CHECK_GE(next_buffer_index_, 0)
424 << next_buffer_index_ << ", deleted " << buffers_deleted;
427 // Invalidate range start time if we've deleted the first buffer of the range.
428 if (buffers_deleted > 0) {
429 range_start_pts_ = kNoTimestamp;
430 // Reset the range end time tracking if there are no more buffers in the
432 if (buffers_.empty())
433 highest_frame_ = nullptr;
436 return total_bytes_deleted;
439 size_t SourceBufferRange::DeleteGOPFromBack(BufferQueue* deleted_buffers) {
440 DVLOG(1) << __func__;
441 DVLOG(4) << ToStringForDebugging();
443 DCHECK(!buffers_.empty());
444 DCHECK(!LastGOPContainsNextBufferPosition());
445 DCHECK(deleted_buffers);
447 // Remove the last GOP's keyframe from the |keyframe_map_|.
448 KeyframeMap::const_iterator back = keyframe_map_.end();
449 DCHECK_GT(keyframe_map_.size(), 0u);
452 // The index of the first buffer in the last GOP is equal to the new size of
453 // |buffers_| after that GOP is deleted.
454 size_t goal_size = back->second - keyframe_map_index_base_;
455 keyframe_map_.erase(back);
457 size_t total_bytes_deleted = 0;
458 while (buffers_.size() != goal_size) {
459 size_t bytes_deleted = buffers_.back()->data_size();
460 DCHECK_GE(size_in_bytes_, bytes_deleted);
461 size_in_bytes_ -= bytes_deleted;
462 total_bytes_deleted += bytes_deleted;
463 // We're removing buffers from the back, so push each removed buffer to the
464 // front of |deleted_buffers| so that |deleted_buffers| are in nondecreasing
466 deleted_buffers->push_front(buffers_.back());
470 UpdateEndTimeUsingLastGOP();
472 return total_bytes_deleted;
475 size_t SourceBufferRange::GetRemovalGOP(
476 base::TimeDelta start_timestamp,
477 base::TimeDelta end_timestamp,
478 size_t total_bytes_to_free,
479 base::TimeDelta* removal_end_timestamp) const {
480 DVLOG(1) << __func__;
481 DVLOG(4) << ToStringForDebugging();
483 size_t bytes_removed = 0;
485 auto gop_itr = GetFirstKeyframeAt(start_timestamp, false);
486 if (gop_itr == keyframe_map_.end())
488 int keyframe_index = gop_itr->second - keyframe_map_index_base_;
489 BufferQueue::const_iterator buffer_itr = buffers_.begin() + keyframe_index;
490 auto gop_end = keyframe_map_.end();
491 if (end_timestamp < GetBufferedEndTimestamp())
492 gop_end = GetFirstKeyframeAtOrBefore(end_timestamp);
494 // Check if the removal range is within a GOP and skip the loop if so.
495 // [keyframe]...[start_timestamp]...[end_timestamp]...[keyframe]
496 auto gop_itr_prev = gop_itr;
497 if (gop_itr_prev != keyframe_map_.begin() && --gop_itr_prev == gop_end)
500 while (gop_itr != gop_end && bytes_removed < total_bytes_to_free) {
504 int next_gop_index = gop_itr == keyframe_map_.end()
506 : gop_itr->second - keyframe_map_index_base_;
507 BufferQueue::const_iterator next_gop_start =
508 buffers_.begin() + next_gop_index;
509 for (; buffer_itr != next_gop_start; ++buffer_itr) {
510 gop_size += (*buffer_itr)->data_size();
513 bytes_removed += gop_size;
515 if (bytes_removed > 0) {
516 *removal_end_timestamp = gop_itr == keyframe_map_.end()
517 ? GetBufferedEndTimestamp()
520 return bytes_removed;
523 bool SourceBufferRange::FirstGOPEarlierThanMediaTime(
524 base::TimeDelta media_time) const {
525 DVLOG(1) << __func__;
526 DVLOG(4) << ToStringForDebugging();
528 if (keyframe_map_.size() == 1u)
529 return (GetBufferedEndTimestamp() <= media_time);
531 auto second_gop = keyframe_map_.begin();
533 return second_gop->first <= media_time;
536 bool SourceBufferRange::FirstGOPContainsNextBufferPosition() const {
537 DVLOG(1) << __func__;
538 DVLOG(4) << ToStringForDebugging();
540 if (!HasNextBufferPosition())
543 // If there is only one GOP, it must contain the next buffer position.
544 if (keyframe_map_.size() == 1u)
547 auto second_gop = keyframe_map_.begin();
549 return next_buffer_index_ < second_gop->second - keyframe_map_index_base_;
552 bool SourceBufferRange::LastGOPContainsNextBufferPosition() const {
553 DVLOG(1) << __func__;
554 DVLOG(4) << ToStringForDebugging();
556 if (!HasNextBufferPosition())
559 // If there is only one GOP, it must contain the next buffer position.
560 if (keyframe_map_.size() == 1u)
563 auto last_gop = keyframe_map_.end();
565 return last_gop->second - keyframe_map_index_base_ <= next_buffer_index_;
568 base::TimeDelta SourceBufferRange::GetNextTimestamp() const {
569 DVLOG(1) << __func__;
570 DVLOG(4) << ToStringForDebugging();
572 CHECK(!buffers_.empty()) << next_buffer_index_;
573 CHECK(HasNextBufferPosition())
574 << next_buffer_index_ << ", size=" << buffers_.size();
576 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) {
580 return buffers_[next_buffer_index_]->timestamp();
583 base::TimeDelta SourceBufferRange::GetStartTimestamp() const {
584 DVLOG(1) << __func__;
585 DVLOG(4) << ToStringForDebugging();
587 DCHECK(!buffers_.empty());
588 base::TimeDelta start_timestamp = range_start_pts_;
589 if (start_timestamp == kNoTimestamp)
590 start_timestamp = buffers_.front()->timestamp();
591 return start_timestamp;
594 base::TimeDelta SourceBufferRange::GetEndTimestamp() const {
595 DVLOG(1) << __func__;
596 DVLOG(4) << ToStringForDebugging();
598 DCHECK(!buffers_.empty());
599 return highest_frame_->timestamp();
602 base::TimeDelta SourceBufferRange::GetBufferedEndTimestamp() const {
603 DVLOG(1) << __func__;
604 DVLOG(4) << ToStringForDebugging();
606 DCHECK(!buffers_.empty());
607 base::TimeDelta duration = highest_frame_->duration();
609 // FrameProcessor should protect against unknown buffer durations.
610 DCHECK_NE(duration, kNoTimestamp);
612 // Because media::Ranges<base::TimeDelta>::Add() ignores 0 duration ranges,
613 // report 1 microsecond for the last buffer's duration if it is a 0 duration
615 if (duration.is_zero())
616 duration = base::Microseconds(1);
618 return GetEndTimestamp() + duration;
621 bool SourceBufferRange::BelongsToRange(base::TimeDelta timestamp) const {
622 DVLOG(1) << __func__;
623 DVLOG(4) << ToStringForDebugging();
625 DCHECK(!buffers_.empty());
627 return (IsNextInPresentationSequence(timestamp) ||
628 (GetStartTimestamp() <= timestamp && timestamp <= GetEndTimestamp()));
631 base::TimeDelta SourceBufferRange::FindHighestBufferedTimestampAtOrBefore(
632 base::TimeDelta timestamp) const {
633 DVLOG(1) << __func__;
634 DVLOG(4) << ToStringForDebugging();
636 DCHECK(!buffers_.empty());
637 DCHECK(BelongsToRange(timestamp));
639 if (keyframe_map_.begin()->first > timestamp) {
640 // If the first keyframe in the range starts after |timestamp|, then
641 // return the range start time (which could be earlier due to coded frame
642 // group signalling.)
643 base::TimeDelta range_start = GetStartTimestamp();
644 DCHECK(timestamp >= range_start) << "BelongsToRange() semantics failed.";
648 if (keyframe_map_.begin()->first == timestamp) {
652 auto key_iter = GetFirstKeyframeAtOrBefore(timestamp);
653 DCHECK(key_iter != keyframe_map_.end())
654 << "BelongsToRange() semantics failed.";
655 DCHECK(key_iter->first <= timestamp);
657 // Scan forward in |buffers_| to find the highest frame with timestamp <=
658 // |timestamp|. Stop once a frame with timestamp > |timestamp| is encountered.
659 size_t key_index = key_iter->second - keyframe_map_index_base_;
660 SourceBufferRange::BufferQueue::const_iterator search_iter =
661 buffers_.begin() + key_index;
662 CHECK(search_iter != buffers_.end());
663 base::TimeDelta cur_frame_time = (*search_iter)->timestamp();
664 base::TimeDelta result = cur_frame_time;
666 result = std::max(result, cur_frame_time);
668 if (search_iter == buffers_.end())
670 cur_frame_time = (*search_iter)->timestamp();
671 if (cur_frame_time > timestamp)
675 NOTREACHED_NORETURN();
678 base::TimeDelta SourceBufferRange::NextKeyframeTimestamp(
679 base::TimeDelta timestamp) const {
680 DVLOG(1) << __func__;
681 DVLOG(4) << ToStringForDebugging();
683 DCHECK(!keyframe_map_.empty());
685 if (timestamp < GetStartTimestamp() || timestamp >= GetBufferedEndTimestamp())
688 auto itr = GetFirstKeyframeAt(timestamp, false);
689 if (itr == keyframe_map_.end())
692 // If the timestamp is inside the gap between the start of the coded frame
693 // group and the first buffer, then just pretend there is a keyframe at the
694 // specified timestamp.
695 if (itr == keyframe_map_.begin() && timestamp > range_start_pts_ &&
696 timestamp < itr->first) {
703 base::TimeDelta SourceBufferRange::KeyframeBeforeTimestamp(
704 base::TimeDelta timestamp) const {
705 DVLOG(1) << __func__;
706 DVLOG(4) << ToStringForDebugging();
708 DCHECK(!keyframe_map_.empty());
710 if (timestamp < GetStartTimestamp() || timestamp >= GetBufferedEndTimestamp())
713 return GetFirstKeyframeAtOrBefore(timestamp)->first;
716 bool SourceBufferRange::GetBuffersInRange(base::TimeDelta start,
718 BufferQueue* buffers) const {
719 DVLOG(1) << __func__;
720 DVLOG(4) << ToStringForDebugging();
722 // Find the nearest buffer with a timestamp <= start.
723 const base::TimeDelta first_timestamp = KeyframeBeforeTimestamp(start);
724 if (first_timestamp == kNoTimestamp)
727 // Find all buffers involved in the range.
728 const size_t previous_size = buffers->size();
729 for (BufferQueue::const_iterator it = GetBufferItrAt(first_timestamp, false);
730 it != buffers_.end(); ++it) {
731 scoped_refptr<StreamParserBuffer> buffer = *it;
732 // Buffers without duration are not supported, so bail if we encounter any.
733 if (buffer->duration() == kNoTimestamp ||
734 buffer->duration() <= base::TimeDelta()) {
737 if (buffer->timestamp() >= end)
740 if (buffer->timestamp() + buffer->duration() <= start)
743 buffers->emplace_back(std::move(buffer));
745 return previous_size < buffers->size();
748 void SourceBufferRange::AdjustEstimatedDurationForNewAppend(
749 const BufferQueue& new_buffers) {
750 if (buffers_.empty() || new_buffers.empty()) {
754 // Do not adjust estimate for Audio buffers to avoid competing with
755 // SourceBufferStream::TrimSpliceOverlap()
756 if (buffers_.front()->type() == StreamParserBuffer::Type::AUDIO) {
760 // If the last of the previously appended buffers contains estimated duration,
761 // we now refine that estimate by taking the PTS delta from the first new
762 // buffer being appended.
763 const auto& last_appended_buffer = buffers_.back();
764 if (last_appended_buffer->is_duration_estimated()) {
765 base::TimeDelta timestamp_delta =
766 new_buffers.front()->timestamp() - last_appended_buffer->timestamp();
767 DCHECK_GE(timestamp_delta, base::TimeDelta());
768 if (last_appended_buffer->duration() != timestamp_delta) {
769 DVLOG(1) << "Replacing estimated duration ("
770 << last_appended_buffer->duration()
771 << ") from previous range-end with derived duration ("
772 << timestamp_delta << ").";
773 last_appended_buffer->set_duration(timestamp_delta);
778 void SourceBufferRange::FreeBufferRange(
779 const BufferQueue::const_iterator& starting_point,
780 const BufferQueue::const_iterator& ending_point) {
781 for (BufferQueue::const_iterator itr = starting_point; itr != ending_point;
783 size_t itr_data_size = static_cast<size_t>((*itr)->data_size());
784 DCHECK_GE(size_in_bytes_, itr_data_size);
785 size_in_bytes_ -= itr_data_size;
787 buffers_.erase(starting_point, ending_point);
790 base::TimeDelta SourceBufferRange::GetFudgeRoom() const {
791 // Because we do not know exactly when is the next timestamp, any buffer
792 // that starts within 2x the approximate duration of a buffer is considered
793 // within this range.
794 return 2 * GetApproximateDuration();
797 base::TimeDelta SourceBufferRange::GetApproximateDuration() const {
798 base::TimeDelta max_interbuffer_distance = interbuffer_distance_cb_.Run();
799 DCHECK(max_interbuffer_distance != kNoTimestamp);
800 return max_interbuffer_distance;
803 void SourceBufferRange::UpdateEndTime(
804 scoped_refptr<StreamParserBuffer> new_buffer) {
805 base::TimeDelta timestamp = new_buffer->timestamp();
806 base::TimeDelta duration = new_buffer->duration();
807 DVLOG(1) << __func__ << " timestamp=" << timestamp
808 << ", duration=" << duration;
809 DCHECK_NE(timestamp, kNoTimestamp);
810 DCHECK_GE(timestamp, base::TimeDelta());
811 DCHECK_GE(duration, base::TimeDelta());
813 if (!highest_frame_) {
814 DVLOG(1) << "Updating range end time from <empty> to "
815 << timestamp.InMicroseconds() << "us, "
816 << (timestamp + duration).InMicroseconds() << "us";
817 highest_frame_ = std::move(new_buffer);
821 if (highest_frame_->timestamp() < timestamp ||
822 (highest_frame_->timestamp() == timestamp &&
823 highest_frame_->duration() <= duration)) {
824 DVLOG(1) << "Updating range end time from "
825 << highest_frame_->timestamp().InMicroseconds() << "us, "
826 << (highest_frame_->timestamp() + highest_frame_->duration())
828 << "us to " << timestamp.InMicroseconds() << "us, "
829 << (timestamp + duration).InMicroseconds();
830 highest_frame_ = std::move(new_buffer);
834 bool SourceBufferRange::IsNextInPresentationSequence(
835 base::TimeDelta timestamp) const {
836 DCHECK_NE(timestamp, kNoTimestamp);
837 CHECK(!buffers_.empty());
838 base::TimeDelta highest_timestamp = highest_frame_->timestamp();
839 DCHECK_NE(highest_timestamp, kNoTimestamp);
840 return (highest_timestamp == timestamp ||
841 (highest_timestamp < timestamp &&
842 (gap_policy_ == ALLOW_GAPS ||
843 timestamp <= highest_timestamp + GetFudgeRoom())));
846 bool SourceBufferRange::IsNextInDecodeSequence(
847 DecodeTimestamp decode_timestamp) const {
848 CHECK(!buffers_.empty());
849 DecodeTimestamp end = buffers_.back()->GetDecodeTimestamp();
851 end == decode_timestamp ||
852 (end < decode_timestamp && (gap_policy_ == ALLOW_GAPS ||
853 decode_timestamp <= end + GetFudgeRoom())));
856 base::TimeDelta SourceBufferRange::NextRangeStartTimeForAppendRangeToEnd(
857 const SourceBufferRange& range) const {
858 DCHECK(!buffers_.empty());
859 DCHECK(!range.buffers_.empty());
861 base::TimeDelta next_range_first_buffer_time =
862 range.buffers_.front()->timestamp();
863 base::TimeDelta this_range_end_time = GetEndTimestamp();
864 if (next_range_first_buffer_time < this_range_end_time)
867 base::TimeDelta next_range_start_time = range.GetStartTimestamp();
868 DCHECK(next_range_start_time <= next_range_first_buffer_time);
870 if (next_range_start_time >= this_range_end_time)
871 return next_range_start_time;
873 return this_range_end_time;
876 size_t SourceBufferRange::GetBufferIndexAt(base::TimeDelta timestamp,
877 bool skip_given_timestamp) const {
878 DVLOG(1) << __func__;
879 DVLOG(4) << ToStringForDebugging();
881 // Find the GOP containing |timestamp| (or trivial buffers_.size() if none
882 // contain |timestamp|).
883 auto gop_iter = GetFirstKeyframeAtOrBefore(timestamp);
884 if (gop_iter == keyframe_map_.end())
885 return buffers_.size();
887 // Then scan forward in this GOP in decode sequence for the first frame with
888 // PTS >= |timestamp| (or strictly > if |skip_given_timestamp| is true). If
889 // this GOP doesn't contain such a frame, returns the index of the keyframe of
890 // the next GOP (which could be the index of end() of |buffers_| if this was
891 // the last GOP in |buffers_|). We do linear scan of the GOP here because we
892 // don't know the DTS for the searched-for frame, and the PTS sequence within
893 // a GOP may not match the DTS-sorted sequence of frames within the GOP.
894 DCHECK_GT(buffers_.size(), 0u);
895 size_t search_index = gop_iter->second - keyframe_map_index_base_;
896 SourceBufferRange::BufferQueue::const_iterator search_iter =
897 buffers_.begin() + search_index;
900 SourceBufferRange::BufferQueue::const_iterator next_gop_start =
901 gop_iter == keyframe_map_.end()
903 : buffers_.begin() + (gop_iter->second - keyframe_map_index_base_);
905 while (search_iter != next_gop_start) {
906 if (((*search_iter)->timestamp() > timestamp) ||
907 (!skip_given_timestamp && (*search_iter)->timestamp() == timestamp)) {
917 SourceBufferRange::BufferQueue::const_iterator
918 SourceBufferRange::GetBufferItrAt(base::TimeDelta timestamp,
919 bool skip_given_timestamp) const {
920 DVLOG(1) << __func__;
921 DVLOG(4) << ToStringForDebugging();
923 return buffers_.begin() + GetBufferIndexAt(timestamp, skip_given_timestamp);
926 SourceBufferRange::KeyframeMap::const_iterator
927 SourceBufferRange::GetFirstKeyframeAt(base::TimeDelta timestamp,
928 bool skip_given_timestamp) const {
929 DVLOG(1) << __func__;
930 DVLOG(4) << ToStringForDebugging();
932 return skip_given_timestamp ? keyframe_map_.upper_bound(timestamp)
933 : keyframe_map_.lower_bound(timestamp);
936 SourceBufferRange::KeyframeMap::const_iterator
937 SourceBufferRange::GetFirstKeyframeAtOrBefore(base::TimeDelta timestamp) const {
938 DVLOG(1) << __func__;
939 DVLOG(4) << ToStringForDebugging();
941 auto result = keyframe_map_.lower_bound(timestamp);
942 // lower_bound() returns the first element >= |timestamp|, so we want the
943 // previous element if it did not return the element exactly equal to
945 if (result != keyframe_map_.begin() &&
946 (result == keyframe_map_.end() || result->first != timestamp)) {
952 bool SourceBufferRange::TruncateAt(const size_t starting_point,
953 BufferQueue* deleted_buffers) {
954 DVLOG(1) << __func__;
955 DVLOG(4) << ToStringForDebugging();
957 CHECK_LE(starting_point, buffers_.size());
958 DCHECK(!deleted_buffers || deleted_buffers->empty());
960 // Return if we're not deleting anything.
961 if (starting_point == buffers_.size())
962 return buffers_.empty();
964 // Reset the next buffer index if we will be deleting the buffer that's next
966 if (HasNextBufferPosition()) {
967 if (static_cast<size_t>(next_buffer_index_) >= starting_point) {
968 if (HasNextBuffer() && deleted_buffers) {
969 BufferQueue saved(buffers_.begin() + next_buffer_index_,
971 deleted_buffers->swap(saved);
973 ResetNextBufferPosition();
977 const BufferQueue::const_iterator starting_point_iter =
978 buffers_.begin() + starting_point;
980 // Remove keyframes from |starting_point| onward.
981 KeyframeMap::const_iterator starting_point_keyframe =
982 keyframe_map_.lower_bound((*starting_point_iter)->timestamp());
983 keyframe_map_.erase(starting_point_keyframe, keyframe_map_.end());
985 // Remove everything from |starting_point| onward.
986 FreeBufferRange(starting_point_iter, buffers_.end());
988 UpdateEndTimeUsingLastGOP();
989 return buffers_.empty();
992 void SourceBufferRange::UpdateEndTimeUsingLastGOP() {
993 DVLOG(1) << __func__;
994 DVLOG(4) << ToStringForDebugging();
996 if (buffers_.empty()) {
997 DVLOG(1) << __func__ << " Empty range, resetting range end";
998 highest_frame_ = nullptr;
1002 highest_frame_ = nullptr;
1004 KeyframeMap::const_iterator last_gop = keyframe_map_.end();
1005 CHECK_GT(keyframe_map_.size(), 0u);
1008 // Iterate through the frames of the last GOP in this range, finding the
1009 // frame with the highest PTS.
1010 for (BufferQueue::const_iterator buffer_itr =
1011 buffers_.begin() + (last_gop->second - keyframe_map_index_base_);
1012 buffer_itr != buffers_.end(); ++buffer_itr) {
1013 UpdateEndTime(*buffer_itr);
1016 DVLOG(1) << __func__ << " Updated range end time to "
1017 << highest_frame_->timestamp() << ", "
1018 << highest_frame_->timestamp() + highest_frame_->duration();
1021 std::string SourceBufferRange::ToStringForDebugging() const {
1022 std::stringstream result;
1024 #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
1025 result << "keyframe_map_index_base_=" << keyframe_map_index_base_
1026 << ", buffers.size()=" << buffers_.size()
1027 << ", keyframe_map_.size()=" << keyframe_map_.size()
1028 << ", keyframe_map_:\n";
1029 for (const auto& [time_delta, idx] : keyframe_map_) {
1030 result << "\t pts " << time_delta.InMicroseconds()
1031 << ", unadjusted idx = " << idx << "\n";
1033 #endif // !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
1035 return result.str();
1038 } // namespace media