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 #if !defined(EWK_BRINGUP) // FIXME: m120 bringup (Removed in Open Source)
234 buffers_[next_buffer_index_]->side_data(),
235 buffers_[next_buffer_index_]->side_data_size(),
237 buffers_[next_buffer_index_]->is_key_frame(),
238 buffers_[next_buffer_index_]->type(),
239 buffers_[next_buffer_index_]->track_id());
241 // Setting other necessary data not copied by previous function
242 new_buffer->SetConfigId(buffers_[next_buffer_index_]->GetConfigId());
243 new_buffer->SetDecodeTimestamp(
244 buffers_[next_buffer_index_]->GetDecodeTimestamp());
245 new_buffer->set_is_duration_estimated(
246 buffers_[next_buffer_index_]->is_duration_estimated());
247 new_buffer->set_duration(buffers_[next_buffer_index_]->duration());
248 new_buffer->set_timestamp(buffers_[next_buffer_index_]->timestamp());
250 // Swapping old buffer to new buffer. Old buffer is discarded.
251 buffers_[next_buffer_index_].swap(new_buffer);
255 bool SourceBufferRange::CanSeekTo(base::TimeDelta timestamp) const {
256 DVLOG(1) << __func__;
257 DVLOG(4) << ToStringForDebugging();
259 base::TimeDelta start_timestamp =
260 std::max(base::TimeDelta(), GetStartTimestamp() - GetFudgeRoom());
261 return !keyframe_map_.empty() && start_timestamp <= timestamp &&
262 timestamp < GetBufferedEndTimestamp();
265 int SourceBufferRange::GetConfigIdAtTime(base::TimeDelta timestamp) const {
266 DVLOG(1) << __func__;
267 DVLOG(4) << ToStringForDebugging();
269 DCHECK(CanSeekTo(timestamp));
270 DCHECK(!keyframe_map_.empty());
272 auto result = GetFirstKeyframeAtOrBefore(timestamp);
273 CHECK(result != keyframe_map_.end());
274 size_t buffer_index = result->second - keyframe_map_index_base_;
275 CHECK_LT(buffer_index, buffers_.size())
276 << buffer_index << ", size = " << buffers_.size();
278 return buffers_[buffer_index]->GetConfigId();
281 bool SourceBufferRange::SameConfigThruRange(base::TimeDelta start,
282 base::TimeDelta end) const {
283 DVLOG(1) << __func__;
284 DVLOG(4) << ToStringForDebugging();
286 DCHECK(CanSeekTo(start));
287 DCHECK(CanSeekTo(end));
288 DCHECK(start <= end);
289 DCHECK(!keyframe_map_.empty());
294 auto result = GetFirstKeyframeAtOrBefore(start);
295 CHECK(result != keyframe_map_.end());
296 size_t buffer_index = result->second - keyframe_map_index_base_;
297 CHECK_LT(buffer_index, buffers_.size())
298 << buffer_index << ", size = " << buffers_.size();
300 int start_config = buffers_[buffer_index]->GetConfigId();
302 while (buffer_index < buffers_.size() &&
303 buffers_[buffer_index]->timestamp() <= end) {
304 if (buffers_[buffer_index]->GetConfigId() != start_config)
312 std::unique_ptr<SourceBufferRange> SourceBufferRange::SplitRange(
313 base::TimeDelta timestamp) {
314 DVLOG(1) << __func__;
315 DVLOG(4) << ToStringForDebugging();
317 CHECK(!buffers_.empty());
319 // Find the first keyframe at or after |timestamp|.
320 auto new_beginning_keyframe = GetFirstKeyframeAt(timestamp, false);
322 // If there is no keyframe at or after |timestamp|, we can't split the range.
323 if (new_beginning_keyframe == keyframe_map_.end())
326 // Remove the data beginning at |keyframe_index| from |buffers_| and save it
327 // into |removed_buffers|.
329 new_beginning_keyframe->second - keyframe_map_index_base_;
330 CHECK_LT(keyframe_index, static_cast<int>(buffers_.size()));
331 BufferQueue::iterator starting_point = buffers_.begin() + keyframe_index;
332 BufferQueue removed_buffers(starting_point, buffers_.end());
334 base::TimeDelta new_range_start_pts =
335 std::max(timestamp, GetStartTimestamp());
336 DCHECK(new_range_start_pts <= removed_buffers.front()->timestamp());
338 keyframe_map_.erase(new_beginning_keyframe, keyframe_map_.end());
339 FreeBufferRange(starting_point, buffers_.end());
340 UpdateEndTimeUsingLastGOP();
342 // Create a new range with |removed_buffers|.
343 std::unique_ptr<SourceBufferRange> split_range =
344 std::make_unique<SourceBufferRange>(gap_policy_, removed_buffers,
346 interbuffer_distance_cb_);
348 // If the next buffer position is now in |split_range|, update the state of
349 // this range and |split_range| accordingly.
350 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) {
351 split_range->next_buffer_index_ = next_buffer_index_ - keyframe_index;
353 int split_range_next_buffer_index = split_range->next_buffer_index_;
354 CHECK_GE(split_range_next_buffer_index, 0);
355 // Note that a SourceBufferRange's |next_buffer_index_| can be the index
356 // of a buffer one beyond what is currently in |buffers_|.
357 CHECK_LE(split_range_next_buffer_index,
358 static_cast<int>(split_range->buffers_.size()));
360 ResetNextBufferPosition();
366 bool SourceBufferRange::TruncateAt(base::TimeDelta timestamp,
367 BufferQueue* deleted_buffers,
369 DVLOG(1) << __func__;
370 DVLOG(4) << ToStringForDebugging();
372 // Find the place in |buffers_| where we will begin deleting data, then
373 // truncate from there.
374 return TruncateAt(GetBufferIndexAt(timestamp, is_exclusive), deleted_buffers);
377 size_t SourceBufferRange::DeleteGOPFromFront(BufferQueue* deleted_buffers) {
378 DVLOG(1) << __func__;
379 DVLOG(4) << ToStringForDebugging();
381 DCHECK(!buffers_.empty());
382 DCHECK(!FirstGOPContainsNextBufferPosition());
383 DCHECK(deleted_buffers);
385 int buffers_deleted = 0;
386 size_t total_bytes_deleted = 0;
388 KeyframeMap::const_iterator front = keyframe_map_.begin();
389 DCHECK(front != keyframe_map_.end());
391 // Delete the keyframe at the start of |keyframe_map_|.
392 keyframe_map_.erase(front);
394 // Now we need to delete all the buffers that depend on the keyframe we've
396 int end_index = keyframe_map_.size() > 0
397 ? keyframe_map_.begin()->second - keyframe_map_index_base_
400 // Delete buffers from the beginning of the buffered range up until (but not
401 // including) the next keyframe.
402 for (int i = 0; i < end_index; i++) {
403 size_t bytes_deleted = buffers_.front()->data_size();
404 DCHECK_GE(size_in_bytes_, bytes_deleted);
405 size_in_bytes_ -= bytes_deleted;
406 total_bytes_deleted += bytes_deleted;
407 deleted_buffers->push_back(buffers_.front());
408 buffers_.pop_front();
412 // Update |keyframe_map_index_base_| to account for the deleted buffers.
413 keyframe_map_index_base_ += buffers_deleted;
415 if (next_buffer_index_ > -1) {
416 next_buffer_index_ -= buffers_deleted;
417 CHECK_GE(next_buffer_index_, 0)
418 << next_buffer_index_ << ", deleted " << buffers_deleted;
421 // Invalidate range start time if we've deleted the first buffer of the range.
422 if (buffers_deleted > 0) {
423 range_start_pts_ = kNoTimestamp;
424 // Reset the range end time tracking if there are no more buffers in the
426 if (buffers_.empty())
427 highest_frame_ = nullptr;
430 return total_bytes_deleted;
433 size_t SourceBufferRange::DeleteGOPFromBack(BufferQueue* deleted_buffers) {
434 DVLOG(1) << __func__;
435 DVLOG(4) << ToStringForDebugging();
437 DCHECK(!buffers_.empty());
438 DCHECK(!LastGOPContainsNextBufferPosition());
439 DCHECK(deleted_buffers);
441 // Remove the last GOP's keyframe from the |keyframe_map_|.
442 KeyframeMap::const_iterator back = keyframe_map_.end();
443 DCHECK_GT(keyframe_map_.size(), 0u);
446 // The index of the first buffer in the last GOP is equal to the new size of
447 // |buffers_| after that GOP is deleted.
448 size_t goal_size = back->second - keyframe_map_index_base_;
449 keyframe_map_.erase(back);
451 size_t total_bytes_deleted = 0;
452 while (buffers_.size() != goal_size) {
453 size_t bytes_deleted = buffers_.back()->data_size();
454 DCHECK_GE(size_in_bytes_, bytes_deleted);
455 size_in_bytes_ -= bytes_deleted;
456 total_bytes_deleted += bytes_deleted;
457 // We're removing buffers from the back, so push each removed buffer to the
458 // front of |deleted_buffers| so that |deleted_buffers| are in nondecreasing
460 deleted_buffers->push_front(buffers_.back());
464 UpdateEndTimeUsingLastGOP();
466 return total_bytes_deleted;
469 size_t SourceBufferRange::GetRemovalGOP(
470 base::TimeDelta start_timestamp,
471 base::TimeDelta end_timestamp,
472 size_t total_bytes_to_free,
473 base::TimeDelta* removal_end_timestamp) const {
474 DVLOG(1) << __func__;
475 DVLOG(4) << ToStringForDebugging();
477 size_t bytes_removed = 0;
479 auto gop_itr = GetFirstKeyframeAt(start_timestamp, false);
480 if (gop_itr == keyframe_map_.end())
482 int keyframe_index = gop_itr->second - keyframe_map_index_base_;
483 BufferQueue::const_iterator buffer_itr = buffers_.begin() + keyframe_index;
484 auto gop_end = keyframe_map_.end();
485 if (end_timestamp < GetBufferedEndTimestamp())
486 gop_end = GetFirstKeyframeAtOrBefore(end_timestamp);
488 // Check if the removal range is within a GOP and skip the loop if so.
489 // [keyframe]...[start_timestamp]...[end_timestamp]...[keyframe]
490 auto gop_itr_prev = gop_itr;
491 if (gop_itr_prev != keyframe_map_.begin() && --gop_itr_prev == gop_end)
494 while (gop_itr != gop_end && bytes_removed < total_bytes_to_free) {
498 int next_gop_index = gop_itr == keyframe_map_.end()
500 : gop_itr->second - keyframe_map_index_base_;
501 BufferQueue::const_iterator next_gop_start =
502 buffers_.begin() + next_gop_index;
503 for (; buffer_itr != next_gop_start; ++buffer_itr) {
504 gop_size += (*buffer_itr)->data_size();
507 bytes_removed += gop_size;
509 if (bytes_removed > 0) {
510 *removal_end_timestamp = gop_itr == keyframe_map_.end()
511 ? GetBufferedEndTimestamp()
514 return bytes_removed;
517 bool SourceBufferRange::FirstGOPEarlierThanMediaTime(
518 base::TimeDelta media_time) const {
519 DVLOG(1) << __func__;
520 DVLOG(4) << ToStringForDebugging();
522 if (keyframe_map_.size() == 1u)
523 return (GetBufferedEndTimestamp() <= media_time);
525 auto second_gop = keyframe_map_.begin();
527 return second_gop->first <= media_time;
530 bool SourceBufferRange::FirstGOPContainsNextBufferPosition() const {
531 DVLOG(1) << __func__;
532 DVLOG(4) << ToStringForDebugging();
534 if (!HasNextBufferPosition())
537 // If there is only one GOP, it must contain the next buffer position.
538 if (keyframe_map_.size() == 1u)
541 auto second_gop = keyframe_map_.begin();
543 return next_buffer_index_ < second_gop->second - keyframe_map_index_base_;
546 bool SourceBufferRange::LastGOPContainsNextBufferPosition() const {
547 DVLOG(1) << __func__;
548 DVLOG(4) << ToStringForDebugging();
550 if (!HasNextBufferPosition())
553 // If there is only one GOP, it must contain the next buffer position.
554 if (keyframe_map_.size() == 1u)
557 auto last_gop = keyframe_map_.end();
559 return last_gop->second - keyframe_map_index_base_ <= next_buffer_index_;
562 base::TimeDelta SourceBufferRange::GetNextTimestamp() const {
563 DVLOG(1) << __func__;
564 DVLOG(4) << ToStringForDebugging();
566 CHECK(!buffers_.empty()) << next_buffer_index_;
567 CHECK(HasNextBufferPosition())
568 << next_buffer_index_ << ", size=" << buffers_.size();
570 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) {
574 return buffers_[next_buffer_index_]->timestamp();
577 base::TimeDelta SourceBufferRange::GetStartTimestamp() const {
578 DVLOG(1) << __func__;
579 DVLOG(4) << ToStringForDebugging();
581 DCHECK(!buffers_.empty());
582 base::TimeDelta start_timestamp = range_start_pts_;
583 if (start_timestamp == kNoTimestamp)
584 start_timestamp = buffers_.front()->timestamp();
585 return start_timestamp;
588 base::TimeDelta SourceBufferRange::GetEndTimestamp() const {
589 DVLOG(1) << __func__;
590 DVLOG(4) << ToStringForDebugging();
592 DCHECK(!buffers_.empty());
593 return highest_frame_->timestamp();
596 base::TimeDelta SourceBufferRange::GetBufferedEndTimestamp() const {
597 DVLOG(1) << __func__;
598 DVLOG(4) << ToStringForDebugging();
600 DCHECK(!buffers_.empty());
601 base::TimeDelta duration = highest_frame_->duration();
603 // FrameProcessor should protect against unknown buffer durations.
604 DCHECK_NE(duration, kNoTimestamp);
606 // Because media::Ranges<base::TimeDelta>::Add() ignores 0 duration ranges,
607 // report 1 microsecond for the last buffer's duration if it is a 0 duration
609 if (duration.is_zero())
610 duration = base::Microseconds(1);
612 return GetEndTimestamp() + duration;
615 bool SourceBufferRange::BelongsToRange(base::TimeDelta timestamp) const {
616 DVLOG(1) << __func__;
617 DVLOG(4) << ToStringForDebugging();
619 DCHECK(!buffers_.empty());
621 return (IsNextInPresentationSequence(timestamp) ||
622 (GetStartTimestamp() <= timestamp && timestamp <= GetEndTimestamp()));
625 base::TimeDelta SourceBufferRange::FindHighestBufferedTimestampAtOrBefore(
626 base::TimeDelta timestamp) const {
627 DVLOG(1) << __func__;
628 DVLOG(4) << ToStringForDebugging();
630 DCHECK(!buffers_.empty());
631 DCHECK(BelongsToRange(timestamp));
633 if (keyframe_map_.begin()->first > timestamp) {
634 // If the first keyframe in the range starts after |timestamp|, then
635 // return the range start time (which could be earlier due to coded frame
636 // group signalling.)
637 base::TimeDelta range_start = GetStartTimestamp();
638 DCHECK(timestamp >= range_start) << "BelongsToRange() semantics failed.";
642 if (keyframe_map_.begin()->first == timestamp) {
646 auto key_iter = GetFirstKeyframeAtOrBefore(timestamp);
647 DCHECK(key_iter != keyframe_map_.end())
648 << "BelongsToRange() semantics failed.";
649 DCHECK(key_iter->first <= timestamp);
651 // Scan forward in |buffers_| to find the highest frame with timestamp <=
652 // |timestamp|. Stop once a frame with timestamp > |timestamp| is encountered.
653 size_t key_index = key_iter->second - keyframe_map_index_base_;
654 SourceBufferRange::BufferQueue::const_iterator search_iter =
655 buffers_.begin() + key_index;
656 CHECK(search_iter != buffers_.end());
657 base::TimeDelta cur_frame_time = (*search_iter)->timestamp();
658 base::TimeDelta result = cur_frame_time;
660 result = std::max(result, cur_frame_time);
662 if (search_iter == buffers_.end())
664 cur_frame_time = (*search_iter)->timestamp();
665 if (cur_frame_time > timestamp)
669 NOTREACHED_NORETURN();
672 base::TimeDelta SourceBufferRange::NextKeyframeTimestamp(
673 base::TimeDelta timestamp) const {
674 DVLOG(1) << __func__;
675 DVLOG(4) << ToStringForDebugging();
677 DCHECK(!keyframe_map_.empty());
679 if (timestamp < GetStartTimestamp() || timestamp >= GetBufferedEndTimestamp())
682 auto itr = GetFirstKeyframeAt(timestamp, false);
683 if (itr == keyframe_map_.end())
686 // If the timestamp is inside the gap between the start of the coded frame
687 // group and the first buffer, then just pretend there is a keyframe at the
688 // specified timestamp.
689 if (itr == keyframe_map_.begin() && timestamp > range_start_pts_ &&
690 timestamp < itr->first) {
697 base::TimeDelta SourceBufferRange::KeyframeBeforeTimestamp(
698 base::TimeDelta timestamp) const {
699 DVLOG(1) << __func__;
700 DVLOG(4) << ToStringForDebugging();
702 DCHECK(!keyframe_map_.empty());
704 if (timestamp < GetStartTimestamp() || timestamp >= GetBufferedEndTimestamp())
707 return GetFirstKeyframeAtOrBefore(timestamp)->first;
710 bool SourceBufferRange::GetBuffersInRange(base::TimeDelta start,
712 BufferQueue* buffers) const {
713 DVLOG(1) << __func__;
714 DVLOG(4) << ToStringForDebugging();
716 // Find the nearest buffer with a timestamp <= start.
717 const base::TimeDelta first_timestamp = KeyframeBeforeTimestamp(start);
718 if (first_timestamp == kNoTimestamp)
721 // Find all buffers involved in the range.
722 const size_t previous_size = buffers->size();
723 for (BufferQueue::const_iterator it = GetBufferItrAt(first_timestamp, false);
724 it != buffers_.end(); ++it) {
725 scoped_refptr<StreamParserBuffer> buffer = *it;
726 // Buffers without duration are not supported, so bail if we encounter any.
727 if (buffer->duration() == kNoTimestamp ||
728 buffer->duration() <= base::TimeDelta()) {
731 if (buffer->timestamp() >= end)
734 if (buffer->timestamp() + buffer->duration() <= start)
737 buffers->emplace_back(std::move(buffer));
739 return previous_size < buffers->size();
742 void SourceBufferRange::AdjustEstimatedDurationForNewAppend(
743 const BufferQueue& new_buffers) {
744 if (buffers_.empty() || new_buffers.empty()) {
748 // Do not adjust estimate for Audio buffers to avoid competing with
749 // SourceBufferStream::TrimSpliceOverlap()
750 if (buffers_.front()->type() == StreamParserBuffer::Type::AUDIO) {
754 // If the last of the previously appended buffers contains estimated duration,
755 // we now refine that estimate by taking the PTS delta from the first new
756 // buffer being appended.
757 const auto& last_appended_buffer = buffers_.back();
758 if (last_appended_buffer->is_duration_estimated()) {
759 base::TimeDelta timestamp_delta =
760 new_buffers.front()->timestamp() - last_appended_buffer->timestamp();
761 DCHECK_GE(timestamp_delta, base::TimeDelta());
762 if (last_appended_buffer->duration() != timestamp_delta) {
763 DVLOG(1) << "Replacing estimated duration ("
764 << last_appended_buffer->duration()
765 << ") from previous range-end with derived duration ("
766 << timestamp_delta << ").";
767 last_appended_buffer->set_duration(timestamp_delta);
772 void SourceBufferRange::FreeBufferRange(
773 const BufferQueue::const_iterator& starting_point,
774 const BufferQueue::const_iterator& ending_point) {
775 for (BufferQueue::const_iterator itr = starting_point; itr != ending_point;
777 size_t itr_data_size = static_cast<size_t>((*itr)->data_size());
778 DCHECK_GE(size_in_bytes_, itr_data_size);
779 size_in_bytes_ -= itr_data_size;
781 buffers_.erase(starting_point, ending_point);
784 base::TimeDelta SourceBufferRange::GetFudgeRoom() const {
785 // Because we do not know exactly when is the next timestamp, any buffer
786 // that starts within 2x the approximate duration of a buffer is considered
787 // within this range.
788 return 2 * GetApproximateDuration();
791 base::TimeDelta SourceBufferRange::GetApproximateDuration() const {
792 base::TimeDelta max_interbuffer_distance = interbuffer_distance_cb_.Run();
793 DCHECK(max_interbuffer_distance != kNoTimestamp);
794 return max_interbuffer_distance;
797 void SourceBufferRange::UpdateEndTime(
798 scoped_refptr<StreamParserBuffer> new_buffer) {
799 base::TimeDelta timestamp = new_buffer->timestamp();
800 base::TimeDelta duration = new_buffer->duration();
801 DVLOG(1) << __func__ << " timestamp=" << timestamp
802 << ", duration=" << duration;
803 DCHECK_NE(timestamp, kNoTimestamp);
804 DCHECK_GE(timestamp, base::TimeDelta());
805 DCHECK_GE(duration, base::TimeDelta());
807 if (!highest_frame_) {
808 DVLOG(1) << "Updating range end time from <empty> to "
809 << timestamp.InMicroseconds() << "us, "
810 << (timestamp + duration).InMicroseconds() << "us";
811 highest_frame_ = std::move(new_buffer);
815 if (highest_frame_->timestamp() < timestamp ||
816 (highest_frame_->timestamp() == timestamp &&
817 highest_frame_->duration() <= duration)) {
818 DVLOG(1) << "Updating range end time from "
819 << highest_frame_->timestamp().InMicroseconds() << "us, "
820 << (highest_frame_->timestamp() + highest_frame_->duration())
822 << "us to " << timestamp.InMicroseconds() << "us, "
823 << (timestamp + duration).InMicroseconds();
824 highest_frame_ = std::move(new_buffer);
828 bool SourceBufferRange::IsNextInPresentationSequence(
829 base::TimeDelta timestamp) const {
830 DCHECK_NE(timestamp, kNoTimestamp);
831 CHECK(!buffers_.empty());
832 base::TimeDelta highest_timestamp = highest_frame_->timestamp();
833 DCHECK_NE(highest_timestamp, kNoTimestamp);
834 return (highest_timestamp == timestamp ||
835 (highest_timestamp < timestamp &&
836 (gap_policy_ == ALLOW_GAPS ||
837 timestamp <= highest_timestamp + GetFudgeRoom())));
840 bool SourceBufferRange::IsNextInDecodeSequence(
841 DecodeTimestamp decode_timestamp) const {
842 CHECK(!buffers_.empty());
843 DecodeTimestamp end = buffers_.back()->GetDecodeTimestamp();
845 end == decode_timestamp ||
846 (end < decode_timestamp && (gap_policy_ == ALLOW_GAPS ||
847 decode_timestamp <= end + GetFudgeRoom())));
850 base::TimeDelta SourceBufferRange::NextRangeStartTimeForAppendRangeToEnd(
851 const SourceBufferRange& range) const {
852 DCHECK(!buffers_.empty());
853 DCHECK(!range.buffers_.empty());
855 base::TimeDelta next_range_first_buffer_time =
856 range.buffers_.front()->timestamp();
857 base::TimeDelta this_range_end_time = GetEndTimestamp();
858 if (next_range_first_buffer_time < this_range_end_time)
861 base::TimeDelta next_range_start_time = range.GetStartTimestamp();
862 DCHECK(next_range_start_time <= next_range_first_buffer_time);
864 if (next_range_start_time >= this_range_end_time)
865 return next_range_start_time;
867 return this_range_end_time;
870 size_t SourceBufferRange::GetBufferIndexAt(base::TimeDelta timestamp,
871 bool skip_given_timestamp) const {
872 DVLOG(1) << __func__;
873 DVLOG(4) << ToStringForDebugging();
875 // Find the GOP containing |timestamp| (or trivial buffers_.size() if none
876 // contain |timestamp|).
877 auto gop_iter = GetFirstKeyframeAtOrBefore(timestamp);
878 if (gop_iter == keyframe_map_.end())
879 return buffers_.size();
881 // Then scan forward in this GOP in decode sequence for the first frame with
882 // PTS >= |timestamp| (or strictly > if |skip_given_timestamp| is true). If
883 // this GOP doesn't contain such a frame, returns the index of the keyframe of
884 // the next GOP (which could be the index of end() of |buffers_| if this was
885 // the last GOP in |buffers_|). We do linear scan of the GOP here because we
886 // don't know the DTS for the searched-for frame, and the PTS sequence within
887 // a GOP may not match the DTS-sorted sequence of frames within the GOP.
888 DCHECK_GT(buffers_.size(), 0u);
889 size_t search_index = gop_iter->second - keyframe_map_index_base_;
890 SourceBufferRange::BufferQueue::const_iterator search_iter =
891 buffers_.begin() + search_index;
894 SourceBufferRange::BufferQueue::const_iterator next_gop_start =
895 gop_iter == keyframe_map_.end()
897 : buffers_.begin() + (gop_iter->second - keyframe_map_index_base_);
899 while (search_iter != next_gop_start) {
900 if (((*search_iter)->timestamp() > timestamp) ||
901 (!skip_given_timestamp && (*search_iter)->timestamp() == timestamp)) {
911 SourceBufferRange::BufferQueue::const_iterator
912 SourceBufferRange::GetBufferItrAt(base::TimeDelta timestamp,
913 bool skip_given_timestamp) const {
914 DVLOG(1) << __func__;
915 DVLOG(4) << ToStringForDebugging();
917 return buffers_.begin() + GetBufferIndexAt(timestamp, skip_given_timestamp);
920 SourceBufferRange::KeyframeMap::const_iterator
921 SourceBufferRange::GetFirstKeyframeAt(base::TimeDelta timestamp,
922 bool skip_given_timestamp) const {
923 DVLOG(1) << __func__;
924 DVLOG(4) << ToStringForDebugging();
926 return skip_given_timestamp ? keyframe_map_.upper_bound(timestamp)
927 : keyframe_map_.lower_bound(timestamp);
930 SourceBufferRange::KeyframeMap::const_iterator
931 SourceBufferRange::GetFirstKeyframeAtOrBefore(base::TimeDelta timestamp) const {
932 DVLOG(1) << __func__;
933 DVLOG(4) << ToStringForDebugging();
935 auto result = keyframe_map_.lower_bound(timestamp);
936 // lower_bound() returns the first element >= |timestamp|, so we want the
937 // previous element if it did not return the element exactly equal to
939 if (result != keyframe_map_.begin() &&
940 (result == keyframe_map_.end() || result->first != timestamp)) {
946 bool SourceBufferRange::TruncateAt(const size_t starting_point,
947 BufferQueue* deleted_buffers) {
948 DVLOG(1) << __func__;
949 DVLOG(4) << ToStringForDebugging();
951 CHECK_LE(starting_point, buffers_.size());
952 DCHECK(!deleted_buffers || deleted_buffers->empty());
954 // Return if we're not deleting anything.
955 if (starting_point == buffers_.size())
956 return buffers_.empty();
958 // Reset the next buffer index if we will be deleting the buffer that's next
960 if (HasNextBufferPosition()) {
961 if (static_cast<size_t>(next_buffer_index_) >= starting_point) {
962 if (HasNextBuffer() && deleted_buffers) {
963 BufferQueue saved(buffers_.begin() + next_buffer_index_,
965 deleted_buffers->swap(saved);
967 ResetNextBufferPosition();
971 const BufferQueue::const_iterator starting_point_iter =
972 buffers_.begin() + starting_point;
974 // Remove keyframes from |starting_point| onward.
975 KeyframeMap::const_iterator starting_point_keyframe =
976 keyframe_map_.lower_bound((*starting_point_iter)->timestamp());
977 keyframe_map_.erase(starting_point_keyframe, keyframe_map_.end());
979 // Remove everything from |starting_point| onward.
980 FreeBufferRange(starting_point_iter, buffers_.end());
982 UpdateEndTimeUsingLastGOP();
983 return buffers_.empty();
986 void SourceBufferRange::UpdateEndTimeUsingLastGOP() {
987 DVLOG(1) << __func__;
988 DVLOG(4) << ToStringForDebugging();
990 if (buffers_.empty()) {
991 DVLOG(1) << __func__ << " Empty range, resetting range end";
992 highest_frame_ = nullptr;
996 highest_frame_ = nullptr;
998 KeyframeMap::const_iterator last_gop = keyframe_map_.end();
999 CHECK_GT(keyframe_map_.size(), 0u);
1002 // Iterate through the frames of the last GOP in this range, finding the
1003 // frame with the highest PTS.
1004 for (BufferQueue::const_iterator buffer_itr =
1005 buffers_.begin() + (last_gop->second - keyframe_map_index_base_);
1006 buffer_itr != buffers_.end(); ++buffer_itr) {
1007 UpdateEndTime(*buffer_itr);
1010 DVLOG(1) << __func__ << " Updated range end time to "
1011 << highest_frame_->timestamp() << ", "
1012 << highest_frame_->timestamp() + highest_frame_->duration();
1015 std::string SourceBufferRange::ToStringForDebugging() const {
1016 std::stringstream result;
1018 #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
1019 result << "keyframe_map_index_base_=" << keyframe_map_index_base_
1020 << ", buffers.size()=" << buffers_.size()
1021 << ", keyframe_map_.size()=" << keyframe_map_.size()
1022 << ", keyframe_map_:\n";
1023 for (const auto& [time_delta, idx] : keyframe_map_) {
1024 result << "\t pts " << time_delta.InMicroseconds()
1025 << ", unadjusted idx = " << idx << "\n";
1027 #endif // !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
1029 return result.str();
1032 } // namespace media