Supervised user whitelists: Cleanup
[chromium-blink-merge.git] / media / filters / source_buffer_stream.cc
blob4271ab9601bb44393a6f79f0db3fd09daf7c00fd
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>
9 #include <sstream>
11 #include "base/bind.h"
12 #include "base/logging.h"
13 #include "base/trace_event/trace_event.h"
14 #include "media/base/audio_splicer.h"
15 #include "media/filters/source_buffer_platform.h"
16 #include "media/filters/source_buffer_range.h"
18 namespace media {
20 // Helper method that returns true if |ranges| is sorted in increasing order,
21 // false otherwise.
22 static bool IsRangeListSorted(
23 const std::list<media::SourceBufferRange*>& ranges) {
24 DecodeTimestamp prev = kNoDecodeTimestamp();
25 for (std::list<SourceBufferRange*>::const_iterator itr =
26 ranges.begin(); itr != ranges.end(); ++itr) {
27 if (prev != kNoDecodeTimestamp() && prev >= (*itr)->GetStartTimestamp())
28 return false;
29 prev = (*itr)->GetEndTimestamp();
31 return true;
34 // Returns an estimate of how far from the beginning or end of a range a buffer
35 // can be to still be considered in the range, given the |approximate_duration|
36 // of a buffer in the stream.
37 // TODO(wolenetz): Once all stream parsers emit accurate frame durations, use
38 // logic like FrameProcessor (2*last_frame_duration + last_decode_timestamp)
39 // instead of an overall maximum interbuffer delta for range discontinuity
40 // detection, and adjust similarly for splice frame discontinuity detection.
41 // See http://crbug.com/351489 and http://crbug.com/351166.
42 static base::TimeDelta ComputeFudgeRoom(base::TimeDelta approximate_duration) {
43 // Because we do not know exactly when is the next timestamp, any buffer
44 // that starts within 2x the approximate duration of a buffer is considered
45 // within this range.
46 return 2 * approximate_duration;
49 // An arbitrarily-chosen number to estimate the duration of a buffer if none
50 // is set and there's not enough information to get a better estimate.
51 static int kDefaultBufferDurationInMs = 125;
53 // The amount of time the beginning of the buffered data can differ from the
54 // start time in order to still be considered the start of stream.
55 static base::TimeDelta kSeekToStartFudgeRoom() {
56 return base::TimeDelta::FromMilliseconds(1000);
59 // Helper method for logging, converts a range into a readable string.
60 static std::string RangeToString(const SourceBufferRange& range) {
61 std::stringstream ss;
62 ss << "[" << range.GetStartTimestamp().InSecondsF()
63 << ";" << range.GetEndTimestamp().InSecondsF()
64 << "(" << range.GetBufferedEndTimestamp().InSecondsF() << ")]";
65 return ss.str();
68 // Helper method for logging, converts a set of ranges into a readable string.
69 static std::string RangesToString(const SourceBufferStream::RangeList& ranges) {
70 if (ranges.empty())
71 return "<EMPTY>";
73 std::stringstream ss;
74 for (const auto* range_ptr : ranges) {
75 if (range_ptr != ranges.front())
76 ss << " ";
77 ss << RangeToString(*range_ptr);
79 return ss.str();
82 static SourceBufferRange::GapPolicy TypeToGapPolicy(
83 SourceBufferStream::Type type) {
84 switch (type) {
85 case SourceBufferStream::kAudio:
86 case SourceBufferStream::kVideo:
87 return SourceBufferRange::NO_GAPS_ALLOWED;
88 case SourceBufferStream::kText:
89 return SourceBufferRange::ALLOW_GAPS;
92 NOTREACHED();
93 return SourceBufferRange::NO_GAPS_ALLOWED;
96 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config,
97 const LogCB& log_cb,
98 bool splice_frames_enabled)
99 : log_cb_(log_cb),
100 current_config_index_(0),
101 append_config_index_(0),
102 seek_pending_(false),
103 end_of_stream_(false),
104 seek_buffer_timestamp_(kNoTimestamp()),
105 selected_range_(NULL),
106 media_segment_start_time_(kNoDecodeTimestamp()),
107 range_for_next_append_(ranges_.end()),
108 new_media_segment_(false),
109 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
110 last_appended_buffer_is_keyframe_(false),
111 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
112 max_interbuffer_distance_(kNoTimestamp()),
113 memory_limit_(kSourceBufferAudioMemoryLimit),
114 config_change_pending_(false),
115 splice_buffers_index_(0),
116 pending_buffers_complete_(false),
117 splice_frames_enabled_(splice_frames_enabled) {
118 DCHECK(audio_config.IsValidConfig());
119 audio_configs_.push_back(audio_config);
122 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config,
123 const LogCB& log_cb,
124 bool splice_frames_enabled)
125 : log_cb_(log_cb),
126 current_config_index_(0),
127 append_config_index_(0),
128 seek_pending_(false),
129 end_of_stream_(false),
130 seek_buffer_timestamp_(kNoTimestamp()),
131 selected_range_(NULL),
132 media_segment_start_time_(kNoDecodeTimestamp()),
133 range_for_next_append_(ranges_.end()),
134 new_media_segment_(false),
135 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
136 last_appended_buffer_is_keyframe_(false),
137 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
138 max_interbuffer_distance_(kNoTimestamp()),
139 memory_limit_(kSourceBufferVideoMemoryLimit),
140 config_change_pending_(false),
141 splice_buffers_index_(0),
142 pending_buffers_complete_(false),
143 splice_frames_enabled_(splice_frames_enabled) {
144 DCHECK(video_config.IsValidConfig());
145 video_configs_.push_back(video_config);
148 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config,
149 const LogCB& log_cb,
150 bool splice_frames_enabled)
151 : log_cb_(log_cb),
152 current_config_index_(0),
153 append_config_index_(0),
154 text_track_config_(text_config),
155 seek_pending_(false),
156 end_of_stream_(false),
157 seek_buffer_timestamp_(kNoTimestamp()),
158 selected_range_(NULL),
159 media_segment_start_time_(kNoDecodeTimestamp()),
160 range_for_next_append_(ranges_.end()),
161 new_media_segment_(false),
162 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
163 last_appended_buffer_is_keyframe_(false),
164 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
165 max_interbuffer_distance_(kNoTimestamp()),
166 memory_limit_(kSourceBufferAudioMemoryLimit),
167 config_change_pending_(false),
168 splice_buffers_index_(0),
169 pending_buffers_complete_(false),
170 splice_frames_enabled_(splice_frames_enabled) {}
172 SourceBufferStream::~SourceBufferStream() {
173 while (!ranges_.empty()) {
174 delete ranges_.front();
175 ranges_.pop_front();
179 void SourceBufferStream::OnNewMediaSegment(
180 DecodeTimestamp media_segment_start_time) {
181 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
182 << " (" << media_segment_start_time.InSecondsF() << ")";
183 DCHECK(!end_of_stream_);
184 media_segment_start_time_ = media_segment_start_time;
185 new_media_segment_ = true;
187 RangeList::iterator last_range = range_for_next_append_;
188 range_for_next_append_ = FindExistingRangeFor(media_segment_start_time);
190 // Only reset |last_appended_buffer_timestamp_| if this new media segment is
191 // not adjacent to the previous media segment appended to the stream.
192 if (range_for_next_append_ == ranges_.end() ||
193 !AreAdjacentInSequence(last_appended_buffer_timestamp_,
194 media_segment_start_time)) {
195 last_appended_buffer_timestamp_ = kNoDecodeTimestamp();
196 last_appended_buffer_is_keyframe_ = false;
197 DVLOG(3) << __FUNCTION__ << " next appended buffers will be in a new range";
198 } else if (last_range != ranges_.end()) {
199 DCHECK(last_range == range_for_next_append_);
200 DVLOG(3) << __FUNCTION__ << " next appended buffers will continue range "
201 << "unless intervening remove makes discontinuity";
205 bool SourceBufferStream::Append(const BufferQueue& buffers) {
206 TRACE_EVENT2("media", "SourceBufferStream::Append",
207 "stream type", GetStreamTypeName(),
208 "buffers to append", buffers.size());
210 DCHECK(!buffers.empty());
211 DCHECK(media_segment_start_time_ != kNoDecodeTimestamp());
212 DCHECK(media_segment_start_time_ <= buffers.front()->GetDecodeTimestamp());
213 DCHECK(!end_of_stream_);
215 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() << ": buffers dts=["
216 << buffers.front()->GetDecodeTimestamp().InSecondsF() << ";"
217 << buffers.back()->GetDecodeTimestamp().InSecondsF() << "] pts=["
218 << buffers.front()->timestamp().InSecondsF() << ";"
219 << buffers.back()->timestamp().InSecondsF() << "(last frame dur="
220 << buffers.back()->duration().InSecondsF() << ")]";
222 // New media segments must begin with a keyframe.
223 // TODO(wolenetz): Relax this requirement. See http://crbug.com/229412.
224 if (new_media_segment_ && !buffers.front()->is_key_frame()) {
225 MEDIA_LOG(ERROR, log_cb_) << "Media segment did not begin with key frame.";
226 return false;
229 // Buffers within a media segment should be monotonically increasing.
230 if (!IsMonotonicallyIncreasing(buffers))
231 return false;
233 if (media_segment_start_time_ < DecodeTimestamp() ||
234 buffers.front()->GetDecodeTimestamp() < DecodeTimestamp()) {
235 MEDIA_LOG(ERROR, log_cb_)
236 << "Cannot append a media segment with negative timestamps.";
237 return false;
240 if (!IsNextTimestampValid(buffers.front()->GetDecodeTimestamp(),
241 buffers.front()->is_key_frame())) {
242 const DecodeTimestamp& dts = buffers.front()->GetDecodeTimestamp();
243 MEDIA_LOG(ERROR, log_cb_) << "Invalid same timestamp construct detected at"
244 << " time " << dts.InSecondsF();
246 return false;
249 UpdateMaxInterbufferDistance(buffers);
250 SetConfigIds(buffers);
252 // Save a snapshot of stream state before range modifications are made.
253 DecodeTimestamp next_buffer_timestamp = GetNextBufferTimestamp();
254 BufferQueue deleted_buffers;
256 PrepareRangesForNextAppend(buffers, &deleted_buffers);
258 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise,
259 // create a new range with |buffers|.
260 if (range_for_next_append_ != ranges_.end()) {
261 (*range_for_next_append_)->AppendBuffersToEnd(buffers);
262 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp();
263 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame();
264 } else {
265 DecodeTimestamp new_range_start_time = std::min(
266 media_segment_start_time_, buffers.front()->GetDecodeTimestamp());
267 const BufferQueue* buffers_for_new_range = &buffers;
268 BufferQueue trimmed_buffers;
270 // If the new range is not being created because of a new media
271 // segment, then we must make sure that we start with a key frame.
272 // This can happen if the GOP in the previous append gets destroyed
273 // by a Remove() call.
274 if (!new_media_segment_) {
275 BufferQueue::const_iterator itr = buffers.begin();
277 // Scan past all the non-key-frames.
278 while (itr != buffers.end() && !(*itr)->is_key_frame()) {
279 ++itr;
282 // If we didn't find a key frame, then update the last appended
283 // buffer state and return.
284 if (itr == buffers.end()) {
285 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp();
286 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame();
287 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
288 << ": new buffers in the middle of media segment depend on"
289 "keyframe that has been removed, and contain no keyframes."
290 "Skipping further processing.";
291 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
292 << ": done. ranges_=" << RangesToString(ranges_);
293 return true;
294 } else if (itr != buffers.begin()) {
295 // Copy the first key frame and everything after it into
296 // |trimmed_buffers|.
297 trimmed_buffers.assign(itr, buffers.end());
298 buffers_for_new_range = &trimmed_buffers;
301 new_range_start_time =
302 buffers_for_new_range->front()->GetDecodeTimestamp();
305 range_for_next_append_ =
306 AddToRanges(new SourceBufferRange(
307 TypeToGapPolicy(GetType()),
308 *buffers_for_new_range, new_range_start_time,
309 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance,
310 base::Unretained(this))));
311 last_appended_buffer_timestamp_ =
312 buffers_for_new_range->back()->GetDecodeTimestamp();
313 last_appended_buffer_is_keyframe_ =
314 buffers_for_new_range->back()->is_key_frame();
317 new_media_segment_ = false;
319 MergeWithAdjacentRangeIfNecessary(range_for_next_append_);
321 // Seek to try to fulfill a previous call to Seek().
322 if (seek_pending_) {
323 DCHECK(!selected_range_);
324 DCHECK(deleted_buffers.empty());
325 Seek(seek_buffer_timestamp_);
328 if (!deleted_buffers.empty()) {
329 DecodeTimestamp start_of_deleted =
330 deleted_buffers.front()->GetDecodeTimestamp();
332 DCHECK(track_buffer_.empty() ||
333 track_buffer_.back()->GetDecodeTimestamp() < start_of_deleted)
334 << "decode timestamp "
335 << track_buffer_.back()->GetDecodeTimestamp().InSecondsF() << " sec"
336 << ", start_of_deleted " << start_of_deleted.InSecondsF()<< " sec";
338 track_buffer_.insert(track_buffer_.end(), deleted_buffers.begin(),
339 deleted_buffers.end());
340 DVLOG(3) << __FUNCTION__ << " Added " << deleted_buffers.size()
341 << " deleted buffers to track buffer. TB size is now "
342 << track_buffer_.size();
343 } else {
344 DVLOG(3) << __FUNCTION__ << " No deleted buffers for track buffer";
347 // Prune any extra buffers in |track_buffer_| if new keyframes
348 // are appended to the range covered by |track_buffer_|.
349 if (!track_buffer_.empty()) {
350 DecodeTimestamp keyframe_timestamp =
351 FindKeyframeAfterTimestamp(track_buffer_.front()->GetDecodeTimestamp());
352 if (keyframe_timestamp != kNoDecodeTimestamp())
353 PruneTrackBuffer(keyframe_timestamp);
356 SetSelectedRangeIfNeeded(next_buffer_timestamp);
358 GarbageCollectIfNeeded();
360 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
361 << ": done. ranges_=" << RangesToString(ranges_);
362 DCHECK(IsRangeListSorted(ranges_));
363 DCHECK(OnlySelectedRangeIsSeeked());
364 return true;
367 void SourceBufferStream::Remove(base::TimeDelta start, base::TimeDelta end,
368 base::TimeDelta duration) {
369 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
370 << " (" << start.InSecondsF() << ", " << end.InSecondsF()
371 << ", " << duration.InSecondsF() << ")";
372 DCHECK(start >= base::TimeDelta()) << start.InSecondsF();
373 DCHECK(start < end) << "start " << start.InSecondsF()
374 << " end " << end.InSecondsF();
375 DCHECK(duration != kNoTimestamp());
377 DecodeTimestamp start_dts = DecodeTimestamp::FromPresentationTime(start);
378 DecodeTimestamp end_dts = DecodeTimestamp::FromPresentationTime(end);
379 DecodeTimestamp remove_end_timestamp =
380 DecodeTimestamp::FromPresentationTime(duration);
381 DecodeTimestamp keyframe_timestamp = FindKeyframeAfterTimestamp(end_dts);
382 if (keyframe_timestamp != kNoDecodeTimestamp()) {
383 remove_end_timestamp = keyframe_timestamp;
384 } else if (end_dts < remove_end_timestamp) {
385 remove_end_timestamp = end_dts;
388 BufferQueue deleted_buffers;
389 RemoveInternal(start_dts, remove_end_timestamp, false, &deleted_buffers);
391 if (!deleted_buffers.empty())
392 SetSelectedRangeIfNeeded(deleted_buffers.front()->GetDecodeTimestamp());
395 void SourceBufferStream::RemoveInternal(DecodeTimestamp start,
396 DecodeTimestamp end,
397 bool exclude_start,
398 BufferQueue* deleted_buffers) {
399 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName() << " ("
400 << start.InSecondsF() << ", " << end.InSecondsF() << ", "
401 << exclude_start << ")";
402 DVLOG(3) << __FUNCTION__ << " " << GetStreamTypeName()
403 << ": before remove ranges_=" << RangesToString(ranges_);
405 DCHECK(start >= DecodeTimestamp());
406 DCHECK(start < end) << "start " << start.InSecondsF()
407 << " end " << end.InSecondsF();
408 DCHECK(deleted_buffers);
410 RangeList::iterator itr = ranges_.begin();
412 while (itr != ranges_.end()) {
413 SourceBufferRange* range = *itr;
414 if (range->GetStartTimestamp() >= end)
415 break;
417 // Split off any remaining GOPs starting at or after |end| and add it to
418 // |ranges_|.
419 SourceBufferRange* new_range = range->SplitRange(end);
420 if (new_range) {
421 itr = ranges_.insert(++itr, new_range);
422 --itr;
424 // Update the selected range if the next buffer position was transferred
425 // to |new_range|.
426 if (new_range->HasNextBufferPosition())
427 SetSelectedRange(new_range);
430 // Truncate the current range so that it only contains data before
431 // the removal range.
432 BufferQueue saved_buffers;
433 bool delete_range = range->TruncateAt(start, &saved_buffers, exclude_start);
435 // Check to see if the current playback position was removed and
436 // update the selected range appropriately.
437 if (!saved_buffers.empty()) {
438 DCHECK(!range->HasNextBufferPosition());
439 DCHECK(deleted_buffers->empty());
441 *deleted_buffers = saved_buffers;
444 if (range == selected_range_ && !range->HasNextBufferPosition())
445 SetSelectedRange(NULL);
447 // If the current range now is completely covered by the removal
448 // range then delete it and move on.
449 if (delete_range) {
450 DeleteAndRemoveRange(&itr);
451 continue;
454 // Clear |range_for_next_append_| if we determine that the removal
455 // operation makes it impossible for the next append to be added
456 // to the current range.
457 if (range_for_next_append_ != ranges_.end() &&
458 *range_for_next_append_ == range &&
459 last_appended_buffer_timestamp_ != kNoDecodeTimestamp()) {
460 DecodeTimestamp potential_next_append_timestamp =
461 last_appended_buffer_timestamp_ +
462 base::TimeDelta::FromInternalValue(1);
464 if (!range->BelongsToRange(potential_next_append_timestamp)) {
465 DVLOG(1) << "Resetting range_for_next_append_ since the next append"
466 << " can't add to the current range.";
467 range_for_next_append_ =
468 FindExistingRangeFor(potential_next_append_timestamp);
472 // Move on to the next range.
473 ++itr;
476 DVLOG(3) << __FUNCTION__ << " " << GetStreamTypeName()
477 << ": after remove ranges_=" << RangesToString(ranges_);
479 DCHECK(IsRangeListSorted(ranges_));
480 DCHECK(OnlySelectedRangeIsSeeked());
483 void SourceBufferStream::ResetSeekState() {
484 SetSelectedRange(NULL);
485 track_buffer_.clear();
486 config_change_pending_ = false;
487 last_output_buffer_timestamp_ = kNoDecodeTimestamp();
488 splice_buffers_index_ = 0;
489 pending_buffer_ = NULL;
490 pending_buffers_complete_ = false;
493 bool SourceBufferStream::ShouldSeekToStartOfBuffered(
494 base::TimeDelta seek_timestamp) const {
495 if (ranges_.empty())
496 return false;
497 base::TimeDelta beginning_of_buffered =
498 ranges_.front()->GetStartTimestamp().ToPresentationTime();
499 return (seek_timestamp <= beginning_of_buffered &&
500 beginning_of_buffered < kSeekToStartFudgeRoom());
503 bool SourceBufferStream::IsMonotonicallyIncreasing(
504 const BufferQueue& buffers) const {
505 DCHECK(!buffers.empty());
506 DecodeTimestamp prev_timestamp = last_appended_buffer_timestamp_;
507 bool prev_is_keyframe = last_appended_buffer_is_keyframe_;
508 for (BufferQueue::const_iterator itr = buffers.begin();
509 itr != buffers.end(); ++itr) {
510 DecodeTimestamp current_timestamp = (*itr)->GetDecodeTimestamp();
511 bool current_is_keyframe = (*itr)->is_key_frame();
512 DCHECK(current_timestamp != kNoDecodeTimestamp());
513 DCHECK((*itr)->duration() >= base::TimeDelta())
514 << "Packet with invalid duration."
515 << " pts " << (*itr)->timestamp().InSecondsF()
516 << " dts " << (*itr)->GetDecodeTimestamp().InSecondsF()
517 << " dur " << (*itr)->duration().InSecondsF();
519 if (prev_timestamp != kNoDecodeTimestamp()) {
520 if (current_timestamp < prev_timestamp) {
521 MEDIA_LOG(ERROR, log_cb_) << "Buffers did not monotonically increase.";
522 return false;
525 if (current_timestamp == prev_timestamp &&
526 !SourceBufferRange::AllowSameTimestamp(prev_is_keyframe,
527 current_is_keyframe)) {
528 MEDIA_LOG(ERROR, log_cb_) << "Unexpected combination of buffers with"
529 << " the same timestamp detected at "
530 << current_timestamp.InSecondsF();
531 return false;
535 prev_timestamp = current_timestamp;
536 prev_is_keyframe = current_is_keyframe;
538 return true;
541 bool SourceBufferStream::IsNextTimestampValid(
542 DecodeTimestamp next_timestamp, bool next_is_keyframe) const {
543 return (last_appended_buffer_timestamp_ != next_timestamp) ||
544 new_media_segment_ ||
545 SourceBufferRange::AllowSameTimestamp(last_appended_buffer_is_keyframe_,
546 next_is_keyframe);
550 bool SourceBufferStream::OnlySelectedRangeIsSeeked() const {
551 for (RangeList::const_iterator itr = ranges_.begin();
552 itr != ranges_.end(); ++itr) {
553 if ((*itr)->HasNextBufferPosition() && (*itr) != selected_range_)
554 return false;
556 return !selected_range_ || selected_range_->HasNextBufferPosition();
559 void SourceBufferStream::UpdateMaxInterbufferDistance(
560 const BufferQueue& buffers) {
561 DCHECK(!buffers.empty());
562 DecodeTimestamp prev_timestamp = last_appended_buffer_timestamp_;
563 for (BufferQueue::const_iterator itr = buffers.begin();
564 itr != buffers.end(); ++itr) {
565 DecodeTimestamp current_timestamp = (*itr)->GetDecodeTimestamp();
566 DCHECK(current_timestamp != kNoDecodeTimestamp());
568 base::TimeDelta interbuffer_distance = (*itr)->duration();
569 DCHECK(interbuffer_distance >= base::TimeDelta());
571 if (prev_timestamp != kNoDecodeTimestamp()) {
572 interbuffer_distance =
573 std::max(current_timestamp - prev_timestamp, interbuffer_distance);
576 if (interbuffer_distance > base::TimeDelta()) {
577 if (max_interbuffer_distance_ == kNoTimestamp()) {
578 max_interbuffer_distance_ = interbuffer_distance;
579 } else {
580 max_interbuffer_distance_ =
581 std::max(max_interbuffer_distance_, interbuffer_distance);
584 prev_timestamp = current_timestamp;
588 void SourceBufferStream::SetConfigIds(const BufferQueue& buffers) {
589 for (BufferQueue::const_iterator itr = buffers.begin();
590 itr != buffers.end(); ++itr) {
591 (*itr)->SetConfigId(append_config_index_);
595 void SourceBufferStream::GarbageCollectIfNeeded() {
596 // Compute size of |ranges_|.
597 int ranges_size = 0;
598 for (RangeList::iterator itr = ranges_.begin(); itr != ranges_.end(); ++itr)
599 ranges_size += (*itr)->size_in_bytes();
601 // Return if we're under or at the memory limit.
602 if (ranges_size <= memory_limit_)
603 return;
605 int bytes_to_free = ranges_size - memory_limit_;
607 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName() << ": Before GC"
608 << " ranges_size=" << ranges_size
609 << " ranges_=" << RangesToString(ranges_)
610 << " memory_limit_=" << memory_limit_;
612 // Begin deleting after the last appended buffer.
613 int bytes_freed = FreeBuffersAfterLastAppended(bytes_to_free);
615 // Begin deleting from the front.
616 if (bytes_to_free - bytes_freed > 0)
617 bytes_freed += FreeBuffers(bytes_to_free - bytes_freed, false);
619 // Begin deleting from the back.
620 if (bytes_to_free - bytes_freed > 0)
621 bytes_freed += FreeBuffers(bytes_to_free - bytes_freed, true);
623 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName() << ": After GC"
624 << " bytes_freed=" << bytes_freed
625 << " ranges_=" << RangesToString(ranges_);
628 int SourceBufferStream::FreeBuffersAfterLastAppended(int total_bytes_to_free) {
629 DecodeTimestamp next_buffer_timestamp = GetNextBufferTimestamp();
630 if (last_appended_buffer_timestamp_ == kNoDecodeTimestamp() ||
631 next_buffer_timestamp == kNoDecodeTimestamp() ||
632 last_appended_buffer_timestamp_ >= next_buffer_timestamp) {
633 return 0;
636 DecodeTimestamp remove_range_start = last_appended_buffer_timestamp_;
637 if (last_appended_buffer_is_keyframe_)
638 remove_range_start += GetMaxInterbufferDistance();
640 DecodeTimestamp remove_range_start_keyframe = FindKeyframeAfterTimestamp(
641 remove_range_start);
642 if (remove_range_start_keyframe != kNoDecodeTimestamp())
643 remove_range_start = remove_range_start_keyframe;
644 if (remove_range_start >= next_buffer_timestamp)
645 return 0;
647 DecodeTimestamp remove_range_end;
648 int bytes_freed = GetRemovalRange(
649 remove_range_start, next_buffer_timestamp, total_bytes_to_free,
650 &remove_range_end);
651 if (bytes_freed > 0) {
652 Remove(remove_range_start.ToPresentationTime(),
653 remove_range_end.ToPresentationTime(),
654 next_buffer_timestamp.ToPresentationTime());
657 return bytes_freed;
660 int SourceBufferStream::GetRemovalRange(
661 DecodeTimestamp start_timestamp, DecodeTimestamp end_timestamp,
662 int total_bytes_to_free, DecodeTimestamp* removal_end_timestamp) {
663 DCHECK(start_timestamp >= DecodeTimestamp()) << start_timestamp.InSecondsF();
664 DCHECK(start_timestamp < end_timestamp)
665 << "start " << start_timestamp.InSecondsF()
666 << ", end " << end_timestamp.InSecondsF();
668 int bytes_to_free = total_bytes_to_free;
669 int bytes_freed = 0;
671 for (RangeList::iterator itr = ranges_.begin();
672 itr != ranges_.end() && bytes_to_free > 0; ++itr) {
673 SourceBufferRange* range = *itr;
674 if (range->GetStartTimestamp() >= end_timestamp)
675 break;
676 if (range->GetEndTimestamp() < start_timestamp)
677 continue;
679 int bytes_removed = range->GetRemovalGOP(
680 start_timestamp, end_timestamp, bytes_to_free, removal_end_timestamp);
681 bytes_to_free -= bytes_removed;
682 bytes_freed += bytes_removed;
684 return bytes_freed;
687 int SourceBufferStream::FreeBuffers(int total_bytes_to_free,
688 bool reverse_direction) {
689 TRACE_EVENT2("media", "SourceBufferStream::FreeBuffers",
690 "total bytes to free", total_bytes_to_free,
691 "reverse direction", reverse_direction);
693 DCHECK_GT(total_bytes_to_free, 0);
694 int bytes_to_free = total_bytes_to_free;
695 int bytes_freed = 0;
697 // This range will save the last GOP appended to |range_for_next_append_|
698 // if the buffers surrounding it get deleted during garbage collection.
699 SourceBufferRange* new_range_for_append = NULL;
701 while (!ranges_.empty() && bytes_to_free > 0) {
702 SourceBufferRange* current_range = NULL;
703 BufferQueue buffers;
704 int bytes_deleted = 0;
706 if (reverse_direction) {
707 current_range = ranges_.back();
708 if (current_range->LastGOPContainsNextBufferPosition()) {
709 DCHECK_EQ(current_range, selected_range_);
710 break;
712 bytes_deleted = current_range->DeleteGOPFromBack(&buffers);
713 } else {
714 current_range = ranges_.front();
715 if (current_range->FirstGOPContainsNextBufferPosition()) {
716 DCHECK_EQ(current_range, selected_range_);
717 break;
719 bytes_deleted = current_range->DeleteGOPFromFront(&buffers);
722 // Check to see if we've just deleted the GOP that was last appended.
723 DecodeTimestamp end_timestamp = buffers.back()->GetDecodeTimestamp();
724 if (end_timestamp == last_appended_buffer_timestamp_) {
725 DCHECK(last_appended_buffer_timestamp_ != kNoDecodeTimestamp());
726 DCHECK(!new_range_for_append);
727 // Create a new range containing these buffers.
728 new_range_for_append = new SourceBufferRange(
729 TypeToGapPolicy(GetType()),
730 buffers, kNoDecodeTimestamp(),
731 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance,
732 base::Unretained(this)));
733 range_for_next_append_ = ranges_.end();
734 } else {
735 bytes_to_free -= bytes_deleted;
736 bytes_freed += bytes_deleted;
739 if (current_range->size_in_bytes() == 0) {
740 DCHECK_NE(current_range, selected_range_);
741 DCHECK(range_for_next_append_ == ranges_.end() ||
742 *range_for_next_append_ != current_range);
743 delete current_range;
744 reverse_direction ? ranges_.pop_back() : ranges_.pop_front();
748 // Insert |new_range_for_append| into |ranges_|, if applicable.
749 if (new_range_for_append) {
750 range_for_next_append_ = AddToRanges(new_range_for_append);
751 DCHECK(range_for_next_append_ != ranges_.end());
753 // Check to see if we need to merge |new_range_for_append| with the range
754 // before or after it. |new_range_for_append| is created whenever the last
755 // GOP appended is encountered, regardless of whether any buffers after it
756 // are ultimately deleted. Merging is necessary if there were no buffers
757 // (or very few buffers) deleted after creating |new_range_for_append|.
758 if (range_for_next_append_ != ranges_.begin()) {
759 RangeList::iterator range_before_next = range_for_next_append_;
760 --range_before_next;
761 MergeWithAdjacentRangeIfNecessary(range_before_next);
763 MergeWithAdjacentRangeIfNecessary(range_for_next_append_);
765 return bytes_freed;
768 void SourceBufferStream::PrepareRangesForNextAppend(
769 const BufferQueue& new_buffers, BufferQueue* deleted_buffers) {
770 DCHECK(deleted_buffers);
772 bool temporarily_select_range = false;
773 if (!track_buffer_.empty()) {
774 DecodeTimestamp tb_timestamp = track_buffer_.back()->GetDecodeTimestamp();
775 DecodeTimestamp seek_timestamp = FindKeyframeAfterTimestamp(tb_timestamp);
776 if (seek_timestamp != kNoDecodeTimestamp() &&
777 seek_timestamp < new_buffers.front()->GetDecodeTimestamp() &&
778 range_for_next_append_ != ranges_.end() &&
779 (*range_for_next_append_)->BelongsToRange(seek_timestamp)) {
780 DCHECK(tb_timestamp < seek_timestamp);
781 DCHECK(!selected_range_);
782 DCHECK(!(*range_for_next_append_)->HasNextBufferPosition());
784 // If there are GOPs between the end of the track buffer and the
785 // beginning of the new buffers, then temporarily seek the range
786 // so that the buffers between these two times will be deposited in
787 // |deleted_buffers| as if they were part of the current playback
788 // position.
789 // TODO(acolwell): Figure out a more elegant way to do this.
790 SeekAndSetSelectedRange(*range_for_next_append_, seek_timestamp);
791 temporarily_select_range = true;
795 // Handle splices between the existing buffers and the new buffers. If a
796 // splice is generated the timestamp and duration of the first buffer in
797 // |new_buffers| will be modified.
798 if (splice_frames_enabled_)
799 GenerateSpliceFrame(new_buffers);
801 DecodeTimestamp prev_timestamp = last_appended_buffer_timestamp_;
802 bool prev_is_keyframe = last_appended_buffer_is_keyframe_;
803 DecodeTimestamp next_timestamp = new_buffers.front()->GetDecodeTimestamp();
804 bool next_is_keyframe = new_buffers.front()->is_key_frame();
806 if (prev_timestamp != kNoDecodeTimestamp() &&
807 prev_timestamp != next_timestamp) {
808 // Clean up the old buffers between the last appended buffer and the
809 // beginning of |new_buffers|.
810 RemoveInternal(prev_timestamp, next_timestamp, true, deleted_buffers);
813 // Make the delete range exclusive if we are dealing with an allowed same
814 // timestamp situation. This prevents the first buffer in the current append
815 // from deleting the last buffer in the previous append if both buffers
816 // have the same timestamp.
818 // The delete range should never be exclusive if a splice frame was generated
819 // because we don't generate splice frames for same timestamp situations.
820 DCHECK(new_buffers.front()->splice_timestamp() !=
821 new_buffers.front()->timestamp());
822 const bool exclude_start =
823 new_buffers.front()->splice_buffers().empty() &&
824 prev_timestamp == next_timestamp &&
825 SourceBufferRange::AllowSameTimestamp(prev_is_keyframe, next_is_keyframe);
827 // Delete the buffers that |new_buffers| overlaps.
828 DecodeTimestamp start = new_buffers.front()->GetDecodeTimestamp();
829 DecodeTimestamp end = new_buffers.back()->GetDecodeTimestamp();
830 base::TimeDelta duration = new_buffers.back()->duration();
832 // Set end time for remove to include the duration of last buffer. If the
833 // duration is estimated, use 1 microsecond instead to ensure frames are not
834 // accidentally removed due to over-estimation.
835 if (duration != kNoTimestamp() && duration > base::TimeDelta() &&
836 !new_buffers.back()->is_duration_estimated()) {
837 end += duration;
838 } else {
839 // TODO(chcunningham): Emit warning when 0ms durations are not expected.
840 // http://crbug.com/312836
841 end += base::TimeDelta::FromInternalValue(1);
844 RemoveInternal(start, end, exclude_start, deleted_buffers);
846 // Restore the range seek state if necessary.
847 if (temporarily_select_range)
848 SetSelectedRange(NULL);
851 bool SourceBufferStream::AreAdjacentInSequence(
852 DecodeTimestamp first_timestamp, DecodeTimestamp second_timestamp) const {
853 return first_timestamp < second_timestamp &&
854 second_timestamp <=
855 first_timestamp + ComputeFudgeRoom(GetMaxInterbufferDistance());
858 void SourceBufferStream::PruneTrackBuffer(const DecodeTimestamp timestamp) {
859 // If we don't have the next timestamp, we don't have anything to delete.
860 if (timestamp == kNoDecodeTimestamp())
861 return;
863 while (!track_buffer_.empty() &&
864 track_buffer_.back()->GetDecodeTimestamp() >= timestamp) {
865 track_buffer_.pop_back();
869 void SourceBufferStream::MergeWithAdjacentRangeIfNecessary(
870 const RangeList::iterator& range_with_new_buffers_itr) {
871 DCHECK(range_with_new_buffers_itr != ranges_.end());
873 SourceBufferRange* range_with_new_buffers = *range_with_new_buffers_itr;
874 RangeList::iterator next_range_itr = range_with_new_buffers_itr;
875 ++next_range_itr;
877 if (next_range_itr == ranges_.end() ||
878 !range_with_new_buffers->CanAppendRangeToEnd(**next_range_itr)) {
879 return;
882 bool transfer_current_position = selected_range_ == *next_range_itr;
883 DVLOG(3) << __FUNCTION__ << " " << GetStreamTypeName()
884 << " merging " << RangeToString(*range_with_new_buffers)
885 << " into " << RangeToString(**next_range_itr);
886 range_with_new_buffers->AppendRangeToEnd(**next_range_itr,
887 transfer_current_position);
888 // Update |selected_range_| pointer if |range| has become selected after
889 // merges.
890 if (transfer_current_position)
891 SetSelectedRange(range_with_new_buffers);
893 if (next_range_itr == range_for_next_append_)
894 range_for_next_append_ = range_with_new_buffers_itr;
896 DeleteAndRemoveRange(&next_range_itr);
899 void SourceBufferStream::Seek(base::TimeDelta timestamp) {
900 DCHECK(timestamp >= base::TimeDelta());
901 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
902 << " (" << timestamp.InSecondsF() << ")";
903 ResetSeekState();
905 if (ShouldSeekToStartOfBuffered(timestamp)) {
906 ranges_.front()->SeekToStart();
907 SetSelectedRange(ranges_.front());
908 seek_pending_ = false;
909 return;
912 seek_buffer_timestamp_ = timestamp;
913 seek_pending_ = true;
915 DecodeTimestamp seek_dts = DecodeTimestamp::FromPresentationTime(timestamp);
917 RangeList::iterator itr = ranges_.end();
918 for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
919 if ((*itr)->CanSeekTo(seek_dts))
920 break;
923 if (itr == ranges_.end())
924 return;
926 SeekAndSetSelectedRange(*itr, seek_dts);
927 seek_pending_ = false;
930 bool SourceBufferStream::IsSeekPending() const {
931 return !(end_of_stream_ && IsEndSelected()) && seek_pending_;
934 void SourceBufferStream::OnSetDuration(base::TimeDelta duration) {
935 DecodeTimestamp duration_dts =
936 DecodeTimestamp::FromPresentationTime(duration);
937 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
938 << " (" << duration.InSecondsF() << ")";
940 RangeList::iterator itr = ranges_.end();
941 for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
942 if ((*itr)->GetEndTimestamp() > duration_dts)
943 break;
945 if (itr == ranges_.end())
946 return;
948 // Need to partially truncate this range.
949 if ((*itr)->GetStartTimestamp() < duration_dts) {
950 bool delete_range = (*itr)->TruncateAt(duration_dts, NULL, false);
951 if ((*itr == selected_range_) && !selected_range_->HasNextBufferPosition())
952 SetSelectedRange(NULL);
954 if (delete_range) {
955 DeleteAndRemoveRange(&itr);
956 } else {
957 ++itr;
961 // Delete all ranges that begin after |duration_dts|.
962 while (itr != ranges_.end()) {
963 // If we're about to delete the selected range, also reset the seek state.
964 DCHECK((*itr)->GetStartTimestamp() >= duration_dts);
965 if (*itr == selected_range_)
966 ResetSeekState();
967 DeleteAndRemoveRange(&itr);
971 SourceBufferStream::Status SourceBufferStream::GetNextBuffer(
972 scoped_refptr<StreamParserBuffer>* out_buffer) {
973 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName();
974 if (!pending_buffer_.get()) {
975 const SourceBufferStream::Status status = GetNextBufferInternal(out_buffer);
976 if (status != SourceBufferStream::kSuccess ||
977 !SetPendingBuffer(out_buffer)) {
978 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName()
979 << ": no pending buffer, returning status " << status;
980 return status;
984 if (!pending_buffer_->splice_buffers().empty()) {
985 const SourceBufferStream::Status status =
986 HandleNextBufferWithSplice(out_buffer);
987 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName()
988 << ": handled next buffer with splice, returning status "
989 << status;
990 return status;
993 DCHECK(pending_buffer_->preroll_buffer().get());
995 const SourceBufferStream::Status status =
996 HandleNextBufferWithPreroll(out_buffer);
997 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName()
998 << ": handled next buffer with preroll, returning status "
999 << status;
1000 return status;
1003 SourceBufferStream::Status SourceBufferStream::HandleNextBufferWithSplice(
1004 scoped_refptr<StreamParserBuffer>* out_buffer) {
1005 const BufferQueue& splice_buffers = pending_buffer_->splice_buffers();
1006 const size_t last_splice_buffer_index = splice_buffers.size() - 1;
1008 // Are there any splice buffers left to hand out? The last buffer should be
1009 // handed out separately since it represents the first post-splice buffer.
1010 if (splice_buffers_index_ < last_splice_buffer_index) {
1011 // Account for config changes which occur between fade out buffers.
1012 if (current_config_index_ !=
1013 splice_buffers[splice_buffers_index_]->GetConfigId()) {
1014 config_change_pending_ = true;
1015 DVLOG(1) << "Config change (splice buffer config ID does not match).";
1016 return SourceBufferStream::kConfigChange;
1019 // Every pre splice buffer must have the same splice_timestamp().
1020 DCHECK(pending_buffer_->splice_timestamp() ==
1021 splice_buffers[splice_buffers_index_]->splice_timestamp());
1023 // No pre splice buffers should have preroll.
1024 DCHECK(!splice_buffers[splice_buffers_index_]->preroll_buffer().get());
1026 *out_buffer = splice_buffers[splice_buffers_index_++];
1027 return SourceBufferStream::kSuccess;
1030 // Did we hand out the last pre-splice buffer on the previous call?
1031 if (!pending_buffers_complete_) {
1032 DCHECK_EQ(splice_buffers_index_, last_splice_buffer_index);
1033 pending_buffers_complete_ = true;
1034 config_change_pending_ = true;
1035 DVLOG(1) << "Config change (forced for fade in of splice frame).";
1036 return SourceBufferStream::kConfigChange;
1039 // All pre-splice buffers have been handed out and a config change completed,
1040 // so hand out the final buffer for fade in. Because a config change is
1041 // always issued prior to handing out this buffer, any changes in config id
1042 // have been inherently handled.
1043 DCHECK(pending_buffers_complete_);
1044 DCHECK_EQ(splice_buffers_index_, splice_buffers.size() - 1);
1045 DCHECK(splice_buffers.back()->splice_timestamp() == kNoTimestamp());
1046 *out_buffer = splice_buffers.back();
1047 pending_buffer_ = NULL;
1049 // If the last splice buffer has preroll, hand off to the preroll handler.
1050 return SetPendingBuffer(out_buffer) ? HandleNextBufferWithPreroll(out_buffer)
1051 : SourceBufferStream::kSuccess;
1054 SourceBufferStream::Status SourceBufferStream::HandleNextBufferWithPreroll(
1055 scoped_refptr<StreamParserBuffer>* out_buffer) {
1056 // Any config change should have already been handled.
1057 DCHECK_EQ(current_config_index_, pending_buffer_->GetConfigId());
1059 // Check if the preroll buffer has already been handed out.
1060 if (!pending_buffers_complete_) {
1061 pending_buffers_complete_ = true;
1062 *out_buffer = pending_buffer_->preroll_buffer();
1063 return SourceBufferStream::kSuccess;
1066 // Preroll complete, hand out the final buffer.
1067 *out_buffer = pending_buffer_;
1068 pending_buffer_ = NULL;
1069 return SourceBufferStream::kSuccess;
1072 SourceBufferStream::Status SourceBufferStream::GetNextBufferInternal(
1073 scoped_refptr<StreamParserBuffer>* out_buffer) {
1074 CHECK(!config_change_pending_);
1076 if (!track_buffer_.empty()) {
1077 DCHECK(!selected_range_);
1078 scoped_refptr<StreamParserBuffer>& next_buffer = track_buffer_.front();
1080 // If the next buffer is an audio splice frame, the next effective config id
1081 // comes from the first splice buffer.
1082 if (next_buffer->GetSpliceBufferConfigId(0) != current_config_index_) {
1083 config_change_pending_ = true;
1084 DVLOG(1) << "Config change (track buffer config ID does not match).";
1085 return kConfigChange;
1088 DVLOG(3) << __FUNCTION__ << " Next buffer coming from track_buffer_";
1089 *out_buffer = next_buffer;
1090 track_buffer_.pop_front();
1091 last_output_buffer_timestamp_ = (*out_buffer)->GetDecodeTimestamp();
1093 // If the track buffer becomes empty, then try to set the selected range
1094 // based on the timestamp of this buffer being returned.
1095 if (track_buffer_.empty())
1096 SetSelectedRangeIfNeeded(last_output_buffer_timestamp_);
1098 return kSuccess;
1101 if (!selected_range_ || !selected_range_->HasNextBuffer()) {
1102 if (end_of_stream_ && IsEndSelected())
1103 return kEndOfStream;
1104 DVLOG(3) << __FUNCTION__ << " " << GetStreamTypeName()
1105 << ": returning kNeedBuffer "
1106 << (selected_range_ ? "(selected range has no next buffer)"
1107 : "(no selected range)");
1108 return kNeedBuffer;
1111 if (selected_range_->GetNextConfigId() != current_config_index_) {
1112 config_change_pending_ = true;
1113 DVLOG(1) << "Config change (selected range config ID does not match).";
1114 return kConfigChange;
1117 CHECK(selected_range_->GetNextBuffer(out_buffer));
1118 last_output_buffer_timestamp_ = (*out_buffer)->GetDecodeTimestamp();
1119 return kSuccess;
1122 DecodeTimestamp SourceBufferStream::GetNextBufferTimestamp() {
1123 if (!track_buffer_.empty())
1124 return track_buffer_.front()->GetDecodeTimestamp();
1126 if (!selected_range_)
1127 return kNoDecodeTimestamp();
1129 DCHECK(selected_range_->HasNextBufferPosition());
1130 return selected_range_->GetNextTimestamp();
1133 SourceBufferStream::RangeList::iterator
1134 SourceBufferStream::FindExistingRangeFor(DecodeTimestamp start_timestamp) {
1135 for (RangeList::iterator itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
1136 if ((*itr)->BelongsToRange(start_timestamp))
1137 return itr;
1139 return ranges_.end();
1142 SourceBufferStream::RangeList::iterator
1143 SourceBufferStream::AddToRanges(SourceBufferRange* new_range) {
1144 DecodeTimestamp start_timestamp = new_range->GetStartTimestamp();
1145 RangeList::iterator itr = ranges_.end();
1146 for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
1147 if ((*itr)->GetStartTimestamp() > start_timestamp)
1148 break;
1150 return ranges_.insert(itr, new_range);
1153 SourceBufferStream::RangeList::iterator
1154 SourceBufferStream::GetSelectedRangeItr() {
1155 DCHECK(selected_range_);
1156 RangeList::iterator itr = ranges_.end();
1157 for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
1158 if (*itr == selected_range_)
1159 break;
1161 DCHECK(itr != ranges_.end());
1162 return itr;
1165 void SourceBufferStream::SeekAndSetSelectedRange(
1166 SourceBufferRange* range, DecodeTimestamp seek_timestamp) {
1167 if (range)
1168 range->Seek(seek_timestamp);
1169 SetSelectedRange(range);
1172 void SourceBufferStream::SetSelectedRange(SourceBufferRange* range) {
1173 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
1174 << ": " << selected_range_ << " -> " << range;
1175 if (selected_range_)
1176 selected_range_->ResetNextBufferPosition();
1177 DCHECK(!range || range->HasNextBufferPosition());
1178 selected_range_ = range;
1181 Ranges<base::TimeDelta> SourceBufferStream::GetBufferedTime() const {
1182 Ranges<base::TimeDelta> ranges;
1183 for (RangeList::const_iterator itr = ranges_.begin();
1184 itr != ranges_.end(); ++itr) {
1185 ranges.Add((*itr)->GetStartTimestamp().ToPresentationTime(),
1186 (*itr)->GetBufferedEndTimestamp().ToPresentationTime());
1188 return ranges;
1191 base::TimeDelta SourceBufferStream::GetBufferedDuration() const {
1192 if (ranges_.empty())
1193 return base::TimeDelta();
1195 return ranges_.back()->GetBufferedEndTimestamp().ToPresentationTime();
1198 void SourceBufferStream::MarkEndOfStream() {
1199 DCHECK(!end_of_stream_);
1200 end_of_stream_ = true;
1203 void SourceBufferStream::UnmarkEndOfStream() {
1204 DCHECK(end_of_stream_);
1205 end_of_stream_ = false;
1208 bool SourceBufferStream::IsEndSelected() const {
1209 if (ranges_.empty())
1210 return true;
1212 if (seek_pending_) {
1213 base::TimeDelta last_range_end_time =
1214 ranges_.back()->GetBufferedEndTimestamp().ToPresentationTime();
1215 return seek_buffer_timestamp_ >= last_range_end_time;
1218 return selected_range_ == ranges_.back();
1221 const AudioDecoderConfig& SourceBufferStream::GetCurrentAudioDecoderConfig() {
1222 if (config_change_pending_)
1223 CompleteConfigChange();
1224 return audio_configs_[current_config_index_];
1227 const VideoDecoderConfig& SourceBufferStream::GetCurrentVideoDecoderConfig() {
1228 if (config_change_pending_)
1229 CompleteConfigChange();
1230 return video_configs_[current_config_index_];
1233 const TextTrackConfig& SourceBufferStream::GetCurrentTextTrackConfig() {
1234 return text_track_config_;
1237 base::TimeDelta SourceBufferStream::GetMaxInterbufferDistance() const {
1238 if (max_interbuffer_distance_ == kNoTimestamp())
1239 return base::TimeDelta::FromMilliseconds(kDefaultBufferDurationInMs);
1240 return max_interbuffer_distance_;
1243 bool SourceBufferStream::UpdateAudioConfig(const AudioDecoderConfig& config) {
1244 DCHECK(!audio_configs_.empty());
1245 DCHECK(video_configs_.empty());
1246 DVLOG(3) << "UpdateAudioConfig.";
1248 if (audio_configs_[0].codec() != config.codec()) {
1249 MEDIA_LOG(ERROR, log_cb_) << "Audio codec changes not allowed.";
1250 return false;
1253 if (audio_configs_[0].is_encrypted() != config.is_encrypted()) {
1254 MEDIA_LOG(ERROR, log_cb_) << "Audio encryption changes not allowed.";
1255 return false;
1258 // Check to see if the new config matches an existing one.
1259 for (size_t i = 0; i < audio_configs_.size(); ++i) {
1260 if (config.Matches(audio_configs_[i])) {
1261 append_config_index_ = i;
1262 return true;
1266 // No matches found so let's add this one to the list.
1267 append_config_index_ = audio_configs_.size();
1268 DVLOG(2) << "New audio config - index: " << append_config_index_;
1269 audio_configs_.resize(audio_configs_.size() + 1);
1270 audio_configs_[append_config_index_] = config;
1271 return true;
1274 bool SourceBufferStream::UpdateVideoConfig(const VideoDecoderConfig& config) {
1275 DCHECK(!video_configs_.empty());
1276 DCHECK(audio_configs_.empty());
1277 DVLOG(3) << "UpdateVideoConfig.";
1279 if (video_configs_[0].codec() != config.codec()) {
1280 MEDIA_LOG(ERROR, log_cb_) << "Video codec changes not allowed.";
1281 return false;
1284 if (video_configs_[0].is_encrypted() != config.is_encrypted()) {
1285 MEDIA_LOG(ERROR, log_cb_) << "Video encryption changes not allowed.";
1286 return false;
1289 // Check to see if the new config matches an existing one.
1290 for (size_t i = 0; i < video_configs_.size(); ++i) {
1291 if (config.Matches(video_configs_[i])) {
1292 append_config_index_ = i;
1293 return true;
1297 // No matches found so let's add this one to the list.
1298 append_config_index_ = video_configs_.size();
1299 DVLOG(2) << "New video config - index: " << append_config_index_;
1300 video_configs_.resize(video_configs_.size() + 1);
1301 video_configs_[append_config_index_] = config;
1302 return true;
1305 void SourceBufferStream::CompleteConfigChange() {
1306 config_change_pending_ = false;
1308 if (pending_buffer_.get()) {
1309 current_config_index_ =
1310 pending_buffer_->GetSpliceBufferConfigId(splice_buffers_index_);
1311 return;
1314 if (!track_buffer_.empty()) {
1315 current_config_index_ = track_buffer_.front()->GetSpliceBufferConfigId(0);
1316 return;
1319 if (selected_range_ && selected_range_->HasNextBuffer())
1320 current_config_index_ = selected_range_->GetNextConfigId();
1323 void SourceBufferStream::SetSelectedRangeIfNeeded(
1324 const DecodeTimestamp timestamp) {
1325 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName()
1326 << "(" << timestamp.InSecondsF() << ")";
1328 if (selected_range_) {
1329 DCHECK(track_buffer_.empty());
1330 return;
1333 if (!track_buffer_.empty()) {
1334 DCHECK(!selected_range_);
1335 return;
1338 DecodeTimestamp start_timestamp = timestamp;
1340 // If the next buffer timestamp is not known then use a timestamp just after
1341 // the timestamp on the last buffer returned by GetNextBuffer().
1342 if (start_timestamp == kNoDecodeTimestamp()) {
1343 if (last_output_buffer_timestamp_ == kNoDecodeTimestamp()) {
1344 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName()
1345 << " no previous output timestamp";
1346 return;
1349 start_timestamp = last_output_buffer_timestamp_ +
1350 base::TimeDelta::FromInternalValue(1);
1353 DecodeTimestamp seek_timestamp =
1354 FindNewSelectedRangeSeekTimestamp(start_timestamp);
1356 // If we don't have buffered data to seek to, then return.
1357 if (seek_timestamp == kNoDecodeTimestamp()) {
1358 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName()
1359 << " couldn't find new selected range seek timestamp";
1360 return;
1363 DCHECK(track_buffer_.empty());
1364 SeekAndSetSelectedRange(*FindExistingRangeFor(seek_timestamp),
1365 seek_timestamp);
1368 DecodeTimestamp SourceBufferStream::FindNewSelectedRangeSeekTimestamp(
1369 const DecodeTimestamp start_timestamp) {
1370 DCHECK(start_timestamp != kNoDecodeTimestamp());
1371 DCHECK(start_timestamp >= DecodeTimestamp());
1373 RangeList::iterator itr = ranges_.begin();
1375 for (; itr != ranges_.end(); ++itr) {
1376 if ((*itr)->GetEndTimestamp() >= start_timestamp) {
1377 break;
1381 if (itr == ranges_.end()) {
1382 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName()
1383 << " no buffered data for dts=" << start_timestamp.InSecondsF();
1384 return kNoDecodeTimestamp();
1387 // First check for a keyframe timestamp >= |start_timestamp|
1388 // in the current range.
1389 DecodeTimestamp keyframe_timestamp =
1390 (*itr)->NextKeyframeTimestamp(start_timestamp);
1392 if (keyframe_timestamp != kNoDecodeTimestamp())
1393 return keyframe_timestamp;
1395 // If a keyframe was not found then look for a keyframe that is
1396 // "close enough" in the current or next range.
1397 DecodeTimestamp end_timestamp =
1398 start_timestamp + ComputeFudgeRoom(GetMaxInterbufferDistance());
1399 DCHECK(start_timestamp < end_timestamp);
1401 // Make sure the current range doesn't start beyond |end_timestamp|.
1402 if ((*itr)->GetStartTimestamp() >= end_timestamp)
1403 return kNoDecodeTimestamp();
1405 keyframe_timestamp = (*itr)->KeyframeBeforeTimestamp(end_timestamp);
1407 // Check to see if the keyframe is within the acceptable range
1408 // (|start_timestamp|, |end_timestamp|].
1409 if (keyframe_timestamp != kNoDecodeTimestamp() &&
1410 start_timestamp < keyframe_timestamp &&
1411 keyframe_timestamp <= end_timestamp) {
1412 return keyframe_timestamp;
1415 // If |end_timestamp| is within this range, then no other checks are
1416 // necessary.
1417 if (end_timestamp <= (*itr)->GetEndTimestamp())
1418 return kNoDecodeTimestamp();
1420 // Move on to the next range.
1421 ++itr;
1423 // Return early if the next range does not contain |end_timestamp|.
1424 if (itr == ranges_.end() || (*itr)->GetStartTimestamp() >= end_timestamp)
1425 return kNoDecodeTimestamp();
1427 keyframe_timestamp = (*itr)->KeyframeBeforeTimestamp(end_timestamp);
1429 // Check to see if the keyframe is within the acceptable range
1430 // (|start_timestamp|, |end_timestamp|].
1431 if (keyframe_timestamp != kNoDecodeTimestamp() &&
1432 start_timestamp < keyframe_timestamp &&
1433 keyframe_timestamp <= end_timestamp) {
1434 return keyframe_timestamp;
1437 return kNoDecodeTimestamp();
1440 DecodeTimestamp SourceBufferStream::FindKeyframeAfterTimestamp(
1441 const DecodeTimestamp timestamp) {
1442 DCHECK(timestamp != kNoDecodeTimestamp());
1444 RangeList::iterator itr = FindExistingRangeFor(timestamp);
1446 if (itr == ranges_.end())
1447 return kNoDecodeTimestamp();
1449 // First check for a keyframe timestamp >= |timestamp|
1450 // in the current range.
1451 return (*itr)->NextKeyframeTimestamp(timestamp);
1454 std::string SourceBufferStream::GetStreamTypeName() const {
1455 switch (GetType()) {
1456 case kAudio:
1457 return "AUDIO";
1458 case kVideo:
1459 return "VIDEO";
1460 case kText:
1461 return "TEXT";
1463 NOTREACHED();
1464 return "";
1467 SourceBufferStream::Type SourceBufferStream::GetType() const {
1468 if (!audio_configs_.empty())
1469 return kAudio;
1470 if (!video_configs_.empty())
1471 return kVideo;
1472 DCHECK_NE(text_track_config_.kind(), kTextNone);
1473 return kText;
1476 void SourceBufferStream::DeleteAndRemoveRange(RangeList::iterator* itr) {
1477 DVLOG(1) << __FUNCTION__;
1479 DCHECK(*itr != ranges_.end());
1480 if (**itr == selected_range_) {
1481 DVLOG(1) << __FUNCTION__ << " deleting selected range.";
1482 SetSelectedRange(NULL);
1485 if (*itr == range_for_next_append_) {
1486 DVLOG(1) << __FUNCTION__ << " deleting range_for_next_append_.";
1487 range_for_next_append_ = ranges_.end();
1488 last_appended_buffer_timestamp_ = kNoDecodeTimestamp();
1489 last_appended_buffer_is_keyframe_ = false;
1492 delete **itr;
1493 *itr = ranges_.erase(*itr);
1496 void SourceBufferStream::GenerateSpliceFrame(const BufferQueue& new_buffers) {
1497 DCHECK(!new_buffers.empty());
1499 // Splice frames are only supported for audio.
1500 if (GetType() != kAudio)
1501 return;
1503 // Find the overlapped range (if any).
1504 const base::TimeDelta splice_timestamp = new_buffers.front()->timestamp();
1505 const DecodeTimestamp splice_dts =
1506 DecodeTimestamp::FromPresentationTime(splice_timestamp);
1507 RangeList::iterator range_itr = FindExistingRangeFor(splice_dts);
1508 if (range_itr == ranges_.end())
1509 return;
1511 const DecodeTimestamp max_splice_end_dts =
1512 splice_dts + base::TimeDelta::FromMilliseconds(
1513 AudioSplicer::kCrossfadeDurationInMilliseconds);
1515 // Find all buffers involved before the splice point.
1516 BufferQueue pre_splice_buffers;
1517 if (!(*range_itr)->GetBuffersInRange(
1518 splice_dts, max_splice_end_dts, &pre_splice_buffers)) {
1519 return;
1522 // If there are gaps in the timeline, it's possible that we only find buffers
1523 // after the splice point but within the splice range. For simplicity, we do
1524 // not generate splice frames in this case.
1526 // We also do not want to generate splices if the first new buffer replaces an
1527 // existing buffer exactly.
1528 if (pre_splice_buffers.front()->timestamp() >= splice_timestamp)
1529 return;
1531 // If any |pre_splice_buffers| are already splices or preroll, do not generate
1532 // a splice.
1533 for (size_t i = 0; i < pre_splice_buffers.size(); ++i) {
1534 const BufferQueue& original_splice_buffers =
1535 pre_splice_buffers[i]->splice_buffers();
1536 if (!original_splice_buffers.empty()) {
1537 DVLOG(1) << "Can't generate splice: overlapped buffers contain a "
1538 "pre-existing splice.";
1539 return;
1542 if (pre_splice_buffers[i]->preroll_buffer().get()) {
1543 DVLOG(1) << "Can't generate splice: overlapped buffers contain preroll.";
1544 return;
1548 // Don't generate splice frames which represent less than two frames, since we
1549 // need at least that much to generate a crossfade. Per the spec, make this
1550 // check using the sample rate of the overlapping buffers.
1551 const base::TimeDelta splice_duration =
1552 pre_splice_buffers.back()->timestamp() +
1553 pre_splice_buffers.back()->duration() - splice_timestamp;
1554 const base::TimeDelta minimum_splice_duration = base::TimeDelta::FromSecondsD(
1555 2.0 / audio_configs_[append_config_index_].samples_per_second());
1556 if (splice_duration < minimum_splice_duration) {
1557 DVLOG(1) << "Can't generate splice: not enough samples for crossfade; have "
1558 << splice_duration.InMicroseconds() << " us, but need "
1559 << minimum_splice_duration.InMicroseconds() << " us.";
1560 return;
1563 new_buffers.front()->ConvertToSpliceBuffer(pre_splice_buffers);
1566 bool SourceBufferStream::SetPendingBuffer(
1567 scoped_refptr<StreamParserBuffer>* out_buffer) {
1568 DCHECK(out_buffer->get());
1569 DCHECK(!pending_buffer_.get());
1571 const bool have_splice_buffers = !(*out_buffer)->splice_buffers().empty();
1572 const bool have_preroll_buffer = !!(*out_buffer)->preroll_buffer().get();
1574 if (!have_splice_buffers && !have_preroll_buffer)
1575 return false;
1577 DCHECK_NE(have_splice_buffers, have_preroll_buffer);
1578 splice_buffers_index_ = 0;
1579 pending_buffer_.swap(*out_buffer);
1580 pending_buffers_complete_ = false;
1581 return true;
1584 } // namespace media