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.
4
5 #include "media/filters/source_buffer_stream.h"
6
7 #include <algorithm>
8 #include <map>
9
10 #include "base/bind.h"
11 #include "base/debug/trace_event.h"
12 #include "base/logging.h"
13 #include "media/base/audio_splicer.h"
14
15 namespace media {
16
17 typedef StreamParser::BufferQueue BufferQueue;
18
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.
AllowSameTimestamp(bool prev_is_keyframe,bool current_is_keyframe,SourceBufferStream::Type type)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;
32 }
33
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|.
GetConfigId(StreamParserBuffer * buffer,size_t index)37 static int GetConfigId(StreamParserBuffer* buffer, size_t index) {
38 return index < buffer->splice_buffers().size()
39 ? buffer->splice_buffers()[index]->GetConfigId()
40 : buffer->GetConfigId();
41 }
42
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;
52
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);
61
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;
67
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;
76
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);
80
81 // Updates |next_buffer_index_| to point to next keyframe after or equal to
82 // |timestamp|.
83 void SeekAheadTo(base::TimeDelta timestamp);
84
85 // Updates |next_buffer_index_| to point to next keyframe strictly after
86 // |timestamp|.
87 void SeekAheadPast(base::TimeDelta timestamp);
88
89 // Seeks to the beginning of the range.
90 void SeekToStart();
91
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);
99
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);
113
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);
119
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);
128
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;
133
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;
141
142 // Returns the config ID for the buffer that will be returned by
143 // GetNextBuffer().
144 int GetNextConfigId() const;
145
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;
150
151 // Resets this range to an "unseeked" state.
152 void ResetNextBufferPosition();
153
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;
157
158 // Returns the start timestamp of the range.
159 base::TimeDelta GetStartTimestamp() const;
160
161 // Returns the timestamp of the last buffer in the range.
162 base::TimeDelta GetEndTimestamp() const;
163
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;
168
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. If |timestamp| is in the "gap" between the value returned by
172 // GetStartTimestamp() and the timestamp on the first buffer in |buffers_|,
173 // then |timestamp| is returned.
174 base::TimeDelta NextKeyframeTimestamp(base::TimeDelta timestamp);
175
176 // Gets the timestamp for the closest keyframe that is <= |timestamp|. If
177 // there isn't a keyframe before |timestamp| or |timestamp| is outside
178 // this range, then kNoTimestamp() is returned.
179 base::TimeDelta KeyframeBeforeTimestamp(base::TimeDelta timestamp);
180
181 // Returns whether a buffer with a starting timestamp of |timestamp| would
182 // belong in this range. This includes a buffer that would be appended to
183 // the end of the range.
184 bool BelongsToRange(base::TimeDelta timestamp) const;
185
186 // Returns true if the range has enough data to seek to the specified
187 // |timestamp|, false otherwise.
188 bool CanSeekTo(base::TimeDelta timestamp) const;
189
190 // Returns true if this range's buffered timespan completely overlaps the
191 // buffered timespan of |range|.
192 bool CompletelyOverlaps(const SourceBufferRange& range) const;
193
194 // Returns true if the end of this range contains buffers that overlaps with
195 // the beginning of |range|.
196 bool EndOverlaps(const SourceBufferRange& range) const;
197
198 // Returns true if |timestamp| is the timestamp of the next buffer in
199 // sequence after |buffers_.back()|, false otherwise.
200 bool IsNextInSequence(base::TimeDelta timestamp, bool is_keyframe) const;
201
202 // Adds all buffers which overlap [start, end) to the end of |buffers|. If
203 // no buffers exist in the range returns false, true otherwise.
204 bool GetBuffersInRange(base::TimeDelta start, base::TimeDelta end,
205 BufferQueue* buffers);
206
size_in_bytes() const207 int size_in_bytes() const { return size_in_bytes_; }
208
209 private:
210 typedef std::map<base::TimeDelta, int> KeyframeMap;
211
212 // Seeks the range to the next keyframe after |timestamp|. If
213 // |skip_given_timestamp| is true, the seek will go to a keyframe with a
214 // timestamp strictly greater than |timestamp|.
215 void SeekAhead(base::TimeDelta timestamp, bool skip_given_timestamp);
216
217 // Returns an iterator in |buffers_| pointing to the buffer at |timestamp|.
218 // If |skip_given_timestamp| is true, this returns the first buffer with
219 // timestamp greater than |timestamp|.
220 BufferQueue::iterator GetBufferItrAt(
221 base::TimeDelta timestamp, bool skip_given_timestamp);
222
223 // Returns an iterator in |keyframe_map_| pointing to the next keyframe after
224 // |timestamp|. If |skip_given_timestamp| is true, this returns the first
225 // keyframe with a timestamp strictly greater than |timestamp|.
226 KeyframeMap::iterator GetFirstKeyframeAt(
227 base::TimeDelta timestamp, bool skip_given_timestamp);
228
229 // Returns an iterator in |keyframe_map_| pointing to the first keyframe
230 // before or at |timestamp|.
231 KeyframeMap::iterator GetFirstKeyframeBefore(base::TimeDelta timestamp);
232
233 // Helper method to delete buffers in |buffers_| starting at
234 // |starting_point|, an iterator in |buffers_|.
235 // Returns true if everything in the range was removed. Returns
236 // false if the range still contains buffers.
237 bool TruncateAt(const BufferQueue::iterator& starting_point,
238 BufferQueue* deleted_buffers);
239
240 // Frees the buffers in |buffers_| from [|start_point|,|ending_point|) and
241 // updates the |size_in_bytes_| accordingly. Does not update |keyframe_map_|.
242 void FreeBufferRange(const BufferQueue::iterator& starting_point,
243 const BufferQueue::iterator& ending_point);
244
245 // Returns the distance in time estimating how far from the beginning or end
246 // of this range a buffer can be to considered in the range.
247 base::TimeDelta GetFudgeRoom() const;
248
249 // Returns the approximate duration of a buffer in this range.
250 base::TimeDelta GetApproximateDuration() const;
251
252 // Type of this stream.
253 const SourceBufferStream::Type type_;
254
255 // An ordered list of buffers in this range.
256 BufferQueue buffers_;
257
258 // Maps keyframe timestamps to its index position in |buffers_|.
259 KeyframeMap keyframe_map_;
260
261 // Index base of all positions in |keyframe_map_|. In other words, the
262 // real position of entry |k| of |keyframe_map_| in the range is:
263 // keyframe_map_[k] - keyframe_map_index_base_
264 int keyframe_map_index_base_;
265
266 // Index into |buffers_| for the next buffer to be returned by
267 // GetNextBuffer(), set to -1 before Seek().
268 int next_buffer_index_;
269
270 // If the first buffer in this range is the beginning of a media segment,
271 // |media_segment_start_time_| is the time when the media segment begins.
272 // |media_segment_start_time_| may be <= the timestamp of the first buffer in
273 // |buffers_|. |media_segment_start_time_| is kNoTimestamp() if this range
274 // does not start at the beginning of a media segment, which can only happen
275 // garbage collection or after an end overlap that results in a split range
276 // (we don't have a way of knowing the media segment timestamp for the new
277 // range).
278 base::TimeDelta media_segment_start_time_;
279
280 // Called to get the largest interbuffer distance seen so far in the stream.
281 InterbufferDistanceCB interbuffer_distance_cb_;
282
283 // Stores the amount of memory taken up by the data in |buffers_|.
284 int size_in_bytes_;
285
286 DISALLOW_COPY_AND_ASSIGN(SourceBufferRange);
287 };
288
289 } // namespace media
290
291 // Helper method that returns true if |ranges| is sorted in increasing order,
292 // false otherwise.
IsRangeListSorted(const std::list<media::SourceBufferRange * > & ranges)293 static bool IsRangeListSorted(
294 const std::list<media::SourceBufferRange*>& ranges) {
295 base::TimeDelta prev = media::kNoTimestamp();
296 for (std::list<media::SourceBufferRange*>::const_iterator itr =
297 ranges.begin(); itr != ranges.end(); ++itr) {
298 if (prev != media::kNoTimestamp() && prev >= (*itr)->GetStartTimestamp())
299 return false;
300 prev = (*itr)->GetEndTimestamp();
301 }
302 return true;
303 }
304
305 // Comparison operators for std::upper_bound() and std::lower_bound().
CompareTimeDeltaToStreamParserBuffer(const base::TimeDelta & decode_timestamp,const scoped_refptr<media::StreamParserBuffer> & buffer)306 static bool CompareTimeDeltaToStreamParserBuffer(
307 const base::TimeDelta& decode_timestamp,
308 const scoped_refptr<media::StreamParserBuffer>& buffer) {
309 return decode_timestamp < buffer->GetDecodeTimestamp();
310 }
CompareStreamParserBufferToTimeDelta(const scoped_refptr<media::StreamParserBuffer> & buffer,const base::TimeDelta & decode_timestamp)311 static bool CompareStreamParserBufferToTimeDelta(
312 const scoped_refptr<media::StreamParserBuffer>& buffer,
313 const base::TimeDelta& decode_timestamp) {
314 return buffer->GetDecodeTimestamp() < decode_timestamp;
315 }
316
317 // Returns an estimate of how far from the beginning or end of a range a buffer
318 // can be to still be considered in the range, given the |approximate_duration|
319 // of a buffer in the stream.
ComputeFudgeRoom(base::TimeDelta approximate_duration)320 static base::TimeDelta ComputeFudgeRoom(base::TimeDelta approximate_duration) {
321 // Because we do not know exactly when is the next timestamp, any buffer
322 // that starts within 2x the approximate duration of a buffer is considered
323 // within this range.
324 return 2 * approximate_duration;
325 }
326
327 // An arbitrarily-chosen number to estimate the duration of a buffer if none
328 // is set and there's not enough information to get a better estimate.
329 static int kDefaultBufferDurationInMs = 125;
330
331 // The amount of time the beginning of the buffered data can differ from the
332 // start time in order to still be considered the start of stream.
kSeekToStartFudgeRoom()333 static base::TimeDelta kSeekToStartFudgeRoom() {
334 return base::TimeDelta::FromMilliseconds(1000);
335 }
336 // The maximum amount of data in bytes the stream will keep in memory.
337 // 12MB: approximately 5 minutes of 320Kbps content.
338 // 150MB: approximately 5 minutes of 4Mbps content.
339 static int kDefaultAudioMemoryLimit = 12 * 1024 * 1024;
340 static int kDefaultVideoMemoryLimit = 150 * 1024 * 1024;
341
342 namespace media {
343
SourceBufferStream(const AudioDecoderConfig & audio_config,const LogCB & log_cb,bool splice_frames_enabled)344 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config,
345 const LogCB& log_cb,
346 bool splice_frames_enabled)
347 : log_cb_(log_cb),
348 current_config_index_(0),
349 append_config_index_(0),
350 seek_pending_(false),
351 end_of_stream_(false),
352 seek_buffer_timestamp_(kNoTimestamp()),
353 selected_range_(NULL),
354 media_segment_start_time_(kNoTimestamp()),
355 range_for_next_append_(ranges_.end()),
356 new_media_segment_(false),
357 last_appended_buffer_timestamp_(kNoTimestamp()),
358 last_appended_buffer_is_keyframe_(false),
359 last_output_buffer_timestamp_(kNoTimestamp()),
360 max_interbuffer_distance_(kNoTimestamp()),
361 memory_limit_(kDefaultAudioMemoryLimit),
362 config_change_pending_(false),
363 splice_buffers_index_(0),
364 pending_buffers_complete_(false),
365 splice_frames_enabled_(splice_frames_enabled) {
366 DCHECK(audio_config.IsValidConfig());
367 audio_configs_.push_back(audio_config);
368 }
369
SourceBufferStream(const VideoDecoderConfig & video_config,const LogCB & log_cb,bool splice_frames_enabled)370 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config,
371 const LogCB& log_cb,
372 bool splice_frames_enabled)
373 : log_cb_(log_cb),
374 current_config_index_(0),
375 append_config_index_(0),
376 seek_pending_(false),
377 end_of_stream_(false),
378 seek_buffer_timestamp_(kNoTimestamp()),
379 selected_range_(NULL),
380 media_segment_start_time_(kNoTimestamp()),
381 range_for_next_append_(ranges_.end()),
382 new_media_segment_(false),
383 last_appended_buffer_timestamp_(kNoTimestamp()),
384 last_appended_buffer_is_keyframe_(false),
385 last_output_buffer_timestamp_(kNoTimestamp()),
386 max_interbuffer_distance_(kNoTimestamp()),
387 memory_limit_(kDefaultVideoMemoryLimit),
388 config_change_pending_(false),
389 splice_buffers_index_(0),
390 pending_buffers_complete_(false),
391 splice_frames_enabled_(splice_frames_enabled) {
392 DCHECK(video_config.IsValidConfig());
393 video_configs_.push_back(video_config);
394 }
395
SourceBufferStream(const TextTrackConfig & text_config,const LogCB & log_cb,bool splice_frames_enabled)396 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config,
397 const LogCB& log_cb,
398 bool splice_frames_enabled)
399 : log_cb_(log_cb),
400 current_config_index_(0),
401 append_config_index_(0),
402 text_track_config_(text_config),
403 seek_pending_(false),
404 end_of_stream_(false),
405 seek_buffer_timestamp_(kNoTimestamp()),
406 selected_range_(NULL),
407 media_segment_start_time_(kNoTimestamp()),
408 range_for_next_append_(ranges_.end()),
409 new_media_segment_(false),
410 last_appended_buffer_timestamp_(kNoTimestamp()),
411 last_appended_buffer_is_keyframe_(false),
412 last_output_buffer_timestamp_(kNoTimestamp()),
413 max_interbuffer_distance_(kNoTimestamp()),
414 memory_limit_(kDefaultAudioMemoryLimit),
415 config_change_pending_(false),
416 splice_buffers_index_(0),
417 pending_buffers_complete_(false),
418 splice_frames_enabled_(splice_frames_enabled) {}
419
~SourceBufferStream()420 SourceBufferStream::~SourceBufferStream() {
421 while (!ranges_.empty()) {
422 delete ranges_.front();
423 ranges_.pop_front();
424 }
425 }
426
OnNewMediaSegment(base::TimeDelta media_segment_start_time)427 void SourceBufferStream::OnNewMediaSegment(
428 base::TimeDelta media_segment_start_time) {
429 DCHECK(!end_of_stream_);
430 media_segment_start_time_ = media_segment_start_time;
431 new_media_segment_ = true;
432
433 RangeList::iterator last_range = range_for_next_append_;
434 range_for_next_append_ = FindExistingRangeFor(media_segment_start_time);
435
436 // Only reset |last_appended_buffer_timestamp_| if this new media segment is
437 // not adjacent to the previous media segment appended to the stream.
438 if (range_for_next_append_ == ranges_.end() ||
439 !AreAdjacentInSequence(last_appended_buffer_timestamp_,
440 media_segment_start_time)) {
441 last_appended_buffer_timestamp_ = kNoTimestamp();
442 last_appended_buffer_is_keyframe_ = false;
443 } else if (last_range != ranges_.end()) {
444 DCHECK(last_range == range_for_next_append_);
445 }
446 }
447
Append(const BufferQueue & buffers)448 bool SourceBufferStream::Append(const BufferQueue& buffers) {
449 TRACE_EVENT2("media", "SourceBufferStream::Append",
450 "stream type", GetStreamTypeName(),
451 "buffers to append", buffers.size());
452
453 DCHECK(!buffers.empty());
454 DCHECK(media_segment_start_time_ != kNoTimestamp());
455 DCHECK(media_segment_start_time_ <= buffers.front()->GetDecodeTimestamp());
456 DCHECK(!end_of_stream_);
457
458 // New media segments must begin with a keyframe.
459 if (new_media_segment_ && !buffers.front()->IsKeyframe()) {
460 MEDIA_LOG(log_cb_) << "Media segment did not begin with keyframe.";
461 return false;
462 }
463
464 // Buffers within a media segment should be monotonically increasing.
465 if (!IsMonotonicallyIncreasing(buffers))
466 return false;
467
468 if (media_segment_start_time_ < base::TimeDelta() ||
469 buffers.front()->GetDecodeTimestamp() < base::TimeDelta()) {
470 MEDIA_LOG(log_cb_)
471 << "Cannot append a media segment with negative timestamps.";
472 return false;
473 }
474
475 if (!IsNextTimestampValid(buffers.front()->GetDecodeTimestamp(),
476 buffers.front()->IsKeyframe())) {
477 MEDIA_LOG(log_cb_) << "Invalid same timestamp construct detected at time "
478 << buffers.front()->GetDecodeTimestamp().InSecondsF();
479
480 return false;
481 }
482
483 UpdateMaxInterbufferDistance(buffers);
484 SetConfigIds(buffers);
485
486 // Save a snapshot of stream state before range modifications are made.
487 base::TimeDelta next_buffer_timestamp = GetNextBufferTimestamp();
488 BufferQueue deleted_buffers;
489
490 PrepareRangesForNextAppend(buffers, &deleted_buffers);
491
492 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise,
493 // create a new range with |buffers|.
494 if (range_for_next_append_ != ranges_.end()) {
495 (*range_for_next_append_)->AppendBuffersToEnd(buffers);
496 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp();
497 last_appended_buffer_is_keyframe_ = buffers.back()->IsKeyframe();
498 } else {
499 base::TimeDelta new_range_start_time = std::min(
500 media_segment_start_time_, buffers.front()->GetDecodeTimestamp());
501 const BufferQueue* buffers_for_new_range = &buffers;
502 BufferQueue trimmed_buffers;
503
504 // If the new range is not being created because of a new media
505 // segment, then we must make sure that we start with a keyframe.
506 // This can happen if the GOP in the previous append gets destroyed
507 // by a Remove() call.
508 if (!new_media_segment_) {
509 BufferQueue::const_iterator itr = buffers.begin();
510
511 // Scan past all the non-keyframes.
512 while (itr != buffers.end() && !(*itr)->IsKeyframe()) {
513 ++itr;
514 }
515
516 // If we didn't find a keyframe, then update the last appended
517 // buffer state and return.
518 if (itr == buffers.end()) {
519 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp();
520 last_appended_buffer_is_keyframe_ = buffers.back()->IsKeyframe();
521 return true;
522 } else if (itr != buffers.begin()) {
523 // Copy the first keyframe and everything after it into
524 // |trimmed_buffers|.
525 trimmed_buffers.assign(itr, buffers.end());
526 buffers_for_new_range = &trimmed_buffers;
527 }
528
529 new_range_start_time =
530 buffers_for_new_range->front()->GetDecodeTimestamp();
531 }
532
533 range_for_next_append_ =
534 AddToRanges(new SourceBufferRange(
535 GetType(), *buffers_for_new_range, new_range_start_time,
536 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance,
537 base::Unretained(this))));
538 last_appended_buffer_timestamp_ =
539 buffers_for_new_range->back()->GetDecodeTimestamp();
540 last_appended_buffer_is_keyframe_ =
541 buffers_for_new_range->back()->IsKeyframe();
542 }
543
544 new_media_segment_ = false;
545
546 MergeWithAdjacentRangeIfNecessary(range_for_next_append_);
547
548 // Seek to try to fulfill a previous call to Seek().
549 if (seek_pending_) {
550 DCHECK(!selected_range_);
551 DCHECK(deleted_buffers.empty());
552 Seek(seek_buffer_timestamp_);
553 }
554
555 if (!deleted_buffers.empty()) {
556 base::TimeDelta start_of_deleted =
557 deleted_buffers.front()->GetDecodeTimestamp();
558
559 DCHECK(track_buffer_.empty() ||
560 track_buffer_.back()->GetDecodeTimestamp() < start_of_deleted)
561 << "decode timestamp "
562 << track_buffer_.back()->GetDecodeTimestamp().InSecondsF() << " sec"
563 << ", start_of_deleted " << start_of_deleted.InSecondsF()<< " sec";
564
565 track_buffer_.insert(track_buffer_.end(), deleted_buffers.begin(),
566 deleted_buffers.end());
567 }
568
569 // Prune any extra buffers in |track_buffer_| if new keyframes
570 // are appended to the range covered by |track_buffer_|.
571 if (!track_buffer_.empty()) {
572 base::TimeDelta keyframe_timestamp =
573 FindKeyframeAfterTimestamp(track_buffer_.front()->GetDecodeTimestamp());
574 if (keyframe_timestamp != kNoTimestamp())
575 PruneTrackBuffer(keyframe_timestamp);
576 }
577
578 SetSelectedRangeIfNeeded(next_buffer_timestamp);
579
580 GarbageCollectIfNeeded();
581
582 DCHECK(IsRangeListSorted(ranges_));
583 DCHECK(OnlySelectedRangeIsSeeked());
584 return true;
585 }
586
Remove(base::TimeDelta start,base::TimeDelta end,base::TimeDelta duration)587 void SourceBufferStream::Remove(base::TimeDelta start, base::TimeDelta end,
588 base::TimeDelta duration) {
589 DVLOG(1) << __FUNCTION__ << "(" << start.InSecondsF()
590 << ", " << end.InSecondsF()
591 << ", " << duration.InSecondsF() << ")";
592 DCHECK(start >= base::TimeDelta()) << start.InSecondsF();
593 DCHECK(start < end) << "start " << start.InSecondsF()
594 << " end " << end.InSecondsF();
595 DCHECK(duration != kNoTimestamp());
596
597 base::TimeDelta remove_end_timestamp = duration;
598 base::TimeDelta keyframe_timestamp = FindKeyframeAfterTimestamp(end);
599 if (keyframe_timestamp != kNoTimestamp()) {
600 remove_end_timestamp = keyframe_timestamp;
601 } else if (end < remove_end_timestamp) {
602 remove_end_timestamp = end;
603 }
604
605 BufferQueue deleted_buffers;
606 RemoveInternal(start, remove_end_timestamp, false, &deleted_buffers);
607
608 if (!deleted_buffers.empty())
609 SetSelectedRangeIfNeeded(deleted_buffers.front()->GetDecodeTimestamp());
610 }
611
RemoveInternal(base::TimeDelta start,base::TimeDelta end,bool is_exclusive,BufferQueue * deleted_buffers)612 void SourceBufferStream::RemoveInternal(
613 base::TimeDelta start, base::TimeDelta end, bool is_exclusive,
614 BufferQueue* deleted_buffers) {
615 DVLOG(1) << __FUNCTION__ << "(" << start.InSecondsF()
616 << ", " << end.InSecondsF()
617 << ", " << is_exclusive << ")";
618
619 DCHECK(start >= base::TimeDelta());
620 DCHECK(start < end) << "start " << start.InSecondsF()
621 << " end " << end.InSecondsF();
622 DCHECK(deleted_buffers);
623
624 RangeList::iterator itr = ranges_.begin();
625
626 while (itr != ranges_.end()) {
627 SourceBufferRange* range = *itr;
628 if (range->GetStartTimestamp() >= end)
629 break;
630
631 // Split off any remaining end piece and add it to |ranges_|.
632 SourceBufferRange* new_range = range->SplitRange(end, is_exclusive);
633 if (new_range) {
634 itr = ranges_.insert(++itr, new_range);
635 --itr;
636
637 // Update the selected range if the next buffer position was transferred
638 // to |new_range|.
639 if (new_range->HasNextBufferPosition())
640 SetSelectedRange(new_range);
641 }
642
643 // Truncate the current range so that it only contains data before
644 // the removal range.
645 BufferQueue saved_buffers;
646 bool delete_range = range->TruncateAt(start, &saved_buffers, is_exclusive);
647
648 // Check to see if the current playback position was removed and
649 // update the selected range appropriately.
650 if (!saved_buffers.empty()) {
651 DCHECK(!range->HasNextBufferPosition());
652 DCHECK(deleted_buffers->empty());
653
654 *deleted_buffers = saved_buffers;
655 }
656
657 if (range == selected_range_ && !range->HasNextBufferPosition())
658 SetSelectedRange(NULL);
659
660 // If the current range now is completely covered by the removal
661 // range then delete it and move on.
662 if (delete_range) {
663 DeleteAndRemoveRange(&itr);
664 continue;
665 }
666
667 // Clear |range_for_next_append_| if we determine that the removal
668 // operation makes it impossible for the next append to be added
669 // to the current range.
670 if (range_for_next_append_ != ranges_.end() &&
671 *range_for_next_append_ == range &&
672 last_appended_buffer_timestamp_ != kNoTimestamp()) {
673 base::TimeDelta potential_next_append_timestamp =
674 last_appended_buffer_timestamp_ +
675 base::TimeDelta::FromInternalValue(1);
676
677 if (!range->BelongsToRange(potential_next_append_timestamp)) {
678 DVLOG(1) << "Resetting range_for_next_append_ since the next append"
679 << " can't add to the current range.";
680 range_for_next_append_ =
681 FindExistingRangeFor(potential_next_append_timestamp);
682 }
683 }
684
685 // Move on to the next range.
686 ++itr;
687 }
688
689 DCHECK(IsRangeListSorted(ranges_));
690 DCHECK(OnlySelectedRangeIsSeeked());
691 DVLOG(1) << __FUNCTION__ << " : done";
692 }
693
ResetSeekState()694 void SourceBufferStream::ResetSeekState() {
695 SetSelectedRange(NULL);
696 track_buffer_.clear();
697 config_change_pending_ = false;
698 last_output_buffer_timestamp_ = kNoTimestamp();
699 splice_buffers_index_ = 0;
700 pending_buffer_ = NULL;
701 pending_buffers_complete_ = false;
702 }
703
ShouldSeekToStartOfBuffered(base::TimeDelta seek_timestamp) const704 bool SourceBufferStream::ShouldSeekToStartOfBuffered(
705 base::TimeDelta seek_timestamp) const {
706 if (ranges_.empty())
707 return false;
708 base::TimeDelta beginning_of_buffered =
709 ranges_.front()->GetStartTimestamp();
710 return (seek_timestamp <= beginning_of_buffered &&
711 beginning_of_buffered < kSeekToStartFudgeRoom());
712 }
713
IsMonotonicallyIncreasing(const BufferQueue & buffers) const714 bool SourceBufferStream::IsMonotonicallyIncreasing(
715 const BufferQueue& buffers) const {
716 DCHECK(!buffers.empty());
717 base::TimeDelta prev_timestamp = last_appended_buffer_timestamp_;
718 bool prev_is_keyframe = last_appended_buffer_is_keyframe_;
719 for (BufferQueue::const_iterator itr = buffers.begin();
720 itr != buffers.end(); ++itr) {
721 base::TimeDelta current_timestamp = (*itr)->GetDecodeTimestamp();
722 bool current_is_keyframe = (*itr)->IsKeyframe();
723 DCHECK(current_timestamp != kNoTimestamp());
724
725 if (prev_timestamp != kNoTimestamp()) {
726 if (current_timestamp < prev_timestamp) {
727 MEDIA_LOG(log_cb_) << "Buffers were not monotonically increasing.";
728 return false;
729 }
730
731 if (current_timestamp == prev_timestamp &&
732 !AllowSameTimestamp(prev_is_keyframe, current_is_keyframe,
733 GetType())) {
734 MEDIA_LOG(log_cb_) << "Unexpected combination of buffers with the"
735 << " same timestamp detected at "
736 << current_timestamp.InSecondsF();
737 return false;
738 }
739 }
740
741 prev_timestamp = current_timestamp;
742 prev_is_keyframe = current_is_keyframe;
743 }
744 return true;
745 }
746
IsNextTimestampValid(base::TimeDelta next_timestamp,bool next_is_keyframe) const747 bool SourceBufferStream::IsNextTimestampValid(
748 base::TimeDelta next_timestamp, bool next_is_keyframe) const {
749 return (last_appended_buffer_timestamp_ != next_timestamp) ||
750 new_media_segment_ ||
751 AllowSameTimestamp(last_appended_buffer_is_keyframe_, next_is_keyframe,
752 GetType());
753 }
754
755
OnlySelectedRangeIsSeeked() const756 bool SourceBufferStream::OnlySelectedRangeIsSeeked() const {
757 for (RangeList::const_iterator itr = ranges_.begin();
758 itr != ranges_.end(); ++itr) {
759 if ((*itr)->HasNextBufferPosition() && (*itr) != selected_range_)
760 return false;
761 }
762 return !selected_range_ || selected_range_->HasNextBufferPosition();
763 }
764
UpdateMaxInterbufferDistance(const BufferQueue & buffers)765 void SourceBufferStream::UpdateMaxInterbufferDistance(
766 const BufferQueue& buffers) {
767 DCHECK(!buffers.empty());
768 base::TimeDelta prev_timestamp = last_appended_buffer_timestamp_;
769 for (BufferQueue::const_iterator itr = buffers.begin();
770 itr != buffers.end(); ++itr) {
771 base::TimeDelta current_timestamp = (*itr)->GetDecodeTimestamp();
772 DCHECK(current_timestamp != kNoTimestamp());
773
774 if (prev_timestamp != kNoTimestamp()) {
775 base::TimeDelta interbuffer_distance = current_timestamp - prev_timestamp;
776 if (max_interbuffer_distance_ == kNoTimestamp()) {
777 max_interbuffer_distance_ = interbuffer_distance;
778 } else {
779 max_interbuffer_distance_ =
780 std::max(max_interbuffer_distance_, interbuffer_distance);
781 }
782 }
783 prev_timestamp = current_timestamp;
784 }
785 }
786
SetConfigIds(const BufferQueue & buffers)787 void SourceBufferStream::SetConfigIds(const BufferQueue& buffers) {
788 for (BufferQueue::const_iterator itr = buffers.begin();
789 itr != buffers.end(); ++itr) {
790 (*itr)->SetConfigId(append_config_index_);
791 }
792 }
793
GarbageCollectIfNeeded()794 void SourceBufferStream::GarbageCollectIfNeeded() {
795 // Compute size of |ranges_|.
796 int ranges_size = 0;
797 for (RangeList::iterator itr = ranges_.begin(); itr != ranges_.end(); ++itr)
798 ranges_size += (*itr)->size_in_bytes();
799
800 // Return if we're under or at the memory limit.
801 if (ranges_size <= memory_limit_)
802 return;
803
804 int bytes_to_free = ranges_size - memory_limit_;
805
806 // Begin deleting after the last appended buffer.
807 int bytes_freed = FreeBuffersAfterLastAppended(bytes_to_free);
808
809 // Begin deleting from the front.
810 if (bytes_to_free - bytes_freed > 0)
811 bytes_freed += FreeBuffers(bytes_to_free - bytes_freed, false);
812
813 // Begin deleting from the back.
814 if (bytes_to_free - bytes_freed > 0)
815 FreeBuffers(bytes_to_free - bytes_freed, true);
816 }
817
FreeBuffersAfterLastAppended(int total_bytes_to_free)818 int SourceBufferStream::FreeBuffersAfterLastAppended(int total_bytes_to_free) {
819 base::TimeDelta next_buffer_timestamp = GetNextBufferTimestamp();
820 if (last_appended_buffer_timestamp_ == kNoTimestamp() ||
821 next_buffer_timestamp == kNoTimestamp() ||
822 last_appended_buffer_timestamp_ >= next_buffer_timestamp) {
823 return 0;
824 }
825
826 base::TimeDelta remove_range_start = last_appended_buffer_timestamp_;
827 if (last_appended_buffer_is_keyframe_)
828 remove_range_start += GetMaxInterbufferDistance();
829
830 base::TimeDelta remove_range_start_keyframe = FindKeyframeAfterTimestamp(
831 remove_range_start);
832 if (remove_range_start_keyframe != kNoTimestamp())
833 remove_range_start = remove_range_start_keyframe;
834 if (remove_range_start >= next_buffer_timestamp)
835 return 0;
836
837 base::TimeDelta remove_range_end;
838 int bytes_freed = GetRemovalRange(
839 remove_range_start, next_buffer_timestamp, total_bytes_to_free,
840 &remove_range_end);
841 if (bytes_freed > 0)
842 Remove(remove_range_start, remove_range_end, next_buffer_timestamp);
843 return bytes_freed;
844 }
845
GetRemovalRange(base::TimeDelta start_timestamp,base::TimeDelta end_timestamp,int total_bytes_to_free,base::TimeDelta * removal_end_timestamp)846 int SourceBufferStream::GetRemovalRange(
847 base::TimeDelta start_timestamp, base::TimeDelta end_timestamp,
848 int total_bytes_to_free, base::TimeDelta* removal_end_timestamp) {
849 DCHECK(start_timestamp >= base::TimeDelta()) << start_timestamp.InSecondsF();
850 DCHECK(start_timestamp < end_timestamp)
851 << "start " << start_timestamp.InSecondsF()
852 << ", end " << end_timestamp.InSecondsF();
853
854 int bytes_to_free = total_bytes_to_free;
855 int bytes_freed = 0;
856
857 for (RangeList::iterator itr = ranges_.begin();
858 itr != ranges_.end() && bytes_to_free > 0; ++itr) {
859 SourceBufferRange* range = *itr;
860 if (range->GetStartTimestamp() >= end_timestamp)
861 break;
862 if (range->GetEndTimestamp() < start_timestamp)
863 continue;
864
865 int bytes_removed = range->GetRemovalGOP(
866 start_timestamp, end_timestamp, bytes_to_free, removal_end_timestamp);
867 bytes_to_free -= bytes_removed;
868 bytes_freed += bytes_removed;
869 }
870 return bytes_freed;
871 }
872
FreeBuffers(int total_bytes_to_free,bool reverse_direction)873 int SourceBufferStream::FreeBuffers(int total_bytes_to_free,
874 bool reverse_direction) {
875 TRACE_EVENT2("media", "SourceBufferStream::FreeBuffers",
876 "total bytes to free", total_bytes_to_free,
877 "reverse direction", reverse_direction);
878
879 DCHECK_GT(total_bytes_to_free, 0);
880 int bytes_to_free = total_bytes_to_free;
881 int bytes_freed = 0;
882
883 // This range will save the last GOP appended to |range_for_next_append_|
884 // if the buffers surrounding it get deleted during garbage collection.
885 SourceBufferRange* new_range_for_append = NULL;
886
887 while (!ranges_.empty() && bytes_to_free > 0) {
888 SourceBufferRange* current_range = NULL;
889 BufferQueue buffers;
890 int bytes_deleted = 0;
891
892 if (reverse_direction) {
893 current_range = ranges_.back();
894 if (current_range->LastGOPContainsNextBufferPosition()) {
895 DCHECK_EQ(current_range, selected_range_);
896 break;
897 }
898 bytes_deleted = current_range->DeleteGOPFromBack(&buffers);
899 } else {
900 current_range = ranges_.front();
901 if (current_range->FirstGOPContainsNextBufferPosition()) {
902 DCHECK_EQ(current_range, selected_range_);
903 break;
904 }
905 bytes_deleted = current_range->DeleteGOPFromFront(&buffers);
906 }
907
908 // Check to see if we've just deleted the GOP that was last appended.
909 base::TimeDelta end_timestamp = buffers.back()->GetDecodeTimestamp();
910 if (end_timestamp == last_appended_buffer_timestamp_) {
911 DCHECK(last_appended_buffer_timestamp_ != kNoTimestamp());
912 DCHECK(!new_range_for_append);
913 // Create a new range containing these buffers.
914 new_range_for_append = new SourceBufferRange(
915 GetType(), buffers, kNoTimestamp(),
916 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance,
917 base::Unretained(this)));
918 range_for_next_append_ = ranges_.end();
919 } else {
920 bytes_to_free -= bytes_deleted;
921 bytes_freed += bytes_deleted;
922 }
923
924 if (current_range->size_in_bytes() == 0) {
925 DCHECK_NE(current_range, selected_range_);
926 DCHECK(range_for_next_append_ == ranges_.end() ||
927 *range_for_next_append_ != current_range);
928 delete current_range;
929 reverse_direction ? ranges_.pop_back() : ranges_.pop_front();
930 }
931 }
932
933 // Insert |new_range_for_append| into |ranges_|, if applicable.
934 if (new_range_for_append) {
935 range_for_next_append_ = AddToRanges(new_range_for_append);
936 DCHECK(range_for_next_append_ != ranges_.end());
937
938 // Check to see if we need to merge |new_range_for_append| with the range
939 // before or after it. |new_range_for_append| is created whenever the last
940 // GOP appended is encountered, regardless of whether any buffers after it
941 // are ultimately deleted. Merging is necessary if there were no buffers
942 // (or very few buffers) deleted after creating |new_range_for_append|.
943 if (range_for_next_append_ != ranges_.begin()) {
944 RangeList::iterator range_before_next = range_for_next_append_;
945 --range_before_next;
946 MergeWithAdjacentRangeIfNecessary(range_before_next);
947 }
948 MergeWithAdjacentRangeIfNecessary(range_for_next_append_);
949 }
950 return bytes_freed;
951 }
952
PrepareRangesForNextAppend(const BufferQueue & new_buffers,BufferQueue * deleted_buffers)953 void SourceBufferStream::PrepareRangesForNextAppend(
954 const BufferQueue& new_buffers, BufferQueue* deleted_buffers) {
955 DCHECK(deleted_buffers);
956
957 bool temporarily_select_range = false;
958 if (!track_buffer_.empty()) {
959 base::TimeDelta tb_timestamp = track_buffer_.back()->GetDecodeTimestamp();
960 base::TimeDelta seek_timestamp = FindKeyframeAfterTimestamp(tb_timestamp);
961 if (seek_timestamp != kNoTimestamp() &&
962 seek_timestamp < new_buffers.front()->GetDecodeTimestamp() &&
963 range_for_next_append_ != ranges_.end() &&
964 (*range_for_next_append_)->BelongsToRange(seek_timestamp)) {
965 DCHECK(tb_timestamp < seek_timestamp);
966 DCHECK(!selected_range_);
967 DCHECK(!(*range_for_next_append_)->HasNextBufferPosition());
968
969 // If there are GOPs between the end of the track buffer and the
970 // beginning of the new buffers, then temporarily seek the range
971 // so that the buffers between these two times will be deposited in
972 // |deleted_buffers| as if they were part of the current playback
973 // position.
974 // TODO(acolwell): Figure out a more elegant way to do this.
975 SeekAndSetSelectedRange(*range_for_next_append_, seek_timestamp);
976 temporarily_select_range = true;
977 }
978 }
979
980 // Handle splices between the existing buffers and the new buffers. If a
981 // splice is generated the timestamp and duration of the first buffer in
982 // |new_buffers| will be modified.
983 if (splice_frames_enabled_)
984 GenerateSpliceFrame(new_buffers);
985
986 base::TimeDelta prev_timestamp = last_appended_buffer_timestamp_;
987 bool prev_is_keyframe = last_appended_buffer_is_keyframe_;
988 base::TimeDelta next_timestamp = new_buffers.front()->GetDecodeTimestamp();
989 bool next_is_keyframe = new_buffers.front()->IsKeyframe();
990
991 if (prev_timestamp != kNoTimestamp() && prev_timestamp != next_timestamp) {
992 // Clean up the old buffers between the last appended buffer and the
993 // beginning of |new_buffers|.
994 RemoveInternal(prev_timestamp, next_timestamp, true, deleted_buffers);
995 }
996
997 // Make the delete range exclusive if we are dealing with an allowed same
998 // timestamp situation. This prevents the first buffer in the current append
999 // from deleting the last buffer in the previous append if both buffers
1000 // have the same timestamp.
1001 //
1002 // The delete range should never be exclusive if a splice frame was generated
1003 // because we don't generate splice frames for same timestamp situations.
1004 DCHECK(new_buffers.front()->splice_timestamp() !=
1005 new_buffers.front()->timestamp());
1006 const bool is_exclusive =
1007 new_buffers.front()->splice_buffers().empty() &&
1008 prev_timestamp == next_timestamp &&
1009 AllowSameTimestamp(prev_is_keyframe, next_is_keyframe, GetType());
1010
1011 // Delete the buffers that |new_buffers| overlaps.
1012 base::TimeDelta start = new_buffers.front()->GetDecodeTimestamp();
1013 base::TimeDelta end = new_buffers.back()->GetDecodeTimestamp();
1014 base::TimeDelta duration = new_buffers.back()->duration();
1015
1016 if (duration != kNoTimestamp() && duration > base::TimeDelta()) {
1017 end += duration;
1018 } else {
1019 // TODO(acolwell): Ensure all buffers actually have proper
1020 // duration info so that this hack isn't needed.
1021 // http://crbug.com/312836
1022 end += base::TimeDelta::FromInternalValue(1);
1023 }
1024
1025 RemoveInternal(start, end, is_exclusive, deleted_buffers);
1026
1027 // Restore the range seek state if necessary.
1028 if (temporarily_select_range)
1029 SetSelectedRange(NULL);
1030 }
1031
AreAdjacentInSequence(base::TimeDelta first_timestamp,base::TimeDelta second_timestamp) const1032 bool SourceBufferStream::AreAdjacentInSequence(
1033 base::TimeDelta first_timestamp, base::TimeDelta second_timestamp) const {
1034 return first_timestamp < second_timestamp &&
1035 second_timestamp <=
1036 first_timestamp + ComputeFudgeRoom(GetMaxInterbufferDistance());
1037 }
1038
PruneTrackBuffer(const base::TimeDelta timestamp)1039 void SourceBufferStream::PruneTrackBuffer(const base::TimeDelta timestamp) {
1040 // If we don't have the next timestamp, we don't have anything to delete.
1041 if (timestamp == kNoTimestamp())
1042 return;
1043
1044 while (!track_buffer_.empty() &&
1045 track_buffer_.back()->GetDecodeTimestamp() >= timestamp) {
1046 track_buffer_.pop_back();
1047 }
1048 }
1049
MergeWithAdjacentRangeIfNecessary(const RangeList::iterator & range_with_new_buffers_itr)1050 void SourceBufferStream::MergeWithAdjacentRangeIfNecessary(
1051 const RangeList::iterator& range_with_new_buffers_itr) {
1052 DCHECK(range_with_new_buffers_itr != ranges_.end());
1053
1054 SourceBufferRange* range_with_new_buffers = *range_with_new_buffers_itr;
1055 RangeList::iterator next_range_itr = range_with_new_buffers_itr;
1056 ++next_range_itr;
1057
1058 if (next_range_itr == ranges_.end() ||
1059 !range_with_new_buffers->CanAppendRangeToEnd(**next_range_itr)) {
1060 return;
1061 }
1062
1063 bool transfer_current_position = selected_range_ == *next_range_itr;
1064 range_with_new_buffers->AppendRangeToEnd(**next_range_itr,
1065 transfer_current_position);
1066 // Update |selected_range_| pointer if |range| has become selected after
1067 // merges.
1068 if (transfer_current_position)
1069 SetSelectedRange(range_with_new_buffers);
1070
1071 if (next_range_itr == range_for_next_append_)
1072 range_for_next_append_ = range_with_new_buffers_itr;
1073
1074 DeleteAndRemoveRange(&next_range_itr);
1075 }
1076
Seek(base::TimeDelta timestamp)1077 void SourceBufferStream::Seek(base::TimeDelta timestamp) {
1078 DCHECK(timestamp >= base::TimeDelta());
1079 ResetSeekState();
1080
1081 if (ShouldSeekToStartOfBuffered(timestamp)) {
1082 ranges_.front()->SeekToStart();
1083 SetSelectedRange(ranges_.front());
1084 seek_pending_ = false;
1085 return;
1086 }
1087
1088 seek_buffer_timestamp_ = timestamp;
1089 seek_pending_ = true;
1090
1091 RangeList::iterator itr = ranges_.end();
1092 for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
1093 if ((*itr)->CanSeekTo(timestamp))
1094 break;
1095 }
1096
1097 if (itr == ranges_.end())
1098 return;
1099
1100 SeekAndSetSelectedRange(*itr, timestamp);
1101 seek_pending_ = false;
1102 }
1103
IsSeekPending() const1104 bool SourceBufferStream::IsSeekPending() const {
1105 return !(end_of_stream_ && IsEndSelected()) && seek_pending_;
1106 }
1107
OnSetDuration(base::TimeDelta duration)1108 void SourceBufferStream::OnSetDuration(base::TimeDelta duration) {
1109 RangeList::iterator itr = ranges_.end();
1110 for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
1111 if ((*itr)->GetEndTimestamp() > duration)
1112 break;
1113 }
1114 if (itr == ranges_.end())
1115 return;
1116
1117 // Need to partially truncate this range.
1118 if ((*itr)->GetStartTimestamp() < duration) {
1119 bool delete_range = (*itr)->TruncateAt(duration, NULL, false);
1120 if ((*itr == selected_range_) && !selected_range_->HasNextBufferPosition())
1121 SetSelectedRange(NULL);
1122
1123 if (delete_range) {
1124 DeleteAndRemoveRange(&itr);
1125 } else {
1126 ++itr;
1127 }
1128 }
1129
1130 // Delete all ranges that begin after |duration|.
1131 while (itr != ranges_.end()) {
1132 // If we're about to delete the selected range, also reset the seek state.
1133 DCHECK((*itr)->GetStartTimestamp() >= duration);
1134 if (*itr == selected_range_)
1135 ResetSeekState();
1136 DeleteAndRemoveRange(&itr);
1137 }
1138 }
1139
GetNextBuffer(scoped_refptr<StreamParserBuffer> * out_buffer)1140 SourceBufferStream::Status SourceBufferStream::GetNextBuffer(
1141 scoped_refptr<StreamParserBuffer>* out_buffer) {
1142 if (!pending_buffer_) {
1143 const SourceBufferStream::Status status = GetNextBufferInternal(out_buffer);
1144 if (status != SourceBufferStream::kSuccess || !SetPendingBuffer(out_buffer))
1145 return status;
1146 }
1147
1148 if (!pending_buffer_->splice_buffers().empty())
1149 return HandleNextBufferWithSplice(out_buffer);
1150
1151 DCHECK(pending_buffer_->preroll_buffer());
1152 return HandleNextBufferWithPreroll(out_buffer);
1153 }
1154
HandleNextBufferWithSplice(scoped_refptr<StreamParserBuffer> * out_buffer)1155 SourceBufferStream::Status SourceBufferStream::HandleNextBufferWithSplice(
1156 scoped_refptr<StreamParserBuffer>* out_buffer) {
1157 const BufferQueue& splice_buffers = pending_buffer_->splice_buffers();
1158 const size_t last_splice_buffer_index = splice_buffers.size() - 1;
1159
1160 // Are there any splice buffers left to hand out? The last buffer should be
1161 // handed out separately since it represents the first post-splice buffer.
1162 if (splice_buffers_index_ < last_splice_buffer_index) {
1163 // Account for config changes which occur between fade out buffers.
1164 if (current_config_index_ !=
1165 splice_buffers[splice_buffers_index_]->GetConfigId()) {
1166 config_change_pending_ = true;
1167 DVLOG(1) << "Config change (splice buffer config ID does not match).";
1168 return SourceBufferStream::kConfigChange;
1169 }
1170
1171 // Every pre splice buffer must have the same splice_timestamp().
1172 DCHECK(pending_buffer_->splice_timestamp() ==
1173 splice_buffers[splice_buffers_index_]->splice_timestamp());
1174
1175 // No pre splice buffers should have preroll.
1176 DCHECK(!splice_buffers[splice_buffers_index_]->preroll_buffer());
1177
1178 *out_buffer = splice_buffers[splice_buffers_index_++];
1179 return SourceBufferStream::kSuccess;
1180 }
1181
1182 // Did we hand out the last pre-splice buffer on the previous call?
1183 if (!pending_buffers_complete_) {
1184 DCHECK_EQ(splice_buffers_index_, last_splice_buffer_index);
1185 pending_buffers_complete_ = true;
1186 config_change_pending_ = true;
1187 DVLOG(1) << "Config change (forced for fade in of splice frame).";
1188 return SourceBufferStream::kConfigChange;
1189 }
1190
1191 // All pre-splice buffers have been handed out and a config change completed,
1192 // so hand out the final buffer for fade in. Because a config change is
1193 // always issued prior to handing out this buffer, any changes in config id
1194 // have been inherently handled.
1195 DCHECK(pending_buffers_complete_);
1196 DCHECK_EQ(splice_buffers_index_, splice_buffers.size() - 1);
1197 DCHECK(splice_buffers.back()->splice_timestamp() == kNoTimestamp());
1198 *out_buffer = splice_buffers.back();
1199 pending_buffer_ = NULL;
1200
1201 // If the last splice buffer has preroll, hand off to the preroll handler.
1202 return SetPendingBuffer(out_buffer) ? HandleNextBufferWithPreroll(out_buffer)
1203 : SourceBufferStream::kSuccess;
1204 }
1205
HandleNextBufferWithPreroll(scoped_refptr<StreamParserBuffer> * out_buffer)1206 SourceBufferStream::Status SourceBufferStream::HandleNextBufferWithPreroll(
1207 scoped_refptr<StreamParserBuffer>* out_buffer) {
1208 // Any config change should have already been handled.
1209 DCHECK_EQ(current_config_index_, pending_buffer_->GetConfigId());
1210
1211 // Check if the preroll buffer has already been handed out.
1212 if (!pending_buffers_complete_) {
1213 pending_buffers_complete_ = true;
1214 *out_buffer = pending_buffer_->preroll_buffer();
1215 return SourceBufferStream::kSuccess;
1216 }
1217
1218 // Preroll complete, hand out the final buffer.
1219 *out_buffer = pending_buffer_;
1220 pending_buffer_ = NULL;
1221 return SourceBufferStream::kSuccess;
1222 }
1223
GetNextBufferInternal(scoped_refptr<StreamParserBuffer> * out_buffer)1224 SourceBufferStream::Status SourceBufferStream::GetNextBufferInternal(
1225 scoped_refptr<StreamParserBuffer>* out_buffer) {
1226 CHECK(!config_change_pending_);
1227
1228 if (!track_buffer_.empty()) {
1229 DCHECK(!selected_range_);
1230 scoped_refptr<StreamParserBuffer>& next_buffer = track_buffer_.front();
1231
1232 // If the next buffer is an audio splice frame, the next effective config id
1233 // comes from the first splice buffer.
1234 if (GetConfigId(next_buffer, 0) != current_config_index_) {
1235 config_change_pending_ = true;
1236 DVLOG(1) << "Config change (track buffer config ID does not match).";
1237 return kConfigChange;
1238 }
1239
1240 *out_buffer = next_buffer;
1241 track_buffer_.pop_front();
1242 last_output_buffer_timestamp_ = (*out_buffer)->GetDecodeTimestamp();
1243
1244 // If the track buffer becomes empty, then try to set the selected range
1245 // based on the timestamp of this buffer being returned.
1246 if (track_buffer_.empty())
1247 SetSelectedRangeIfNeeded(last_output_buffer_timestamp_);
1248
1249 return kSuccess;
1250 }
1251
1252 if (!selected_range_ || !selected_range_->HasNextBuffer()) {
1253 if (end_of_stream_ && IsEndSelected())
1254 return kEndOfStream;
1255 return kNeedBuffer;
1256 }
1257
1258 if (selected_range_->GetNextConfigId() != current_config_index_) {
1259 config_change_pending_ = true;
1260 DVLOG(1) << "Config change (selected range config ID does not match).";
1261 return kConfigChange;
1262 }
1263
1264 CHECK(selected_range_->GetNextBuffer(out_buffer));
1265 last_output_buffer_timestamp_ = (*out_buffer)->GetDecodeTimestamp();
1266 return kSuccess;
1267 }
1268
GetNextBufferTimestamp()1269 base::TimeDelta SourceBufferStream::GetNextBufferTimestamp() {
1270 if (!track_buffer_.empty())
1271 return track_buffer_.front()->GetDecodeTimestamp();
1272
1273 if (!selected_range_)
1274 return kNoTimestamp();
1275
1276 DCHECK(selected_range_->HasNextBufferPosition());
1277 return selected_range_->GetNextTimestamp();
1278 }
1279
GetEndBufferTimestamp()1280 base::TimeDelta SourceBufferStream::GetEndBufferTimestamp() {
1281 if (!selected_range_)
1282 return kNoTimestamp();
1283 return selected_range_->GetEndTimestamp();
1284 }
1285
1286 SourceBufferStream::RangeList::iterator
FindExistingRangeFor(base::TimeDelta start_timestamp)1287 SourceBufferStream::FindExistingRangeFor(base::TimeDelta start_timestamp) {
1288 for (RangeList::iterator itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
1289 if ((*itr)->BelongsToRange(start_timestamp))
1290 return itr;
1291 }
1292 return ranges_.end();
1293 }
1294
1295 SourceBufferStream::RangeList::iterator
AddToRanges(SourceBufferRange * new_range)1296 SourceBufferStream::AddToRanges(SourceBufferRange* new_range) {
1297 base::TimeDelta start_timestamp = new_range->GetStartTimestamp();
1298 RangeList::iterator itr = ranges_.end();
1299 for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
1300 if ((*itr)->GetStartTimestamp() > start_timestamp)
1301 break;
1302 }
1303 return ranges_.insert(itr, new_range);
1304 }
1305
1306 SourceBufferStream::RangeList::iterator
GetSelectedRangeItr()1307 SourceBufferStream::GetSelectedRangeItr() {
1308 DCHECK(selected_range_);
1309 RangeList::iterator itr = ranges_.end();
1310 for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
1311 if (*itr == selected_range_)
1312 break;
1313 }
1314 DCHECK(itr != ranges_.end());
1315 return itr;
1316 }
1317
SeekAndSetSelectedRange(SourceBufferRange * range,base::TimeDelta seek_timestamp)1318 void SourceBufferStream::SeekAndSetSelectedRange(
1319 SourceBufferRange* range, base::TimeDelta seek_timestamp) {
1320 if (range)
1321 range->Seek(seek_timestamp);
1322 SetSelectedRange(range);
1323 }
1324
SetSelectedRange(SourceBufferRange * range)1325 void SourceBufferStream::SetSelectedRange(SourceBufferRange* range) {
1326 DVLOG(1) << __FUNCTION__ << " : " << selected_range_ << " -> " << range;
1327 if (selected_range_)
1328 selected_range_->ResetNextBufferPosition();
1329 DCHECK(!range || range->HasNextBufferPosition());
1330 selected_range_ = range;
1331 }
1332
GetBufferedTime() const1333 Ranges<base::TimeDelta> SourceBufferStream::GetBufferedTime() const {
1334 Ranges<base::TimeDelta> ranges;
1335 for (RangeList::const_iterator itr = ranges_.begin();
1336 itr != ranges_.end(); ++itr) {
1337 ranges.Add((*itr)->GetStartTimestamp(), (*itr)->GetBufferedEndTimestamp());
1338 }
1339 return ranges;
1340 }
1341
GetBufferedDuration() const1342 base::TimeDelta SourceBufferStream::GetBufferedDuration() const {
1343 if (ranges_.empty())
1344 return base::TimeDelta();
1345
1346 return ranges_.back()->GetBufferedEndTimestamp();
1347 }
1348
MarkEndOfStream()1349 void SourceBufferStream::MarkEndOfStream() {
1350 DCHECK(!end_of_stream_);
1351 end_of_stream_ = true;
1352 }
1353
UnmarkEndOfStream()1354 void SourceBufferStream::UnmarkEndOfStream() {
1355 DCHECK(end_of_stream_);
1356 end_of_stream_ = false;
1357 }
1358
IsEndSelected() const1359 bool SourceBufferStream::IsEndSelected() const {
1360 if (ranges_.empty())
1361 return true;
1362
1363 if (seek_pending_)
1364 return seek_buffer_timestamp_ >= ranges_.back()->GetBufferedEndTimestamp();
1365
1366 return selected_range_ == ranges_.back();
1367 }
1368
GetCurrentAudioDecoderConfig()1369 const AudioDecoderConfig& SourceBufferStream::GetCurrentAudioDecoderConfig() {
1370 if (config_change_pending_)
1371 CompleteConfigChange();
1372 return audio_configs_[current_config_index_];
1373 }
1374
GetCurrentVideoDecoderConfig()1375 const VideoDecoderConfig& SourceBufferStream::GetCurrentVideoDecoderConfig() {
1376 if (config_change_pending_)
1377 CompleteConfigChange();
1378 return video_configs_[current_config_index_];
1379 }
1380
GetCurrentTextTrackConfig()1381 const TextTrackConfig& SourceBufferStream::GetCurrentTextTrackConfig() {
1382 return text_track_config_;
1383 }
1384
GetMaxInterbufferDistance() const1385 base::TimeDelta SourceBufferStream::GetMaxInterbufferDistance() const {
1386 if (max_interbuffer_distance_ == kNoTimestamp())
1387 return base::TimeDelta::FromMilliseconds(kDefaultBufferDurationInMs);
1388 return max_interbuffer_distance_;
1389 }
1390
UpdateAudioConfig(const AudioDecoderConfig & config)1391 bool SourceBufferStream::UpdateAudioConfig(const AudioDecoderConfig& config) {
1392 DCHECK(!audio_configs_.empty());
1393 DCHECK(video_configs_.empty());
1394 DVLOG(3) << "UpdateAudioConfig.";
1395
1396 if (audio_configs_[0].codec() != config.codec()) {
1397 MEDIA_LOG(log_cb_) << "Audio codec changes not allowed.";
1398 return false;
1399 }
1400
1401 if (audio_configs_[0].is_encrypted() != config.is_encrypted()) {
1402 MEDIA_LOG(log_cb_) << "Audio encryption changes not allowed.";
1403 return false;
1404 }
1405
1406 // Check to see if the new config matches an existing one.
1407 for (size_t i = 0; i < audio_configs_.size(); ++i) {
1408 if (config.Matches(audio_configs_[i])) {
1409 append_config_index_ = i;
1410 return true;
1411 }
1412 }
1413
1414 // No matches found so let's add this one to the list.
1415 append_config_index_ = audio_configs_.size();
1416 DVLOG(2) << "New audio config - index: " << append_config_index_;
1417 audio_configs_.resize(audio_configs_.size() + 1);
1418 audio_configs_[append_config_index_] = config;
1419 return true;
1420 }
1421
UpdateVideoConfig(const VideoDecoderConfig & config)1422 bool SourceBufferStream::UpdateVideoConfig(const VideoDecoderConfig& config) {
1423 DCHECK(!video_configs_.empty());
1424 DCHECK(audio_configs_.empty());
1425 DVLOG(3) << "UpdateVideoConfig.";
1426
1427 if (video_configs_[0].codec() != config.codec()) {
1428 MEDIA_LOG(log_cb_) << "Video codec changes not allowed.";
1429 return false;
1430 }
1431
1432 if (video_configs_[0].is_encrypted() != config.is_encrypted()) {
1433 MEDIA_LOG(log_cb_) << "Video encryption changes not allowed.";
1434 return false;
1435 }
1436
1437 // Check to see if the new config matches an existing one.
1438 for (size_t i = 0; i < video_configs_.size(); ++i) {
1439 if (config.Matches(video_configs_[i])) {
1440 append_config_index_ = i;
1441 return true;
1442 }
1443 }
1444
1445 // No matches found so let's add this one to the list.
1446 append_config_index_ = video_configs_.size();
1447 DVLOG(2) << "New video config - index: " << append_config_index_;
1448 video_configs_.resize(video_configs_.size() + 1);
1449 video_configs_[append_config_index_] = config;
1450 return true;
1451 }
1452
CompleteConfigChange()1453 void SourceBufferStream::CompleteConfigChange() {
1454 config_change_pending_ = false;
1455
1456 if (pending_buffer_) {
1457 current_config_index_ =
1458 GetConfigId(pending_buffer_, splice_buffers_index_);
1459 return;
1460 }
1461
1462 if (!track_buffer_.empty()) {
1463 current_config_index_ = GetConfigId(track_buffer_.front(), 0);
1464 return;
1465 }
1466
1467 if (selected_range_ && selected_range_->HasNextBuffer())
1468 current_config_index_ = selected_range_->GetNextConfigId();
1469 }
1470
SetSelectedRangeIfNeeded(const base::TimeDelta timestamp)1471 void SourceBufferStream::SetSelectedRangeIfNeeded(
1472 const base::TimeDelta timestamp) {
1473 DVLOG(1) << __FUNCTION__ << "(" << timestamp.InSecondsF() << ")";
1474
1475 if (selected_range_) {
1476 DCHECK(track_buffer_.empty());
1477 return;
1478 }
1479
1480 if (!track_buffer_.empty()) {
1481 DCHECK(!selected_range_);
1482 return;
1483 }
1484
1485 base::TimeDelta start_timestamp = timestamp;
1486
1487 // If the next buffer timestamp is not known then use a timestamp just after
1488 // the timestamp on the last buffer returned by GetNextBuffer().
1489 if (start_timestamp == kNoTimestamp()) {
1490 if (last_output_buffer_timestamp_ == kNoTimestamp())
1491 return;
1492
1493 start_timestamp = last_output_buffer_timestamp_ +
1494 base::TimeDelta::FromInternalValue(1);
1495 }
1496
1497 base::TimeDelta seek_timestamp =
1498 FindNewSelectedRangeSeekTimestamp(start_timestamp);
1499
1500 // If we don't have buffered data to seek to, then return.
1501 if (seek_timestamp == kNoTimestamp())
1502 return;
1503
1504 DCHECK(track_buffer_.empty());
1505 SeekAndSetSelectedRange(*FindExistingRangeFor(seek_timestamp),
1506 seek_timestamp);
1507 }
1508
FindNewSelectedRangeSeekTimestamp(const base::TimeDelta start_timestamp)1509 base::TimeDelta SourceBufferStream::FindNewSelectedRangeSeekTimestamp(
1510 const base::TimeDelta start_timestamp) {
1511 DCHECK(start_timestamp != kNoTimestamp());
1512 DCHECK(start_timestamp >= base::TimeDelta());
1513
1514 RangeList::iterator itr = ranges_.begin();
1515
1516 for (; itr != ranges_.end(); ++itr) {
1517 if ((*itr)->GetEndTimestamp() >= start_timestamp) {
1518 break;
1519 }
1520 }
1521
1522 if (itr == ranges_.end())
1523 return kNoTimestamp();
1524
1525 // First check for a keyframe timestamp >= |start_timestamp|
1526 // in the current range.
1527 base::TimeDelta keyframe_timestamp =
1528 (*itr)->NextKeyframeTimestamp(start_timestamp);
1529
1530 if (keyframe_timestamp != kNoTimestamp())
1531 return keyframe_timestamp;
1532
1533 // If a keyframe was not found then look for a keyframe that is
1534 // "close enough" in the current or next range.
1535 base::TimeDelta end_timestamp =
1536 start_timestamp + ComputeFudgeRoom(GetMaxInterbufferDistance());
1537 DCHECK(start_timestamp < end_timestamp);
1538
1539 // Make sure the current range doesn't start beyond |end_timestamp|.
1540 if ((*itr)->GetStartTimestamp() >= end_timestamp)
1541 return kNoTimestamp();
1542
1543 keyframe_timestamp = (*itr)->KeyframeBeforeTimestamp(end_timestamp);
1544
1545 // Check to see if the keyframe is within the acceptable range
1546 // (|start_timestamp|, |end_timestamp|].
1547 if (keyframe_timestamp != kNoTimestamp() &&
1548 start_timestamp < keyframe_timestamp &&
1549 keyframe_timestamp <= end_timestamp) {
1550 return keyframe_timestamp;
1551 }
1552
1553 // If |end_timestamp| is within this range, then no other checks are
1554 // necessary.
1555 if (end_timestamp <= (*itr)->GetEndTimestamp())
1556 return kNoTimestamp();
1557
1558 // Move on to the next range.
1559 ++itr;
1560
1561 // Return early if the next range does not contain |end_timestamp|.
1562 if (itr == ranges_.end() || (*itr)->GetStartTimestamp() >= end_timestamp)
1563 return kNoTimestamp();
1564
1565 keyframe_timestamp = (*itr)->KeyframeBeforeTimestamp(end_timestamp);
1566
1567 // Check to see if the keyframe is within the acceptable range
1568 // (|start_timestamp|, |end_timestamp|].
1569 if (keyframe_timestamp != kNoTimestamp() &&
1570 start_timestamp < keyframe_timestamp &&
1571 keyframe_timestamp <= end_timestamp) {
1572 return keyframe_timestamp;
1573 }
1574
1575 return kNoTimestamp();
1576 }
1577
FindKeyframeAfterTimestamp(const base::TimeDelta timestamp)1578 base::TimeDelta SourceBufferStream::FindKeyframeAfterTimestamp(
1579 const base::TimeDelta timestamp) {
1580 DCHECK(timestamp != kNoTimestamp());
1581
1582 RangeList::iterator itr = FindExistingRangeFor(timestamp);
1583
1584 if (itr == ranges_.end())
1585 return kNoTimestamp();
1586
1587 // First check for a keyframe timestamp >= |timestamp|
1588 // in the current range.
1589 return (*itr)->NextKeyframeTimestamp(timestamp);
1590 }
1591
GetStreamTypeName() const1592 std::string SourceBufferStream::GetStreamTypeName() const {
1593 switch (GetType()) {
1594 case kAudio:
1595 return "AUDIO";
1596 case kVideo:
1597 return "VIDEO";
1598 case kText:
1599 return "TEXT";
1600 }
1601 NOTREACHED();
1602 return "";
1603 }
1604
GetType() const1605 SourceBufferStream::Type SourceBufferStream::GetType() const {
1606 if (!audio_configs_.empty())
1607 return kAudio;
1608 if (!video_configs_.empty())
1609 return kVideo;
1610 DCHECK_NE(text_track_config_.kind(), kTextNone);
1611 return kText;
1612 }
1613
DeleteAndRemoveRange(RangeList::iterator * itr)1614 void SourceBufferStream::DeleteAndRemoveRange(RangeList::iterator* itr) {
1615 DVLOG(1) << __FUNCTION__;
1616
1617 DCHECK(*itr != ranges_.end());
1618 if (**itr == selected_range_) {
1619 DVLOG(1) << __FUNCTION__ << " deleting selected range.";
1620 SetSelectedRange(NULL);
1621 }
1622
1623 if (*itr == range_for_next_append_) {
1624 DVLOG(1) << __FUNCTION__ << " deleting range_for_next_append_.";
1625 range_for_next_append_ = ranges_.end();
1626 last_appended_buffer_timestamp_ = kNoTimestamp();
1627 last_appended_buffer_is_keyframe_ = false;
1628 }
1629
1630 delete **itr;
1631 *itr = ranges_.erase(*itr);
1632 }
1633
GenerateSpliceFrame(const BufferQueue & new_buffers)1634 void SourceBufferStream::GenerateSpliceFrame(const BufferQueue& new_buffers) {
1635 DCHECK(!new_buffers.empty());
1636
1637 // Splice frames are only supported for audio.
1638 if (GetType() != kAudio)
1639 return;
1640
1641 // Find the overlapped range (if any).
1642 const base::TimeDelta splice_timestamp = new_buffers.front()->timestamp();
1643 RangeList::iterator range_itr = FindExistingRangeFor(splice_timestamp);
1644 if (range_itr == ranges_.end())
1645 return;
1646
1647 const base::TimeDelta max_splice_end_timestamp =
1648 splice_timestamp + base::TimeDelta::FromMilliseconds(
1649 AudioSplicer::kCrossfadeDurationInMilliseconds);
1650
1651 // Find all buffers involved before the splice point.
1652 BufferQueue pre_splice_buffers;
1653 if (!(*range_itr)->GetBuffersInRange(
1654 splice_timestamp, max_splice_end_timestamp, &pre_splice_buffers)) {
1655 return;
1656 }
1657
1658 // If there are gaps in the timeline, it's possible that we only find buffers
1659 // after the splice point but within the splice range. For simplicity, we do
1660 // not generate splice frames in this case.
1661 //
1662 // We also do not want to generate splices if the first new buffer replaces an
1663 // existing buffer exactly.
1664 if (pre_splice_buffers.front()->timestamp() >= splice_timestamp)
1665 return;
1666
1667 // If any |pre_splice_buffers| are already splices or preroll, do not generate
1668 // a splice.
1669 for (size_t i = 0; i < pre_splice_buffers.size(); ++i) {
1670 const BufferQueue& original_splice_buffers =
1671 pre_splice_buffers[i]->splice_buffers();
1672 if (!original_splice_buffers.empty()) {
1673 DVLOG(1) << "Can't generate splice: overlapped buffers contain a "
1674 "pre-existing splice.";
1675 return;
1676 }
1677
1678 if (pre_splice_buffers[i]->preroll_buffer()) {
1679 DVLOG(1) << "Can't generate splice: overlapped buffers contain preroll.";
1680 return;
1681 }
1682 }
1683
1684 // Don't generate splice frames which represent less than two frames, since we
1685 // need at least that much to generate a crossfade. Per the spec, make this
1686 // check using the sample rate of the overlapping buffers.
1687 const base::TimeDelta splice_duration =
1688 pre_splice_buffers.back()->timestamp() +
1689 pre_splice_buffers.back()->duration() - splice_timestamp;
1690 const base::TimeDelta minimum_splice_duration = base::TimeDelta::FromSecondsD(
1691 2.0 / audio_configs_[append_config_index_].samples_per_second());
1692 if (splice_duration < minimum_splice_duration) {
1693 DVLOG(1) << "Can't generate splice: not enough samples for crossfade; have "
1694 << splice_duration.InMicroseconds() << " us, but need "
1695 << minimum_splice_duration.InMicroseconds() << " us.";
1696 return;
1697 }
1698
1699 new_buffers.front()->ConvertToSpliceBuffer(pre_splice_buffers);
1700 }
1701
SourceBufferRange(SourceBufferStream::Type type,const BufferQueue & new_buffers,base::TimeDelta media_segment_start_time,const InterbufferDistanceCB & interbuffer_distance_cb)1702 SourceBufferRange::SourceBufferRange(
1703 SourceBufferStream::Type type, const BufferQueue& new_buffers,
1704 base::TimeDelta media_segment_start_time,
1705 const InterbufferDistanceCB& interbuffer_distance_cb)
1706 : type_(type),
1707 keyframe_map_index_base_(0),
1708 next_buffer_index_(-1),
1709 media_segment_start_time_(media_segment_start_time),
1710 interbuffer_distance_cb_(interbuffer_distance_cb),
1711 size_in_bytes_(0) {
1712 CHECK(!new_buffers.empty());
1713 DCHECK(new_buffers.front()->IsKeyframe());
1714 DCHECK(!interbuffer_distance_cb.is_null());
1715 AppendBuffersToEnd(new_buffers);
1716 }
1717
AppendBuffersToEnd(const BufferQueue & new_buffers)1718 void SourceBufferRange::AppendBuffersToEnd(const BufferQueue& new_buffers) {
1719 DCHECK(buffers_.empty() || CanAppendBuffersToEnd(new_buffers));
1720 DCHECK(media_segment_start_time_ == kNoTimestamp() ||
1721 media_segment_start_time_ <=
1722 new_buffers.front()->GetDecodeTimestamp());
1723 for (BufferQueue::const_iterator itr = new_buffers.begin();
1724 itr != new_buffers.end();
1725 ++itr) {
1726 DCHECK((*itr)->GetDecodeTimestamp() != kNoTimestamp());
1727 buffers_.push_back(*itr);
1728 size_in_bytes_ += (*itr)->data_size();
1729
1730 if ((*itr)->IsKeyframe()) {
1731 keyframe_map_.insert(
1732 std::make_pair((*itr)->GetDecodeTimestamp(),
1733 buffers_.size() - 1 + keyframe_map_index_base_));
1734 }
1735 }
1736 }
1737
Seek(base::TimeDelta timestamp)1738 void SourceBufferRange::Seek(base::TimeDelta timestamp) {
1739 DCHECK(CanSeekTo(timestamp));
1740 DCHECK(!keyframe_map_.empty());
1741
1742 KeyframeMap::iterator result = GetFirstKeyframeBefore(timestamp);
1743 next_buffer_index_ = result->second - keyframe_map_index_base_;
1744 DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size()));
1745 }
1746
SeekAheadTo(base::TimeDelta timestamp)1747 void SourceBufferRange::SeekAheadTo(base::TimeDelta timestamp) {
1748 SeekAhead(timestamp, false);
1749 }
1750
SeekAheadPast(base::TimeDelta timestamp)1751 void SourceBufferRange::SeekAheadPast(base::TimeDelta timestamp) {
1752 SeekAhead(timestamp, true);
1753 }
1754
SeekAhead(base::TimeDelta timestamp,bool skip_given_timestamp)1755 void SourceBufferRange::SeekAhead(base::TimeDelta timestamp,
1756 bool skip_given_timestamp) {
1757 DCHECK(!keyframe_map_.empty());
1758
1759 KeyframeMap::iterator result =
1760 GetFirstKeyframeAt(timestamp, skip_given_timestamp);
1761
1762 // If there isn't a keyframe after |timestamp|, then seek to end and return
1763 // kNoTimestamp to signal such.
1764 if (result == keyframe_map_.end()) {
1765 next_buffer_index_ = -1;
1766 return;
1767 }
1768 next_buffer_index_ = result->second - keyframe_map_index_base_;
1769 DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size()));
1770 }
1771
SeekToStart()1772 void SourceBufferRange::SeekToStart() {
1773 DCHECK(!buffers_.empty());
1774 next_buffer_index_ = 0;
1775 }
1776
SplitRange(base::TimeDelta timestamp,bool is_exclusive)1777 SourceBufferRange* SourceBufferRange::SplitRange(
1778 base::TimeDelta timestamp, bool is_exclusive) {
1779 CHECK(!buffers_.empty());
1780
1781 // Find the first keyframe after |timestamp|. If |is_exclusive|, do not
1782 // include keyframes at |timestamp|.
1783 KeyframeMap::iterator new_beginning_keyframe =
1784 GetFirstKeyframeAt(timestamp, is_exclusive);
1785
1786 // If there is no keyframe after |timestamp|, we can't split the range.
1787 if (new_beginning_keyframe == keyframe_map_.end())
1788 return NULL;
1789
1790 // Remove the data beginning at |keyframe_index| from |buffers_| and save it
1791 // into |removed_buffers|.
1792 int keyframe_index =
1793 new_beginning_keyframe->second - keyframe_map_index_base_;
1794 DCHECK_LT(keyframe_index, static_cast<int>(buffers_.size()));
1795 BufferQueue::iterator starting_point = buffers_.begin() + keyframe_index;
1796 BufferQueue removed_buffers(starting_point, buffers_.end());
1797
1798 base::TimeDelta new_range_start_timestamp = kNoTimestamp();
1799 if (GetStartTimestamp() < buffers_.front()->GetDecodeTimestamp() &&
1800 timestamp < removed_buffers.front()->GetDecodeTimestamp()) {
1801 // The split is in the gap between |media_segment_start_time_| and
1802 // the first buffer of the new range so we should set the start
1803 // time of the new range to |timestamp| so we preserve part of the
1804 // gap in the new range.
1805 new_range_start_timestamp = timestamp;
1806 }
1807
1808 keyframe_map_.erase(new_beginning_keyframe, keyframe_map_.end());
1809 FreeBufferRange(starting_point, buffers_.end());
1810
1811 // Create a new range with |removed_buffers|.
1812 SourceBufferRange* split_range =
1813 new SourceBufferRange(
1814 type_, removed_buffers, new_range_start_timestamp,
1815 interbuffer_distance_cb_);
1816
1817 // If the next buffer position is now in |split_range|, update the state of
1818 // this range and |split_range| accordingly.
1819 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) {
1820 split_range->next_buffer_index_ = next_buffer_index_ - keyframe_index;
1821 ResetNextBufferPosition();
1822 }
1823
1824 return split_range;
1825 }
1826
GetBufferItrAt(base::TimeDelta timestamp,bool skip_given_timestamp)1827 BufferQueue::iterator SourceBufferRange::GetBufferItrAt(
1828 base::TimeDelta timestamp,
1829 bool skip_given_timestamp) {
1830 return skip_given_timestamp
1831 ? std::upper_bound(buffers_.begin(),
1832 buffers_.end(),
1833 timestamp,
1834 CompareTimeDeltaToStreamParserBuffer)
1835 : std::lower_bound(buffers_.begin(),
1836 buffers_.end(),
1837 timestamp,
1838 CompareStreamParserBufferToTimeDelta);
1839 }
1840
1841 SourceBufferRange::KeyframeMap::iterator
GetFirstKeyframeAt(base::TimeDelta timestamp,bool skip_given_timestamp)1842 SourceBufferRange::GetFirstKeyframeAt(base::TimeDelta timestamp,
1843 bool skip_given_timestamp) {
1844 return skip_given_timestamp ?
1845 keyframe_map_.upper_bound(timestamp) :
1846 keyframe_map_.lower_bound(timestamp);
1847 }
1848
1849 SourceBufferRange::KeyframeMap::iterator
GetFirstKeyframeBefore(base::TimeDelta timestamp)1850 SourceBufferRange::GetFirstKeyframeBefore(base::TimeDelta timestamp) {
1851 KeyframeMap::iterator result = keyframe_map_.lower_bound(timestamp);
1852 // lower_bound() returns the first element >= |timestamp|, so we want the
1853 // previous element if it did not return the element exactly equal to
1854 // |timestamp|.
1855 if (result != keyframe_map_.begin() &&
1856 (result == keyframe_map_.end() || result->first != timestamp)) {
1857 --result;
1858 }
1859 return result;
1860 }
1861
DeleteAll(BufferQueue * removed_buffers)1862 void SourceBufferRange::DeleteAll(BufferQueue* removed_buffers) {
1863 TruncateAt(buffers_.begin(), removed_buffers);
1864 }
1865
TruncateAt(base::TimeDelta timestamp,BufferQueue * removed_buffers,bool is_exclusive)1866 bool SourceBufferRange::TruncateAt(
1867 base::TimeDelta timestamp, BufferQueue* removed_buffers,
1868 bool is_exclusive) {
1869 // Find the place in |buffers_| where we will begin deleting data.
1870 BufferQueue::iterator starting_point =
1871 GetBufferItrAt(timestamp, is_exclusive);
1872 return TruncateAt(starting_point, removed_buffers);
1873 }
1874
DeleteGOPFromFront(BufferQueue * deleted_buffers)1875 int SourceBufferRange::DeleteGOPFromFront(BufferQueue* deleted_buffers) {
1876 DCHECK(!FirstGOPContainsNextBufferPosition());
1877 DCHECK(deleted_buffers);
1878
1879 int buffers_deleted = 0;
1880 int total_bytes_deleted = 0;
1881
1882 KeyframeMap::iterator front = keyframe_map_.begin();
1883 DCHECK(front != keyframe_map_.end());
1884
1885 // Delete the keyframe at the start of |keyframe_map_|.
1886 keyframe_map_.erase(front);
1887
1888 // Now we need to delete all the buffers that depend on the keyframe we've
1889 // just deleted.
1890 int end_index = keyframe_map_.size() > 0 ?
1891 keyframe_map_.begin()->second - keyframe_map_index_base_ :
1892 buffers_.size();
1893
1894 // Delete buffers from the beginning of the buffered range up until (but not
1895 // including) the next keyframe.
1896 for (int i = 0; i < end_index; i++) {
1897 int bytes_deleted = buffers_.front()->data_size();
1898 size_in_bytes_ -= bytes_deleted;
1899 total_bytes_deleted += bytes_deleted;
1900 deleted_buffers->push_back(buffers_.front());
1901 buffers_.pop_front();
1902 ++buffers_deleted;
1903 }
1904
1905 // Update |keyframe_map_index_base_| to account for the deleted buffers.
1906 keyframe_map_index_base_ += buffers_deleted;
1907
1908 if (next_buffer_index_ > -1) {
1909 next_buffer_index_ -= buffers_deleted;
1910 DCHECK_GE(next_buffer_index_, 0);
1911 }
1912
1913 // Invalidate media segment start time if we've deleted the first buffer of
1914 // the range.
1915 if (buffers_deleted > 0)
1916 media_segment_start_time_ = kNoTimestamp();
1917
1918 return total_bytes_deleted;
1919 }
1920
DeleteGOPFromBack(BufferQueue * deleted_buffers)1921 int SourceBufferRange::DeleteGOPFromBack(BufferQueue* deleted_buffers) {
1922 DCHECK(!LastGOPContainsNextBufferPosition());
1923 DCHECK(deleted_buffers);
1924
1925 // Remove the last GOP's keyframe from the |keyframe_map_|.
1926 KeyframeMap::iterator back = keyframe_map_.end();
1927 DCHECK_GT(keyframe_map_.size(), 0u);
1928 --back;
1929
1930 // The index of the first buffer in the last GOP is equal to the new size of
1931 // |buffers_| after that GOP is deleted.
1932 size_t goal_size = back->second - keyframe_map_index_base_;
1933 keyframe_map_.erase(back);
1934
1935 int total_bytes_deleted = 0;
1936 while (buffers_.size() != goal_size) {
1937 int bytes_deleted = buffers_.back()->data_size();
1938 size_in_bytes_ -= bytes_deleted;
1939 total_bytes_deleted += bytes_deleted;
1940 // We're removing buffers from the back, so push each removed buffer to the
1941 // front of |deleted_buffers| so that |deleted_buffers| are in nondecreasing
1942 // order.
1943 deleted_buffers->push_front(buffers_.back());
1944 buffers_.pop_back();
1945 }
1946
1947 return total_bytes_deleted;
1948 }
1949
GetRemovalGOP(base::TimeDelta start_timestamp,base::TimeDelta end_timestamp,int total_bytes_to_free,base::TimeDelta * removal_end_timestamp)1950 int SourceBufferRange::GetRemovalGOP(
1951 base::TimeDelta start_timestamp, base::TimeDelta end_timestamp,
1952 int total_bytes_to_free, base::TimeDelta* removal_end_timestamp) {
1953 int bytes_to_free = total_bytes_to_free;
1954 int bytes_removed = 0;
1955
1956 KeyframeMap::iterator gop_itr = GetFirstKeyframeAt(start_timestamp, false);
1957 if (gop_itr == keyframe_map_.end())
1958 return 0;
1959 int keyframe_index = gop_itr->second - keyframe_map_index_base_;
1960 BufferQueue::iterator buffer_itr = buffers_.begin() + keyframe_index;
1961 KeyframeMap::iterator gop_end = keyframe_map_.end();
1962 if (end_timestamp < GetBufferedEndTimestamp())
1963 gop_end = GetFirstKeyframeBefore(end_timestamp);
1964
1965 // Check if the removal range is within a GOP and skip the loop if so.
1966 // [keyframe]...[start_timestamp]...[end_timestamp]...[keyframe]
1967 KeyframeMap::iterator gop_itr_prev = gop_itr;
1968 if (gop_itr_prev != keyframe_map_.begin() && --gop_itr_prev == gop_end)
1969 gop_end = gop_itr;
1970
1971 while (gop_itr != gop_end && bytes_to_free > 0) {
1972 ++gop_itr;
1973
1974 int gop_size = 0;
1975 int next_gop_index = gop_itr == keyframe_map_.end() ?
1976 buffers_.size() : gop_itr->second - keyframe_map_index_base_;
1977 BufferQueue::iterator next_gop_start = buffers_.begin() + next_gop_index;
1978 for (; buffer_itr != next_gop_start; ++buffer_itr)
1979 gop_size += (*buffer_itr)->data_size();
1980
1981 bytes_removed += gop_size;
1982 bytes_to_free -= gop_size;
1983 }
1984 if (bytes_removed > 0) {
1985 *removal_end_timestamp = gop_itr == keyframe_map_.end() ?
1986 GetBufferedEndTimestamp() : gop_itr->first;
1987 }
1988 return bytes_removed;
1989 }
1990
FirstGOPContainsNextBufferPosition() const1991 bool SourceBufferRange::FirstGOPContainsNextBufferPosition() const {
1992 if (!HasNextBufferPosition())
1993 return false;
1994
1995 // If there is only one GOP, it must contain the next buffer position.
1996 if (keyframe_map_.size() == 1u)
1997 return true;
1998
1999 KeyframeMap::const_iterator second_gop = keyframe_map_.begin();
2000 ++second_gop;
2001 return next_buffer_index_ < second_gop->second - keyframe_map_index_base_;
2002 }
2003
LastGOPContainsNextBufferPosition() const2004 bool SourceBufferRange::LastGOPContainsNextBufferPosition() const {
2005 if (!HasNextBufferPosition())
2006 return false;
2007
2008 // If there is only one GOP, it must contain the next buffer position.
2009 if (keyframe_map_.size() == 1u)
2010 return true;
2011
2012 KeyframeMap::const_iterator last_gop = keyframe_map_.end();
2013 --last_gop;
2014 return last_gop->second - keyframe_map_index_base_ <= next_buffer_index_;
2015 }
2016
FreeBufferRange(const BufferQueue::iterator & starting_point,const BufferQueue::iterator & ending_point)2017 void SourceBufferRange::FreeBufferRange(
2018 const BufferQueue::iterator& starting_point,
2019 const BufferQueue::iterator& ending_point) {
2020 for (BufferQueue::iterator itr = starting_point;
2021 itr != ending_point; ++itr) {
2022 size_in_bytes_ -= (*itr)->data_size();
2023 DCHECK_GE(size_in_bytes_, 0);
2024 }
2025 buffers_.erase(starting_point, ending_point);
2026 }
2027
TruncateAt(const BufferQueue::iterator & starting_point,BufferQueue * removed_buffers)2028 bool SourceBufferRange::TruncateAt(
2029 const BufferQueue::iterator& starting_point, BufferQueue* removed_buffers) {
2030 DCHECK(!removed_buffers || removed_buffers->empty());
2031
2032 // Return if we're not deleting anything.
2033 if (starting_point == buffers_.end())
2034 return buffers_.empty();
2035
2036 // Reset the next buffer index if we will be deleting the buffer that's next
2037 // in sequence.
2038 if (HasNextBufferPosition()) {
2039 base::TimeDelta next_buffer_timestamp = GetNextTimestamp();
2040 if (next_buffer_timestamp == kNoTimestamp() ||
2041 next_buffer_timestamp >= (*starting_point)->GetDecodeTimestamp()) {
2042 if (HasNextBuffer() && removed_buffers) {
2043 int starting_offset = starting_point - buffers_.begin();
2044 int next_buffer_offset = next_buffer_index_ - starting_offset;
2045 DCHECK_GE(next_buffer_offset, 0);
2046 BufferQueue saved(starting_point + next_buffer_offset, buffers_.end());
2047 removed_buffers->swap(saved);
2048 }
2049 ResetNextBufferPosition();
2050 }
2051 }
2052
2053 // Remove keyframes from |starting_point| onward.
2054 KeyframeMap::iterator starting_point_keyframe =
2055 keyframe_map_.lower_bound((*starting_point)->GetDecodeTimestamp());
2056 keyframe_map_.erase(starting_point_keyframe, keyframe_map_.end());
2057
2058 // Remove everything from |starting_point| onward.
2059 FreeBufferRange(starting_point, buffers_.end());
2060 return buffers_.empty();
2061 }
2062
GetNextBuffer(scoped_refptr<StreamParserBuffer> * out_buffer)2063 bool SourceBufferRange::GetNextBuffer(
2064 scoped_refptr<StreamParserBuffer>* out_buffer) {
2065 if (!HasNextBuffer())
2066 return false;
2067
2068 *out_buffer = buffers_[next_buffer_index_];
2069 next_buffer_index_++;
2070 return true;
2071 }
2072
HasNextBuffer() const2073 bool SourceBufferRange::HasNextBuffer() const {
2074 return next_buffer_index_ >= 0 &&
2075 next_buffer_index_ < static_cast<int>(buffers_.size());
2076 }
2077
GetNextConfigId() const2078 int SourceBufferRange::GetNextConfigId() const {
2079 DCHECK(HasNextBuffer());
2080 // If the next buffer is an audio splice frame, the next effective config id
2081 // comes from the first fade out preroll buffer.
2082 return GetConfigId(buffers_[next_buffer_index_], 0);
2083 }
2084
GetNextTimestamp() const2085 base::TimeDelta SourceBufferRange::GetNextTimestamp() const {
2086 DCHECK(!buffers_.empty());
2087 DCHECK(HasNextBufferPosition());
2088
2089 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) {
2090 return kNoTimestamp();
2091 }
2092
2093 return buffers_[next_buffer_index_]->GetDecodeTimestamp();
2094 }
2095
HasNextBufferPosition() const2096 bool SourceBufferRange::HasNextBufferPosition() const {
2097 return next_buffer_index_ >= 0;
2098 }
2099
ResetNextBufferPosition()2100 void SourceBufferRange::ResetNextBufferPosition() {
2101 next_buffer_index_ = -1;
2102 }
2103
AppendRangeToEnd(const SourceBufferRange & range,bool transfer_current_position)2104 void SourceBufferRange::AppendRangeToEnd(const SourceBufferRange& range,
2105 bool transfer_current_position) {
2106 DCHECK(CanAppendRangeToEnd(range));
2107 DCHECK(!buffers_.empty());
2108
2109 if (transfer_current_position && range.next_buffer_index_ >= 0)
2110 next_buffer_index_ = range.next_buffer_index_ + buffers_.size();
2111
2112 AppendBuffersToEnd(range.buffers_);
2113 }
2114
CanAppendRangeToEnd(const SourceBufferRange & range) const2115 bool SourceBufferRange::CanAppendRangeToEnd(
2116 const SourceBufferRange& range) const {
2117 return CanAppendBuffersToEnd(range.buffers_);
2118 }
2119
CanAppendBuffersToEnd(const BufferQueue & buffers) const2120 bool SourceBufferRange::CanAppendBuffersToEnd(
2121 const BufferQueue& buffers) const {
2122 DCHECK(!buffers_.empty());
2123 return IsNextInSequence(buffers.front()->GetDecodeTimestamp(),
2124 buffers.front()->IsKeyframe());
2125 }
2126
BelongsToRange(base::TimeDelta timestamp) const2127 bool SourceBufferRange::BelongsToRange(base::TimeDelta timestamp) const {
2128 DCHECK(!buffers_.empty());
2129
2130 return (IsNextInSequence(timestamp, false) ||
2131 (GetStartTimestamp() <= timestamp && timestamp <= GetEndTimestamp()));
2132 }
2133
CanSeekTo(base::TimeDelta timestamp) const2134 bool SourceBufferRange::CanSeekTo(base::TimeDelta timestamp) const {
2135 base::TimeDelta start_timestamp =
2136 std::max(base::TimeDelta(), GetStartTimestamp() - GetFudgeRoom());
2137 return !keyframe_map_.empty() && start_timestamp <= timestamp &&
2138 timestamp < GetBufferedEndTimestamp();
2139 }
2140
CompletelyOverlaps(const SourceBufferRange & range) const2141 bool SourceBufferRange::CompletelyOverlaps(
2142 const SourceBufferRange& range) const {
2143 return GetStartTimestamp() <= range.GetStartTimestamp() &&
2144 GetEndTimestamp() >= range.GetEndTimestamp();
2145 }
2146
EndOverlaps(const SourceBufferRange & range) const2147 bool SourceBufferRange::EndOverlaps(const SourceBufferRange& range) const {
2148 return range.GetStartTimestamp() <= GetEndTimestamp() &&
2149 GetEndTimestamp() < range.GetEndTimestamp();
2150 }
2151
GetStartTimestamp() const2152 base::TimeDelta SourceBufferRange::GetStartTimestamp() const {
2153 DCHECK(!buffers_.empty());
2154 base::TimeDelta start_timestamp = media_segment_start_time_;
2155 if (start_timestamp == kNoTimestamp())
2156 start_timestamp = buffers_.front()->GetDecodeTimestamp();
2157 return start_timestamp;
2158 }
2159
GetEndTimestamp() const2160 base::TimeDelta SourceBufferRange::GetEndTimestamp() const {
2161 DCHECK(!buffers_.empty());
2162 return buffers_.back()->GetDecodeTimestamp();
2163 }
2164
GetBufferedEndTimestamp() const2165 base::TimeDelta SourceBufferRange::GetBufferedEndTimestamp() const {
2166 DCHECK(!buffers_.empty());
2167 base::TimeDelta duration = buffers_.back()->duration();
2168 if (duration == kNoTimestamp() || duration == base::TimeDelta())
2169 duration = GetApproximateDuration();
2170 return GetEndTimestamp() + duration;
2171 }
2172
NextKeyframeTimestamp(base::TimeDelta timestamp)2173 base::TimeDelta SourceBufferRange::NextKeyframeTimestamp(
2174 base::TimeDelta timestamp) {
2175 DCHECK(!keyframe_map_.empty());
2176
2177 if (timestamp < GetStartTimestamp() || timestamp >= GetBufferedEndTimestamp())
2178 return kNoTimestamp();
2179
2180 KeyframeMap::iterator itr = GetFirstKeyframeAt(timestamp, false);
2181 if (itr == keyframe_map_.end())
2182 return kNoTimestamp();
2183
2184 // If the timestamp is inside the gap between the start of the media
2185 // segment and the first buffer, then just pretend there is a
2186 // keyframe at the specified timestamp.
2187 if (itr == keyframe_map_.begin() &&
2188 timestamp > media_segment_start_time_ &&
2189 timestamp < itr->first) {
2190 return timestamp;
2191 }
2192
2193 return itr->first;
2194 }
2195
KeyframeBeforeTimestamp(base::TimeDelta timestamp)2196 base::TimeDelta SourceBufferRange::KeyframeBeforeTimestamp(
2197 base::TimeDelta timestamp) {
2198 DCHECK(!keyframe_map_.empty());
2199
2200 if (timestamp < GetStartTimestamp() || timestamp >= GetBufferedEndTimestamp())
2201 return kNoTimestamp();
2202
2203 return GetFirstKeyframeBefore(timestamp)->first;
2204 }
2205
IsNextInSequence(base::TimeDelta timestamp,bool is_keyframe) const2206 bool SourceBufferRange::IsNextInSequence(
2207 base::TimeDelta timestamp, bool is_keyframe) const {
2208 base::TimeDelta end = buffers_.back()->GetDecodeTimestamp();
2209 if (end < timestamp &&
2210 (type_ == SourceBufferStream::kText ||
2211 timestamp <= end + GetFudgeRoom())) {
2212 return true;
2213 }
2214
2215 return timestamp == end && AllowSameTimestamp(
2216 buffers_.back()->IsKeyframe(), is_keyframe, type_);
2217 }
2218
GetFudgeRoom() const2219 base::TimeDelta SourceBufferRange::GetFudgeRoom() const {
2220 return ComputeFudgeRoom(GetApproximateDuration());
2221 }
2222
GetApproximateDuration() const2223 base::TimeDelta SourceBufferRange::GetApproximateDuration() const {
2224 base::TimeDelta max_interbuffer_distance = interbuffer_distance_cb_.Run();
2225 DCHECK(max_interbuffer_distance != kNoTimestamp());
2226 return max_interbuffer_distance;
2227 }
2228
GetBuffersInRange(base::TimeDelta start,base::TimeDelta end,BufferQueue * buffers)2229 bool SourceBufferRange::GetBuffersInRange(base::TimeDelta start,
2230 base::TimeDelta end,
2231 BufferQueue* buffers) {
2232 // Find the nearest buffer with a decode timestamp <= start.
2233 const base::TimeDelta first_timestamp = KeyframeBeforeTimestamp(start);
2234 if (first_timestamp == kNoTimestamp())
2235 return false;
2236
2237 // Find all buffers involved in the range.
2238 const size_t previous_size = buffers->size();
2239 for (BufferQueue::iterator it = GetBufferItrAt(first_timestamp, false);
2240 it != buffers_.end();
2241 ++it) {
2242 const scoped_refptr<StreamParserBuffer>& buffer = *it;
2243 // Buffers without duration are not supported, so bail if we encounter any.
2244 if (buffer->duration() == kNoTimestamp() ||
2245 buffer->duration() <= base::TimeDelta()) {
2246 return false;
2247 }
2248 if (buffer->end_of_stream() || buffer->timestamp() >= end)
2249 break;
2250 if (buffer->timestamp() + buffer->duration() <= start)
2251 continue;
2252 buffers->push_back(buffer);
2253 }
2254 return previous_size < buffers->size();
2255 }
2256
SetPendingBuffer(scoped_refptr<StreamParserBuffer> * out_buffer)2257 bool SourceBufferStream::SetPendingBuffer(
2258 scoped_refptr<StreamParserBuffer>* out_buffer) {
2259 DCHECK(*out_buffer);
2260 DCHECK(!pending_buffer_);
2261
2262 const bool have_splice_buffers = !(*out_buffer)->splice_buffers().empty();
2263 const bool have_preroll_buffer = !!(*out_buffer)->preroll_buffer();
2264
2265 if (!have_splice_buffers && !have_preroll_buffer)
2266 return false;
2267
2268 DCHECK_NE(have_splice_buffers, have_preroll_buffer);
2269 splice_buffers_index_ = 0;
2270 pending_buffer_.swap(*out_buffer);
2271 pending_buffers_complete_ = false;
2272 return true;
2273 }
2274
2275 } // namespace media
2276