1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/filters/source_buffer_stream.h"
10 #include "base/bind.h"
11 #include "base/debug/trace_event.h"
12 #include "base/logging.h"
16 // Buffers with the same timestamp are only allowed under certain conditions.
17 // Video: Allowed when the previous frame and current frame are NOT keyframes.
18 // This is the situation for VP8 Alt-Ref frames.
19 // Otherwise: Allowed in all situations except where a non-keyframe is followed
21 // Returns true if |prev_is_keyframe| and |current_is_keyframe| indicate a
22 // same timestamp situation that is allowed. False is returned otherwise.
23 static bool AllowSameTimestamp(
24 bool prev_is_keyframe, bool current_is_keyframe, bool is_video) {
26 return !prev_is_keyframe && !current_is_keyframe;
28 return prev_is_keyframe || !current_is_keyframe;
31 // Helper class representing a range of buffered data. All buffers in a
32 // SourceBufferRange are ordered sequentially in presentation order with no
34 class SourceBufferRange {
36 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue;
38 // Returns the maximum distance in time between any buffer seen in this
39 // stream. Used to estimate the duration of a buffer if its duration is not
41 typedef base::Callback<base::TimeDelta()> InterbufferDistanceCB;
43 // Creates a source buffer range with |new_buffers|. |new_buffers| cannot be
44 // empty and the front of |new_buffers| must be a keyframe.
45 // |media_segment_start_time| refers to the starting timestamp for the media
46 // segment to which these buffers belong.
47 SourceBufferRange(bool is_video,
48 const BufferQueue& new_buffers,
49 base::TimeDelta media_segment_start_time,
50 const InterbufferDistanceCB& interbuffer_distance_cb);
52 // Appends |buffers| to the end of the range and updates |keyframe_map_| as
53 // it encounters new keyframes. Assumes |buffers| belongs at the end of the
55 void AppendBuffersToEnd(const BufferQueue& buffers);
56 bool CanAppendBuffersToEnd(const BufferQueue& buffers) const;
58 // Appends the buffers from |range| into this range.
59 // The first buffer in |range| must come directly after the last buffer
61 // If |transfer_current_position| is true, |range|'s |next_buffer_index_|
62 // is transfered to this SourceBufferRange.
63 void AppendRangeToEnd(const SourceBufferRange& range,
64 bool transfer_current_position);
65 bool CanAppendRangeToEnd(const SourceBufferRange& range) const;
67 // Updates |next_buffer_index_| to point to the Buffer containing |timestamp|.
68 // Assumes |timestamp| is valid and in this range.
69 void Seek(base::TimeDelta timestamp);
71 // Updates |next_buffer_index_| to point to next keyframe after or equal to
73 void SeekAheadTo(base::TimeDelta timestamp);
75 // Updates |next_buffer_index_| to point to next keyframe strictly after
77 void SeekAheadPast(base::TimeDelta timestamp);
79 // Seeks to the beginning of the range.
82 // Finds the next keyframe from |buffers_| after |timestamp| (or at
83 // |timestamp| if |is_exclusive| is false) and creates and returns a new
84 // SourceBufferRange with the buffers from that keyframe onward.
85 // The buffers in the new SourceBufferRange are moved out of this range. If
86 // there is no keyframe after |timestamp|, SplitRange() returns null and this
87 // range is unmodified.
88 SourceBufferRange* SplitRange(base::TimeDelta timestamp, bool is_exclusive);
90 // Deletes the buffers from this range starting at |timestamp|, exclusive if
91 // |is_exclusive| is true, inclusive otherwise.
92 // Resets |next_buffer_index_| if the buffer at |next_buffer_index_| was
93 // deleted, and deletes the |keyframe_map_| entries for the buffers that
95 // |deleted_buffers| contains the buffers that were deleted from this range,
96 // starting at the buffer that had been at |next_buffer_index_|.
97 void TruncateAt(base::TimeDelta timestamp,
98 BufferQueue* deleted_buffers, bool is_exclusive);
99 // Deletes all buffers in range.
100 void DeleteAll(BufferQueue* deleted_buffers);
102 // Deletes a GOP from the front or back of the range and moves these
103 // buffers into |deleted_buffers|. Returns the number of bytes deleted from
104 // the range (i.e. the size in bytes of |deleted_buffers|).
105 int DeleteGOPFromFront(BufferQueue* deleted_buffers);
106 int DeleteGOPFromBack(BufferQueue* deleted_buffers);
108 // Gets the range of GOP to secure at least |bytes_to_free| from
109 // [|start_timestamp|, |end_timestamp|).
110 // Returns the size of the buffers to secure if the buffers of
111 // [|start_timestamp|, |end_removal_timestamp|) is removed.
112 // Will not update |end_removal_timestamp| if the returned size is 0.
114 base::TimeDelta start_timestamp, base::TimeDelta end_timestamp,
115 int bytes_to_free, base::TimeDelta* end_removal_timestamp);
117 // Indicates whether the GOP at the beginning or end of the range contains the
118 // next buffer position.
119 bool FirstGOPContainsNextBufferPosition() const;
120 bool LastGOPContainsNextBufferPosition() const;
122 // Updates |out_buffer| with the next buffer in presentation order. Seek()
123 // must be called before calls to GetNextBuffer(), and buffers are returned
124 // in order from the last call to Seek(). Returns true if |out_buffer| is
125 // filled with a valid buffer, false if there is not enough data to fulfill
127 bool GetNextBuffer(scoped_refptr<StreamParserBuffer>* out_buffer);
128 bool HasNextBuffer() const;
130 // Returns the config ID for the buffer that will be returned by
132 int GetNextConfigId() const;
134 // Returns true if the range knows the position of the next buffer it should
135 // return, i.e. it has been Seek()ed. This does not necessarily mean that it
136 // has the next buffer yet.
137 bool HasNextBufferPosition() const;
139 // Resets this range to an "unseeked" state.
140 void ResetNextBufferPosition();
142 // Returns the timestamp of the next buffer that will be returned from
143 // GetNextBuffer(), or kNoTimestamp() if the timestamp is unknown.
144 base::TimeDelta GetNextTimestamp() const;
146 // Returns the start timestamp of the range.
147 base::TimeDelta GetStartTimestamp() const;
149 // Returns the timestamp of the last buffer in the range.
150 base::TimeDelta GetEndTimestamp() const;
152 // Returns the timestamp for the end of the buffered region in this range.
153 // This is an approximation if the duration for the last buffer in the range
155 base::TimeDelta GetBufferedEndTimestamp() const;
157 // Gets the timestamp for the keyframe that is after |timestamp|. If
158 // there isn't a keyframe in the range after |timestamp| then kNoTimestamp()
160 base::TimeDelta NextKeyframeTimestamp(base::TimeDelta timestamp);
162 // Gets the timestamp for the closest keyframe that is <= |timestamp|. If
163 // there isn't a keyframe before |timestamp| or |timestamp| is outside
164 // this range, then kNoTimestamp() is returned.
165 base::TimeDelta KeyframeBeforeTimestamp(base::TimeDelta timestamp);
167 // Returns whether a buffer with a starting timestamp of |timestamp| would
168 // belong in this range. This includes a buffer that would be appended to
169 // the end of the range.
170 bool BelongsToRange(base::TimeDelta timestamp) const;
172 // Returns true if the range has enough data to seek to the specified
173 // |timestamp|, false otherwise.
174 bool CanSeekTo(base::TimeDelta timestamp) const;
176 // Returns true if this range's buffered timespan completely overlaps the
177 // buffered timespan of |range|.
178 bool CompletelyOverlaps(const SourceBufferRange& range) const;
180 // Returns true if the end of this range contains buffers that overlaps with
181 // the beginning of |range|.
182 bool EndOverlaps(const SourceBufferRange& range) const;
184 // Returns true if |timestamp| is the timestamp of the next buffer in
185 // sequence after |buffers_.back()|, false otherwise.
186 bool IsNextInSequence(base::TimeDelta timestamp, bool is_keyframe) const;
188 int size_in_bytes() const { return size_in_bytes_; }
191 typedef std::map<base::TimeDelta, int> KeyframeMap;
193 // Seeks the range to the next keyframe after |timestamp|. If
194 // |skip_given_timestamp| is true, the seek will go to a keyframe with a
195 // timestamp strictly greater than |timestamp|.
196 void SeekAhead(base::TimeDelta timestamp, bool skip_given_timestamp);
198 // Returns an iterator in |buffers_| pointing to the buffer at |timestamp|.
199 // If |skip_given_timestamp| is true, this returns the first buffer with
200 // timestamp greater than |timestamp|.
201 BufferQueue::iterator GetBufferItrAt(
202 base::TimeDelta timestamp, bool skip_given_timestamp);
204 // Returns an iterator in |keyframe_map_| pointing to the next keyframe after
205 // |timestamp|. If |skip_given_timestamp| is true, this returns the first
206 // keyframe with a timestamp strictly greater than |timestamp|.
207 KeyframeMap::iterator GetFirstKeyframeAt(
208 base::TimeDelta timestamp, bool skip_given_timestamp);
210 // Returns an iterator in |keyframe_map_| pointing to the first keyframe
211 // before or at |timestamp|.
212 KeyframeMap::iterator GetFirstKeyframeBefore(base::TimeDelta timestamp);
214 // Helper method to delete buffers in |buffers_| starting at
215 // |starting_point|, an iterator in |buffers_|.
216 void TruncateAt(const BufferQueue::iterator& starting_point,
217 BufferQueue* deleted_buffers);
219 // Frees the buffers in |buffers_| from [|start_point|,|ending_point|) and
220 // updates the |size_in_bytes_| accordingly. Does not update |keyframe_map_|.
221 void FreeBufferRange(const BufferQueue::iterator& starting_point,
222 const BufferQueue::iterator& ending_point);
224 // Returns the distance in time estimating how far from the beginning or end
225 // of this range a buffer can be to considered in the range.
226 base::TimeDelta GetFudgeRoom() const;
228 // Returns the approximate duration of a buffer in this range.
229 base::TimeDelta GetApproximateDuration() const;
231 // True if this object stores video data.
234 // An ordered list of buffers in this range.
235 BufferQueue buffers_;
237 // Maps keyframe timestamps to its index position in |buffers_|.
238 KeyframeMap keyframe_map_;
240 // Index base of all positions in |keyframe_map_|. In other words, the
241 // real position of entry |k| of |keyframe_map_| in the range is:
242 // keyframe_map_[k] - keyframe_map_index_base_
243 int keyframe_map_index_base_;
245 // Index into |buffers_| for the next buffer to be returned by
246 // GetNextBuffer(), set to -1 before Seek().
247 int next_buffer_index_;
249 // If the first buffer in this range is the beginning of a media segment,
250 // |media_segment_start_time_| is the time when the media segment begins.
251 // |media_segment_start_time_| may be <= the timestamp of the first buffer in
252 // |buffers_|. |media_segment_start_time_| is kNoTimestamp() if this range
253 // does not start at the beginning of a media segment, which can only happen
254 // garbage collection or after an end overlap that results in a split range
255 // (we don't have a way of knowing the media segment timestamp for the new
257 base::TimeDelta media_segment_start_time_;
259 // Called to get the largest interbuffer distance seen so far in the stream.
260 InterbufferDistanceCB interbuffer_distance_cb_;
262 // Stores the amount of memory taken up by the data in |buffers_|.
265 DISALLOW_COPY_AND_ASSIGN(SourceBufferRange);
270 // Helper method that returns true if |ranges| is sorted in increasing order,
272 static bool IsRangeListSorted(
273 const std::list<media::SourceBufferRange*>& ranges) {
274 base::TimeDelta prev = media::kNoTimestamp();
275 for (std::list<media::SourceBufferRange*>::const_iterator itr =
276 ranges.begin(); itr != ranges.end(); ++itr) {
277 if (prev != media::kNoTimestamp() && prev >= (*itr)->GetStartTimestamp())
279 prev = (*itr)->GetEndTimestamp();
284 // Comparison function for two Buffers based on timestamp.
285 static bool BufferComparator(
286 const scoped_refptr<media::StreamParserBuffer>& first,
287 const scoped_refptr<media::StreamParserBuffer>& second) {
288 return first->GetDecodeTimestamp() < second->GetDecodeTimestamp();
291 // Returns an estimate of how far from the beginning or end of a range a buffer
292 // can be to still be considered in the range, given the |approximate_duration|
293 // of a buffer in the stream.
294 static base::TimeDelta ComputeFudgeRoom(base::TimeDelta approximate_duration) {
295 // Because we do not know exactly when is the next timestamp, any buffer
296 // that starts within 2x the approximate duration of a buffer is considered
297 // within this range.
298 return 2 * approximate_duration;
301 // An arbitrarily-chosen number to estimate the duration of a buffer if none
302 // is set and there's not enough information to get a better estimate.
303 static int kDefaultBufferDurationInMs = 125;
305 // The amount of time the beginning of the buffered data can differ from the
306 // start time in order to still be considered the start of stream.
307 static base::TimeDelta kSeekToStartFudgeRoom() {
308 return base::TimeDelta::FromMilliseconds(1000);
310 // The maximum amount of data in bytes the stream will keep in memory.
311 #if defined(GOOGLE_TV)
312 // In Google TV, set the size of the buffer to 1 min because of
313 // the limited memory of the embedded system.
314 // 2MB: approximately 1 minutes of 256Kbps content.
315 // 30MB: approximately 1 minutes of 4Mbps content.
316 static int kDefaultAudioMemoryLimit = 2 * 1024 * 1024;
317 static int kDefaultVideoMemoryLimit = 30 * 1024 * 1024;
319 // 12MB: approximately 5 minutes of 320Kbps content.
320 // 150MB: approximately 5 minutes of 4Mbps content.
321 static int kDefaultAudioMemoryLimit = 12 * 1024 * 1024;
322 static int kDefaultVideoMemoryLimit = 150 * 1024 * 1024;
327 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config,
330 current_config_index_(0),
331 append_config_index_(0),
332 seek_pending_(false),
333 end_of_stream_(false),
334 seek_buffer_timestamp_(kNoTimestamp()),
335 selected_range_(NULL),
336 media_segment_start_time_(kNoTimestamp()),
337 range_for_next_append_(ranges_.end()),
338 new_media_segment_(false),
339 last_appended_buffer_timestamp_(kNoTimestamp()),
340 last_appended_buffer_is_keyframe_(false),
341 last_output_buffer_timestamp_(kNoTimestamp()),
342 max_interbuffer_distance_(kNoTimestamp()),
343 memory_limit_(kDefaultAudioMemoryLimit),
344 config_change_pending_(false) {
345 DCHECK(audio_config.IsValidConfig());
346 audio_configs_.push_back(audio_config);
349 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config,
352 current_config_index_(0),
353 append_config_index_(0),
354 seek_pending_(false),
355 end_of_stream_(false),
356 seek_buffer_timestamp_(kNoTimestamp()),
357 selected_range_(NULL),
358 media_segment_start_time_(kNoTimestamp()),
359 range_for_next_append_(ranges_.end()),
360 new_media_segment_(false),
361 last_appended_buffer_timestamp_(kNoTimestamp()),
362 last_appended_buffer_is_keyframe_(false),
363 last_output_buffer_timestamp_(kNoTimestamp()),
364 max_interbuffer_distance_(kNoTimestamp()),
365 memory_limit_(kDefaultVideoMemoryLimit),
366 config_change_pending_(false) {
367 DCHECK(video_config.IsValidConfig());
368 video_configs_.push_back(video_config);
371 SourceBufferStream::~SourceBufferStream() {
372 while (!ranges_.empty()) {
373 delete ranges_.front();
378 void SourceBufferStream::OnNewMediaSegment(
379 base::TimeDelta media_segment_start_time) {
380 DCHECK(!end_of_stream_);
381 media_segment_start_time_ = media_segment_start_time;
382 new_media_segment_ = true;
384 RangeList::iterator last_range = range_for_next_append_;
385 range_for_next_append_ = FindExistingRangeFor(media_segment_start_time);
387 // Only reset |last_appended_buffer_timestamp_| if this new media segment is
388 // not adjacent to the previous media segment appended to the stream.
389 if (range_for_next_append_ == ranges_.end() ||
390 !AreAdjacentInSequence(last_appended_buffer_timestamp_,
391 media_segment_start_time)) {
392 last_appended_buffer_timestamp_ = kNoTimestamp();
393 last_appended_buffer_is_keyframe_ = false;
394 } else if (last_range != ranges_.end()) {
395 DCHECK(last_range == range_for_next_append_);
399 bool SourceBufferStream::Append(
400 const SourceBufferStream::BufferQueue& buffers) {
401 TRACE_EVENT2("mse", "SourceBufferStream::Append",
402 "stream type", GetStreamTypeName(),
403 "buffers to append", buffers.size());
405 DCHECK(!buffers.empty());
406 DCHECK(media_segment_start_time_ != kNoTimestamp());
407 DCHECK(!end_of_stream_);
409 // New media segments must begin with a keyframe.
410 if (new_media_segment_ && !buffers.front()->IsKeyframe()) {
411 MEDIA_LOG(log_cb_) << "Media segment did not begin with keyframe.";
415 // Buffers within a media segment should be monotonically increasing.
416 if (!IsMonotonicallyIncreasing(buffers))
419 if (media_segment_start_time_ < base::TimeDelta() ||
420 buffers.front()->GetDecodeTimestamp() < base::TimeDelta()) {
422 << "Cannot append a media segment with negative timestamps.";
426 if (!IsNextTimestampValid(buffers.front()->GetDecodeTimestamp(),
427 buffers.front()->IsKeyframe())) {
428 MEDIA_LOG(log_cb_) << "Invalid same timestamp construct detected at time "
429 << buffers.front()->GetDecodeTimestamp().InSecondsF();
434 UpdateMaxInterbufferDistance(buffers);
435 SetConfigIds(buffers);
437 // Save a snapshot of stream state before range modifications are made.
438 base::TimeDelta next_buffer_timestamp = GetNextBufferTimestamp();
439 BufferQueue deleted_buffers;
441 PrepareRangesForNextAppend(buffers, &deleted_buffers);
443 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise,
444 // create a new range with |buffers|.
445 if (range_for_next_append_ != ranges_.end()) {
446 (*range_for_next_append_)->AppendBuffersToEnd(buffers);
447 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp();
448 last_appended_buffer_is_keyframe_ = buffers.back()->IsKeyframe();
450 base::TimeDelta new_range_start_time = media_segment_start_time_;
451 const BufferQueue* buffers_for_new_range = &buffers;
452 BufferQueue trimmed_buffers;
454 // If the new range is not being created because of a new media
455 // segment, then we must make sure that we start with a keyframe.
456 // This can happen if the GOP in the previous append gets destroyed
457 // by a Remove() call.
458 if (!new_media_segment_ && !buffers.front()->IsKeyframe()) {
459 BufferQueue::const_iterator itr = buffers.begin();
461 // Scan past all the non-keyframes.
462 while (itr != buffers.end() && !(*itr)->IsKeyframe()) {
466 // If we didn't find a keyframe, then update the last appended
467 // buffer state and return.
468 if (itr == buffers.end()) {
469 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp();
470 last_appended_buffer_is_keyframe_ = buffers.back()->IsKeyframe();
474 // Copy the first keyframe and everything after it into |trimmed_buffers|.
475 trimmed_buffers.assign(itr, buffers.end());
477 new_range_start_time = trimmed_buffers.front()->GetDecodeTimestamp();
478 buffers_for_new_range = &trimmed_buffers;
481 range_for_next_append_ =
482 AddToRanges(new SourceBufferRange(
483 is_video(), *buffers_for_new_range, new_range_start_time,
484 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance,
485 base::Unretained(this))));
486 last_appended_buffer_timestamp_ =
487 buffers_for_new_range->back()->GetDecodeTimestamp();
488 last_appended_buffer_is_keyframe_ =
489 buffers_for_new_range->back()->IsKeyframe();
492 new_media_segment_ = false;
494 MergeWithAdjacentRangeIfNecessary(range_for_next_append_);
496 // Seek to try to fulfill a previous call to Seek().
498 DCHECK(!selected_range_);
499 DCHECK(deleted_buffers.empty());
500 Seek(seek_buffer_timestamp_);
503 if (!deleted_buffers.empty()) {
504 base::TimeDelta start_of_deleted =
505 deleted_buffers.front()->GetDecodeTimestamp();
507 DCHECK(track_buffer_.empty() ||
508 track_buffer_.back()->GetDecodeTimestamp() < start_of_deleted)
509 << "decode timestamp "
510 << track_buffer_.back()->GetDecodeTimestamp().InSecondsF() << " sec"
511 << ", start_of_deleted " << start_of_deleted.InSecondsF()<< " sec";
513 track_buffer_.insert(track_buffer_.end(), deleted_buffers.begin(),
514 deleted_buffers.end());
517 // Prune any extra buffers in |track_buffer_| if new keyframes
518 // are appended to the range covered by |track_buffer_|.
519 if (!track_buffer_.empty()) {
520 base::TimeDelta keyframe_timestamp =
521 FindKeyframeAfterTimestamp(track_buffer_.front()->GetDecodeTimestamp());
522 if (keyframe_timestamp != kNoTimestamp())
523 PruneTrackBuffer(keyframe_timestamp);
526 SetSelectedRangeIfNeeded(next_buffer_timestamp);
528 GarbageCollectIfNeeded();
530 DCHECK(IsRangeListSorted(ranges_));
531 DCHECK(OnlySelectedRangeIsSeeked());
535 void SourceBufferStream::Remove(base::TimeDelta start, base::TimeDelta end,
536 base::TimeDelta duration) {
537 DVLOG(1) << __FUNCTION__ << "(" << start.InSecondsF()
538 << ", " << end.InSecondsF()
539 << ", " << duration.InSecondsF() << ")";
540 DCHECK(start >= base::TimeDelta()) << start.InSecondsF();
541 DCHECK(start < end) << "start " << start.InSecondsF()
542 << " end " << end.InSecondsF();
543 DCHECK(duration != kNoTimestamp());
545 base::TimeDelta remove_end_timestamp = duration;
546 base::TimeDelta keyframe_timestamp = FindKeyframeAfterTimestamp(end);
547 if (keyframe_timestamp != kNoTimestamp()) {
548 remove_end_timestamp = keyframe_timestamp;
549 } else if (end < remove_end_timestamp) {
550 remove_end_timestamp = end;
553 BufferQueue deleted_buffers;
554 RemoveInternal(start, remove_end_timestamp, false, &deleted_buffers);
556 if (!deleted_buffers.empty())
557 SetSelectedRangeIfNeeded(deleted_buffers.front()->GetDecodeTimestamp());
560 void SourceBufferStream::RemoveInternal(
561 base::TimeDelta start, base::TimeDelta end, bool is_exclusive,
562 BufferQueue* deleted_buffers) {
563 DVLOG(1) << __FUNCTION__ << "(" << start.InSecondsF()
564 << ", " << end.InSecondsF()
565 << ", " << is_exclusive << ")";
567 DCHECK(start >= base::TimeDelta());
568 DCHECK(start < end) << "start " << start.InSecondsF()
569 << " end " << end.InSecondsF();
570 DCHECK(deleted_buffers);
572 RangeList::iterator itr = ranges_.begin();
574 while (itr != ranges_.end()) {
575 SourceBufferRange* range = *itr;
576 if (range->GetStartTimestamp() >= end)
579 // Split off any remaining end piece and add it to |ranges_|.
580 SourceBufferRange* new_range = range->SplitRange(end, is_exclusive);
582 itr = ranges_.insert(++itr, new_range);
585 // Update the selected range if the next buffer position was transferred
587 if (new_range->HasNextBufferPosition())
588 SetSelectedRange(new_range);
591 // If the current range now is completely covered by the removal
592 // range then we want to delete it.
593 bool delete_range = start < range->GetStartTimestamp() ||
594 (!is_exclusive && start == range->GetStartTimestamp());
596 // Truncate the current range so that it only contains data before
597 // the removal range.
598 BufferQueue saved_buffers;
599 range->TruncateAt(start, &saved_buffers, is_exclusive);
601 // Check to see if the current playback position was removed and
602 // update the selected range appropriately.
603 if (!saved_buffers.empty()) {
604 DCHECK(!range->HasNextBufferPosition());
605 DCHECK(deleted_buffers->empty());
607 *deleted_buffers = saved_buffers;
610 if (range == selected_range_ && !range->HasNextBufferPosition())
611 SetSelectedRange(NULL);
613 // If the current range now is completely covered by the removal
614 // range then delete it and move on.
616 DeleteAndRemoveRange(&itr);
620 // Clear |range_for_next_append_| if we determine that the removal
621 // operation makes it impossible for the next append to be added
622 // to the current range.
623 if (range_for_next_append_ != ranges_.end() &&
624 *range_for_next_append_ == range &&
625 last_appended_buffer_timestamp_ != kNoTimestamp()) {
626 base::TimeDelta potential_next_append_timestamp =
627 last_appended_buffer_timestamp_ +
628 base::TimeDelta::FromInternalValue(1);
630 if (!range->BelongsToRange(potential_next_append_timestamp)) {
631 DVLOG(1) << "Resetting range_for_next_append_ since the next append"
632 << " can't add to the current range.";
633 range_for_next_append_ =
634 FindExistingRangeFor(potential_next_append_timestamp);
638 // Move on to the next range.
642 DCHECK(IsRangeListSorted(ranges_));
643 DCHECK(OnlySelectedRangeIsSeeked());
644 DVLOG(1) << __FUNCTION__ << " : done";
647 void SourceBufferStream::ResetSeekState() {
648 SetSelectedRange(NULL);
649 track_buffer_.clear();
650 config_change_pending_ = false;
651 last_output_buffer_timestamp_ = kNoTimestamp();
654 bool SourceBufferStream::ShouldSeekToStartOfBuffered(
655 base::TimeDelta seek_timestamp) const {
658 base::TimeDelta beginning_of_buffered =
659 ranges_.front()->GetStartTimestamp();
660 return (seek_timestamp <= beginning_of_buffered &&
661 beginning_of_buffered < kSeekToStartFudgeRoom());
664 bool SourceBufferStream::IsMonotonicallyIncreasing(
665 const BufferQueue& buffers) const {
666 DCHECK(!buffers.empty());
667 base::TimeDelta prev_timestamp = last_appended_buffer_timestamp_;
668 bool prev_is_keyframe = last_appended_buffer_is_keyframe_;
669 for (BufferQueue::const_iterator itr = buffers.begin();
670 itr != buffers.end(); ++itr) {
671 base::TimeDelta current_timestamp = (*itr)->GetDecodeTimestamp();
672 bool current_is_keyframe = (*itr)->IsKeyframe();
673 DCHECK(current_timestamp != kNoTimestamp());
675 if (prev_timestamp != kNoTimestamp()) {
676 if (current_timestamp < prev_timestamp) {
677 MEDIA_LOG(log_cb_) << "Buffers were not monotonically increasing.";
681 if (current_timestamp == prev_timestamp &&
682 !AllowSameTimestamp(prev_is_keyframe, current_is_keyframe,
684 MEDIA_LOG(log_cb_) << "Unexpected combination of buffers with the"
685 << " same timestamp detected at "
686 << current_timestamp.InSecondsF();
691 prev_timestamp = current_timestamp;
692 prev_is_keyframe = current_is_keyframe;
697 bool SourceBufferStream::IsNextTimestampValid(
698 base::TimeDelta next_timestamp, bool next_is_keyframe) const {
699 return (last_appended_buffer_timestamp_ != next_timestamp) ||
700 new_media_segment_ ||
701 AllowSameTimestamp(last_appended_buffer_is_keyframe_, next_is_keyframe,
706 bool SourceBufferStream::OnlySelectedRangeIsSeeked() const {
707 for (RangeList::const_iterator itr = ranges_.begin();
708 itr != ranges_.end(); ++itr) {
709 if ((*itr)->HasNextBufferPosition() && (*itr) != selected_range_)
712 return !selected_range_ || selected_range_->HasNextBufferPosition();
715 void SourceBufferStream::UpdateMaxInterbufferDistance(
716 const BufferQueue& buffers) {
717 DCHECK(!buffers.empty());
718 base::TimeDelta prev_timestamp = last_appended_buffer_timestamp_;
719 for (BufferQueue::const_iterator itr = buffers.begin();
720 itr != buffers.end(); ++itr) {
721 base::TimeDelta current_timestamp = (*itr)->GetDecodeTimestamp();
722 DCHECK(current_timestamp != kNoTimestamp());
724 if (prev_timestamp != kNoTimestamp()) {
725 base::TimeDelta interbuffer_distance = current_timestamp - prev_timestamp;
726 if (max_interbuffer_distance_ == kNoTimestamp()) {
727 max_interbuffer_distance_ = interbuffer_distance;
729 max_interbuffer_distance_ =
730 std::max(max_interbuffer_distance_, interbuffer_distance);
733 prev_timestamp = current_timestamp;
737 void SourceBufferStream::SetConfigIds(const BufferQueue& buffers) {
738 for (BufferQueue::const_iterator itr = buffers.begin();
739 itr != buffers.end(); ++itr) {
740 (*itr)->SetConfigId(append_config_index_);
744 void SourceBufferStream::GarbageCollectIfNeeded() {
745 // Compute size of |ranges_|.
747 for (RangeList::iterator itr = ranges_.begin(); itr != ranges_.end(); ++itr)
748 ranges_size += (*itr)->size_in_bytes();
750 // Return if we're under or at the memory limit.
751 if (ranges_size <= memory_limit_)
754 int bytes_to_free = ranges_size - memory_limit_;
756 // Begin deleting after the last appended buffer.
757 int bytes_freed = FreeBuffersAfterLastAppended(bytes_to_free);
759 // Begin deleting from the front.
760 if (bytes_to_free - bytes_freed > 0)
761 bytes_freed += FreeBuffers(bytes_to_free - bytes_freed, false);
763 // Begin deleting from the back.
764 if (bytes_to_free - bytes_freed > 0)
765 FreeBuffers(bytes_to_free - bytes_freed, true);
768 int SourceBufferStream::FreeBuffersAfterLastAppended(int total_bytes_to_free) {
769 base::TimeDelta next_buffer_timestamp = GetNextBufferTimestamp();
770 if (last_appended_buffer_timestamp_ == kNoTimestamp() ||
771 next_buffer_timestamp == kNoTimestamp() ||
772 last_appended_buffer_timestamp_ >= next_buffer_timestamp) {
776 base::TimeDelta remove_range_start = last_appended_buffer_timestamp_;
777 if (last_appended_buffer_is_keyframe_)
778 remove_range_start += GetMaxInterbufferDistance();
780 base::TimeDelta remove_range_start_keyframe = FindKeyframeAfterTimestamp(
782 if (remove_range_start_keyframe != kNoTimestamp())
783 remove_range_start = remove_range_start_keyframe;
784 if (remove_range_start >= next_buffer_timestamp)
787 base::TimeDelta remove_range_end;
788 int bytes_freed = GetRemovalRange(
789 remove_range_start, next_buffer_timestamp, total_bytes_to_free,
792 Remove(remove_range_start, remove_range_end, next_buffer_timestamp);
796 int SourceBufferStream::GetRemovalRange(
797 base::TimeDelta start_timestamp, base::TimeDelta end_timestamp,
798 int total_bytes_to_free, base::TimeDelta* removal_end_timestamp) {
799 DCHECK(start_timestamp >= base::TimeDelta()) << start_timestamp.InSecondsF();
800 DCHECK(start_timestamp < end_timestamp)
801 << "start " << start_timestamp.InSecondsF()
802 << ", end " << end_timestamp.InSecondsF();
804 int bytes_to_free = total_bytes_to_free;
807 for (RangeList::iterator itr = ranges_.begin();
808 itr != ranges_.end() && bytes_to_free > 0; ++itr) {
809 SourceBufferRange* range = *itr;
810 if (range->GetStartTimestamp() >= end_timestamp)
812 if (range->GetEndTimestamp() < start_timestamp)
815 int bytes_removed = range->GetRemovalGOP(
816 start_timestamp, end_timestamp, bytes_to_free, removal_end_timestamp);
817 bytes_to_free -= bytes_removed;
818 bytes_freed += bytes_removed;
823 int SourceBufferStream::FreeBuffers(int total_bytes_to_free,
824 bool reverse_direction) {
825 TRACE_EVENT2("mse", "SourceBufferStream::FreeBuffers",
826 "total bytes to free", total_bytes_to_free,
827 "reverse direction", reverse_direction);
829 DCHECK_GT(total_bytes_to_free, 0);
830 int bytes_to_free = total_bytes_to_free;
833 // This range will save the last GOP appended to |range_for_next_append_|
834 // if the buffers surrounding it get deleted during garbage collection.
835 SourceBufferRange* new_range_for_append = NULL;
837 while (!ranges_.empty() && bytes_to_free > 0) {
838 SourceBufferRange* current_range = NULL;
840 int bytes_deleted = 0;
842 if (reverse_direction) {
843 current_range = ranges_.back();
844 if (current_range->LastGOPContainsNextBufferPosition()) {
845 DCHECK_EQ(current_range, selected_range_);
848 bytes_deleted = current_range->DeleteGOPFromBack(&buffers);
850 current_range = ranges_.front();
851 if (current_range->FirstGOPContainsNextBufferPosition()) {
852 DCHECK_EQ(current_range, selected_range_);
855 bytes_deleted = current_range->DeleteGOPFromFront(&buffers);
858 // Check to see if we've just deleted the GOP that was last appended.
859 base::TimeDelta end_timestamp = buffers.back()->GetDecodeTimestamp();
860 if (end_timestamp == last_appended_buffer_timestamp_) {
861 DCHECK(last_appended_buffer_timestamp_ != kNoTimestamp());
862 DCHECK(!new_range_for_append);
863 // Create a new range containing these buffers.
864 new_range_for_append = new SourceBufferRange(
865 is_video(), buffers, kNoTimestamp(),
866 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance,
867 base::Unretained(this)));
868 range_for_next_append_ = ranges_.end();
870 bytes_to_free -= bytes_deleted;
871 bytes_freed += bytes_deleted;
874 if (current_range->size_in_bytes() == 0) {
875 DCHECK_NE(current_range, selected_range_);
876 DCHECK(range_for_next_append_ == ranges_.end() ||
877 *range_for_next_append_ != current_range);
878 delete current_range;
879 reverse_direction ? ranges_.pop_back() : ranges_.pop_front();
883 // Insert |new_range_for_append| into |ranges_|, if applicable.
884 if (new_range_for_append) {
885 range_for_next_append_ = AddToRanges(new_range_for_append);
886 DCHECK(range_for_next_append_ != ranges_.end());
888 // Check to see if we need to merge |new_range_for_append| with the range
889 // before or after it. |new_range_for_append| is created whenever the last
890 // GOP appended is encountered, regardless of whether any buffers after it
891 // are ultimately deleted. Merging is necessary if there were no buffers
892 // (or very few buffers) deleted after creating |new_range_for_append|.
893 if (range_for_next_append_ != ranges_.begin()) {
894 RangeList::iterator range_before_next = range_for_next_append_;
896 MergeWithAdjacentRangeIfNecessary(range_before_next);
898 MergeWithAdjacentRangeIfNecessary(range_for_next_append_);
903 void SourceBufferStream::PrepareRangesForNextAppend(
904 const BufferQueue& new_buffers, BufferQueue* deleted_buffers) {
905 DCHECK(deleted_buffers);
907 bool temporarily_select_range = false;
908 if (!track_buffer_.empty()) {
909 base::TimeDelta tb_timestamp = track_buffer_.back()->GetDecodeTimestamp();
910 base::TimeDelta seek_timestamp = FindKeyframeAfterTimestamp(tb_timestamp);
911 if (seek_timestamp != kNoTimestamp() &&
912 seek_timestamp < new_buffers.front()->GetDecodeTimestamp() &&
913 range_for_next_append_ != ranges_.end() &&
914 (*range_for_next_append_)->BelongsToRange(seek_timestamp)) {
915 DCHECK(tb_timestamp < seek_timestamp);
916 DCHECK(!selected_range_);
917 DCHECK(!(*range_for_next_append_)->HasNextBufferPosition());
919 // If there are GOPs between the end of the track buffer and the
920 // beginning of the new buffers, then temporarily seek the range
921 // so that the buffers between these two times will be deposited in
922 // |deleted_buffers| as if they were part of the current playback
924 // TODO(acolwell): Figure out a more elegant way to do this.
925 SeekAndSetSelectedRange(*range_for_next_append_, seek_timestamp);
926 temporarily_select_range = true;
930 base::TimeDelta prev_timestamp = last_appended_buffer_timestamp_;
931 bool prev_is_keyframe = last_appended_buffer_is_keyframe_;
932 base::TimeDelta next_timestamp = new_buffers.front()->GetDecodeTimestamp();
933 bool next_is_keyframe = new_buffers.front()->IsKeyframe();
935 if (prev_timestamp != kNoTimestamp() && prev_timestamp != next_timestamp) {
936 // Clean up the old buffers between the last appended buffer and the
937 // beginning of |new_buffers|.
938 RemoveInternal(prev_timestamp, next_timestamp, true, deleted_buffers);
941 // Make the delete range exclusive if we are dealing with an allowed same
942 // timestamp situation. This prevents the first buffer in the current append
943 // from deleting the last buffer in the previous append if both buffers
944 // have the same timestamp.
945 bool is_exclusive = (prev_timestamp == next_timestamp) &&
946 AllowSameTimestamp(prev_is_keyframe, next_is_keyframe, is_video());
948 // Delete the buffers that |new_buffers| overlaps.
949 base::TimeDelta start = new_buffers.front()->GetDecodeTimestamp();
950 base::TimeDelta end = new_buffers.back()->GetDecodeTimestamp();
951 base::TimeDelta duration = new_buffers.back()->duration();
953 if (duration != kNoTimestamp() && duration > base::TimeDelta()) {
956 // TODO(acolwell): Ensure all buffers actually have proper
957 // duration info so that this hack isn't needed.
958 // http://crbug.com/312836
959 end += base::TimeDelta::FromInternalValue(1);
962 RemoveInternal(start, end, is_exclusive, deleted_buffers);
964 // Restore the range seek state if necessary.
965 if (temporarily_select_range)
966 SetSelectedRange(NULL);
969 bool SourceBufferStream::AreAdjacentInSequence(
970 base::TimeDelta first_timestamp, base::TimeDelta second_timestamp) const {
971 return first_timestamp < second_timestamp &&
973 first_timestamp + ComputeFudgeRoom(GetMaxInterbufferDistance());
976 void SourceBufferStream::PruneTrackBuffer(const base::TimeDelta timestamp) {
977 // If we don't have the next timestamp, we don't have anything to delete.
978 if (timestamp == kNoTimestamp())
981 while (!track_buffer_.empty() &&
982 track_buffer_.back()->GetDecodeTimestamp() >= timestamp) {
983 track_buffer_.pop_back();
987 void SourceBufferStream::MergeWithAdjacentRangeIfNecessary(
988 const RangeList::iterator& range_with_new_buffers_itr) {
989 DCHECK(range_with_new_buffers_itr != ranges_.end());
991 SourceBufferRange* range_with_new_buffers = *range_with_new_buffers_itr;
992 RangeList::iterator next_range_itr = range_with_new_buffers_itr;
995 if (next_range_itr == ranges_.end() ||
996 !range_with_new_buffers->CanAppendRangeToEnd(**next_range_itr)) {
1000 bool transfer_current_position = selected_range_ == *next_range_itr;
1001 range_with_new_buffers->AppendRangeToEnd(**next_range_itr,
1002 transfer_current_position);
1003 // Update |selected_range_| pointer if |range| has become selected after
1005 if (transfer_current_position)
1006 SetSelectedRange(range_with_new_buffers);
1008 if (next_range_itr == range_for_next_append_)
1009 range_for_next_append_ = range_with_new_buffers_itr;
1011 DeleteAndRemoveRange(&next_range_itr);
1014 void SourceBufferStream::Seek(base::TimeDelta timestamp) {
1015 DCHECK(timestamp >= base::TimeDelta());
1018 if (ShouldSeekToStartOfBuffered(timestamp)) {
1019 ranges_.front()->SeekToStart();
1020 SetSelectedRange(ranges_.front());
1021 seek_pending_ = false;
1025 seek_buffer_timestamp_ = timestamp;
1026 seek_pending_ = true;
1028 RangeList::iterator itr = ranges_.end();
1029 for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
1030 if ((*itr)->CanSeekTo(timestamp))
1034 if (itr == ranges_.end())
1037 SeekAndSetSelectedRange(*itr, timestamp);
1038 seek_pending_ = false;
1041 bool SourceBufferStream::IsSeekPending() const {
1042 return !(end_of_stream_ && IsEndSelected()) && seek_pending_;
1045 void SourceBufferStream::OnSetDuration(base::TimeDelta duration) {
1046 RangeList::iterator itr = ranges_.end();
1047 for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
1048 if ((*itr)->GetEndTimestamp() > duration)
1051 if (itr == ranges_.end())
1054 // Need to partially truncate this range.
1055 if ((*itr)->GetStartTimestamp() < duration) {
1056 (*itr)->TruncateAt(duration, NULL, false);
1060 // Delete all ranges that begin after |duration|.
1061 while (itr != ranges_.end()) {
1062 // If we're about to delete the selected range, also reset the seek state.
1063 DCHECK((*itr)->GetStartTimestamp() >= duration);
1064 if (*itr == selected_range_)
1066 DeleteAndRemoveRange(&itr);
1070 SourceBufferStream::Status SourceBufferStream::GetNextBuffer(
1071 scoped_refptr<StreamParserBuffer>* out_buffer) {
1072 CHECK(!config_change_pending_);
1074 if (!track_buffer_.empty()) {
1075 DCHECK(!selected_range_);
1076 if (track_buffer_.front()->GetConfigId() != current_config_index_) {
1077 config_change_pending_ = true;
1078 DVLOG(1) << "Config change (track buffer config ID does not match).";
1079 return kConfigChange;
1082 *out_buffer = track_buffer_.front();
1083 track_buffer_.pop_front();
1084 last_output_buffer_timestamp_ = (*out_buffer)->GetDecodeTimestamp();
1086 // If the track buffer becomes empty, then try to set the selected range
1087 // based on the timestamp of this buffer being returned.
1088 if (track_buffer_.empty())
1089 SetSelectedRangeIfNeeded(last_output_buffer_timestamp_);
1094 if (!selected_range_ || !selected_range_->HasNextBuffer()) {
1095 if (end_of_stream_ && IsEndSelected())
1096 return kEndOfStream;
1100 if (selected_range_->GetNextConfigId() != current_config_index_) {
1101 config_change_pending_ = true;
1102 DVLOG(1) << "Config change (selected range config ID does not match).";
1103 return kConfigChange;
1106 CHECK(selected_range_->GetNextBuffer(out_buffer));
1107 last_output_buffer_timestamp_ = (*out_buffer)->GetDecodeTimestamp();
1111 base::TimeDelta SourceBufferStream::GetNextBufferTimestamp() {
1112 if (!track_buffer_.empty())
1113 return track_buffer_.front()->GetDecodeTimestamp();
1115 if (!selected_range_)
1116 return kNoTimestamp();
1118 DCHECK(selected_range_->HasNextBufferPosition());
1119 return selected_range_->GetNextTimestamp();
1122 base::TimeDelta SourceBufferStream::GetEndBufferTimestamp() {
1123 if (!selected_range_)
1124 return kNoTimestamp();
1125 return selected_range_->GetEndTimestamp();
1128 SourceBufferStream::RangeList::iterator
1129 SourceBufferStream::FindExistingRangeFor(base::TimeDelta start_timestamp) {
1130 for (RangeList::iterator itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
1131 if ((*itr)->BelongsToRange(start_timestamp))
1134 return ranges_.end();
1137 SourceBufferStream::RangeList::iterator
1138 SourceBufferStream::AddToRanges(SourceBufferRange* new_range) {
1139 base::TimeDelta start_timestamp = new_range->GetStartTimestamp();
1140 RangeList::iterator itr = ranges_.end();
1141 for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
1142 if ((*itr)->GetStartTimestamp() > start_timestamp)
1145 return ranges_.insert(itr, new_range);
1148 SourceBufferStream::RangeList::iterator
1149 SourceBufferStream::GetSelectedRangeItr() {
1150 DCHECK(selected_range_);
1151 RangeList::iterator itr = ranges_.end();
1152 for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
1153 if (*itr == selected_range_)
1156 DCHECK(itr != ranges_.end());
1160 void SourceBufferStream::SeekAndSetSelectedRange(
1161 SourceBufferRange* range, base::TimeDelta seek_timestamp) {
1163 range->Seek(seek_timestamp);
1164 SetSelectedRange(range);
1167 void SourceBufferStream::SetSelectedRange(SourceBufferRange* range) {
1168 DVLOG(1) << __FUNCTION__ << " : " << selected_range_ << " -> " << range;
1169 if (selected_range_)
1170 selected_range_->ResetNextBufferPosition();
1171 DCHECK(!range || range->HasNextBufferPosition());
1172 selected_range_ = range;
1175 Ranges<base::TimeDelta> SourceBufferStream::GetBufferedTime() const {
1176 Ranges<base::TimeDelta> ranges;
1177 for (RangeList::const_iterator itr = ranges_.begin();
1178 itr != ranges_.end(); ++itr) {
1179 ranges.Add((*itr)->GetStartTimestamp(), (*itr)->GetBufferedEndTimestamp());
1184 void SourceBufferStream::MarkEndOfStream() {
1185 DCHECK(!end_of_stream_);
1186 end_of_stream_ = true;
1189 void SourceBufferStream::UnmarkEndOfStream() {
1190 DCHECK(end_of_stream_);
1191 end_of_stream_ = false;
1194 bool SourceBufferStream::IsEndSelected() const {
1195 if (ranges_.empty())
1199 return seek_buffer_timestamp_ >= ranges_.back()->GetBufferedEndTimestamp();
1201 return selected_range_ == ranges_.back();
1204 const AudioDecoderConfig& SourceBufferStream::GetCurrentAudioDecoderConfig() {
1205 if (config_change_pending_)
1206 CompleteConfigChange();
1207 return audio_configs_[current_config_index_];
1210 const VideoDecoderConfig& SourceBufferStream::GetCurrentVideoDecoderConfig() {
1211 if (config_change_pending_)
1212 CompleteConfigChange();
1213 return video_configs_[current_config_index_];
1216 base::TimeDelta SourceBufferStream::GetMaxInterbufferDistance() const {
1217 if (max_interbuffer_distance_ == kNoTimestamp())
1218 return base::TimeDelta::FromMilliseconds(kDefaultBufferDurationInMs);
1219 return max_interbuffer_distance_;
1222 bool SourceBufferStream::UpdateAudioConfig(const AudioDecoderConfig& config) {
1223 DCHECK(!audio_configs_.empty());
1224 DCHECK(video_configs_.empty());
1225 DVLOG(3) << "UpdateAudioConfig.";
1227 if (audio_configs_[0].codec() != config.codec()) {
1228 MEDIA_LOG(log_cb_) << "Audio codec changes not allowed.";
1232 if (audio_configs_[0].samples_per_second() != config.samples_per_second()) {
1233 MEDIA_LOG(log_cb_) << "Audio sample rate changes not allowed.";
1237 if (audio_configs_[0].channel_layout() != config.channel_layout()) {
1238 MEDIA_LOG(log_cb_) << "Audio channel layout changes not allowed.";
1242 if (audio_configs_[0].bits_per_channel() != config.bits_per_channel()) {
1243 MEDIA_LOG(log_cb_) << "Audio bits per channel changes not allowed.";
1247 if (audio_configs_[0].is_encrypted() != config.is_encrypted()) {
1248 MEDIA_LOG(log_cb_) << "Audio encryption changes not allowed.";
1252 // Check to see if the new config matches an existing one.
1253 for (size_t i = 0; i < audio_configs_.size(); ++i) {
1254 if (config.Matches(audio_configs_[i])) {
1255 append_config_index_ = i;
1260 // No matches found so let's add this one to the list.
1261 append_config_index_ = audio_configs_.size();
1262 DVLOG(2) << "New audio config - index: " << append_config_index_;
1263 audio_configs_.resize(audio_configs_.size() + 1);
1264 audio_configs_[append_config_index_] = config;
1268 bool SourceBufferStream::UpdateVideoConfig(const VideoDecoderConfig& config) {
1269 DCHECK(!video_configs_.empty());
1270 DCHECK(audio_configs_.empty());
1271 DVLOG(3) << "UpdateVideoConfig.";
1273 if (video_configs_[0].is_encrypted() != config.is_encrypted()) {
1274 MEDIA_LOG(log_cb_) << "Video Encryption changes not allowed.";
1278 if (video_configs_[0].codec() != config.codec()) {
1279 MEDIA_LOG(log_cb_) << "Video codec changes not allowed.";
1283 if (video_configs_[0].is_encrypted() != config.is_encrypted()) {
1284 MEDIA_LOG(log_cb_) << "Video encryption changes not allowed.";
1288 // Check to see if the new config matches an existing one.
1289 for (size_t i = 0; i < video_configs_.size(); ++i) {
1290 if (config.Matches(video_configs_[i])) {
1291 append_config_index_ = i;
1296 // No matches found so let's add this one to the list.
1297 append_config_index_ = video_configs_.size();
1298 DVLOG(2) << "New video config - index: " << append_config_index_;
1299 video_configs_.resize(video_configs_.size() + 1);
1300 video_configs_[append_config_index_] = config;
1304 void SourceBufferStream::CompleteConfigChange() {
1305 config_change_pending_ = false;
1307 if (!track_buffer_.empty()) {
1308 current_config_index_ = track_buffer_.front()->GetConfigId();
1312 if (selected_range_ && selected_range_->HasNextBuffer())
1313 current_config_index_ = selected_range_->GetNextConfigId();
1316 void SourceBufferStream::SetSelectedRangeIfNeeded(
1317 const base::TimeDelta timestamp) {
1318 DVLOG(1) << __FUNCTION__ << "(" << timestamp.InSecondsF() << ")";
1320 if (selected_range_) {
1321 DCHECK(track_buffer_.empty());
1325 if (!track_buffer_.empty()) {
1326 DCHECK(!selected_range_);
1330 base::TimeDelta start_timestamp = timestamp;
1332 // If the next buffer timestamp is not known then use a timestamp just after
1333 // the timestamp on the last buffer returned by GetNextBuffer().
1334 if (start_timestamp == kNoTimestamp()) {
1335 if (last_output_buffer_timestamp_ == kNoTimestamp())
1338 start_timestamp = last_output_buffer_timestamp_ +
1339 base::TimeDelta::FromInternalValue(1);
1342 base::TimeDelta seek_timestamp =
1343 FindNewSelectedRangeSeekTimestamp(start_timestamp);
1345 // If we don't have buffered data to seek to, then return.
1346 if (seek_timestamp == kNoTimestamp())
1349 DCHECK(track_buffer_.empty());
1350 SeekAndSetSelectedRange(*FindExistingRangeFor(seek_timestamp),
1354 base::TimeDelta SourceBufferStream::FindNewSelectedRangeSeekTimestamp(
1355 const base::TimeDelta start_timestamp) {
1356 DCHECK(start_timestamp != kNoTimestamp());
1357 DCHECK(start_timestamp >= base::TimeDelta());
1359 RangeList::iterator itr = ranges_.begin();
1361 for (; itr != ranges_.end(); ++itr) {
1362 if ((*itr)->GetEndTimestamp() >= start_timestamp) {
1367 if (itr == ranges_.end())
1368 return kNoTimestamp();
1370 // First check for a keyframe timestamp >= |start_timestamp|
1371 // in the current range.
1372 base::TimeDelta keyframe_timestamp =
1373 (*itr)->NextKeyframeTimestamp(start_timestamp);
1375 if (keyframe_timestamp != kNoTimestamp())
1376 return keyframe_timestamp;
1378 // If a keyframe was not found then look for a keyframe that is
1379 // "close enough" in the current or next range.
1380 base::TimeDelta end_timestamp =
1381 start_timestamp + ComputeFudgeRoom(GetMaxInterbufferDistance());
1382 DCHECK(start_timestamp < end_timestamp);
1384 // Make sure the current range doesn't start beyond |end_timestamp|.
1385 if ((*itr)->GetStartTimestamp() >= end_timestamp)
1386 return kNoTimestamp();
1388 keyframe_timestamp = (*itr)->KeyframeBeforeTimestamp(end_timestamp);
1390 // Check to see if the keyframe is within the acceptable range
1391 // (|start_timestamp|, |end_timestamp|].
1392 if (keyframe_timestamp != kNoTimestamp() &&
1393 start_timestamp < keyframe_timestamp &&
1394 keyframe_timestamp <= end_timestamp) {
1395 return keyframe_timestamp;
1398 // If |end_timestamp| is within this range, then no other checks are
1400 if (end_timestamp <= (*itr)->GetEndTimestamp())
1401 return kNoTimestamp();
1403 // Move on to the next range.
1406 // Return early if the next range does not contain |end_timestamp|.
1407 if (itr == ranges_.end() || (*itr)->GetStartTimestamp() >= end_timestamp)
1408 return kNoTimestamp();
1410 keyframe_timestamp = (*itr)->KeyframeBeforeTimestamp(end_timestamp);
1412 // Check to see if the keyframe is within the acceptable range
1413 // (|start_timestamp|, |end_timestamp|].
1414 if (keyframe_timestamp != kNoTimestamp() &&
1415 start_timestamp < keyframe_timestamp &&
1416 keyframe_timestamp <= end_timestamp) {
1417 return keyframe_timestamp;
1420 return kNoTimestamp();
1423 base::TimeDelta SourceBufferStream::FindKeyframeAfterTimestamp(
1424 const base::TimeDelta timestamp) {
1425 DCHECK(timestamp != kNoTimestamp());
1427 RangeList::iterator itr = FindExistingRangeFor(timestamp);
1429 if (itr == ranges_.end())
1430 return kNoTimestamp();
1432 // First check for a keyframe timestamp >= |timestamp|
1433 // in the current range.
1434 return (*itr)->NextKeyframeTimestamp(timestamp);
1437 std::string SourceBufferStream::GetStreamTypeName() const {
1438 if (!video_configs_.empty()) {
1439 DCHECK(audio_configs_.empty());
1443 DCHECK(!audio_configs_.empty());
1447 void SourceBufferStream::DeleteAndRemoveRange(RangeList::iterator* itr) {
1448 DVLOG(1) << __FUNCTION__;
1450 DCHECK(*itr != ranges_.end());
1451 if (**itr == selected_range_) {
1452 DVLOG(1) << __FUNCTION__ << " deleting selected range.";
1453 SetSelectedRange(NULL);
1456 if (*itr == range_for_next_append_) {
1457 DVLOG(1) << __FUNCTION__ << " deleting range_for_next_append_.";
1458 range_for_next_append_ = ranges_.end();
1462 *itr = ranges_.erase(*itr);
1465 SourceBufferRange::SourceBufferRange(
1466 bool is_video, const BufferQueue& new_buffers,
1467 base::TimeDelta media_segment_start_time,
1468 const InterbufferDistanceCB& interbuffer_distance_cb)
1469 : is_video_(is_video),
1470 keyframe_map_index_base_(0),
1471 next_buffer_index_(-1),
1472 media_segment_start_time_(media_segment_start_time),
1473 interbuffer_distance_cb_(interbuffer_distance_cb),
1475 DCHECK(!new_buffers.empty());
1476 DCHECK(new_buffers.front()->IsKeyframe());
1477 DCHECK(!interbuffer_distance_cb.is_null());
1478 AppendBuffersToEnd(new_buffers);
1481 void SourceBufferRange::AppendBuffersToEnd(const BufferQueue& new_buffers) {
1482 DCHECK(buffers_.empty() || CanAppendBuffersToEnd(new_buffers));
1484 for (BufferQueue::const_iterator itr = new_buffers.begin();
1485 itr != new_buffers.end(); ++itr) {
1486 DCHECK((*itr)->GetDecodeTimestamp() != kNoTimestamp());
1487 buffers_.push_back(*itr);
1488 size_in_bytes_ += (*itr)->data_size();
1490 if ((*itr)->IsKeyframe()) {
1491 keyframe_map_.insert(
1492 std::make_pair((*itr)->GetDecodeTimestamp(),
1493 buffers_.size() - 1 + keyframe_map_index_base_));
1498 void SourceBufferRange::Seek(base::TimeDelta timestamp) {
1499 DCHECK(CanSeekTo(timestamp));
1500 DCHECK(!keyframe_map_.empty());
1502 KeyframeMap::iterator result = GetFirstKeyframeBefore(timestamp);
1503 next_buffer_index_ = result->second - keyframe_map_index_base_;
1504 DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size()));
1507 void SourceBufferRange::SeekAheadTo(base::TimeDelta timestamp) {
1508 SeekAhead(timestamp, false);
1511 void SourceBufferRange::SeekAheadPast(base::TimeDelta timestamp) {
1512 SeekAhead(timestamp, true);
1515 void SourceBufferRange::SeekAhead(base::TimeDelta timestamp,
1516 bool skip_given_timestamp) {
1517 DCHECK(!keyframe_map_.empty());
1519 KeyframeMap::iterator result =
1520 GetFirstKeyframeAt(timestamp, skip_given_timestamp);
1522 // If there isn't a keyframe after |timestamp|, then seek to end and return
1523 // kNoTimestamp to signal such.
1524 if (result == keyframe_map_.end()) {
1525 next_buffer_index_ = -1;
1528 next_buffer_index_ = result->second - keyframe_map_index_base_;
1529 DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size()));
1532 void SourceBufferRange::SeekToStart() {
1533 DCHECK(!buffers_.empty());
1534 next_buffer_index_ = 0;
1537 SourceBufferRange* SourceBufferRange::SplitRange(
1538 base::TimeDelta timestamp, bool is_exclusive) {
1539 // Find the first keyframe after |timestamp|. If |is_exclusive|, do not
1540 // include keyframes at |timestamp|.
1541 KeyframeMap::iterator new_beginning_keyframe =
1542 GetFirstKeyframeAt(timestamp, is_exclusive);
1544 // If there is no keyframe after |timestamp|, we can't split the range.
1545 if (new_beginning_keyframe == keyframe_map_.end())
1548 // Remove the data beginning at |keyframe_index| from |buffers_| and save it
1549 // into |removed_buffers|.
1550 int keyframe_index =
1551 new_beginning_keyframe->second - keyframe_map_index_base_;
1552 DCHECK_LT(keyframe_index, static_cast<int>(buffers_.size()));
1553 BufferQueue::iterator starting_point = buffers_.begin() + keyframe_index;
1554 BufferQueue removed_buffers(starting_point, buffers_.end());
1555 keyframe_map_.erase(new_beginning_keyframe, keyframe_map_.end());
1556 FreeBufferRange(starting_point, buffers_.end());
1558 // Create a new range with |removed_buffers|.
1559 SourceBufferRange* split_range =
1560 new SourceBufferRange(
1561 is_video_, removed_buffers, kNoTimestamp(), interbuffer_distance_cb_);
1563 // If the next buffer position is now in |split_range|, update the state of
1564 // this range and |split_range| accordingly.
1565 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) {
1566 split_range->next_buffer_index_ = next_buffer_index_ - keyframe_index;
1567 ResetNextBufferPosition();
1573 SourceBufferRange::BufferQueue::iterator SourceBufferRange::GetBufferItrAt(
1574 base::TimeDelta timestamp, bool skip_given_timestamp) {
1575 // Need to make a dummy buffer with timestamp |timestamp| in order to search
1576 // the |buffers_| container.
1577 scoped_refptr<StreamParserBuffer> dummy_buffer =
1578 StreamParserBuffer::CopyFrom(NULL, 0, false);
1579 dummy_buffer->SetDecodeTimestamp(timestamp);
1581 if (skip_given_timestamp) {
1582 return std::upper_bound(
1583 buffers_.begin(), buffers_.end(), dummy_buffer, BufferComparator);
1585 return std::lower_bound(
1586 buffers_.begin(), buffers_.end(), dummy_buffer, BufferComparator);
1589 SourceBufferRange::KeyframeMap::iterator
1590 SourceBufferRange::GetFirstKeyframeAt(base::TimeDelta timestamp,
1591 bool skip_given_timestamp) {
1592 return skip_given_timestamp ?
1593 keyframe_map_.upper_bound(timestamp) :
1594 keyframe_map_.lower_bound(timestamp);
1597 SourceBufferRange::KeyframeMap::iterator
1598 SourceBufferRange::GetFirstKeyframeBefore(base::TimeDelta timestamp) {
1599 KeyframeMap::iterator result = keyframe_map_.lower_bound(timestamp);
1600 // lower_bound() returns the first element >= |timestamp|, so we want the
1601 // previous element if it did not return the element exactly equal to
1603 if (result != keyframe_map_.begin() &&
1604 (result == keyframe_map_.end() || result->first != timestamp)) {
1610 void SourceBufferRange::DeleteAll(BufferQueue* removed_buffers) {
1611 TruncateAt(buffers_.begin(), removed_buffers);
1614 void SourceBufferRange::TruncateAt(
1615 base::TimeDelta timestamp, BufferQueue* removed_buffers,
1616 bool is_exclusive) {
1617 // Find the place in |buffers_| where we will begin deleting data.
1618 BufferQueue::iterator starting_point =
1619 GetBufferItrAt(timestamp, is_exclusive);
1620 TruncateAt(starting_point, removed_buffers);
1623 int SourceBufferRange::DeleteGOPFromFront(BufferQueue* deleted_buffers) {
1624 DCHECK(!FirstGOPContainsNextBufferPosition());
1625 DCHECK(deleted_buffers);
1627 int buffers_deleted = 0;
1628 int total_bytes_deleted = 0;
1630 KeyframeMap::iterator front = keyframe_map_.begin();
1631 DCHECK(front != keyframe_map_.end());
1633 // Delete the keyframe at the start of |keyframe_map_|.
1634 keyframe_map_.erase(front);
1636 // Now we need to delete all the buffers that depend on the keyframe we've
1638 int end_index = keyframe_map_.size() > 0 ?
1639 keyframe_map_.begin()->second - keyframe_map_index_base_ :
1642 // Delete buffers from the beginning of the buffered range up until (but not
1643 // including) the next keyframe.
1644 for (int i = 0; i < end_index; i++) {
1645 int bytes_deleted = buffers_.front()->data_size();
1646 size_in_bytes_ -= bytes_deleted;
1647 total_bytes_deleted += bytes_deleted;
1648 deleted_buffers->push_back(buffers_.front());
1649 buffers_.pop_front();
1653 // Update |keyframe_map_index_base_| to account for the deleted buffers.
1654 keyframe_map_index_base_ += buffers_deleted;
1656 if (next_buffer_index_ > -1) {
1657 next_buffer_index_ -= buffers_deleted;
1658 DCHECK_GE(next_buffer_index_, 0);
1661 // Invalidate media segment start time if we've deleted the first buffer of
1663 if (buffers_deleted > 0)
1664 media_segment_start_time_ = kNoTimestamp();
1666 return total_bytes_deleted;
1669 int SourceBufferRange::DeleteGOPFromBack(BufferQueue* deleted_buffers) {
1670 DCHECK(!LastGOPContainsNextBufferPosition());
1671 DCHECK(deleted_buffers);
1673 // Remove the last GOP's keyframe from the |keyframe_map_|.
1674 KeyframeMap::iterator back = keyframe_map_.end();
1675 DCHECK_GT(keyframe_map_.size(), 0u);
1678 // The index of the first buffer in the last GOP is equal to the new size of
1679 // |buffers_| after that GOP is deleted.
1680 size_t goal_size = back->second - keyframe_map_index_base_;
1681 keyframe_map_.erase(back);
1683 int total_bytes_deleted = 0;
1684 while (buffers_.size() != goal_size) {
1685 int bytes_deleted = buffers_.back()->data_size();
1686 size_in_bytes_ -= bytes_deleted;
1687 total_bytes_deleted += bytes_deleted;
1688 // We're removing buffers from the back, so push each removed buffer to the
1689 // front of |deleted_buffers| so that |deleted_buffers| are in nondecreasing
1691 deleted_buffers->push_front(buffers_.back());
1692 buffers_.pop_back();
1695 return total_bytes_deleted;
1698 int SourceBufferRange::GetRemovalGOP(
1699 base::TimeDelta start_timestamp, base::TimeDelta end_timestamp,
1700 int total_bytes_to_free, base::TimeDelta* removal_end_timestamp) {
1701 int bytes_to_free = total_bytes_to_free;
1702 int bytes_removed = 0;
1704 KeyframeMap::iterator gop_itr = GetFirstKeyframeAt(start_timestamp, false);
1705 if (gop_itr == keyframe_map_.end())
1707 int keyframe_index = gop_itr->second - keyframe_map_index_base_;
1708 BufferQueue::iterator buffer_itr = buffers_.begin() + keyframe_index;
1709 KeyframeMap::iterator gop_end = keyframe_map_.end();
1710 if (end_timestamp < GetBufferedEndTimestamp())
1711 gop_end = GetFirstKeyframeBefore(end_timestamp);
1713 // Check if the removal range is within a GOP and skip the loop if so.
1714 // [keyframe]...[start_timestamp]...[end_timestamp]...[keyframe]
1715 KeyframeMap::iterator gop_itr_prev = gop_itr;
1716 if (gop_itr_prev != keyframe_map_.begin() && --gop_itr_prev == gop_end)
1719 while (gop_itr != gop_end && bytes_to_free > 0) {
1723 int next_gop_index = gop_itr == keyframe_map_.end() ?
1724 buffers_.size() : gop_itr->second - keyframe_map_index_base_;
1725 BufferQueue::iterator next_gop_start = buffers_.begin() + next_gop_index;
1726 for (; buffer_itr != next_gop_start; ++buffer_itr)
1727 gop_size += (*buffer_itr)->data_size();
1729 bytes_removed += gop_size;
1730 bytes_to_free -= gop_size;
1732 if (bytes_removed > 0) {
1733 *removal_end_timestamp = gop_itr == keyframe_map_.end() ?
1734 GetBufferedEndTimestamp() : gop_itr->first;
1736 return bytes_removed;
1739 bool SourceBufferRange::FirstGOPContainsNextBufferPosition() const {
1740 if (!HasNextBufferPosition())
1743 // If there is only one GOP, it must contain the next buffer position.
1744 if (keyframe_map_.size() == 1u)
1747 KeyframeMap::const_iterator second_gop = keyframe_map_.begin();
1749 return next_buffer_index_ < second_gop->second - keyframe_map_index_base_;
1752 bool SourceBufferRange::LastGOPContainsNextBufferPosition() const {
1753 if (!HasNextBufferPosition())
1756 // If there is only one GOP, it must contain the next buffer position.
1757 if (keyframe_map_.size() == 1u)
1760 KeyframeMap::const_iterator last_gop = keyframe_map_.end();
1762 return last_gop->second - keyframe_map_index_base_ <= next_buffer_index_;
1765 void SourceBufferRange::FreeBufferRange(
1766 const BufferQueue::iterator& starting_point,
1767 const BufferQueue::iterator& ending_point) {
1768 for (BufferQueue::iterator itr = starting_point;
1769 itr != ending_point; ++itr) {
1770 size_in_bytes_ -= (*itr)->data_size();
1771 DCHECK_GE(size_in_bytes_, 0);
1773 buffers_.erase(starting_point, ending_point);
1776 void SourceBufferRange::TruncateAt(
1777 const BufferQueue::iterator& starting_point, BufferQueue* removed_buffers) {
1778 DCHECK(!removed_buffers || removed_buffers->empty());
1780 // Return if we're not deleting anything.
1781 if (starting_point == buffers_.end())
1784 // Reset the next buffer index if we will be deleting the buffer that's next
1786 if (HasNextBufferPosition()) {
1787 base::TimeDelta next_buffer_timestamp = GetNextTimestamp();
1788 if (next_buffer_timestamp == kNoTimestamp() ||
1789 next_buffer_timestamp >= (*starting_point)->GetDecodeTimestamp()) {
1790 if (HasNextBuffer() && removed_buffers) {
1791 int starting_offset = starting_point - buffers_.begin();
1792 int next_buffer_offset = next_buffer_index_ - starting_offset;
1793 DCHECK_GE(next_buffer_offset, 0);
1794 BufferQueue saved(starting_point + next_buffer_offset, buffers_.end());
1795 removed_buffers->swap(saved);
1797 ResetNextBufferPosition();
1801 // Remove keyframes from |starting_point| onward.
1802 KeyframeMap::iterator starting_point_keyframe =
1803 keyframe_map_.lower_bound((*starting_point)->GetDecodeTimestamp());
1804 keyframe_map_.erase(starting_point_keyframe, keyframe_map_.end());
1806 // Remove everything from |starting_point| onward.
1807 FreeBufferRange(starting_point, buffers_.end());
1810 bool SourceBufferRange::GetNextBuffer(
1811 scoped_refptr<StreamParserBuffer>* out_buffer) {
1812 if (!HasNextBuffer())
1815 *out_buffer = buffers_.at(next_buffer_index_);
1816 next_buffer_index_++;
1820 bool SourceBufferRange::HasNextBuffer() const {
1821 return next_buffer_index_ >= 0 &&
1822 next_buffer_index_ < static_cast<int>(buffers_.size());
1825 int SourceBufferRange::GetNextConfigId() const {
1826 DCHECK(HasNextBuffer());
1827 return buffers_.at(next_buffer_index_)->GetConfigId();
1830 base::TimeDelta SourceBufferRange::GetNextTimestamp() const {
1831 DCHECK(!buffers_.empty());
1832 DCHECK(HasNextBufferPosition());
1834 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) {
1835 return kNoTimestamp();
1838 return buffers_.at(next_buffer_index_)->GetDecodeTimestamp();
1841 bool SourceBufferRange::HasNextBufferPosition() const {
1842 return next_buffer_index_ >= 0;
1845 void SourceBufferRange::ResetNextBufferPosition() {
1846 next_buffer_index_ = -1;
1849 void SourceBufferRange::AppendRangeToEnd(const SourceBufferRange& range,
1850 bool transfer_current_position) {
1851 DCHECK(CanAppendRangeToEnd(range));
1852 DCHECK(!buffers_.empty());
1854 if (transfer_current_position && range.next_buffer_index_ >= 0)
1855 next_buffer_index_ = range.next_buffer_index_ + buffers_.size();
1857 AppendBuffersToEnd(range.buffers_);
1860 bool SourceBufferRange::CanAppendRangeToEnd(
1861 const SourceBufferRange& range) const {
1862 return CanAppendBuffersToEnd(range.buffers_);
1865 bool SourceBufferRange::CanAppendBuffersToEnd(
1866 const BufferQueue& buffers) const {
1867 DCHECK(!buffers_.empty());
1868 return IsNextInSequence(buffers.front()->GetDecodeTimestamp(),
1869 buffers.front()->IsKeyframe());
1872 bool SourceBufferRange::BelongsToRange(base::TimeDelta timestamp) const {
1873 DCHECK(!buffers_.empty());
1875 return (IsNextInSequence(timestamp, false) ||
1876 (GetStartTimestamp() <= timestamp && timestamp <= GetEndTimestamp()));
1879 bool SourceBufferRange::CanSeekTo(base::TimeDelta timestamp) const {
1880 base::TimeDelta start_timestamp =
1881 std::max(base::TimeDelta(), GetStartTimestamp() - GetFudgeRoom());
1882 return !keyframe_map_.empty() && start_timestamp <= timestamp &&
1883 timestamp < GetBufferedEndTimestamp();
1886 bool SourceBufferRange::CompletelyOverlaps(
1887 const SourceBufferRange& range) const {
1888 return GetStartTimestamp() <= range.GetStartTimestamp() &&
1889 GetEndTimestamp() >= range.GetEndTimestamp();
1892 bool SourceBufferRange::EndOverlaps(const SourceBufferRange& range) const {
1893 return range.GetStartTimestamp() <= GetEndTimestamp() &&
1894 GetEndTimestamp() < range.GetEndTimestamp();
1897 base::TimeDelta SourceBufferRange::GetStartTimestamp() const {
1898 DCHECK(!buffers_.empty());
1899 base::TimeDelta start_timestamp = media_segment_start_time_;
1900 if (start_timestamp == kNoTimestamp())
1901 start_timestamp = buffers_.front()->GetDecodeTimestamp();
1902 return start_timestamp;
1905 base::TimeDelta SourceBufferRange::GetEndTimestamp() const {
1906 DCHECK(!buffers_.empty());
1907 return buffers_.back()->GetDecodeTimestamp();
1910 base::TimeDelta SourceBufferRange::GetBufferedEndTimestamp() const {
1911 DCHECK(!buffers_.empty());
1912 base::TimeDelta duration = buffers_.back()->duration();
1913 if (duration == kNoTimestamp() || duration == base::TimeDelta())
1914 duration = GetApproximateDuration();
1915 return GetEndTimestamp() + duration;
1918 base::TimeDelta SourceBufferRange::NextKeyframeTimestamp(
1919 base::TimeDelta timestamp) {
1920 DCHECK(!keyframe_map_.empty());
1922 if (timestamp < GetStartTimestamp() || timestamp >= GetBufferedEndTimestamp())
1923 return kNoTimestamp();
1925 KeyframeMap::iterator itr = GetFirstKeyframeAt(timestamp, false);
1926 if (itr == keyframe_map_.end())
1927 return kNoTimestamp();
1931 base::TimeDelta SourceBufferRange::KeyframeBeforeTimestamp(
1932 base::TimeDelta timestamp) {
1933 DCHECK(!keyframe_map_.empty());
1935 if (timestamp < GetStartTimestamp() || timestamp >= GetBufferedEndTimestamp())
1936 return kNoTimestamp();
1938 return GetFirstKeyframeBefore(timestamp)->first;
1941 bool SourceBufferRange::IsNextInSequence(
1942 base::TimeDelta timestamp, bool is_keyframe) const {
1943 base::TimeDelta end = buffers_.back()->GetDecodeTimestamp();
1944 return (end < timestamp && timestamp <= end + GetFudgeRoom()) ||
1945 (timestamp == end && AllowSameTimestamp(
1946 buffers_.back()->IsKeyframe(), is_keyframe, is_video_));
1949 base::TimeDelta SourceBufferRange::GetFudgeRoom() const {
1950 return ComputeFudgeRoom(GetApproximateDuration());
1953 base::TimeDelta SourceBufferRange::GetApproximateDuration() const {
1954 base::TimeDelta max_interbuffer_distance = interbuffer_distance_cb_.Run();
1955 DCHECK(max_interbuffer_distance != kNoTimestamp());
1956 return max_interbuffer_distance;
1959 } // namespace media