cleanup: pass string as const reference from c/b/extension
[chromium-blink-merge.git] / media / filters / source_buffer_stream.cc
blob6207c99810a58cc09998a68db7704318a9475d79
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"
7 #include <algorithm>
8 #include <map>
10 #include "base/bind.h"
11 #include "base/debug/trace_event.h"
12 #include "base/logging.h"
13 #include "media/base/audio_splicer.h"
15 namespace media {
17 typedef StreamParser::BufferQueue BufferQueue;
19 // Buffers with the same timestamp are only allowed under certain conditions.
20 // More precisely, it is allowed in all situations except when the previous
21 // frame is not a key frame and the current is a key frame.
22 // Examples of situations where DTS of two consecutive frames can be equal:
23 // - Video: VP8 Alt-Ref frames.
24 // - Video: IPBPBP...: DTS for I frame and for P frame can be equal.
25 // - Text track cues that start at same time.
26 // Returns true if |prev_is_keyframe| and |current_is_keyframe| indicate a
27 // same timestamp situation that is allowed. False is returned otherwise.
28 static bool AllowSameTimestamp(
29 bool prev_is_keyframe, bool current_is_keyframe,
30 SourceBufferStream::Type type) {
31 return prev_is_keyframe || !current_is_keyframe;
34 // Returns the config ID of |buffer| if |buffer| has no splice buffers or
35 // |index| is out of range. Otherwise returns the config ID for the fade out
36 // preroll buffer at position |index|.
37 static int GetConfigId(StreamParserBuffer* buffer, size_t index) {
38 return index < buffer->get_splice_buffers().size()
39 ? buffer->get_splice_buffers()[index]->GetConfigId()
40 : buffer->GetConfigId();
43 // Helper class representing a range of buffered data. All buffers in a
44 // SourceBufferRange are ordered sequentially in presentation order with no
45 // gaps.
46 class SourceBufferRange {
47 public:
48 // Returns the maximum distance in time between any buffer seen in this
49 // stream. Used to estimate the duration of a buffer if its duration is not
50 // known.
51 typedef base::Callback<base::TimeDelta()> InterbufferDistanceCB;
53 // Creates a source buffer range with |new_buffers|. |new_buffers| cannot be
54 // empty and the front of |new_buffers| must be a keyframe.
55 // |media_segment_start_time| refers to the starting timestamp for the media
56 // segment to which these buffers belong.
57 SourceBufferRange(SourceBufferStream::Type type,
58 const BufferQueue& new_buffers,
59 base::TimeDelta media_segment_start_time,
60 const InterbufferDistanceCB& interbuffer_distance_cb);
62 // Appends |buffers| to the end of the range and updates |keyframe_map_| as
63 // it encounters new keyframes. Assumes |buffers| belongs at the end of the
64 // range.
65 void AppendBuffersToEnd(const BufferQueue& buffers);
66 bool CanAppendBuffersToEnd(const BufferQueue& buffers) const;
68 // Appends the buffers from |range| into this range.
69 // The first buffer in |range| must come directly after the last buffer
70 // in this range.
71 // If |transfer_current_position| is true, |range|'s |next_buffer_index_|
72 // is transfered to this SourceBufferRange.
73 void AppendRangeToEnd(const SourceBufferRange& range,
74 bool transfer_current_position);
75 bool CanAppendRangeToEnd(const SourceBufferRange& range) const;
77 // Updates |next_buffer_index_| to point to the Buffer containing |timestamp|.
78 // Assumes |timestamp| is valid and in this range.
79 void Seek(base::TimeDelta timestamp);
81 // Updates |next_buffer_index_| to point to next keyframe after or equal to
82 // |timestamp|.
83 void SeekAheadTo(base::TimeDelta timestamp);
85 // Updates |next_buffer_index_| to point to next keyframe strictly after
86 // |timestamp|.
87 void SeekAheadPast(base::TimeDelta timestamp);
89 // Seeks to the beginning of the range.
90 void SeekToStart();
92 // Finds the next keyframe from |buffers_| after |timestamp| (or at
93 // |timestamp| if |is_exclusive| is false) and creates and returns a new
94 // SourceBufferRange with the buffers from that keyframe onward.
95 // The buffers in the new SourceBufferRange are moved out of this range. If
96 // there is no keyframe after |timestamp|, SplitRange() returns null and this
97 // range is unmodified.
98 SourceBufferRange* SplitRange(base::TimeDelta timestamp, bool is_exclusive);
100 // Deletes the buffers from this range starting at |timestamp|, exclusive if
101 // |is_exclusive| is true, inclusive otherwise.
102 // Resets |next_buffer_index_| if the buffer at |next_buffer_index_| was
103 // deleted, and deletes the |keyframe_map_| entries for the buffers that
104 // were removed.
105 // |deleted_buffers| contains the buffers that were deleted from this range,
106 // starting at the buffer that had been at |next_buffer_index_|.
107 // Returns true if everything in the range was deleted. Otherwise
108 // returns false.
109 bool TruncateAt(base::TimeDelta timestamp,
110 BufferQueue* deleted_buffers, bool is_exclusive);
111 // Deletes all buffers in range.
112 void DeleteAll(BufferQueue* deleted_buffers);
114 // Deletes a GOP from the front or back of the range and moves these
115 // buffers into |deleted_buffers|. Returns the number of bytes deleted from
116 // the range (i.e. the size in bytes of |deleted_buffers|).
117 int DeleteGOPFromFront(BufferQueue* deleted_buffers);
118 int DeleteGOPFromBack(BufferQueue* deleted_buffers);
120 // Gets the range of GOP to secure at least |bytes_to_free| from
121 // [|start_timestamp|, |end_timestamp|).
122 // Returns the size of the buffers to secure if the buffers of
123 // [|start_timestamp|, |end_removal_timestamp|) is removed.
124 // Will not update |end_removal_timestamp| if the returned size is 0.
125 int GetRemovalGOP(
126 base::TimeDelta start_timestamp, base::TimeDelta end_timestamp,
127 int bytes_to_free, base::TimeDelta* end_removal_timestamp);
129 // Indicates whether the GOP at the beginning or end of the range contains the
130 // next buffer position.
131 bool FirstGOPContainsNextBufferPosition() const;
132 bool LastGOPContainsNextBufferPosition() const;
134 // Updates |out_buffer| with the next buffer in presentation order. Seek()
135 // must be called before calls to GetNextBuffer(), and buffers are returned
136 // in order from the last call to Seek(). Returns true if |out_buffer| is
137 // filled with a valid buffer, false if there is not enough data to fulfill
138 // the request.
139 bool GetNextBuffer(scoped_refptr<StreamParserBuffer>* out_buffer);
140 bool HasNextBuffer() const;
142 // Returns the config ID for the buffer that will be returned by
143 // GetNextBuffer().
144 int GetNextConfigId() const;
146 // Returns true if the range knows the position of the next buffer it should
147 // return, i.e. it has been Seek()ed. This does not necessarily mean that it
148 // has the next buffer yet.
149 bool HasNextBufferPosition() const;
151 // Resets this range to an "unseeked" state.
152 void ResetNextBufferPosition();
154 // Returns the timestamp of the next buffer that will be returned from
155 // GetNextBuffer(), or kNoTimestamp() if the timestamp is unknown.
156 base::TimeDelta GetNextTimestamp() const;
158 // Returns the start timestamp of the range.
159 base::TimeDelta GetStartTimestamp() const;
161 // Returns the timestamp of the last buffer in the range.
162 base::TimeDelta GetEndTimestamp() const;
164 // Returns the timestamp for the end of the buffered region in this range.
165 // This is an approximation if the duration for the last buffer in the range
166 // is unset.
167 base::TimeDelta GetBufferedEndTimestamp() const;
169 // Gets the timestamp for the keyframe that is after |timestamp|. If
170 // there isn't a keyframe in the range after |timestamp| then kNoTimestamp()
171 // is returned.
172 base::TimeDelta NextKeyframeTimestamp(base::TimeDelta timestamp);
174 // Gets the timestamp for the closest keyframe that is <= |timestamp|. If
175 // there isn't a keyframe before |timestamp| or |timestamp| is outside
176 // this range, then kNoTimestamp() is returned.
177 base::TimeDelta KeyframeBeforeTimestamp(base::TimeDelta timestamp);
179 // Returns whether a buffer with a starting timestamp of |timestamp| would
180 // belong in this range. This includes a buffer that would be appended to
181 // the end of the range.
182 bool BelongsToRange(base::TimeDelta timestamp) const;
184 // Returns true if the range has enough data to seek to the specified
185 // |timestamp|, false otherwise.
186 bool CanSeekTo(base::TimeDelta timestamp) const;
188 // Returns true if this range's buffered timespan completely overlaps the
189 // buffered timespan of |range|.
190 bool CompletelyOverlaps(const SourceBufferRange& range) const;
192 // Returns true if the end of this range contains buffers that overlaps with
193 // the beginning of |range|.
194 bool EndOverlaps(const SourceBufferRange& range) const;
196 // Returns true if |timestamp| is the timestamp of the next buffer in
197 // sequence after |buffers_.back()|, false otherwise.
198 bool IsNextInSequence(base::TimeDelta timestamp, bool is_keyframe) const;
200 // Adds all buffers which overlap [start, end) to the end of |buffers|. If
201 // no buffers exist in the range returns false, true otherwise.
202 bool GetBuffersInRange(base::TimeDelta start, base::TimeDelta end,
203 BufferQueue* buffers);
205 int size_in_bytes() const { return size_in_bytes_; }
207 private:
208 typedef std::map<base::TimeDelta, int> KeyframeMap;
210 // Seeks the range to the next keyframe after |timestamp|. If
211 // |skip_given_timestamp| is true, the seek will go to a keyframe with a
212 // timestamp strictly greater than |timestamp|.
213 void SeekAhead(base::TimeDelta timestamp, bool skip_given_timestamp);
215 // Returns an iterator in |buffers_| pointing to the buffer at |timestamp|.
216 // If |skip_given_timestamp| is true, this returns the first buffer with
217 // timestamp greater than |timestamp|.
218 BufferQueue::iterator GetBufferItrAt(
219 base::TimeDelta timestamp, bool skip_given_timestamp);
221 // Returns an iterator in |keyframe_map_| pointing to the next keyframe after
222 // |timestamp|. If |skip_given_timestamp| is true, this returns the first
223 // keyframe with a timestamp strictly greater than |timestamp|.
224 KeyframeMap::iterator GetFirstKeyframeAt(
225 base::TimeDelta timestamp, bool skip_given_timestamp);
227 // Returns an iterator in |keyframe_map_| pointing to the first keyframe
228 // before or at |timestamp|.
229 KeyframeMap::iterator GetFirstKeyframeBefore(base::TimeDelta timestamp);
231 // Helper method to delete buffers in |buffers_| starting at
232 // |starting_point|, an iterator in |buffers_|.
233 // Returns true if everything in the range was removed. Returns
234 // false if the range still contains buffers.
235 bool TruncateAt(const BufferQueue::iterator& starting_point,
236 BufferQueue* deleted_buffers);
238 // Frees the buffers in |buffers_| from [|start_point|,|ending_point|) and
239 // updates the |size_in_bytes_| accordingly. Does not update |keyframe_map_|.
240 void FreeBufferRange(const BufferQueue::iterator& starting_point,
241 const BufferQueue::iterator& ending_point);
243 // Returns the distance in time estimating how far from the beginning or end
244 // of this range a buffer can be to considered in the range.
245 base::TimeDelta GetFudgeRoom() const;
247 // Returns the approximate duration of a buffer in this range.
248 base::TimeDelta GetApproximateDuration() const;
250 // Type of this stream.
251 const SourceBufferStream::Type type_;
253 // An ordered list of buffers in this range.
254 BufferQueue buffers_;
256 // Maps keyframe timestamps to its index position in |buffers_|.
257 KeyframeMap keyframe_map_;
259 // Index base of all positions in |keyframe_map_|. In other words, the
260 // real position of entry |k| of |keyframe_map_| in the range is:
261 // keyframe_map_[k] - keyframe_map_index_base_
262 int keyframe_map_index_base_;
264 // Index into |buffers_| for the next buffer to be returned by
265 // GetNextBuffer(), set to -1 before Seek().
266 int next_buffer_index_;
268 // If the first buffer in this range is the beginning of a media segment,
269 // |media_segment_start_time_| is the time when the media segment begins.
270 // |media_segment_start_time_| may be <= the timestamp of the first buffer in
271 // |buffers_|. |media_segment_start_time_| is kNoTimestamp() if this range
272 // does not start at the beginning of a media segment, which can only happen
273 // garbage collection or after an end overlap that results in a split range
274 // (we don't have a way of knowing the media segment timestamp for the new
275 // range).
276 base::TimeDelta media_segment_start_time_;
278 // Called to get the largest interbuffer distance seen so far in the stream.
279 InterbufferDistanceCB interbuffer_distance_cb_;
281 // Stores the amount of memory taken up by the data in |buffers_|.
282 int size_in_bytes_;
284 DISALLOW_COPY_AND_ASSIGN(SourceBufferRange);
287 } // namespace media
289 // Helper method that returns true if |ranges| is sorted in increasing order,
290 // false otherwise.
291 static bool IsRangeListSorted(
292 const std::list<media::SourceBufferRange*>& ranges) {
293 base::TimeDelta prev = media::kNoTimestamp();
294 for (std::list<media::SourceBufferRange*>::const_iterator itr =
295 ranges.begin(); itr != ranges.end(); ++itr) {
296 if (prev != media::kNoTimestamp() && prev >= (*itr)->GetStartTimestamp())
297 return false;
298 prev = (*itr)->GetEndTimestamp();
300 return true;
303 // Comparison operators for std::upper_bound() and std::lower_bound().
304 static bool CompareTimeDeltaToStreamParserBuffer(
305 const base::TimeDelta& decode_timestamp,
306 const scoped_refptr<media::StreamParserBuffer>& buffer) {
307 return decode_timestamp < buffer->GetDecodeTimestamp();
309 static bool CompareStreamParserBufferToTimeDelta(
310 const scoped_refptr<media::StreamParserBuffer>& buffer,
311 const base::TimeDelta& decode_timestamp) {
312 return buffer->GetDecodeTimestamp() < decode_timestamp;
315 // Returns an estimate of how far from the beginning or end of a range a buffer
316 // can be to still be considered in the range, given the |approximate_duration|
317 // of a buffer in the stream.
318 static base::TimeDelta ComputeFudgeRoom(base::TimeDelta approximate_duration) {
319 // Because we do not know exactly when is the next timestamp, any buffer
320 // that starts within 2x the approximate duration of a buffer is considered
321 // within this range.
322 return 2 * approximate_duration;
325 // An arbitrarily-chosen number to estimate the duration of a buffer if none
326 // is set and there's not enough information to get a better estimate.
327 static int kDefaultBufferDurationInMs = 125;
329 // The amount of time the beginning of the buffered data can differ from the
330 // start time in order to still be considered the start of stream.
331 static base::TimeDelta kSeekToStartFudgeRoom() {
332 return base::TimeDelta::FromMilliseconds(1000);
334 // The maximum amount of data in bytes the stream will keep in memory.
335 // 12MB: approximately 5 minutes of 320Kbps content.
336 // 150MB: approximately 5 minutes of 4Mbps content.
337 static int kDefaultAudioMemoryLimit = 12 * 1024 * 1024;
338 static int kDefaultVideoMemoryLimit = 150 * 1024 * 1024;
340 namespace media {
342 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config,
343 const LogCB& log_cb,
344 bool splice_frames_enabled)
345 : log_cb_(log_cb),
346 current_config_index_(0),
347 append_config_index_(0),
348 seek_pending_(false),
349 end_of_stream_(false),
350 seek_buffer_timestamp_(kNoTimestamp()),
351 selected_range_(NULL),
352 media_segment_start_time_(kNoTimestamp()),
353 range_for_next_append_(ranges_.end()),
354 new_media_segment_(false),
355 last_appended_buffer_timestamp_(kNoTimestamp()),
356 last_appended_buffer_is_keyframe_(false),
357 last_output_buffer_timestamp_(kNoTimestamp()),
358 max_interbuffer_distance_(kNoTimestamp()),
359 memory_limit_(kDefaultAudioMemoryLimit),
360 config_change_pending_(false),
361 splice_buffers_index_(0),
362 pre_splice_complete_(false),
363 splice_frames_enabled_(splice_frames_enabled) {
364 DCHECK(audio_config.IsValidConfig());
365 audio_configs_.push_back(audio_config);
368 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config,
369 const LogCB& log_cb,
370 bool splice_frames_enabled)
371 : log_cb_(log_cb),
372 current_config_index_(0),
373 append_config_index_(0),
374 seek_pending_(false),
375 end_of_stream_(false),
376 seek_buffer_timestamp_(kNoTimestamp()),
377 selected_range_(NULL),
378 media_segment_start_time_(kNoTimestamp()),
379 range_for_next_append_(ranges_.end()),
380 new_media_segment_(false),
381 last_appended_buffer_timestamp_(kNoTimestamp()),
382 last_appended_buffer_is_keyframe_(false),
383 last_output_buffer_timestamp_(kNoTimestamp()),
384 max_interbuffer_distance_(kNoTimestamp()),
385 memory_limit_(kDefaultVideoMemoryLimit),
386 config_change_pending_(false),
387 splice_buffers_index_(0),
388 pre_splice_complete_(false),
389 splice_frames_enabled_(splice_frames_enabled) {
390 DCHECK(video_config.IsValidConfig());
391 video_configs_.push_back(video_config);
394 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config,
395 const LogCB& log_cb,
396 bool splice_frames_enabled)
397 : log_cb_(log_cb),
398 current_config_index_(0),
399 append_config_index_(0),
400 text_track_config_(text_config),
401 seek_pending_(false),
402 end_of_stream_(false),
403 seek_buffer_timestamp_(kNoTimestamp()),
404 selected_range_(NULL),
405 media_segment_start_time_(kNoTimestamp()),
406 range_for_next_append_(ranges_.end()),
407 new_media_segment_(false),
408 last_appended_buffer_timestamp_(kNoTimestamp()),
409 last_appended_buffer_is_keyframe_(false),
410 last_output_buffer_timestamp_(kNoTimestamp()),
411 max_interbuffer_distance_(kNoTimestamp()),
412 memory_limit_(kDefaultAudioMemoryLimit),
413 config_change_pending_(false),
414 splice_buffers_index_(0),
415 pre_splice_complete_(false),
416 splice_frames_enabled_(splice_frames_enabled) {}
418 SourceBufferStream::~SourceBufferStream() {
419 while (!ranges_.empty()) {
420 delete ranges_.front();
421 ranges_.pop_front();
425 void SourceBufferStream::OnNewMediaSegment(
426 base::TimeDelta media_segment_start_time) {
427 DCHECK(!end_of_stream_);
428 media_segment_start_time_ = media_segment_start_time;
429 new_media_segment_ = true;
431 RangeList::iterator last_range = range_for_next_append_;
432 range_for_next_append_ = FindExistingRangeFor(media_segment_start_time);
434 // Only reset |last_appended_buffer_timestamp_| if this new media segment is
435 // not adjacent to the previous media segment appended to the stream.
436 if (range_for_next_append_ == ranges_.end() ||
437 !AreAdjacentInSequence(last_appended_buffer_timestamp_,
438 media_segment_start_time)) {
439 last_appended_buffer_timestamp_ = kNoTimestamp();
440 last_appended_buffer_is_keyframe_ = false;
441 } else if (last_range != ranges_.end()) {
442 DCHECK(last_range == range_for_next_append_);
446 bool SourceBufferStream::Append(const BufferQueue& buffers) {
447 TRACE_EVENT2("media", "SourceBufferStream::Append",
448 "stream type", GetStreamTypeName(),
449 "buffers to append", buffers.size());
451 DCHECK(!buffers.empty());
452 DCHECK(media_segment_start_time_ != kNoTimestamp());
453 DCHECK(media_segment_start_time_ <= buffers.front()->GetDecodeTimestamp());
454 DCHECK(!end_of_stream_);
456 // New media segments must begin with a keyframe.
457 if (new_media_segment_ && !buffers.front()->IsKeyframe()) {
458 MEDIA_LOG(log_cb_) << "Media segment did not begin with keyframe.";
459 return false;
462 // Buffers within a media segment should be monotonically increasing.
463 if (!IsMonotonicallyIncreasing(buffers))
464 return false;
466 if (media_segment_start_time_ < base::TimeDelta() ||
467 buffers.front()->GetDecodeTimestamp() < base::TimeDelta()) {
468 MEDIA_LOG(log_cb_)
469 << "Cannot append a media segment with negative timestamps.";
470 return false;
473 if (!IsNextTimestampValid(buffers.front()->GetDecodeTimestamp(),
474 buffers.front()->IsKeyframe())) {
475 MEDIA_LOG(log_cb_) << "Invalid same timestamp construct detected at time "
476 << buffers.front()->GetDecodeTimestamp().InSecondsF();
478 return false;
481 UpdateMaxInterbufferDistance(buffers);
482 SetConfigIds(buffers);
484 // Save a snapshot of stream state before range modifications are made.
485 base::TimeDelta next_buffer_timestamp = GetNextBufferTimestamp();
486 BufferQueue deleted_buffers;
488 PrepareRangesForNextAppend(buffers, &deleted_buffers);
490 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise,
491 // create a new range with |buffers|.
492 if (range_for_next_append_ != ranges_.end()) {
493 (*range_for_next_append_)->AppendBuffersToEnd(buffers);
494 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp();
495 last_appended_buffer_is_keyframe_ = buffers.back()->IsKeyframe();
496 } else {
497 base::TimeDelta new_range_start_time = std::min(
498 media_segment_start_time_, buffers.front()->GetDecodeTimestamp());
499 const BufferQueue* buffers_for_new_range = &buffers;
500 BufferQueue trimmed_buffers;
502 // If the new range is not being created because of a new media
503 // segment, then we must make sure that we start with a keyframe.
504 // This can happen if the GOP in the previous append gets destroyed
505 // by a Remove() call.
506 if (!new_media_segment_ && !buffers.front()->IsKeyframe()) {
507 BufferQueue::const_iterator itr = buffers.begin();
509 // Scan past all the non-keyframes.
510 while (itr != buffers.end() && !(*itr)->IsKeyframe()) {
511 ++itr;
514 // If we didn't find a keyframe, then update the last appended
515 // buffer state and return.
516 if (itr == buffers.end()) {
517 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp();
518 last_appended_buffer_is_keyframe_ = buffers.back()->IsKeyframe();
519 return true;
522 // Copy the first keyframe and everything after it into |trimmed_buffers|.
523 trimmed_buffers.assign(itr, buffers.end());
525 new_range_start_time = trimmed_buffers.front()->GetDecodeTimestamp();
526 buffers_for_new_range = &trimmed_buffers;
529 range_for_next_append_ =
530 AddToRanges(new SourceBufferRange(
531 GetType(), *buffers_for_new_range, new_range_start_time,
532 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance,
533 base::Unretained(this))));
534 last_appended_buffer_timestamp_ =
535 buffers_for_new_range->back()->GetDecodeTimestamp();
536 last_appended_buffer_is_keyframe_ =
537 buffers_for_new_range->back()->IsKeyframe();
540 new_media_segment_ = false;
542 MergeWithAdjacentRangeIfNecessary(range_for_next_append_);
544 // Seek to try to fulfill a previous call to Seek().
545 if (seek_pending_) {
546 DCHECK(!selected_range_);
547 DCHECK(deleted_buffers.empty());
548 Seek(seek_buffer_timestamp_);
551 if (!deleted_buffers.empty()) {
552 base::TimeDelta start_of_deleted =
553 deleted_buffers.front()->GetDecodeTimestamp();
555 DCHECK(track_buffer_.empty() ||
556 track_buffer_.back()->GetDecodeTimestamp() < start_of_deleted)
557 << "decode timestamp "
558 << track_buffer_.back()->GetDecodeTimestamp().InSecondsF() << " sec"
559 << ", start_of_deleted " << start_of_deleted.InSecondsF()<< " sec";
561 track_buffer_.insert(track_buffer_.end(), deleted_buffers.begin(),
562 deleted_buffers.end());
565 // Prune any extra buffers in |track_buffer_| if new keyframes
566 // are appended to the range covered by |track_buffer_|.
567 if (!track_buffer_.empty()) {
568 base::TimeDelta keyframe_timestamp =
569 FindKeyframeAfterTimestamp(track_buffer_.front()->GetDecodeTimestamp());
570 if (keyframe_timestamp != kNoTimestamp())
571 PruneTrackBuffer(keyframe_timestamp);
574 SetSelectedRangeIfNeeded(next_buffer_timestamp);
576 GarbageCollectIfNeeded();
578 DCHECK(IsRangeListSorted(ranges_));
579 DCHECK(OnlySelectedRangeIsSeeked());
580 return true;
583 void SourceBufferStream::Remove(base::TimeDelta start, base::TimeDelta end,
584 base::TimeDelta duration) {
585 DVLOG(1) << __FUNCTION__ << "(" << start.InSecondsF()
586 << ", " << end.InSecondsF()
587 << ", " << duration.InSecondsF() << ")";
588 DCHECK(start >= base::TimeDelta()) << start.InSecondsF();
589 DCHECK(start < end) << "start " << start.InSecondsF()
590 << " end " << end.InSecondsF();
591 DCHECK(duration != kNoTimestamp());
593 base::TimeDelta remove_end_timestamp = duration;
594 base::TimeDelta keyframe_timestamp = FindKeyframeAfterTimestamp(end);
595 if (keyframe_timestamp != kNoTimestamp()) {
596 remove_end_timestamp = keyframe_timestamp;
597 } else if (end < remove_end_timestamp) {
598 remove_end_timestamp = end;
601 BufferQueue deleted_buffers;
602 RemoveInternal(start, remove_end_timestamp, false, &deleted_buffers);
604 if (!deleted_buffers.empty())
605 SetSelectedRangeIfNeeded(deleted_buffers.front()->GetDecodeTimestamp());
608 void SourceBufferStream::RemoveInternal(
609 base::TimeDelta start, base::TimeDelta end, bool is_exclusive,
610 BufferQueue* deleted_buffers) {
611 DVLOG(1) << __FUNCTION__ << "(" << start.InSecondsF()
612 << ", " << end.InSecondsF()
613 << ", " << is_exclusive << ")";
615 DCHECK(start >= base::TimeDelta());
616 DCHECK(start < end) << "start " << start.InSecondsF()
617 << " end " << end.InSecondsF();
618 DCHECK(deleted_buffers);
620 RangeList::iterator itr = ranges_.begin();
622 while (itr != ranges_.end()) {
623 SourceBufferRange* range = *itr;
624 if (range->GetStartTimestamp() >= end)
625 break;
627 // Split off any remaining end piece and add it to |ranges_|.
628 SourceBufferRange* new_range = range->SplitRange(end, is_exclusive);
629 if (new_range) {
630 itr = ranges_.insert(++itr, new_range);
631 --itr;
633 // Update the selected range if the next buffer position was transferred
634 // to |new_range|.
635 if (new_range->HasNextBufferPosition())
636 SetSelectedRange(new_range);
639 // Truncate the current range so that it only contains data before
640 // the removal range.
641 BufferQueue saved_buffers;
642 bool delete_range = range->TruncateAt(start, &saved_buffers, is_exclusive);
644 // Check to see if the current playback position was removed and
645 // update the selected range appropriately.
646 if (!saved_buffers.empty()) {
647 DCHECK(!range->HasNextBufferPosition());
648 DCHECK(deleted_buffers->empty());
650 *deleted_buffers = saved_buffers;
653 if (range == selected_range_ && !range->HasNextBufferPosition())
654 SetSelectedRange(NULL);
656 // If the current range now is completely covered by the removal
657 // range then delete it and move on.
658 if (delete_range) {
659 DeleteAndRemoveRange(&itr);
660 continue;
663 // Clear |range_for_next_append_| if we determine that the removal
664 // operation makes it impossible for the next append to be added
665 // to the current range.
666 if (range_for_next_append_ != ranges_.end() &&
667 *range_for_next_append_ == range &&
668 last_appended_buffer_timestamp_ != kNoTimestamp()) {
669 base::TimeDelta potential_next_append_timestamp =
670 last_appended_buffer_timestamp_ +
671 base::TimeDelta::FromInternalValue(1);
673 if (!range->BelongsToRange(potential_next_append_timestamp)) {
674 DVLOG(1) << "Resetting range_for_next_append_ since the next append"
675 << " can't add to the current range.";
676 range_for_next_append_ =
677 FindExistingRangeFor(potential_next_append_timestamp);
681 // Move on to the next range.
682 ++itr;
685 DCHECK(IsRangeListSorted(ranges_));
686 DCHECK(OnlySelectedRangeIsSeeked());
687 DVLOG(1) << __FUNCTION__ << " : done";
690 void SourceBufferStream::ResetSeekState() {
691 SetSelectedRange(NULL);
692 track_buffer_.clear();
693 config_change_pending_ = false;
694 last_output_buffer_timestamp_ = kNoTimestamp();
695 splice_buffers_index_ = 0;
696 splice_buffer_ = NULL;
697 pre_splice_complete_ = false;
700 bool SourceBufferStream::ShouldSeekToStartOfBuffered(
701 base::TimeDelta seek_timestamp) const {
702 if (ranges_.empty())
703 return false;
704 base::TimeDelta beginning_of_buffered =
705 ranges_.front()->GetStartTimestamp();
706 return (seek_timestamp <= beginning_of_buffered &&
707 beginning_of_buffered < kSeekToStartFudgeRoom());
710 bool SourceBufferStream::IsMonotonicallyIncreasing(
711 const BufferQueue& buffers) const {
712 DCHECK(!buffers.empty());
713 base::TimeDelta prev_timestamp = last_appended_buffer_timestamp_;
714 bool prev_is_keyframe = last_appended_buffer_is_keyframe_;
715 for (BufferQueue::const_iterator itr = buffers.begin();
716 itr != buffers.end(); ++itr) {
717 base::TimeDelta current_timestamp = (*itr)->GetDecodeTimestamp();
718 bool current_is_keyframe = (*itr)->IsKeyframe();
719 DCHECK(current_timestamp != kNoTimestamp());
721 if (prev_timestamp != kNoTimestamp()) {
722 if (current_timestamp < prev_timestamp) {
723 MEDIA_LOG(log_cb_) << "Buffers were not monotonically increasing.";
724 return false;
727 if (current_timestamp == prev_timestamp &&
728 !AllowSameTimestamp(prev_is_keyframe, current_is_keyframe,
729 GetType())) {
730 MEDIA_LOG(log_cb_) << "Unexpected combination of buffers with the"
731 << " same timestamp detected at "
732 << current_timestamp.InSecondsF();
733 return false;
737 prev_timestamp = current_timestamp;
738 prev_is_keyframe = current_is_keyframe;
740 return true;
743 bool SourceBufferStream::IsNextTimestampValid(
744 base::TimeDelta next_timestamp, bool next_is_keyframe) const {
745 return (last_appended_buffer_timestamp_ != next_timestamp) ||
746 new_media_segment_ ||
747 AllowSameTimestamp(last_appended_buffer_is_keyframe_, next_is_keyframe,
748 GetType());
752 bool SourceBufferStream::OnlySelectedRangeIsSeeked() const {
753 for (RangeList::const_iterator itr = ranges_.begin();
754 itr != ranges_.end(); ++itr) {
755 if ((*itr)->HasNextBufferPosition() && (*itr) != selected_range_)
756 return false;
758 return !selected_range_ || selected_range_->HasNextBufferPosition();
761 void SourceBufferStream::UpdateMaxInterbufferDistance(
762 const BufferQueue& buffers) {
763 DCHECK(!buffers.empty());
764 base::TimeDelta prev_timestamp = last_appended_buffer_timestamp_;
765 for (BufferQueue::const_iterator itr = buffers.begin();
766 itr != buffers.end(); ++itr) {
767 base::TimeDelta current_timestamp = (*itr)->GetDecodeTimestamp();
768 DCHECK(current_timestamp != kNoTimestamp());
770 if (prev_timestamp != kNoTimestamp()) {
771 base::TimeDelta interbuffer_distance = current_timestamp - prev_timestamp;
772 if (max_interbuffer_distance_ == kNoTimestamp()) {
773 max_interbuffer_distance_ = interbuffer_distance;
774 } else {
775 max_interbuffer_distance_ =
776 std::max(max_interbuffer_distance_, interbuffer_distance);
779 prev_timestamp = current_timestamp;
783 void SourceBufferStream::SetConfigIds(const BufferQueue& buffers) {
784 for (BufferQueue::const_iterator itr = buffers.begin();
785 itr != buffers.end(); ++itr) {
786 (*itr)->SetConfigId(append_config_index_);
790 void SourceBufferStream::GarbageCollectIfNeeded() {
791 // Compute size of |ranges_|.
792 int ranges_size = 0;
793 for (RangeList::iterator itr = ranges_.begin(); itr != ranges_.end(); ++itr)
794 ranges_size += (*itr)->size_in_bytes();
796 // Return if we're under or at the memory limit.
797 if (ranges_size <= memory_limit_)
798 return;
800 int bytes_to_free = ranges_size - memory_limit_;
802 // Begin deleting after the last appended buffer.
803 int bytes_freed = FreeBuffersAfterLastAppended(bytes_to_free);
805 // Begin deleting from the front.
806 if (bytes_to_free - bytes_freed > 0)
807 bytes_freed += FreeBuffers(bytes_to_free - bytes_freed, false);
809 // Begin deleting from the back.
810 if (bytes_to_free - bytes_freed > 0)
811 FreeBuffers(bytes_to_free - bytes_freed, true);
814 int SourceBufferStream::FreeBuffersAfterLastAppended(int total_bytes_to_free) {
815 base::TimeDelta next_buffer_timestamp = GetNextBufferTimestamp();
816 if (last_appended_buffer_timestamp_ == kNoTimestamp() ||
817 next_buffer_timestamp == kNoTimestamp() ||
818 last_appended_buffer_timestamp_ >= next_buffer_timestamp) {
819 return 0;
822 base::TimeDelta remove_range_start = last_appended_buffer_timestamp_;
823 if (last_appended_buffer_is_keyframe_)
824 remove_range_start += GetMaxInterbufferDistance();
826 base::TimeDelta remove_range_start_keyframe = FindKeyframeAfterTimestamp(
827 remove_range_start);
828 if (remove_range_start_keyframe != kNoTimestamp())
829 remove_range_start = remove_range_start_keyframe;
830 if (remove_range_start >= next_buffer_timestamp)
831 return 0;
833 base::TimeDelta remove_range_end;
834 int bytes_freed = GetRemovalRange(
835 remove_range_start, next_buffer_timestamp, total_bytes_to_free,
836 &remove_range_end);
837 if (bytes_freed > 0)
838 Remove(remove_range_start, remove_range_end, next_buffer_timestamp);
839 return bytes_freed;
842 int SourceBufferStream::GetRemovalRange(
843 base::TimeDelta start_timestamp, base::TimeDelta end_timestamp,
844 int total_bytes_to_free, base::TimeDelta* removal_end_timestamp) {
845 DCHECK(start_timestamp >= base::TimeDelta()) << start_timestamp.InSecondsF();
846 DCHECK(start_timestamp < end_timestamp)
847 << "start " << start_timestamp.InSecondsF()
848 << ", end " << end_timestamp.InSecondsF();
850 int bytes_to_free = total_bytes_to_free;
851 int bytes_freed = 0;
853 for (RangeList::iterator itr = ranges_.begin();
854 itr != ranges_.end() && bytes_to_free > 0; ++itr) {
855 SourceBufferRange* range = *itr;
856 if (range->GetStartTimestamp() >= end_timestamp)
857 break;
858 if (range->GetEndTimestamp() < start_timestamp)
859 continue;
861 int bytes_removed = range->GetRemovalGOP(
862 start_timestamp, end_timestamp, bytes_to_free, removal_end_timestamp);
863 bytes_to_free -= bytes_removed;
864 bytes_freed += bytes_removed;
866 return bytes_freed;
869 int SourceBufferStream::FreeBuffers(int total_bytes_to_free,
870 bool reverse_direction) {
871 TRACE_EVENT2("media", "SourceBufferStream::FreeBuffers",
872 "total bytes to free", total_bytes_to_free,
873 "reverse direction", reverse_direction);
875 DCHECK_GT(total_bytes_to_free, 0);
876 int bytes_to_free = total_bytes_to_free;
877 int bytes_freed = 0;
879 // This range will save the last GOP appended to |range_for_next_append_|
880 // if the buffers surrounding it get deleted during garbage collection.
881 SourceBufferRange* new_range_for_append = NULL;
883 while (!ranges_.empty() && bytes_to_free > 0) {
884 SourceBufferRange* current_range = NULL;
885 BufferQueue buffers;
886 int bytes_deleted = 0;
888 if (reverse_direction) {
889 current_range = ranges_.back();
890 if (current_range->LastGOPContainsNextBufferPosition()) {
891 DCHECK_EQ(current_range, selected_range_);
892 break;
894 bytes_deleted = current_range->DeleteGOPFromBack(&buffers);
895 } else {
896 current_range = ranges_.front();
897 if (current_range->FirstGOPContainsNextBufferPosition()) {
898 DCHECK_EQ(current_range, selected_range_);
899 break;
901 bytes_deleted = current_range->DeleteGOPFromFront(&buffers);
904 // Check to see if we've just deleted the GOP that was last appended.
905 base::TimeDelta end_timestamp = buffers.back()->GetDecodeTimestamp();
906 if (end_timestamp == last_appended_buffer_timestamp_) {
907 DCHECK(last_appended_buffer_timestamp_ != kNoTimestamp());
908 DCHECK(!new_range_for_append);
909 // Create a new range containing these buffers.
910 new_range_for_append = new SourceBufferRange(
911 GetType(), buffers, kNoTimestamp(),
912 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance,
913 base::Unretained(this)));
914 range_for_next_append_ = ranges_.end();
915 } else {
916 bytes_to_free -= bytes_deleted;
917 bytes_freed += bytes_deleted;
920 if (current_range->size_in_bytes() == 0) {
921 DCHECK_NE(current_range, selected_range_);
922 DCHECK(range_for_next_append_ == ranges_.end() ||
923 *range_for_next_append_ != current_range);
924 delete current_range;
925 reverse_direction ? ranges_.pop_back() : ranges_.pop_front();
929 // Insert |new_range_for_append| into |ranges_|, if applicable.
930 if (new_range_for_append) {
931 range_for_next_append_ = AddToRanges(new_range_for_append);
932 DCHECK(range_for_next_append_ != ranges_.end());
934 // Check to see if we need to merge |new_range_for_append| with the range
935 // before or after it. |new_range_for_append| is created whenever the last
936 // GOP appended is encountered, regardless of whether any buffers after it
937 // are ultimately deleted. Merging is necessary if there were no buffers
938 // (or very few buffers) deleted after creating |new_range_for_append|.
939 if (range_for_next_append_ != ranges_.begin()) {
940 RangeList::iterator range_before_next = range_for_next_append_;
941 --range_before_next;
942 MergeWithAdjacentRangeIfNecessary(range_before_next);
944 MergeWithAdjacentRangeIfNecessary(range_for_next_append_);
946 return bytes_freed;
949 void SourceBufferStream::PrepareRangesForNextAppend(
950 const BufferQueue& new_buffers, BufferQueue* deleted_buffers) {
951 DCHECK(deleted_buffers);
953 bool temporarily_select_range = false;
954 if (!track_buffer_.empty()) {
955 base::TimeDelta tb_timestamp = track_buffer_.back()->GetDecodeTimestamp();
956 base::TimeDelta seek_timestamp = FindKeyframeAfterTimestamp(tb_timestamp);
957 if (seek_timestamp != kNoTimestamp() &&
958 seek_timestamp < new_buffers.front()->GetDecodeTimestamp() &&
959 range_for_next_append_ != ranges_.end() &&
960 (*range_for_next_append_)->BelongsToRange(seek_timestamp)) {
961 DCHECK(tb_timestamp < seek_timestamp);
962 DCHECK(!selected_range_);
963 DCHECK(!(*range_for_next_append_)->HasNextBufferPosition());
965 // If there are GOPs between the end of the track buffer and the
966 // beginning of the new buffers, then temporarily seek the range
967 // so that the buffers between these two times will be deposited in
968 // |deleted_buffers| as if they were part of the current playback
969 // position.
970 // TODO(acolwell): Figure out a more elegant way to do this.
971 SeekAndSetSelectedRange(*range_for_next_append_, seek_timestamp);
972 temporarily_select_range = true;
976 // Handle splices between the existing buffers and the new buffers. If a
977 // splice is generated the timestamp and duration of the first buffer in
978 // |new_buffers| will be modified.
979 if (splice_frames_enabled_)
980 GenerateSpliceFrame(new_buffers);
982 base::TimeDelta prev_timestamp = last_appended_buffer_timestamp_;
983 bool prev_is_keyframe = last_appended_buffer_is_keyframe_;
984 base::TimeDelta next_timestamp = new_buffers.front()->GetDecodeTimestamp();
985 bool next_is_keyframe = new_buffers.front()->IsKeyframe();
987 if (prev_timestamp != kNoTimestamp() && prev_timestamp != next_timestamp) {
988 // Clean up the old buffers between the last appended buffer and the
989 // beginning of |new_buffers|.
990 RemoveInternal(prev_timestamp, next_timestamp, true, deleted_buffers);
993 // Make the delete range exclusive if we are dealing with an allowed same
994 // timestamp situation. This prevents the first buffer in the current append
995 // from deleting the last buffer in the previous append if both buffers
996 // have the same timestamp.
998 // The delete range should never be exclusive if a splice frame was generated
999 // because we don't generate splice frames for same timestamp situations.
1000 DCHECK(new_buffers.front()->splice_timestamp() !=
1001 new_buffers.front()->timestamp());
1002 const bool is_exclusive =
1003 new_buffers.front()->get_splice_buffers().empty() &&
1004 prev_timestamp == next_timestamp &&
1005 AllowSameTimestamp(prev_is_keyframe, next_is_keyframe, GetType());
1007 // Delete the buffers that |new_buffers| overlaps.
1008 base::TimeDelta start = new_buffers.front()->GetDecodeTimestamp();
1009 base::TimeDelta end = new_buffers.back()->GetDecodeTimestamp();
1010 base::TimeDelta duration = new_buffers.back()->duration();
1012 if (duration != kNoTimestamp() && duration > base::TimeDelta()) {
1013 end += duration;
1014 } else {
1015 // TODO(acolwell): Ensure all buffers actually have proper
1016 // duration info so that this hack isn't needed.
1017 // http://crbug.com/312836
1018 end += base::TimeDelta::FromInternalValue(1);
1021 RemoveInternal(start, end, is_exclusive, deleted_buffers);
1023 // Restore the range seek state if necessary.
1024 if (temporarily_select_range)
1025 SetSelectedRange(NULL);
1028 bool SourceBufferStream::AreAdjacentInSequence(
1029 base::TimeDelta first_timestamp, base::TimeDelta second_timestamp) const {
1030 return first_timestamp < second_timestamp &&
1031 second_timestamp <=
1032 first_timestamp + ComputeFudgeRoom(GetMaxInterbufferDistance());
1035 void SourceBufferStream::PruneTrackBuffer(const base::TimeDelta timestamp) {
1036 // If we don't have the next timestamp, we don't have anything to delete.
1037 if (timestamp == kNoTimestamp())
1038 return;
1040 while (!track_buffer_.empty() &&
1041 track_buffer_.back()->GetDecodeTimestamp() >= timestamp) {
1042 track_buffer_.pop_back();
1046 void SourceBufferStream::MergeWithAdjacentRangeIfNecessary(
1047 const RangeList::iterator& range_with_new_buffers_itr) {
1048 DCHECK(range_with_new_buffers_itr != ranges_.end());
1050 SourceBufferRange* range_with_new_buffers = *range_with_new_buffers_itr;
1051 RangeList::iterator next_range_itr = range_with_new_buffers_itr;
1052 ++next_range_itr;
1054 if (next_range_itr == ranges_.end() ||
1055 !range_with_new_buffers->CanAppendRangeToEnd(**next_range_itr)) {
1056 return;
1059 bool transfer_current_position = selected_range_ == *next_range_itr;
1060 range_with_new_buffers->AppendRangeToEnd(**next_range_itr,
1061 transfer_current_position);
1062 // Update |selected_range_| pointer if |range| has become selected after
1063 // merges.
1064 if (transfer_current_position)
1065 SetSelectedRange(range_with_new_buffers);
1067 if (next_range_itr == range_for_next_append_)
1068 range_for_next_append_ = range_with_new_buffers_itr;
1070 DeleteAndRemoveRange(&next_range_itr);
1073 void SourceBufferStream::Seek(base::TimeDelta timestamp) {
1074 DCHECK(timestamp >= base::TimeDelta());
1075 ResetSeekState();
1077 if (ShouldSeekToStartOfBuffered(timestamp)) {
1078 ranges_.front()->SeekToStart();
1079 SetSelectedRange(ranges_.front());
1080 seek_pending_ = false;
1081 return;
1084 seek_buffer_timestamp_ = timestamp;
1085 seek_pending_ = true;
1087 RangeList::iterator itr = ranges_.end();
1088 for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
1089 if ((*itr)->CanSeekTo(timestamp))
1090 break;
1093 if (itr == ranges_.end())
1094 return;
1096 SeekAndSetSelectedRange(*itr, timestamp);
1097 seek_pending_ = false;
1100 bool SourceBufferStream::IsSeekPending() const {
1101 return !(end_of_stream_ && IsEndSelected()) && seek_pending_;
1104 void SourceBufferStream::OnSetDuration(base::TimeDelta duration) {
1105 RangeList::iterator itr = ranges_.end();
1106 for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
1107 if ((*itr)->GetEndTimestamp() > duration)
1108 break;
1110 if (itr == ranges_.end())
1111 return;
1113 // Need to partially truncate this range.
1114 if ((*itr)->GetStartTimestamp() < duration) {
1115 bool delete_range = (*itr)->TruncateAt(duration, NULL, false);
1116 if ((*itr == selected_range_) && !selected_range_->HasNextBufferPosition())
1117 SetSelectedRange(NULL);
1119 if (delete_range) {
1120 DeleteAndRemoveRange(&itr);
1121 } else {
1122 ++itr;
1126 // Delete all ranges that begin after |duration|.
1127 while (itr != ranges_.end()) {
1128 // If we're about to delete the selected range, also reset the seek state.
1129 DCHECK((*itr)->GetStartTimestamp() >= duration);
1130 if (*itr == selected_range_)
1131 ResetSeekState();
1132 DeleteAndRemoveRange(&itr);
1136 SourceBufferStream::Status SourceBufferStream::GetNextBuffer(
1137 scoped_refptr<StreamParserBuffer>* out_buffer) {
1138 if (!splice_buffer_) {
1139 const SourceBufferStream::Status status = GetNextBufferInternal(out_buffer);
1141 // Just return if GetNextBufferInternal() failed or there's no fade out
1142 // preroll, there's nothing else to do.
1143 if (status != SourceBufferStream::kSuccess ||
1144 (*out_buffer)->get_splice_buffers().empty()) {
1145 return status;
1148 // Fall through into splice buffer processing.
1149 splice_buffers_index_ = 0;
1150 splice_buffer_.swap(*out_buffer);
1153 DCHECK(splice_buffer_);
1154 const BufferQueue& splice_buffers = splice_buffer_->get_splice_buffers();
1155 const size_t last_splice_buffer_index = splice_buffers.size() - 1;
1157 // Are there any splice buffers left to hand out? The last buffer should be
1158 // handed out separately since it represents the first post-splice buffer.
1159 if (splice_buffers_index_ < last_splice_buffer_index) {
1160 // Account for config changes which occur between fade out buffers.
1161 if (current_config_index_ !=
1162 splice_buffers[splice_buffers_index_]->GetConfigId()) {
1163 config_change_pending_ = true;
1164 DVLOG(1) << "Config change (splice buffer config ID does not match).";
1165 return SourceBufferStream::kConfigChange;
1168 // Every pre splice buffer must have the same splice_timestamp().
1169 DCHECK(splice_buffer_->splice_timestamp() ==
1170 splice_buffers[splice_buffers_index_]->splice_timestamp());
1172 *out_buffer = splice_buffers[splice_buffers_index_++];
1173 return SourceBufferStream::kSuccess;
1176 // Did we hand out the last pre-splice buffer on the previous call?
1177 if (!pre_splice_complete_) {
1178 DCHECK_EQ(splice_buffers_index_, last_splice_buffer_index);
1179 pre_splice_complete_ = true;
1180 config_change_pending_ = true;
1181 DVLOG(1) << "Config change (forced for fade in of splice frame).";
1182 return SourceBufferStream::kConfigChange;
1185 // All pre-splice buffers have been handed out and a config change completed,
1186 // so hand out the final buffer for fade in. Because a config change is
1187 // always issued prior to handing out this buffer, any changes in config id
1188 // have been inherently handled.
1189 DCHECK(pre_splice_complete_);
1190 DCHECK_EQ(splice_buffers_index_, splice_buffers.size() - 1);
1191 DCHECK(splice_buffers.back()->splice_timestamp() == kNoTimestamp());
1192 *out_buffer = splice_buffers.back();
1193 splice_buffer_ = NULL;
1194 splice_buffers_index_ = 0;
1195 pre_splice_complete_ = false;
1196 return SourceBufferStream::kSuccess;
1199 SourceBufferStream::Status SourceBufferStream::GetNextBufferInternal(
1200 scoped_refptr<StreamParserBuffer>* out_buffer) {
1201 CHECK(!config_change_pending_);
1203 if (!track_buffer_.empty()) {
1204 DCHECK(!selected_range_);
1205 scoped_refptr<StreamParserBuffer>& next_buffer = track_buffer_.front();
1207 // If the next buffer is an audio splice frame, the next effective config id
1208 // comes from the first splice buffer.
1209 if (GetConfigId(next_buffer, 0) != current_config_index_) {
1210 config_change_pending_ = true;
1211 DVLOG(1) << "Config change (track buffer config ID does not match).";
1212 return kConfigChange;
1215 *out_buffer = next_buffer;
1216 track_buffer_.pop_front();
1217 last_output_buffer_timestamp_ = (*out_buffer)->GetDecodeTimestamp();
1219 // If the track buffer becomes empty, then try to set the selected range
1220 // based on the timestamp of this buffer being returned.
1221 if (track_buffer_.empty())
1222 SetSelectedRangeIfNeeded(last_output_buffer_timestamp_);
1224 return kSuccess;
1227 if (!selected_range_ || !selected_range_->HasNextBuffer()) {
1228 if (end_of_stream_ && IsEndSelected())
1229 return kEndOfStream;
1230 return kNeedBuffer;
1233 if (selected_range_->GetNextConfigId() != current_config_index_) {
1234 config_change_pending_ = true;
1235 DVLOG(1) << "Config change (selected range config ID does not match).";
1236 return kConfigChange;
1239 CHECK(selected_range_->GetNextBuffer(out_buffer));
1240 last_output_buffer_timestamp_ = (*out_buffer)->GetDecodeTimestamp();
1241 return kSuccess;
1244 base::TimeDelta SourceBufferStream::GetNextBufferTimestamp() {
1245 if (!track_buffer_.empty())
1246 return track_buffer_.front()->GetDecodeTimestamp();
1248 if (!selected_range_)
1249 return kNoTimestamp();
1251 DCHECK(selected_range_->HasNextBufferPosition());
1252 return selected_range_->GetNextTimestamp();
1255 base::TimeDelta SourceBufferStream::GetEndBufferTimestamp() {
1256 if (!selected_range_)
1257 return kNoTimestamp();
1258 return selected_range_->GetEndTimestamp();
1261 SourceBufferStream::RangeList::iterator
1262 SourceBufferStream::FindExistingRangeFor(base::TimeDelta start_timestamp) {
1263 for (RangeList::iterator itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
1264 if ((*itr)->BelongsToRange(start_timestamp))
1265 return itr;
1267 return ranges_.end();
1270 SourceBufferStream::RangeList::iterator
1271 SourceBufferStream::AddToRanges(SourceBufferRange* new_range) {
1272 base::TimeDelta start_timestamp = new_range->GetStartTimestamp();
1273 RangeList::iterator itr = ranges_.end();
1274 for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
1275 if ((*itr)->GetStartTimestamp() > start_timestamp)
1276 break;
1278 return ranges_.insert(itr, new_range);
1281 SourceBufferStream::RangeList::iterator
1282 SourceBufferStream::GetSelectedRangeItr() {
1283 DCHECK(selected_range_);
1284 RangeList::iterator itr = ranges_.end();
1285 for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
1286 if (*itr == selected_range_)
1287 break;
1289 DCHECK(itr != ranges_.end());
1290 return itr;
1293 void SourceBufferStream::SeekAndSetSelectedRange(
1294 SourceBufferRange* range, base::TimeDelta seek_timestamp) {
1295 if (range)
1296 range->Seek(seek_timestamp);
1297 SetSelectedRange(range);
1300 void SourceBufferStream::SetSelectedRange(SourceBufferRange* range) {
1301 DVLOG(1) << __FUNCTION__ << " : " << selected_range_ << " -> " << range;
1302 if (selected_range_)
1303 selected_range_->ResetNextBufferPosition();
1304 DCHECK(!range || range->HasNextBufferPosition());
1305 selected_range_ = range;
1308 Ranges<base::TimeDelta> SourceBufferStream::GetBufferedTime() const {
1309 Ranges<base::TimeDelta> ranges;
1310 for (RangeList::const_iterator itr = ranges_.begin();
1311 itr != ranges_.end(); ++itr) {
1312 ranges.Add((*itr)->GetStartTimestamp(), (*itr)->GetBufferedEndTimestamp());
1314 return ranges;
1317 base::TimeDelta SourceBufferStream::GetBufferedDuration() const {
1318 if (ranges_.empty())
1319 return base::TimeDelta();
1321 return ranges_.back()->GetBufferedEndTimestamp();
1324 void SourceBufferStream::MarkEndOfStream() {
1325 DCHECK(!end_of_stream_);
1326 end_of_stream_ = true;
1329 void SourceBufferStream::UnmarkEndOfStream() {
1330 DCHECK(end_of_stream_);
1331 end_of_stream_ = false;
1334 bool SourceBufferStream::IsEndSelected() const {
1335 if (ranges_.empty())
1336 return true;
1338 if (seek_pending_)
1339 return seek_buffer_timestamp_ >= ranges_.back()->GetBufferedEndTimestamp();
1341 return selected_range_ == ranges_.back();
1344 const AudioDecoderConfig& SourceBufferStream::GetCurrentAudioDecoderConfig() {
1345 if (config_change_pending_)
1346 CompleteConfigChange();
1347 return audio_configs_[current_config_index_];
1350 const VideoDecoderConfig& SourceBufferStream::GetCurrentVideoDecoderConfig() {
1351 if (config_change_pending_)
1352 CompleteConfigChange();
1353 return video_configs_[current_config_index_];
1356 const TextTrackConfig& SourceBufferStream::GetCurrentTextTrackConfig() {
1357 return text_track_config_;
1360 base::TimeDelta SourceBufferStream::GetMaxInterbufferDistance() const {
1361 if (max_interbuffer_distance_ == kNoTimestamp())
1362 return base::TimeDelta::FromMilliseconds(kDefaultBufferDurationInMs);
1363 return max_interbuffer_distance_;
1366 bool SourceBufferStream::UpdateAudioConfig(const AudioDecoderConfig& config) {
1367 DCHECK(!audio_configs_.empty());
1368 DCHECK(video_configs_.empty());
1369 DVLOG(3) << "UpdateAudioConfig.";
1371 if (audio_configs_[0].codec() != config.codec()) {
1372 MEDIA_LOG(log_cb_) << "Audio codec changes not allowed.";
1373 return false;
1376 if (audio_configs_[0].is_encrypted() != config.is_encrypted()) {
1377 MEDIA_LOG(log_cb_) << "Audio encryption changes not allowed.";
1378 return false;
1381 // Check to see if the new config matches an existing one.
1382 for (size_t i = 0; i < audio_configs_.size(); ++i) {
1383 if (config.Matches(audio_configs_[i])) {
1384 append_config_index_ = i;
1385 return true;
1389 // No matches found so let's add this one to the list.
1390 append_config_index_ = audio_configs_.size();
1391 DVLOG(2) << "New audio config - index: " << append_config_index_;
1392 audio_configs_.resize(audio_configs_.size() + 1);
1393 audio_configs_[append_config_index_] = config;
1394 return true;
1397 bool SourceBufferStream::UpdateVideoConfig(const VideoDecoderConfig& config) {
1398 DCHECK(!video_configs_.empty());
1399 DCHECK(audio_configs_.empty());
1400 DVLOG(3) << "UpdateVideoConfig.";
1402 if (video_configs_[0].is_encrypted() != config.is_encrypted()) {
1403 MEDIA_LOG(log_cb_) << "Video Encryption changes not allowed.";
1404 return false;
1407 if (video_configs_[0].codec() != config.codec()) {
1408 MEDIA_LOG(log_cb_) << "Video codec changes not allowed.";
1409 return false;
1412 if (video_configs_[0].is_encrypted() != config.is_encrypted()) {
1413 MEDIA_LOG(log_cb_) << "Video encryption changes not allowed.";
1414 return false;
1417 // Check to see if the new config matches an existing one.
1418 for (size_t i = 0; i < video_configs_.size(); ++i) {
1419 if (config.Matches(video_configs_[i])) {
1420 append_config_index_ = i;
1421 return true;
1425 // No matches found so let's add this one to the list.
1426 append_config_index_ = video_configs_.size();
1427 DVLOG(2) << "New video config - index: " << append_config_index_;
1428 video_configs_.resize(video_configs_.size() + 1);
1429 video_configs_[append_config_index_] = config;
1430 return true;
1433 void SourceBufferStream::CompleteConfigChange() {
1434 config_change_pending_ = false;
1436 if (splice_buffer_) {
1437 current_config_index_ =
1438 GetConfigId(splice_buffer_, splice_buffers_index_);
1439 return;
1442 if (!track_buffer_.empty()) {
1443 current_config_index_ = GetConfigId(track_buffer_.front(), 0);
1444 return;
1447 if (selected_range_ && selected_range_->HasNextBuffer())
1448 current_config_index_ = selected_range_->GetNextConfigId();
1451 void SourceBufferStream::SetSelectedRangeIfNeeded(
1452 const base::TimeDelta timestamp) {
1453 DVLOG(1) << __FUNCTION__ << "(" << timestamp.InSecondsF() << ")";
1455 if (selected_range_) {
1456 DCHECK(track_buffer_.empty());
1457 return;
1460 if (!track_buffer_.empty()) {
1461 DCHECK(!selected_range_);
1462 return;
1465 base::TimeDelta start_timestamp = timestamp;
1467 // If the next buffer timestamp is not known then use a timestamp just after
1468 // the timestamp on the last buffer returned by GetNextBuffer().
1469 if (start_timestamp == kNoTimestamp()) {
1470 if (last_output_buffer_timestamp_ == kNoTimestamp())
1471 return;
1473 start_timestamp = last_output_buffer_timestamp_ +
1474 base::TimeDelta::FromInternalValue(1);
1477 base::TimeDelta seek_timestamp =
1478 FindNewSelectedRangeSeekTimestamp(start_timestamp);
1480 // If we don't have buffered data to seek to, then return.
1481 if (seek_timestamp == kNoTimestamp())
1482 return;
1484 DCHECK(track_buffer_.empty());
1485 SeekAndSetSelectedRange(*FindExistingRangeFor(seek_timestamp),
1486 seek_timestamp);
1489 base::TimeDelta SourceBufferStream::FindNewSelectedRangeSeekTimestamp(
1490 const base::TimeDelta start_timestamp) {
1491 DCHECK(start_timestamp != kNoTimestamp());
1492 DCHECK(start_timestamp >= base::TimeDelta());
1494 RangeList::iterator itr = ranges_.begin();
1496 for (; itr != ranges_.end(); ++itr) {
1497 if ((*itr)->GetEndTimestamp() >= start_timestamp) {
1498 break;
1502 if (itr == ranges_.end())
1503 return kNoTimestamp();
1505 // First check for a keyframe timestamp >= |start_timestamp|
1506 // in the current range.
1507 base::TimeDelta keyframe_timestamp =
1508 (*itr)->NextKeyframeTimestamp(start_timestamp);
1510 if (keyframe_timestamp != kNoTimestamp())
1511 return keyframe_timestamp;
1513 // If a keyframe was not found then look for a keyframe that is
1514 // "close enough" in the current or next range.
1515 base::TimeDelta end_timestamp =
1516 start_timestamp + ComputeFudgeRoom(GetMaxInterbufferDistance());
1517 DCHECK(start_timestamp < end_timestamp);
1519 // Make sure the current range doesn't start beyond |end_timestamp|.
1520 if ((*itr)->GetStartTimestamp() >= end_timestamp)
1521 return kNoTimestamp();
1523 keyframe_timestamp = (*itr)->KeyframeBeforeTimestamp(end_timestamp);
1525 // Check to see if the keyframe is within the acceptable range
1526 // (|start_timestamp|, |end_timestamp|].
1527 if (keyframe_timestamp != kNoTimestamp() &&
1528 start_timestamp < keyframe_timestamp &&
1529 keyframe_timestamp <= end_timestamp) {
1530 return keyframe_timestamp;
1533 // If |end_timestamp| is within this range, then no other checks are
1534 // necessary.
1535 if (end_timestamp <= (*itr)->GetEndTimestamp())
1536 return kNoTimestamp();
1538 // Move on to the next range.
1539 ++itr;
1541 // Return early if the next range does not contain |end_timestamp|.
1542 if (itr == ranges_.end() || (*itr)->GetStartTimestamp() >= end_timestamp)
1543 return kNoTimestamp();
1545 keyframe_timestamp = (*itr)->KeyframeBeforeTimestamp(end_timestamp);
1547 // Check to see if the keyframe is within the acceptable range
1548 // (|start_timestamp|, |end_timestamp|].
1549 if (keyframe_timestamp != kNoTimestamp() &&
1550 start_timestamp < keyframe_timestamp &&
1551 keyframe_timestamp <= end_timestamp) {
1552 return keyframe_timestamp;
1555 return kNoTimestamp();
1558 base::TimeDelta SourceBufferStream::FindKeyframeAfterTimestamp(
1559 const base::TimeDelta timestamp) {
1560 DCHECK(timestamp != kNoTimestamp());
1562 RangeList::iterator itr = FindExistingRangeFor(timestamp);
1564 if (itr == ranges_.end())
1565 return kNoTimestamp();
1567 // First check for a keyframe timestamp >= |timestamp|
1568 // in the current range.
1569 return (*itr)->NextKeyframeTimestamp(timestamp);
1572 std::string SourceBufferStream::GetStreamTypeName() const {
1573 switch (GetType()) {
1574 case kAudio:
1575 return "AUDIO";
1576 case kVideo:
1577 return "VIDEO";
1578 case kText:
1579 return "TEXT";
1581 NOTREACHED();
1582 return "";
1585 SourceBufferStream::Type SourceBufferStream::GetType() const {
1586 if (!audio_configs_.empty())
1587 return kAudio;
1588 if (!video_configs_.empty())
1589 return kVideo;
1590 DCHECK_NE(text_track_config_.kind(), kTextNone);
1591 return kText;
1594 void SourceBufferStream::DeleteAndRemoveRange(RangeList::iterator* itr) {
1595 DVLOG(1) << __FUNCTION__;
1597 DCHECK(*itr != ranges_.end());
1598 if (**itr == selected_range_) {
1599 DVLOG(1) << __FUNCTION__ << " deleting selected range.";
1600 SetSelectedRange(NULL);
1603 if (*itr == range_for_next_append_) {
1604 DVLOG(1) << __FUNCTION__ << " deleting range_for_next_append_.";
1605 range_for_next_append_ = ranges_.end();
1608 delete **itr;
1609 *itr = ranges_.erase(*itr);
1612 void SourceBufferStream::GenerateSpliceFrame(const BufferQueue& new_buffers) {
1613 DCHECK(!new_buffers.empty());
1615 // Splice frames are only supported for audio.
1616 if (GetType() != kAudio)
1617 return;
1619 // Find the overlapped range (if any).
1620 const base::TimeDelta splice_timestamp = new_buffers.front()->timestamp();
1621 RangeList::iterator range_itr = FindExistingRangeFor(splice_timestamp);
1622 if (range_itr == ranges_.end())
1623 return;
1625 const base::TimeDelta max_splice_end_timestamp =
1626 splice_timestamp + base::TimeDelta::FromMilliseconds(
1627 AudioSplicer::kCrossfadeDurationInMilliseconds);
1629 // Find all buffers involved before the splice point.
1630 BufferQueue pre_splice_buffers;
1631 if (!(*range_itr)->GetBuffersInRange(
1632 splice_timestamp, max_splice_end_timestamp, &pre_splice_buffers)) {
1633 return;
1636 // If there are gaps in the timeline, it's possible that we only find buffers
1637 // after the splice point but within the splice range. For simplicity, we do
1638 // not generate splice frames in this case.
1640 // We also do not want to generate splices if the first new buffer replaces an
1641 // existing buffer exactly.
1642 if (pre_splice_buffers.front()->timestamp() >= splice_timestamp)
1643 return;
1645 // Sanitize |pre_splice_buffers| so that there are no recursive splices.
1646 for (size_t i = 0; i < pre_splice_buffers.size(); ++i) {
1647 const BufferQueue& original_splice_buffers =
1648 pre_splice_buffers[i]->get_splice_buffers();
1649 if (original_splice_buffers.empty())
1650 continue;
1652 // Remove the original splice and move our index back to compensate. NOTE:
1653 // |i| will underflow if the splice is the first buffer, this is okay. It
1654 // will be corrected below or on the next loop iteration.
1655 pre_splice_buffers.erase(pre_splice_buffers.begin() + i--);
1657 // Cull all buffers which start after the end of the new splice point or
1658 // after original overlapping buffer; this may introduce gaps, but no more
1659 // than Remove() does currently.
1660 const scoped_refptr<StreamParserBuffer>& overlapping_buffer =
1661 original_splice_buffers.back();
1662 for (BufferQueue::const_iterator it = original_splice_buffers.begin();
1663 it != original_splice_buffers.end();
1664 ++it) {
1665 const scoped_refptr<StreamParserBuffer>& buffer = *it;
1666 if (buffer->timestamp() <= max_splice_end_timestamp &&
1667 (buffer->timestamp() < overlapping_buffer->timestamp() ||
1668 buffer == overlapping_buffer)) {
1669 // Add the buffer and adjust the index forward to compensate.
1670 pre_splice_buffers.insert(pre_splice_buffers.begin() + ++i, buffer);
1675 new_buffers.front()->ConvertToSpliceBuffer(pre_splice_buffers);
1678 SourceBufferRange::SourceBufferRange(
1679 SourceBufferStream::Type type, const BufferQueue& new_buffers,
1680 base::TimeDelta media_segment_start_time,
1681 const InterbufferDistanceCB& interbuffer_distance_cb)
1682 : type_(type),
1683 keyframe_map_index_base_(0),
1684 next_buffer_index_(-1),
1685 media_segment_start_time_(media_segment_start_time),
1686 interbuffer_distance_cb_(interbuffer_distance_cb),
1687 size_in_bytes_(0) {
1688 DCHECK(!new_buffers.empty());
1689 DCHECK(new_buffers.front()->IsKeyframe());
1690 DCHECK(!interbuffer_distance_cb.is_null());
1691 AppendBuffersToEnd(new_buffers);
1694 void SourceBufferRange::AppendBuffersToEnd(const BufferQueue& new_buffers) {
1695 DCHECK(buffers_.empty() || CanAppendBuffersToEnd(new_buffers));
1696 DCHECK(media_segment_start_time_ == kNoTimestamp() ||
1697 media_segment_start_time_ <=
1698 new_buffers.front()->GetDecodeTimestamp());
1699 for (BufferQueue::const_iterator itr = new_buffers.begin();
1700 itr != new_buffers.end();
1701 ++itr) {
1702 DCHECK((*itr)->GetDecodeTimestamp() != kNoTimestamp());
1703 buffers_.push_back(*itr);
1704 size_in_bytes_ += (*itr)->data_size();
1706 if ((*itr)->IsKeyframe()) {
1707 keyframe_map_.insert(
1708 std::make_pair((*itr)->GetDecodeTimestamp(),
1709 buffers_.size() - 1 + keyframe_map_index_base_));
1714 void SourceBufferRange::Seek(base::TimeDelta timestamp) {
1715 DCHECK(CanSeekTo(timestamp));
1716 DCHECK(!keyframe_map_.empty());
1718 KeyframeMap::iterator result = GetFirstKeyframeBefore(timestamp);
1719 next_buffer_index_ = result->second - keyframe_map_index_base_;
1720 DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size()));
1723 void SourceBufferRange::SeekAheadTo(base::TimeDelta timestamp) {
1724 SeekAhead(timestamp, false);
1727 void SourceBufferRange::SeekAheadPast(base::TimeDelta timestamp) {
1728 SeekAhead(timestamp, true);
1731 void SourceBufferRange::SeekAhead(base::TimeDelta timestamp,
1732 bool skip_given_timestamp) {
1733 DCHECK(!keyframe_map_.empty());
1735 KeyframeMap::iterator result =
1736 GetFirstKeyframeAt(timestamp, skip_given_timestamp);
1738 // If there isn't a keyframe after |timestamp|, then seek to end and return
1739 // kNoTimestamp to signal such.
1740 if (result == keyframe_map_.end()) {
1741 next_buffer_index_ = -1;
1742 return;
1744 next_buffer_index_ = result->second - keyframe_map_index_base_;
1745 DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size()));
1748 void SourceBufferRange::SeekToStart() {
1749 DCHECK(!buffers_.empty());
1750 next_buffer_index_ = 0;
1753 SourceBufferRange* SourceBufferRange::SplitRange(
1754 base::TimeDelta timestamp, bool is_exclusive) {
1755 // Find the first keyframe after |timestamp|. If |is_exclusive|, do not
1756 // include keyframes at |timestamp|.
1757 KeyframeMap::iterator new_beginning_keyframe =
1758 GetFirstKeyframeAt(timestamp, is_exclusive);
1760 // If there is no keyframe after |timestamp|, we can't split the range.
1761 if (new_beginning_keyframe == keyframe_map_.end())
1762 return NULL;
1764 // Remove the data beginning at |keyframe_index| from |buffers_| and save it
1765 // into |removed_buffers|.
1766 int keyframe_index =
1767 new_beginning_keyframe->second - keyframe_map_index_base_;
1768 DCHECK_LT(keyframe_index, static_cast<int>(buffers_.size()));
1769 BufferQueue::iterator starting_point = buffers_.begin() + keyframe_index;
1770 BufferQueue removed_buffers(starting_point, buffers_.end());
1771 keyframe_map_.erase(new_beginning_keyframe, keyframe_map_.end());
1772 FreeBufferRange(starting_point, buffers_.end());
1774 // Create a new range with |removed_buffers|.
1775 SourceBufferRange* split_range =
1776 new SourceBufferRange(
1777 type_, removed_buffers, kNoTimestamp(), interbuffer_distance_cb_);
1779 // If the next buffer position is now in |split_range|, update the state of
1780 // this range and |split_range| accordingly.
1781 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) {
1782 split_range->next_buffer_index_ = next_buffer_index_ - keyframe_index;
1783 ResetNextBufferPosition();
1786 return split_range;
1789 BufferQueue::iterator SourceBufferRange::GetBufferItrAt(
1790 base::TimeDelta timestamp,
1791 bool skip_given_timestamp) {
1792 return skip_given_timestamp
1793 ? std::upper_bound(buffers_.begin(),
1794 buffers_.end(),
1795 timestamp,
1796 CompareTimeDeltaToStreamParserBuffer)
1797 : std::lower_bound(buffers_.begin(),
1798 buffers_.end(),
1799 timestamp,
1800 CompareStreamParserBufferToTimeDelta);
1803 SourceBufferRange::KeyframeMap::iterator
1804 SourceBufferRange::GetFirstKeyframeAt(base::TimeDelta timestamp,
1805 bool skip_given_timestamp) {
1806 return skip_given_timestamp ?
1807 keyframe_map_.upper_bound(timestamp) :
1808 keyframe_map_.lower_bound(timestamp);
1811 SourceBufferRange::KeyframeMap::iterator
1812 SourceBufferRange::GetFirstKeyframeBefore(base::TimeDelta timestamp) {
1813 KeyframeMap::iterator result = keyframe_map_.lower_bound(timestamp);
1814 // lower_bound() returns the first element >= |timestamp|, so we want the
1815 // previous element if it did not return the element exactly equal to
1816 // |timestamp|.
1817 if (result != keyframe_map_.begin() &&
1818 (result == keyframe_map_.end() || result->first != timestamp)) {
1819 --result;
1821 return result;
1824 void SourceBufferRange::DeleteAll(BufferQueue* removed_buffers) {
1825 TruncateAt(buffers_.begin(), removed_buffers);
1828 bool SourceBufferRange::TruncateAt(
1829 base::TimeDelta timestamp, BufferQueue* removed_buffers,
1830 bool is_exclusive) {
1831 // Find the place in |buffers_| where we will begin deleting data.
1832 BufferQueue::iterator starting_point =
1833 GetBufferItrAt(timestamp, is_exclusive);
1834 return TruncateAt(starting_point, removed_buffers);
1837 int SourceBufferRange::DeleteGOPFromFront(BufferQueue* deleted_buffers) {
1838 DCHECK(!FirstGOPContainsNextBufferPosition());
1839 DCHECK(deleted_buffers);
1841 int buffers_deleted = 0;
1842 int total_bytes_deleted = 0;
1844 KeyframeMap::iterator front = keyframe_map_.begin();
1845 DCHECK(front != keyframe_map_.end());
1847 // Delete the keyframe at the start of |keyframe_map_|.
1848 keyframe_map_.erase(front);
1850 // Now we need to delete all the buffers that depend on the keyframe we've
1851 // just deleted.
1852 int end_index = keyframe_map_.size() > 0 ?
1853 keyframe_map_.begin()->second - keyframe_map_index_base_ :
1854 buffers_.size();
1856 // Delete buffers from the beginning of the buffered range up until (but not
1857 // including) the next keyframe.
1858 for (int i = 0; i < end_index; i++) {
1859 int bytes_deleted = buffers_.front()->data_size();
1860 size_in_bytes_ -= bytes_deleted;
1861 total_bytes_deleted += bytes_deleted;
1862 deleted_buffers->push_back(buffers_.front());
1863 buffers_.pop_front();
1864 ++buffers_deleted;
1867 // Update |keyframe_map_index_base_| to account for the deleted buffers.
1868 keyframe_map_index_base_ += buffers_deleted;
1870 if (next_buffer_index_ > -1) {
1871 next_buffer_index_ -= buffers_deleted;
1872 DCHECK_GE(next_buffer_index_, 0);
1875 // Invalidate media segment start time if we've deleted the first buffer of
1876 // the range.
1877 if (buffers_deleted > 0)
1878 media_segment_start_time_ = kNoTimestamp();
1880 return total_bytes_deleted;
1883 int SourceBufferRange::DeleteGOPFromBack(BufferQueue* deleted_buffers) {
1884 DCHECK(!LastGOPContainsNextBufferPosition());
1885 DCHECK(deleted_buffers);
1887 // Remove the last GOP's keyframe from the |keyframe_map_|.
1888 KeyframeMap::iterator back = keyframe_map_.end();
1889 DCHECK_GT(keyframe_map_.size(), 0u);
1890 --back;
1892 // The index of the first buffer in the last GOP is equal to the new size of
1893 // |buffers_| after that GOP is deleted.
1894 size_t goal_size = back->second - keyframe_map_index_base_;
1895 keyframe_map_.erase(back);
1897 int total_bytes_deleted = 0;
1898 while (buffers_.size() != goal_size) {
1899 int bytes_deleted = buffers_.back()->data_size();
1900 size_in_bytes_ -= bytes_deleted;
1901 total_bytes_deleted += bytes_deleted;
1902 // We're removing buffers from the back, so push each removed buffer to the
1903 // front of |deleted_buffers| so that |deleted_buffers| are in nondecreasing
1904 // order.
1905 deleted_buffers->push_front(buffers_.back());
1906 buffers_.pop_back();
1909 return total_bytes_deleted;
1912 int SourceBufferRange::GetRemovalGOP(
1913 base::TimeDelta start_timestamp, base::TimeDelta end_timestamp,
1914 int total_bytes_to_free, base::TimeDelta* removal_end_timestamp) {
1915 int bytes_to_free = total_bytes_to_free;
1916 int bytes_removed = 0;
1918 KeyframeMap::iterator gop_itr = GetFirstKeyframeAt(start_timestamp, false);
1919 if (gop_itr == keyframe_map_.end())
1920 return 0;
1921 int keyframe_index = gop_itr->second - keyframe_map_index_base_;
1922 BufferQueue::iterator buffer_itr = buffers_.begin() + keyframe_index;
1923 KeyframeMap::iterator gop_end = keyframe_map_.end();
1924 if (end_timestamp < GetBufferedEndTimestamp())
1925 gop_end = GetFirstKeyframeBefore(end_timestamp);
1927 // Check if the removal range is within a GOP and skip the loop if so.
1928 // [keyframe]...[start_timestamp]...[end_timestamp]...[keyframe]
1929 KeyframeMap::iterator gop_itr_prev = gop_itr;
1930 if (gop_itr_prev != keyframe_map_.begin() && --gop_itr_prev == gop_end)
1931 gop_end = gop_itr;
1933 while (gop_itr != gop_end && bytes_to_free > 0) {
1934 ++gop_itr;
1936 int gop_size = 0;
1937 int next_gop_index = gop_itr == keyframe_map_.end() ?
1938 buffers_.size() : gop_itr->second - keyframe_map_index_base_;
1939 BufferQueue::iterator next_gop_start = buffers_.begin() + next_gop_index;
1940 for (; buffer_itr != next_gop_start; ++buffer_itr)
1941 gop_size += (*buffer_itr)->data_size();
1943 bytes_removed += gop_size;
1944 bytes_to_free -= gop_size;
1946 if (bytes_removed > 0) {
1947 *removal_end_timestamp = gop_itr == keyframe_map_.end() ?
1948 GetBufferedEndTimestamp() : gop_itr->first;
1950 return bytes_removed;
1953 bool SourceBufferRange::FirstGOPContainsNextBufferPosition() const {
1954 if (!HasNextBufferPosition())
1955 return false;
1957 // If there is only one GOP, it must contain the next buffer position.
1958 if (keyframe_map_.size() == 1u)
1959 return true;
1961 KeyframeMap::const_iterator second_gop = keyframe_map_.begin();
1962 ++second_gop;
1963 return next_buffer_index_ < second_gop->second - keyframe_map_index_base_;
1966 bool SourceBufferRange::LastGOPContainsNextBufferPosition() const {
1967 if (!HasNextBufferPosition())
1968 return false;
1970 // If there is only one GOP, it must contain the next buffer position.
1971 if (keyframe_map_.size() == 1u)
1972 return true;
1974 KeyframeMap::const_iterator last_gop = keyframe_map_.end();
1975 --last_gop;
1976 return last_gop->second - keyframe_map_index_base_ <= next_buffer_index_;
1979 void SourceBufferRange::FreeBufferRange(
1980 const BufferQueue::iterator& starting_point,
1981 const BufferQueue::iterator& ending_point) {
1982 for (BufferQueue::iterator itr = starting_point;
1983 itr != ending_point; ++itr) {
1984 size_in_bytes_ -= (*itr)->data_size();
1985 DCHECK_GE(size_in_bytes_, 0);
1987 buffers_.erase(starting_point, ending_point);
1990 bool SourceBufferRange::TruncateAt(
1991 const BufferQueue::iterator& starting_point, BufferQueue* removed_buffers) {
1992 DCHECK(!removed_buffers || removed_buffers->empty());
1994 // Return if we're not deleting anything.
1995 if (starting_point == buffers_.end())
1996 return false;
1998 // Reset the next buffer index if we will be deleting the buffer that's next
1999 // in sequence.
2000 if (HasNextBufferPosition()) {
2001 base::TimeDelta next_buffer_timestamp = GetNextTimestamp();
2002 if (next_buffer_timestamp == kNoTimestamp() ||
2003 next_buffer_timestamp >= (*starting_point)->GetDecodeTimestamp()) {
2004 if (HasNextBuffer() && removed_buffers) {
2005 int starting_offset = starting_point - buffers_.begin();
2006 int next_buffer_offset = next_buffer_index_ - starting_offset;
2007 DCHECK_GE(next_buffer_offset, 0);
2008 BufferQueue saved(starting_point + next_buffer_offset, buffers_.end());
2009 removed_buffers->swap(saved);
2011 ResetNextBufferPosition();
2015 // Remove keyframes from |starting_point| onward.
2016 KeyframeMap::iterator starting_point_keyframe =
2017 keyframe_map_.lower_bound((*starting_point)->GetDecodeTimestamp());
2018 keyframe_map_.erase(starting_point_keyframe, keyframe_map_.end());
2020 // Remove everything from |starting_point| onward.
2021 FreeBufferRange(starting_point, buffers_.end());
2022 return buffers_.empty();
2025 bool SourceBufferRange::GetNextBuffer(
2026 scoped_refptr<StreamParserBuffer>* out_buffer) {
2027 if (!HasNextBuffer())
2028 return false;
2030 *out_buffer = buffers_[next_buffer_index_];
2031 next_buffer_index_++;
2032 return true;
2035 bool SourceBufferRange::HasNextBuffer() const {
2036 return next_buffer_index_ >= 0 &&
2037 next_buffer_index_ < static_cast<int>(buffers_.size());
2040 int SourceBufferRange::GetNextConfigId() const {
2041 DCHECK(HasNextBuffer());
2042 // If the next buffer is an audio splice frame, the next effective config id
2043 // comes from the first fade out preroll buffer.
2044 return GetConfigId(buffers_[next_buffer_index_], 0);
2047 base::TimeDelta SourceBufferRange::GetNextTimestamp() const {
2048 DCHECK(!buffers_.empty());
2049 DCHECK(HasNextBufferPosition());
2051 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) {
2052 return kNoTimestamp();
2055 return buffers_[next_buffer_index_]->GetDecodeTimestamp();
2058 bool SourceBufferRange::HasNextBufferPosition() const {
2059 return next_buffer_index_ >= 0;
2062 void SourceBufferRange::ResetNextBufferPosition() {
2063 next_buffer_index_ = -1;
2066 void SourceBufferRange::AppendRangeToEnd(const SourceBufferRange& range,
2067 bool transfer_current_position) {
2068 DCHECK(CanAppendRangeToEnd(range));
2069 DCHECK(!buffers_.empty());
2071 if (transfer_current_position && range.next_buffer_index_ >= 0)
2072 next_buffer_index_ = range.next_buffer_index_ + buffers_.size();
2074 AppendBuffersToEnd(range.buffers_);
2077 bool SourceBufferRange::CanAppendRangeToEnd(
2078 const SourceBufferRange& range) const {
2079 return CanAppendBuffersToEnd(range.buffers_);
2082 bool SourceBufferRange::CanAppendBuffersToEnd(
2083 const BufferQueue& buffers) const {
2084 DCHECK(!buffers_.empty());
2085 return IsNextInSequence(buffers.front()->GetDecodeTimestamp(),
2086 buffers.front()->IsKeyframe());
2089 bool SourceBufferRange::BelongsToRange(base::TimeDelta timestamp) const {
2090 DCHECK(!buffers_.empty());
2092 return (IsNextInSequence(timestamp, false) ||
2093 (GetStartTimestamp() <= timestamp && timestamp <= GetEndTimestamp()));
2096 bool SourceBufferRange::CanSeekTo(base::TimeDelta timestamp) const {
2097 base::TimeDelta start_timestamp =
2098 std::max(base::TimeDelta(), GetStartTimestamp() - GetFudgeRoom());
2099 return !keyframe_map_.empty() && start_timestamp <= timestamp &&
2100 timestamp < GetBufferedEndTimestamp();
2103 bool SourceBufferRange::CompletelyOverlaps(
2104 const SourceBufferRange& range) const {
2105 return GetStartTimestamp() <= range.GetStartTimestamp() &&
2106 GetEndTimestamp() >= range.GetEndTimestamp();
2109 bool SourceBufferRange::EndOverlaps(const SourceBufferRange& range) const {
2110 return range.GetStartTimestamp() <= GetEndTimestamp() &&
2111 GetEndTimestamp() < range.GetEndTimestamp();
2114 base::TimeDelta SourceBufferRange::GetStartTimestamp() const {
2115 DCHECK(!buffers_.empty());
2116 base::TimeDelta start_timestamp = media_segment_start_time_;
2117 if (start_timestamp == kNoTimestamp())
2118 start_timestamp = buffers_.front()->GetDecodeTimestamp();
2119 return start_timestamp;
2122 base::TimeDelta SourceBufferRange::GetEndTimestamp() const {
2123 DCHECK(!buffers_.empty());
2124 return buffers_.back()->GetDecodeTimestamp();
2127 base::TimeDelta SourceBufferRange::GetBufferedEndTimestamp() const {
2128 DCHECK(!buffers_.empty());
2129 base::TimeDelta duration = buffers_.back()->duration();
2130 if (duration == kNoTimestamp() || duration == base::TimeDelta())
2131 duration = GetApproximateDuration();
2132 return GetEndTimestamp() + duration;
2135 base::TimeDelta SourceBufferRange::NextKeyframeTimestamp(
2136 base::TimeDelta timestamp) {
2137 DCHECK(!keyframe_map_.empty());
2139 if (timestamp < GetStartTimestamp() || timestamp >= GetBufferedEndTimestamp())
2140 return kNoTimestamp();
2142 KeyframeMap::iterator itr = GetFirstKeyframeAt(timestamp, false);
2143 if (itr == keyframe_map_.end())
2144 return kNoTimestamp();
2145 return itr->first;
2148 base::TimeDelta SourceBufferRange::KeyframeBeforeTimestamp(
2149 base::TimeDelta timestamp) {
2150 DCHECK(!keyframe_map_.empty());
2152 if (timestamp < GetStartTimestamp() || timestamp >= GetBufferedEndTimestamp())
2153 return kNoTimestamp();
2155 return GetFirstKeyframeBefore(timestamp)->first;
2158 bool SourceBufferRange::IsNextInSequence(
2159 base::TimeDelta timestamp, bool is_keyframe) const {
2160 base::TimeDelta end = buffers_.back()->GetDecodeTimestamp();
2161 if (end < timestamp &&
2162 (type_ == SourceBufferStream::kText ||
2163 timestamp <= end + GetFudgeRoom())) {
2164 return true;
2167 return timestamp == end && AllowSameTimestamp(
2168 buffers_.back()->IsKeyframe(), is_keyframe, type_);
2171 base::TimeDelta SourceBufferRange::GetFudgeRoom() const {
2172 return ComputeFudgeRoom(GetApproximateDuration());
2175 base::TimeDelta SourceBufferRange::GetApproximateDuration() const {
2176 base::TimeDelta max_interbuffer_distance = interbuffer_distance_cb_.Run();
2177 DCHECK(max_interbuffer_distance != kNoTimestamp());
2178 return max_interbuffer_distance;
2181 bool SourceBufferRange::GetBuffersInRange(base::TimeDelta start,
2182 base::TimeDelta end,
2183 BufferQueue* buffers) {
2184 // Find the nearest buffer with a decode timestamp <= start.
2185 const base::TimeDelta first_timestamp = KeyframeBeforeTimestamp(start);
2186 if (first_timestamp == kNoTimestamp())
2187 return false;
2189 // Find all buffers involved in the range.
2190 const size_t previous_size = buffers->size();
2191 for (BufferQueue::iterator it = GetBufferItrAt(first_timestamp, false);
2192 it != buffers_.end();
2193 ++it) {
2194 const scoped_refptr<StreamParserBuffer>& buffer = *it;
2195 // Buffers without duration are not supported, so bail if we encounter any.
2196 if (buffer->duration() == kNoTimestamp() ||
2197 buffer->duration() <= base::TimeDelta()) {
2198 return false;
2200 if (buffer->end_of_stream() || buffer->timestamp() >= end)
2201 break;
2202 if (buffer->timestamp() + buffer->duration() <= start)
2203 continue;
2204 buffers->push_back(buffer);
2206 return previous_size < buffers->size();
2209 } // namespace media