Roll src/third_party/WebKit 05e9c31:d6595eb (svn 198725:198727)
[chromium-blink-merge.git] / media / filters / source_buffer_stream.cc
blobab6b4eea38f3940a302ee1ba8a746d421ed76984
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) {
173 SourceBufferStream::~SourceBufferStream() {
174 while (!ranges_.empty()) {
175 delete ranges_.front();
176 ranges_.pop_front();
180 void SourceBufferStream::OnNewMediaSegment(
181 DecodeTimestamp media_segment_start_time) {
182 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
183 << " (" << media_segment_start_time.InSecondsF() << ")";
184 DCHECK(!end_of_stream_);
185 media_segment_start_time_ = media_segment_start_time;
186 new_media_segment_ = true;
188 RangeList::iterator last_range = range_for_next_append_;
189 range_for_next_append_ = FindExistingRangeFor(media_segment_start_time);
191 // Only reset |last_appended_buffer_timestamp_| if this new media segment is
192 // not adjacent to the previous media segment appended to the stream.
193 if (range_for_next_append_ == ranges_.end() ||
194 !AreAdjacentInSequence(last_appended_buffer_timestamp_,
195 media_segment_start_time)) {
196 last_appended_buffer_timestamp_ = kNoDecodeTimestamp();
197 last_appended_buffer_is_keyframe_ = false;
198 DVLOG(3) << __FUNCTION__ << " next appended buffers will be in a new range";
199 } else if (last_range != ranges_.end()) {
200 DCHECK(last_range == range_for_next_append_);
201 DVLOG(3) << __FUNCTION__ << " next appended buffers will continue range "
202 << "unless intervening remove makes discontinuity";
206 bool SourceBufferStream::Append(const BufferQueue& buffers) {
207 TRACE_EVENT2("media", "SourceBufferStream::Append",
208 "stream type", GetStreamTypeName(),
209 "buffers to append", buffers.size());
211 DCHECK(!buffers.empty());
212 DCHECK(media_segment_start_time_ != kNoDecodeTimestamp());
213 DCHECK(media_segment_start_time_ <= buffers.front()->GetDecodeTimestamp());
214 DCHECK(!end_of_stream_);
216 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() << ": buffers dts=["
217 << buffers.front()->GetDecodeTimestamp().InSecondsF() << ";"
218 << buffers.back()->GetDecodeTimestamp().InSecondsF() << "] pts=["
219 << buffers.front()->timestamp().InSecondsF() << ";"
220 << buffers.back()->timestamp().InSecondsF() << "(last frame dur="
221 << buffers.back()->duration().InSecondsF() << ")]";
223 // New media segments must begin with a keyframe.
224 // TODO(wolenetz): Relax this requirement. See http://crbug.com/229412.
225 if (new_media_segment_ && !buffers.front()->is_key_frame()) {
226 MEDIA_LOG(ERROR, log_cb_) << "Media segment did not begin with key frame.";
227 return false;
230 // Buffers within a media segment should be monotonically increasing.
231 if (!IsMonotonicallyIncreasing(buffers))
232 return false;
234 if (media_segment_start_time_ < DecodeTimestamp() ||
235 buffers.front()->GetDecodeTimestamp() < DecodeTimestamp()) {
236 MEDIA_LOG(ERROR, log_cb_)
237 << "Cannot append a media segment with negative timestamps.";
238 return false;
241 if (!IsNextTimestampValid(buffers.front()->GetDecodeTimestamp(),
242 buffers.front()->is_key_frame())) {
243 const DecodeTimestamp& dts = buffers.front()->GetDecodeTimestamp();
244 MEDIA_LOG(ERROR, log_cb_) << "Invalid same timestamp construct detected at"
245 << " time " << dts.InSecondsF();
247 return false;
250 UpdateMaxInterbufferDistance(buffers);
251 SetConfigIds(buffers);
253 // Save a snapshot of stream state before range modifications are made.
254 DecodeTimestamp next_buffer_timestamp = GetNextBufferTimestamp();
255 BufferQueue deleted_buffers;
257 PrepareRangesForNextAppend(buffers, &deleted_buffers);
259 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise,
260 // create a new range with |buffers|.
261 if (range_for_next_append_ != ranges_.end()) {
262 (*range_for_next_append_)->AppendBuffersToEnd(buffers);
263 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp();
264 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame();
265 } else {
266 DecodeTimestamp new_range_start_time = std::min(
267 media_segment_start_time_, buffers.front()->GetDecodeTimestamp());
268 const BufferQueue* buffers_for_new_range = &buffers;
269 BufferQueue trimmed_buffers;
271 // If the new range is not being created because of a new media
272 // segment, then we must make sure that we start with a key frame.
273 // This can happen if the GOP in the previous append gets destroyed
274 // by a Remove() call.
275 if (!new_media_segment_) {
276 BufferQueue::const_iterator itr = buffers.begin();
278 // Scan past all the non-key-frames.
279 while (itr != buffers.end() && !(*itr)->is_key_frame()) {
280 ++itr;
283 // If we didn't find a key frame, then update the last appended
284 // buffer state and return.
285 if (itr == buffers.end()) {
286 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp();
287 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame();
288 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
289 << ": new buffers in the middle of media segment depend on"
290 "keyframe that has been removed, and contain no keyframes."
291 "Skipping further processing.";
292 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
293 << ": done. ranges_=" << RangesToString(ranges_);
294 return true;
295 } else if (itr != buffers.begin()) {
296 // Copy the first key frame and everything after it into
297 // |trimmed_buffers|.
298 trimmed_buffers.assign(itr, buffers.end());
299 buffers_for_new_range = &trimmed_buffers;
302 new_range_start_time =
303 buffers_for_new_range->front()->GetDecodeTimestamp();
306 range_for_next_append_ =
307 AddToRanges(new SourceBufferRange(
308 TypeToGapPolicy(GetType()),
309 *buffers_for_new_range, new_range_start_time,
310 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance,
311 base::Unretained(this))));
312 last_appended_buffer_timestamp_ =
313 buffers_for_new_range->back()->GetDecodeTimestamp();
314 last_appended_buffer_is_keyframe_ =
315 buffers_for_new_range->back()->is_key_frame();
318 new_media_segment_ = false;
320 MergeWithAdjacentRangeIfNecessary(range_for_next_append_);
322 // Seek to try to fulfill a previous call to Seek().
323 if (seek_pending_) {
324 DCHECK(!selected_range_);
325 DCHECK(deleted_buffers.empty());
326 Seek(seek_buffer_timestamp_);
329 if (!deleted_buffers.empty()) {
330 DecodeTimestamp start_of_deleted =
331 deleted_buffers.front()->GetDecodeTimestamp();
333 DCHECK(track_buffer_.empty() ||
334 track_buffer_.back()->GetDecodeTimestamp() < start_of_deleted)
335 << "decode timestamp "
336 << track_buffer_.back()->GetDecodeTimestamp().InSecondsF() << " sec"
337 << ", start_of_deleted " << start_of_deleted.InSecondsF()<< " sec";
339 track_buffer_.insert(track_buffer_.end(), deleted_buffers.begin(),
340 deleted_buffers.end());
341 DVLOG(3) << __FUNCTION__ << " Added " << deleted_buffers.size()
342 << " deleted buffers to track buffer. TB size is now "
343 << track_buffer_.size();
344 } else {
345 DVLOG(3) << __FUNCTION__ << " No deleted buffers for track buffer";
348 // Prune any extra buffers in |track_buffer_| if new keyframes
349 // are appended to the range covered by |track_buffer_|.
350 if (!track_buffer_.empty()) {
351 DecodeTimestamp keyframe_timestamp =
352 FindKeyframeAfterTimestamp(track_buffer_.front()->GetDecodeTimestamp());
353 if (keyframe_timestamp != kNoDecodeTimestamp())
354 PruneTrackBuffer(keyframe_timestamp);
357 SetSelectedRangeIfNeeded(next_buffer_timestamp);
359 GarbageCollectIfNeeded();
361 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
362 << ": done. ranges_=" << RangesToString(ranges_);
363 DCHECK(IsRangeListSorted(ranges_));
364 DCHECK(OnlySelectedRangeIsSeeked());
365 return true;
368 void SourceBufferStream::Remove(base::TimeDelta start, base::TimeDelta end,
369 base::TimeDelta duration) {
370 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
371 << " (" << start.InSecondsF() << ", " << end.InSecondsF()
372 << ", " << duration.InSecondsF() << ")";
373 DCHECK(start >= base::TimeDelta()) << start.InSecondsF();
374 DCHECK(start < end) << "start " << start.InSecondsF()
375 << " end " << end.InSecondsF();
376 DCHECK(duration != kNoTimestamp());
378 DecodeTimestamp start_dts = DecodeTimestamp::FromPresentationTime(start);
379 DecodeTimestamp end_dts = DecodeTimestamp::FromPresentationTime(end);
380 DecodeTimestamp remove_end_timestamp =
381 DecodeTimestamp::FromPresentationTime(duration);
382 DecodeTimestamp keyframe_timestamp = FindKeyframeAfterTimestamp(end_dts);
383 if (keyframe_timestamp != kNoDecodeTimestamp()) {
384 remove_end_timestamp = keyframe_timestamp;
385 } else if (end_dts < remove_end_timestamp) {
386 remove_end_timestamp = end_dts;
389 BufferQueue deleted_buffers;
390 RemoveInternal(start_dts, remove_end_timestamp, false, &deleted_buffers);
392 if (!deleted_buffers.empty()) {
393 // Buffers for the current position have been removed.
394 SetSelectedRangeIfNeeded(deleted_buffers.front()->GetDecodeTimestamp());
395 if (last_output_buffer_timestamp_ == kNoDecodeTimestamp()) {
396 // We just removed buffers for the current playback position for this
397 // stream, yet we also had output no buffer since the last Seek.
398 // Re-seek to prevent stall.
399 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
400 << ": re-seeking to " << seek_buffer_timestamp_
401 << " to prevent stall if this time becomes buffered again";
402 Seek(seek_buffer_timestamp_);
407 void SourceBufferStream::RemoveInternal(DecodeTimestamp start,
408 DecodeTimestamp end,
409 bool exclude_start,
410 BufferQueue* deleted_buffers) {
411 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName() << " ("
412 << start.InSecondsF() << ", " << end.InSecondsF() << ", "
413 << exclude_start << ")";
414 DVLOG(3) << __FUNCTION__ << " " << GetStreamTypeName()
415 << ": before remove ranges_=" << RangesToString(ranges_);
417 DCHECK(start >= DecodeTimestamp());
418 DCHECK(start < end) << "start " << start.InSecondsF()
419 << " end " << end.InSecondsF();
420 DCHECK(deleted_buffers);
422 RangeList::iterator itr = ranges_.begin();
424 while (itr != ranges_.end()) {
425 SourceBufferRange* range = *itr;
426 if (range->GetStartTimestamp() >= end)
427 break;
429 // Split off any remaining GOPs starting at or after |end| and add it to
430 // |ranges_|.
431 SourceBufferRange* new_range = range->SplitRange(end);
432 if (new_range) {
433 itr = ranges_.insert(++itr, new_range);
434 --itr;
436 // Update the selected range if the next buffer position was transferred
437 // to |new_range|.
438 if (new_range->HasNextBufferPosition())
439 SetSelectedRange(new_range);
442 // Truncate the current range so that it only contains data before
443 // the removal range.
444 BufferQueue saved_buffers;
445 bool delete_range = range->TruncateAt(start, &saved_buffers, exclude_start);
447 // Check to see if the current playback position was removed and
448 // update the selected range appropriately.
449 if (!saved_buffers.empty()) {
450 DCHECK(!range->HasNextBufferPosition());
451 DCHECK(deleted_buffers->empty());
453 *deleted_buffers = saved_buffers;
456 if (range == selected_range_ && !range->HasNextBufferPosition())
457 SetSelectedRange(NULL);
459 // If the current range now is completely covered by the removal
460 // range then delete it and move on.
461 if (delete_range) {
462 DeleteAndRemoveRange(&itr);
463 continue;
466 // Clear |range_for_next_append_| if we determine that the removal
467 // operation makes it impossible for the next append to be added
468 // to the current range.
469 if (range_for_next_append_ != ranges_.end() &&
470 *range_for_next_append_ == range &&
471 last_appended_buffer_timestamp_ != kNoDecodeTimestamp()) {
472 DecodeTimestamp potential_next_append_timestamp =
473 last_appended_buffer_timestamp_ +
474 base::TimeDelta::FromInternalValue(1);
476 if (!range->BelongsToRange(potential_next_append_timestamp)) {
477 DVLOG(1) << "Resetting range_for_next_append_ since the next append"
478 << " can't add to the current range.";
479 range_for_next_append_ =
480 FindExistingRangeFor(potential_next_append_timestamp);
484 // Move on to the next range.
485 ++itr;
488 DVLOG(3) << __FUNCTION__ << " " << GetStreamTypeName()
489 << ": after remove ranges_=" << RangesToString(ranges_);
491 DCHECK(IsRangeListSorted(ranges_));
492 DCHECK(OnlySelectedRangeIsSeeked());
495 void SourceBufferStream::ResetSeekState() {
496 SetSelectedRange(NULL);
497 track_buffer_.clear();
498 config_change_pending_ = false;
499 last_output_buffer_timestamp_ = kNoDecodeTimestamp();
500 splice_buffers_index_ = 0;
501 pending_buffer_ = NULL;
502 pending_buffers_complete_ = false;
505 bool SourceBufferStream::ShouldSeekToStartOfBuffered(
506 base::TimeDelta seek_timestamp) const {
507 if (ranges_.empty())
508 return false;
509 base::TimeDelta beginning_of_buffered =
510 ranges_.front()->GetStartTimestamp().ToPresentationTime();
511 return (seek_timestamp <= beginning_of_buffered &&
512 beginning_of_buffered < kSeekToStartFudgeRoom());
515 bool SourceBufferStream::IsMonotonicallyIncreasing(
516 const BufferQueue& buffers) const {
517 DCHECK(!buffers.empty());
518 DecodeTimestamp prev_timestamp = last_appended_buffer_timestamp_;
519 bool prev_is_keyframe = last_appended_buffer_is_keyframe_;
520 for (BufferQueue::const_iterator itr = buffers.begin();
521 itr != buffers.end(); ++itr) {
522 DecodeTimestamp current_timestamp = (*itr)->GetDecodeTimestamp();
523 bool current_is_keyframe = (*itr)->is_key_frame();
524 DCHECK(current_timestamp != kNoDecodeTimestamp());
525 DCHECK((*itr)->duration() >= base::TimeDelta())
526 << "Packet with invalid duration."
527 << " pts " << (*itr)->timestamp().InSecondsF()
528 << " dts " << (*itr)->GetDecodeTimestamp().InSecondsF()
529 << " dur " << (*itr)->duration().InSecondsF();
531 if (prev_timestamp != kNoDecodeTimestamp()) {
532 if (current_timestamp < prev_timestamp) {
533 MEDIA_LOG(ERROR, log_cb_) << "Buffers did not monotonically increase.";
534 return false;
537 if (current_timestamp == prev_timestamp &&
538 !SourceBufferRange::AllowSameTimestamp(prev_is_keyframe,
539 current_is_keyframe)) {
540 MEDIA_LOG(ERROR, log_cb_) << "Unexpected combination of buffers with"
541 << " the same timestamp detected at "
542 << current_timestamp.InSecondsF();
543 return false;
547 prev_timestamp = current_timestamp;
548 prev_is_keyframe = current_is_keyframe;
550 return true;
553 bool SourceBufferStream::IsNextTimestampValid(
554 DecodeTimestamp next_timestamp, bool next_is_keyframe) const {
555 return (last_appended_buffer_timestamp_ != next_timestamp) ||
556 new_media_segment_ ||
557 SourceBufferRange::AllowSameTimestamp(last_appended_buffer_is_keyframe_,
558 next_is_keyframe);
562 bool SourceBufferStream::OnlySelectedRangeIsSeeked() const {
563 for (RangeList::const_iterator itr = ranges_.begin();
564 itr != ranges_.end(); ++itr) {
565 if ((*itr)->HasNextBufferPosition() && (*itr) != selected_range_)
566 return false;
568 return !selected_range_ || selected_range_->HasNextBufferPosition();
571 void SourceBufferStream::UpdateMaxInterbufferDistance(
572 const BufferQueue& buffers) {
573 DCHECK(!buffers.empty());
574 DecodeTimestamp prev_timestamp = last_appended_buffer_timestamp_;
575 for (BufferQueue::const_iterator itr = buffers.begin();
576 itr != buffers.end(); ++itr) {
577 DecodeTimestamp current_timestamp = (*itr)->GetDecodeTimestamp();
578 DCHECK(current_timestamp != kNoDecodeTimestamp());
580 base::TimeDelta interbuffer_distance = (*itr)->duration();
581 DCHECK(interbuffer_distance >= base::TimeDelta());
583 if (prev_timestamp != kNoDecodeTimestamp()) {
584 interbuffer_distance =
585 std::max(current_timestamp - prev_timestamp, interbuffer_distance);
588 if (interbuffer_distance > base::TimeDelta()) {
589 if (max_interbuffer_distance_ == kNoTimestamp()) {
590 max_interbuffer_distance_ = interbuffer_distance;
591 } else {
592 max_interbuffer_distance_ =
593 std::max(max_interbuffer_distance_, interbuffer_distance);
596 prev_timestamp = current_timestamp;
600 void SourceBufferStream::SetConfigIds(const BufferQueue& buffers) {
601 for (BufferQueue::const_iterator itr = buffers.begin();
602 itr != buffers.end(); ++itr) {
603 (*itr)->SetConfigId(append_config_index_);
607 void SourceBufferStream::GarbageCollectIfNeeded() {
608 // Compute size of |ranges_|.
609 int ranges_size = 0;
610 for (RangeList::iterator itr = ranges_.begin(); itr != ranges_.end(); ++itr)
611 ranges_size += (*itr)->size_in_bytes();
613 // Return if we're under or at the memory limit.
614 if (ranges_size <= memory_limit_)
615 return;
617 int bytes_to_free = ranges_size - memory_limit_;
619 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName() << ": Before GC"
620 << " ranges_size=" << ranges_size
621 << " ranges_=" << RangesToString(ranges_)
622 << " memory_limit_=" << memory_limit_;
624 // Begin deleting after the last appended buffer.
625 int bytes_freed = FreeBuffersAfterLastAppended(bytes_to_free);
627 // Begin deleting from the front.
628 if (bytes_to_free - bytes_freed > 0)
629 bytes_freed += FreeBuffers(bytes_to_free - bytes_freed, false);
631 // Begin deleting from the back.
632 if (bytes_to_free - bytes_freed > 0)
633 bytes_freed += FreeBuffers(bytes_to_free - bytes_freed, true);
635 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName() << ": After GC"
636 << " bytes_freed=" << bytes_freed
637 << " ranges_=" << RangesToString(ranges_);
640 int SourceBufferStream::FreeBuffersAfterLastAppended(int total_bytes_to_free) {
641 DecodeTimestamp next_buffer_timestamp = GetNextBufferTimestamp();
642 if (last_appended_buffer_timestamp_ == kNoDecodeTimestamp() ||
643 next_buffer_timestamp == kNoDecodeTimestamp() ||
644 last_appended_buffer_timestamp_ >= next_buffer_timestamp) {
645 return 0;
648 DecodeTimestamp remove_range_start = last_appended_buffer_timestamp_;
649 if (last_appended_buffer_is_keyframe_)
650 remove_range_start += GetMaxInterbufferDistance();
652 DecodeTimestamp remove_range_start_keyframe = FindKeyframeAfterTimestamp(
653 remove_range_start);
654 if (remove_range_start_keyframe != kNoDecodeTimestamp())
655 remove_range_start = remove_range_start_keyframe;
656 if (remove_range_start >= next_buffer_timestamp)
657 return 0;
659 DecodeTimestamp remove_range_end;
660 int bytes_freed = GetRemovalRange(
661 remove_range_start, next_buffer_timestamp, total_bytes_to_free,
662 &remove_range_end);
663 if (bytes_freed > 0) {
664 Remove(remove_range_start.ToPresentationTime(),
665 remove_range_end.ToPresentationTime(),
666 next_buffer_timestamp.ToPresentationTime());
669 return bytes_freed;
672 int SourceBufferStream::GetRemovalRange(
673 DecodeTimestamp start_timestamp, DecodeTimestamp end_timestamp,
674 int total_bytes_to_free, DecodeTimestamp* removal_end_timestamp) {
675 DCHECK(start_timestamp >= DecodeTimestamp()) << start_timestamp.InSecondsF();
676 DCHECK(start_timestamp < end_timestamp)
677 << "start " << start_timestamp.InSecondsF()
678 << ", end " << end_timestamp.InSecondsF();
680 int bytes_to_free = total_bytes_to_free;
681 int bytes_freed = 0;
683 for (RangeList::iterator itr = ranges_.begin();
684 itr != ranges_.end() && bytes_to_free > 0; ++itr) {
685 SourceBufferRange* range = *itr;
686 if (range->GetStartTimestamp() >= end_timestamp)
687 break;
688 if (range->GetEndTimestamp() < start_timestamp)
689 continue;
691 int bytes_removed = range->GetRemovalGOP(
692 start_timestamp, end_timestamp, bytes_to_free, removal_end_timestamp);
693 bytes_to_free -= bytes_removed;
694 bytes_freed += bytes_removed;
696 return bytes_freed;
699 int SourceBufferStream::FreeBuffers(int total_bytes_to_free,
700 bool reverse_direction) {
701 TRACE_EVENT2("media", "SourceBufferStream::FreeBuffers",
702 "total bytes to free", total_bytes_to_free,
703 "reverse direction", reverse_direction);
705 DCHECK_GT(total_bytes_to_free, 0);
706 int bytes_to_free = total_bytes_to_free;
707 int bytes_freed = 0;
709 // This range will save the last GOP appended to |range_for_next_append_|
710 // if the buffers surrounding it get deleted during garbage collection.
711 SourceBufferRange* new_range_for_append = NULL;
713 while (!ranges_.empty() && bytes_to_free > 0) {
714 SourceBufferRange* current_range = NULL;
715 BufferQueue buffers;
716 int bytes_deleted = 0;
718 if (reverse_direction) {
719 current_range = ranges_.back();
720 if (current_range->LastGOPContainsNextBufferPosition()) {
721 DCHECK_EQ(current_range, selected_range_);
722 break;
724 bytes_deleted = current_range->DeleteGOPFromBack(&buffers);
725 } else {
726 current_range = ranges_.front();
727 if (current_range->FirstGOPContainsNextBufferPosition()) {
728 DCHECK_EQ(current_range, selected_range_);
729 break;
731 bytes_deleted = current_range->DeleteGOPFromFront(&buffers);
734 // Check to see if we've just deleted the GOP that was last appended.
735 DecodeTimestamp end_timestamp = buffers.back()->GetDecodeTimestamp();
736 if (end_timestamp == last_appended_buffer_timestamp_) {
737 DCHECK(last_appended_buffer_timestamp_ != kNoDecodeTimestamp());
738 DCHECK(!new_range_for_append);
739 // Create a new range containing these buffers.
740 new_range_for_append = new SourceBufferRange(
741 TypeToGapPolicy(GetType()),
742 buffers, kNoDecodeTimestamp(),
743 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance,
744 base::Unretained(this)));
745 range_for_next_append_ = ranges_.end();
746 } else {
747 bytes_to_free -= bytes_deleted;
748 bytes_freed += bytes_deleted;
751 if (current_range->size_in_bytes() == 0) {
752 DCHECK_NE(current_range, selected_range_);
753 DCHECK(range_for_next_append_ == ranges_.end() ||
754 *range_for_next_append_ != current_range);
755 delete current_range;
756 reverse_direction ? ranges_.pop_back() : ranges_.pop_front();
760 // Insert |new_range_for_append| into |ranges_|, if applicable.
761 if (new_range_for_append) {
762 range_for_next_append_ = AddToRanges(new_range_for_append);
763 DCHECK(range_for_next_append_ != ranges_.end());
765 // Check to see if we need to merge |new_range_for_append| with the range
766 // before or after it. |new_range_for_append| is created whenever the last
767 // GOP appended is encountered, regardless of whether any buffers after it
768 // are ultimately deleted. Merging is necessary if there were no buffers
769 // (or very few buffers) deleted after creating |new_range_for_append|.
770 if (range_for_next_append_ != ranges_.begin()) {
771 RangeList::iterator range_before_next = range_for_next_append_;
772 --range_before_next;
773 MergeWithAdjacentRangeIfNecessary(range_before_next);
775 MergeWithAdjacentRangeIfNecessary(range_for_next_append_);
777 return bytes_freed;
780 void SourceBufferStream::PrepareRangesForNextAppend(
781 const BufferQueue& new_buffers, BufferQueue* deleted_buffers) {
782 DCHECK(deleted_buffers);
784 bool temporarily_select_range = false;
785 if (!track_buffer_.empty()) {
786 DecodeTimestamp tb_timestamp = track_buffer_.back()->GetDecodeTimestamp();
787 DecodeTimestamp seek_timestamp = FindKeyframeAfterTimestamp(tb_timestamp);
788 if (seek_timestamp != kNoDecodeTimestamp() &&
789 seek_timestamp < new_buffers.front()->GetDecodeTimestamp() &&
790 range_for_next_append_ != ranges_.end() &&
791 (*range_for_next_append_)->BelongsToRange(seek_timestamp)) {
792 DCHECK(tb_timestamp < seek_timestamp);
793 DCHECK(!selected_range_);
794 DCHECK(!(*range_for_next_append_)->HasNextBufferPosition());
796 // If there are GOPs between the end of the track buffer and the
797 // beginning of the new buffers, then temporarily seek the range
798 // so that the buffers between these two times will be deposited in
799 // |deleted_buffers| as if they were part of the current playback
800 // position.
801 // TODO(acolwell): Figure out a more elegant way to do this.
802 SeekAndSetSelectedRange(*range_for_next_append_, seek_timestamp);
803 temporarily_select_range = true;
807 // Handle splices between the existing buffers and the new buffers. If a
808 // splice is generated the timestamp and duration of the first buffer in
809 // |new_buffers| will be modified.
810 if (splice_frames_enabled_)
811 GenerateSpliceFrame(new_buffers);
813 DecodeTimestamp prev_timestamp = last_appended_buffer_timestamp_;
814 bool prev_is_keyframe = last_appended_buffer_is_keyframe_;
815 DecodeTimestamp next_timestamp = new_buffers.front()->GetDecodeTimestamp();
816 bool next_is_keyframe = new_buffers.front()->is_key_frame();
818 if (prev_timestamp != kNoDecodeTimestamp() &&
819 prev_timestamp != next_timestamp) {
820 // Clean up the old buffers between the last appended buffer and the
821 // beginning of |new_buffers|.
822 RemoveInternal(prev_timestamp, next_timestamp, true, deleted_buffers);
825 // Make the delete range exclusive if we are dealing with an allowed same
826 // timestamp situation. This prevents the first buffer in the current append
827 // from deleting the last buffer in the previous append if both buffers
828 // have the same timestamp.
830 // The delete range should never be exclusive if a splice frame was generated
831 // because we don't generate splice frames for same timestamp situations.
832 DCHECK(new_buffers.front()->splice_timestamp() !=
833 new_buffers.front()->timestamp());
834 const bool exclude_start =
835 new_buffers.front()->splice_buffers().empty() &&
836 prev_timestamp == next_timestamp &&
837 SourceBufferRange::AllowSameTimestamp(prev_is_keyframe, next_is_keyframe);
839 // Delete the buffers that |new_buffers| overlaps.
840 DecodeTimestamp start = new_buffers.front()->GetDecodeTimestamp();
841 DecodeTimestamp end = new_buffers.back()->GetDecodeTimestamp();
842 base::TimeDelta duration = new_buffers.back()->duration();
844 // Set end time for remove to include the duration of last buffer. If the
845 // duration is estimated, use 1 microsecond instead to ensure frames are not
846 // accidentally removed due to over-estimation.
847 if (duration != kNoTimestamp() && duration > base::TimeDelta() &&
848 !new_buffers.back()->is_duration_estimated()) {
849 end += duration;
850 } else {
851 // TODO(chcunningham): Emit warning when 0ms durations are not expected.
852 // http://crbug.com/312836
853 end += base::TimeDelta::FromInternalValue(1);
856 RemoveInternal(start, end, exclude_start, deleted_buffers);
858 // Restore the range seek state if necessary.
859 if (temporarily_select_range)
860 SetSelectedRange(NULL);
863 bool SourceBufferStream::AreAdjacentInSequence(
864 DecodeTimestamp first_timestamp, DecodeTimestamp second_timestamp) const {
865 return first_timestamp < second_timestamp &&
866 second_timestamp <=
867 first_timestamp + ComputeFudgeRoom(GetMaxInterbufferDistance());
870 void SourceBufferStream::PruneTrackBuffer(const DecodeTimestamp timestamp) {
871 // If we don't have the next timestamp, we don't have anything to delete.
872 if (timestamp == kNoDecodeTimestamp())
873 return;
875 while (!track_buffer_.empty() &&
876 track_buffer_.back()->GetDecodeTimestamp() >= timestamp) {
877 track_buffer_.pop_back();
881 void SourceBufferStream::MergeWithAdjacentRangeIfNecessary(
882 const RangeList::iterator& range_with_new_buffers_itr) {
883 DCHECK(range_with_new_buffers_itr != ranges_.end());
885 SourceBufferRange* range_with_new_buffers = *range_with_new_buffers_itr;
886 RangeList::iterator next_range_itr = range_with_new_buffers_itr;
887 ++next_range_itr;
889 if (next_range_itr == ranges_.end() ||
890 !range_with_new_buffers->CanAppendRangeToEnd(**next_range_itr)) {
891 return;
894 bool transfer_current_position = selected_range_ == *next_range_itr;
895 DVLOG(3) << __FUNCTION__ << " " << GetStreamTypeName()
896 << " merging " << RangeToString(*range_with_new_buffers)
897 << " into " << RangeToString(**next_range_itr);
898 range_with_new_buffers->AppendRangeToEnd(**next_range_itr,
899 transfer_current_position);
900 // Update |selected_range_| pointer if |range| has become selected after
901 // merges.
902 if (transfer_current_position)
903 SetSelectedRange(range_with_new_buffers);
905 if (next_range_itr == range_for_next_append_)
906 range_for_next_append_ = range_with_new_buffers_itr;
908 DeleteAndRemoveRange(&next_range_itr);
911 void SourceBufferStream::Seek(base::TimeDelta timestamp) {
912 DCHECK(timestamp >= base::TimeDelta());
913 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
914 << " (" << timestamp.InSecondsF() << ")";
915 ResetSeekState();
917 seek_buffer_timestamp_ = timestamp;
918 seek_pending_ = true;
920 if (ShouldSeekToStartOfBuffered(timestamp)) {
921 ranges_.front()->SeekToStart();
922 SetSelectedRange(ranges_.front());
923 seek_pending_ = false;
924 return;
927 DecodeTimestamp seek_dts = DecodeTimestamp::FromPresentationTime(timestamp);
929 RangeList::iterator itr = ranges_.end();
930 for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
931 if ((*itr)->CanSeekTo(seek_dts))
932 break;
935 if (itr == ranges_.end())
936 return;
938 SeekAndSetSelectedRange(*itr, seek_dts);
939 seek_pending_ = false;
942 bool SourceBufferStream::IsSeekPending() const {
943 return seek_pending_ && !IsEndOfStreamReached();
946 void SourceBufferStream::OnSetDuration(base::TimeDelta duration) {
947 DecodeTimestamp duration_dts =
948 DecodeTimestamp::FromPresentationTime(duration);
949 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
950 << " (" << duration.InSecondsF() << ")";
952 RangeList::iterator itr = ranges_.end();
953 for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
954 if ((*itr)->GetEndTimestamp() > duration_dts)
955 break;
957 if (itr == ranges_.end())
958 return;
960 // Need to partially truncate this range.
961 if ((*itr)->GetStartTimestamp() < duration_dts) {
962 bool delete_range = (*itr)->TruncateAt(duration_dts, NULL, false);
963 if ((*itr == selected_range_) && !selected_range_->HasNextBufferPosition())
964 SetSelectedRange(NULL);
966 if (delete_range) {
967 DeleteAndRemoveRange(&itr);
968 } else {
969 ++itr;
973 // Delete all ranges that begin after |duration_dts|.
974 while (itr != ranges_.end()) {
975 // If we're about to delete the selected range, also reset the seek state.
976 DCHECK((*itr)->GetStartTimestamp() >= duration_dts);
977 if (*itr == selected_range_)
978 ResetSeekState();
979 DeleteAndRemoveRange(&itr);
983 SourceBufferStream::Status SourceBufferStream::GetNextBuffer(
984 scoped_refptr<StreamParserBuffer>* out_buffer) {
985 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName();
986 if (!pending_buffer_.get()) {
987 const SourceBufferStream::Status status = GetNextBufferInternal(out_buffer);
988 if (status != SourceBufferStream::kSuccess ||
989 !SetPendingBuffer(out_buffer)) {
990 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName()
991 << ": no pending buffer, returning status " << status;
992 return status;
996 if (!pending_buffer_->splice_buffers().empty()) {
997 const SourceBufferStream::Status status =
998 HandleNextBufferWithSplice(out_buffer);
999 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName()
1000 << ": handled next buffer with splice, returning status "
1001 << status;
1002 return status;
1005 DCHECK(pending_buffer_->preroll_buffer().get());
1007 const SourceBufferStream::Status status =
1008 HandleNextBufferWithPreroll(out_buffer);
1009 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName()
1010 << ": handled next buffer with preroll, returning status "
1011 << status;
1012 return status;
1015 SourceBufferStream::Status SourceBufferStream::HandleNextBufferWithSplice(
1016 scoped_refptr<StreamParserBuffer>* out_buffer) {
1017 const BufferQueue& splice_buffers = pending_buffer_->splice_buffers();
1018 const size_t last_splice_buffer_index = splice_buffers.size() - 1;
1020 // Are there any splice buffers left to hand out? The last buffer should be
1021 // handed out separately since it represents the first post-splice buffer.
1022 if (splice_buffers_index_ < last_splice_buffer_index) {
1023 // Account for config changes which occur between fade out buffers.
1024 if (current_config_index_ !=
1025 splice_buffers[splice_buffers_index_]->GetConfigId()) {
1026 config_change_pending_ = true;
1027 DVLOG(1) << "Config change (splice buffer config ID does not match).";
1028 return SourceBufferStream::kConfigChange;
1031 // Every pre splice buffer must have the same splice_timestamp().
1032 DCHECK(pending_buffer_->splice_timestamp() ==
1033 splice_buffers[splice_buffers_index_]->splice_timestamp());
1035 // No pre splice buffers should have preroll.
1036 DCHECK(!splice_buffers[splice_buffers_index_]->preroll_buffer().get());
1038 *out_buffer = splice_buffers[splice_buffers_index_++];
1039 return SourceBufferStream::kSuccess;
1042 // Did we hand out the last pre-splice buffer on the previous call?
1043 if (!pending_buffers_complete_) {
1044 DCHECK_EQ(splice_buffers_index_, last_splice_buffer_index);
1045 pending_buffers_complete_ = true;
1046 config_change_pending_ = true;
1047 DVLOG(1) << "Config change (forced for fade in of splice frame).";
1048 return SourceBufferStream::kConfigChange;
1051 // All pre-splice buffers have been handed out and a config change completed,
1052 // so hand out the final buffer for fade in. Because a config change is
1053 // always issued prior to handing out this buffer, any changes in config id
1054 // have been inherently handled.
1055 DCHECK(pending_buffers_complete_);
1056 DCHECK_EQ(splice_buffers_index_, splice_buffers.size() - 1);
1057 DCHECK(splice_buffers.back()->splice_timestamp() == kNoTimestamp());
1058 *out_buffer = splice_buffers.back();
1059 pending_buffer_ = NULL;
1061 // If the last splice buffer has preroll, hand off to the preroll handler.
1062 return SetPendingBuffer(out_buffer) ? HandleNextBufferWithPreroll(out_buffer)
1063 : SourceBufferStream::kSuccess;
1066 SourceBufferStream::Status SourceBufferStream::HandleNextBufferWithPreroll(
1067 scoped_refptr<StreamParserBuffer>* out_buffer) {
1068 // Any config change should have already been handled.
1069 DCHECK_EQ(current_config_index_, pending_buffer_->GetConfigId());
1071 // Check if the preroll buffer has already been handed out.
1072 if (!pending_buffers_complete_) {
1073 pending_buffers_complete_ = true;
1074 *out_buffer = pending_buffer_->preroll_buffer();
1075 return SourceBufferStream::kSuccess;
1078 // Preroll complete, hand out the final buffer.
1079 *out_buffer = pending_buffer_;
1080 pending_buffer_ = NULL;
1081 return SourceBufferStream::kSuccess;
1084 SourceBufferStream::Status SourceBufferStream::GetNextBufferInternal(
1085 scoped_refptr<StreamParserBuffer>* out_buffer) {
1086 CHECK(!config_change_pending_);
1088 if (!track_buffer_.empty()) {
1089 DCHECK(!selected_range_);
1090 scoped_refptr<StreamParserBuffer>& next_buffer = track_buffer_.front();
1092 // If the next buffer is an audio splice frame, the next effective config id
1093 // comes from the first splice buffer.
1094 if (next_buffer->GetSpliceBufferConfigId(0) != current_config_index_) {
1095 config_change_pending_ = true;
1096 DVLOG(1) << "Config change (track buffer config ID does not match).";
1097 return kConfigChange;
1100 DVLOG(3) << __FUNCTION__ << " Next buffer coming from track_buffer_";
1101 *out_buffer = next_buffer;
1102 track_buffer_.pop_front();
1103 last_output_buffer_timestamp_ = (*out_buffer)->GetDecodeTimestamp();
1105 // If the track buffer becomes empty, then try to set the selected range
1106 // based on the timestamp of this buffer being returned.
1107 if (track_buffer_.empty())
1108 SetSelectedRangeIfNeeded(last_output_buffer_timestamp_);
1110 return kSuccess;
1113 DCHECK(track_buffer_.empty());
1114 if (!selected_range_ || !selected_range_->HasNextBuffer()) {
1115 if (IsEndOfStreamReached()) {
1116 return kEndOfStream;
1118 DVLOG(3) << __FUNCTION__ << " " << GetStreamTypeName()
1119 << ": returning kNeedBuffer "
1120 << (selected_range_ ? "(selected range has no next buffer)"
1121 : "(no selected range)");
1122 return kNeedBuffer;
1125 if (selected_range_->GetNextConfigId() != current_config_index_) {
1126 config_change_pending_ = true;
1127 DVLOG(1) << "Config change (selected range config ID does not match).";
1128 return kConfigChange;
1131 CHECK(selected_range_->GetNextBuffer(out_buffer));
1132 last_output_buffer_timestamp_ = (*out_buffer)->GetDecodeTimestamp();
1133 return kSuccess;
1136 DecodeTimestamp SourceBufferStream::GetNextBufferTimestamp() {
1137 if (!track_buffer_.empty())
1138 return track_buffer_.front()->GetDecodeTimestamp();
1140 if (!selected_range_)
1141 return kNoDecodeTimestamp();
1143 DCHECK(selected_range_->HasNextBufferPosition());
1144 return selected_range_->GetNextTimestamp();
1147 SourceBufferStream::RangeList::iterator
1148 SourceBufferStream::FindExistingRangeFor(DecodeTimestamp start_timestamp) {
1149 for (RangeList::iterator itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
1150 if ((*itr)->BelongsToRange(start_timestamp))
1151 return itr;
1153 return ranges_.end();
1156 SourceBufferStream::RangeList::iterator
1157 SourceBufferStream::AddToRanges(SourceBufferRange* new_range) {
1158 DecodeTimestamp start_timestamp = new_range->GetStartTimestamp();
1159 RangeList::iterator itr = ranges_.end();
1160 for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
1161 if ((*itr)->GetStartTimestamp() > start_timestamp)
1162 break;
1164 return ranges_.insert(itr, new_range);
1167 SourceBufferStream::RangeList::iterator
1168 SourceBufferStream::GetSelectedRangeItr() {
1169 DCHECK(selected_range_);
1170 RangeList::iterator itr = ranges_.end();
1171 for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
1172 if (*itr == selected_range_)
1173 break;
1175 DCHECK(itr != ranges_.end());
1176 return itr;
1179 void SourceBufferStream::SeekAndSetSelectedRange(
1180 SourceBufferRange* range, DecodeTimestamp seek_timestamp) {
1181 if (range)
1182 range->Seek(seek_timestamp);
1183 SetSelectedRange(range);
1186 void SourceBufferStream::SetSelectedRange(SourceBufferRange* range) {
1187 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
1188 << ": " << selected_range_ << " -> " << range;
1189 if (selected_range_)
1190 selected_range_->ResetNextBufferPosition();
1191 DCHECK(!range || range->HasNextBufferPosition());
1192 selected_range_ = range;
1195 Ranges<base::TimeDelta> SourceBufferStream::GetBufferedTime() const {
1196 Ranges<base::TimeDelta> ranges;
1197 for (RangeList::const_iterator itr = ranges_.begin();
1198 itr != ranges_.end(); ++itr) {
1199 ranges.Add((*itr)->GetStartTimestamp().ToPresentationTime(),
1200 (*itr)->GetBufferedEndTimestamp().ToPresentationTime());
1202 return ranges;
1205 base::TimeDelta SourceBufferStream::GetBufferedDuration() const {
1206 if (ranges_.empty())
1207 return base::TimeDelta();
1209 return ranges_.back()->GetBufferedEndTimestamp().ToPresentationTime();
1212 void SourceBufferStream::MarkEndOfStream() {
1213 DCHECK(!end_of_stream_);
1214 end_of_stream_ = true;
1217 void SourceBufferStream::UnmarkEndOfStream() {
1218 DCHECK(end_of_stream_);
1219 end_of_stream_ = false;
1222 bool SourceBufferStream::IsEndOfStreamReached() const {
1223 if (!end_of_stream_ || !track_buffer_.empty())
1224 return false;
1226 if (ranges_.empty())
1227 return true;
1229 if (seek_pending_) {
1230 base::TimeDelta last_range_end_time =
1231 ranges_.back()->GetBufferedEndTimestamp().ToPresentationTime();
1232 return seek_buffer_timestamp_ >= last_range_end_time;
1235 if (!selected_range_)
1236 return true;
1238 return selected_range_ == ranges_.back();
1241 const AudioDecoderConfig& SourceBufferStream::GetCurrentAudioDecoderConfig() {
1242 if (config_change_pending_)
1243 CompleteConfigChange();
1244 return audio_configs_[current_config_index_];
1247 const VideoDecoderConfig& SourceBufferStream::GetCurrentVideoDecoderConfig() {
1248 if (config_change_pending_)
1249 CompleteConfigChange();
1250 return video_configs_[current_config_index_];
1253 const TextTrackConfig& SourceBufferStream::GetCurrentTextTrackConfig() {
1254 return text_track_config_;
1257 base::TimeDelta SourceBufferStream::GetMaxInterbufferDistance() const {
1258 if (max_interbuffer_distance_ == kNoTimestamp())
1259 return base::TimeDelta::FromMilliseconds(kDefaultBufferDurationInMs);
1260 return max_interbuffer_distance_;
1263 bool SourceBufferStream::UpdateAudioConfig(const AudioDecoderConfig& config) {
1264 DCHECK(!audio_configs_.empty());
1265 DCHECK(video_configs_.empty());
1266 DVLOG(3) << "UpdateAudioConfig.";
1268 if (audio_configs_[0].codec() != config.codec()) {
1269 MEDIA_LOG(ERROR, log_cb_) << "Audio codec changes not allowed.";
1270 return false;
1273 if (audio_configs_[0].is_encrypted() != config.is_encrypted()) {
1274 MEDIA_LOG(ERROR, log_cb_) << "Audio encryption changes not allowed.";
1275 return false;
1278 // Check to see if the new config matches an existing one.
1279 for (size_t i = 0; i < audio_configs_.size(); ++i) {
1280 if (config.Matches(audio_configs_[i])) {
1281 append_config_index_ = i;
1282 return true;
1286 // No matches found so let's add this one to the list.
1287 append_config_index_ = audio_configs_.size();
1288 DVLOG(2) << "New audio config - index: " << append_config_index_;
1289 audio_configs_.resize(audio_configs_.size() + 1);
1290 audio_configs_[append_config_index_] = config;
1291 return true;
1294 bool SourceBufferStream::UpdateVideoConfig(const VideoDecoderConfig& config) {
1295 DCHECK(!video_configs_.empty());
1296 DCHECK(audio_configs_.empty());
1297 DVLOG(3) << "UpdateVideoConfig.";
1299 if (video_configs_[0].codec() != config.codec()) {
1300 MEDIA_LOG(ERROR, log_cb_) << "Video codec changes not allowed.";
1301 return false;
1304 if (video_configs_[0].is_encrypted() != config.is_encrypted()) {
1305 MEDIA_LOG(ERROR, log_cb_) << "Video encryption changes not allowed.";
1306 return false;
1309 // Check to see if the new config matches an existing one.
1310 for (size_t i = 0; i < video_configs_.size(); ++i) {
1311 if (config.Matches(video_configs_[i])) {
1312 append_config_index_ = i;
1313 return true;
1317 // No matches found so let's add this one to the list.
1318 append_config_index_ = video_configs_.size();
1319 DVLOG(2) << "New video config - index: " << append_config_index_;
1320 video_configs_.resize(video_configs_.size() + 1);
1321 video_configs_[append_config_index_] = config;
1322 return true;
1325 void SourceBufferStream::CompleteConfigChange() {
1326 config_change_pending_ = false;
1328 if (pending_buffer_.get()) {
1329 current_config_index_ =
1330 pending_buffer_->GetSpliceBufferConfigId(splice_buffers_index_);
1331 return;
1334 if (!track_buffer_.empty()) {
1335 current_config_index_ = track_buffer_.front()->GetSpliceBufferConfigId(0);
1336 return;
1339 if (selected_range_ && selected_range_->HasNextBuffer())
1340 current_config_index_ = selected_range_->GetNextConfigId();
1343 void SourceBufferStream::SetSelectedRangeIfNeeded(
1344 const DecodeTimestamp timestamp) {
1345 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName()
1346 << "(" << timestamp.InSecondsF() << ")";
1348 if (selected_range_) {
1349 DCHECK(track_buffer_.empty());
1350 return;
1353 if (!track_buffer_.empty()) {
1354 DCHECK(!selected_range_);
1355 return;
1358 DecodeTimestamp start_timestamp = timestamp;
1360 // If the next buffer timestamp is not known then use a timestamp just after
1361 // the timestamp on the last buffer returned by GetNextBuffer().
1362 if (start_timestamp == kNoDecodeTimestamp()) {
1363 if (last_output_buffer_timestamp_ == kNoDecodeTimestamp()) {
1364 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName()
1365 << " no previous output timestamp";
1366 return;
1369 start_timestamp = last_output_buffer_timestamp_ +
1370 base::TimeDelta::FromInternalValue(1);
1373 DecodeTimestamp seek_timestamp =
1374 FindNewSelectedRangeSeekTimestamp(start_timestamp);
1376 // If we don't have buffered data to seek to, then return.
1377 if (seek_timestamp == kNoDecodeTimestamp()) {
1378 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName()
1379 << " couldn't find new selected range seek timestamp";
1380 return;
1383 DCHECK(track_buffer_.empty());
1384 SeekAndSetSelectedRange(*FindExistingRangeFor(seek_timestamp),
1385 seek_timestamp);
1388 DecodeTimestamp SourceBufferStream::FindNewSelectedRangeSeekTimestamp(
1389 const DecodeTimestamp start_timestamp) {
1390 DCHECK(start_timestamp != kNoDecodeTimestamp());
1391 DCHECK(start_timestamp >= DecodeTimestamp());
1393 RangeList::iterator itr = ranges_.begin();
1395 for (; itr != ranges_.end(); ++itr) {
1396 if ((*itr)->GetEndTimestamp() >= start_timestamp) {
1397 break;
1401 if (itr == ranges_.end()) {
1402 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName()
1403 << " no buffered data for dts=" << start_timestamp.InSecondsF();
1404 return kNoDecodeTimestamp();
1407 // First check for a keyframe timestamp >= |start_timestamp|
1408 // in the current range.
1409 DecodeTimestamp keyframe_timestamp =
1410 (*itr)->NextKeyframeTimestamp(start_timestamp);
1412 if (keyframe_timestamp != kNoDecodeTimestamp())
1413 return keyframe_timestamp;
1415 // If a keyframe was not found then look for a keyframe that is
1416 // "close enough" in the current or next range.
1417 DecodeTimestamp end_timestamp =
1418 start_timestamp + ComputeFudgeRoom(GetMaxInterbufferDistance());
1419 DCHECK(start_timestamp < end_timestamp);
1421 // Make sure the current range doesn't start beyond |end_timestamp|.
1422 if ((*itr)->GetStartTimestamp() >= end_timestamp)
1423 return kNoDecodeTimestamp();
1425 keyframe_timestamp = (*itr)->KeyframeBeforeTimestamp(end_timestamp);
1427 // Check to see if the keyframe is within the acceptable range
1428 // (|start_timestamp|, |end_timestamp|].
1429 if (keyframe_timestamp != kNoDecodeTimestamp() &&
1430 start_timestamp < keyframe_timestamp &&
1431 keyframe_timestamp <= end_timestamp) {
1432 return keyframe_timestamp;
1435 // If |end_timestamp| is within this range, then no other checks are
1436 // necessary.
1437 if (end_timestamp <= (*itr)->GetEndTimestamp())
1438 return kNoDecodeTimestamp();
1440 // Move on to the next range.
1441 ++itr;
1443 // Return early if the next range does not contain |end_timestamp|.
1444 if (itr == ranges_.end() || (*itr)->GetStartTimestamp() >= end_timestamp)
1445 return kNoDecodeTimestamp();
1447 keyframe_timestamp = (*itr)->KeyframeBeforeTimestamp(end_timestamp);
1449 // Check to see if the keyframe is within the acceptable range
1450 // (|start_timestamp|, |end_timestamp|].
1451 if (keyframe_timestamp != kNoDecodeTimestamp() &&
1452 start_timestamp < keyframe_timestamp &&
1453 keyframe_timestamp <= end_timestamp) {
1454 return keyframe_timestamp;
1457 return kNoDecodeTimestamp();
1460 DecodeTimestamp SourceBufferStream::FindKeyframeAfterTimestamp(
1461 const DecodeTimestamp timestamp) {
1462 DCHECK(timestamp != kNoDecodeTimestamp());
1464 RangeList::iterator itr = FindExistingRangeFor(timestamp);
1466 if (itr == ranges_.end())
1467 return kNoDecodeTimestamp();
1469 // First check for a keyframe timestamp >= |timestamp|
1470 // in the current range.
1471 return (*itr)->NextKeyframeTimestamp(timestamp);
1474 std::string SourceBufferStream::GetStreamTypeName() const {
1475 switch (GetType()) {
1476 case kAudio:
1477 return "AUDIO";
1478 case kVideo:
1479 return "VIDEO";
1480 case kText:
1481 return "TEXT";
1483 NOTREACHED();
1484 return "";
1487 SourceBufferStream::Type SourceBufferStream::GetType() const {
1488 if (!audio_configs_.empty())
1489 return kAudio;
1490 if (!video_configs_.empty())
1491 return kVideo;
1492 DCHECK_NE(text_track_config_.kind(), kTextNone);
1493 return kText;
1496 void SourceBufferStream::DeleteAndRemoveRange(RangeList::iterator* itr) {
1497 DVLOG(1) << __FUNCTION__;
1499 DCHECK(*itr != ranges_.end());
1500 if (**itr == selected_range_) {
1501 DVLOG(1) << __FUNCTION__ << " deleting selected range.";
1502 SetSelectedRange(NULL);
1505 if (*itr == range_for_next_append_) {
1506 DVLOG(1) << __FUNCTION__ << " deleting range_for_next_append_.";
1507 range_for_next_append_ = ranges_.end();
1508 last_appended_buffer_timestamp_ = kNoDecodeTimestamp();
1509 last_appended_buffer_is_keyframe_ = false;
1512 delete **itr;
1513 *itr = ranges_.erase(*itr);
1516 void SourceBufferStream::GenerateSpliceFrame(const BufferQueue& new_buffers) {
1517 DCHECK(!new_buffers.empty());
1519 // Splice frames are only supported for audio.
1520 if (GetType() != kAudio)
1521 return;
1523 // Find the overlapped range (if any).
1524 const base::TimeDelta splice_timestamp = new_buffers.front()->timestamp();
1525 const DecodeTimestamp splice_dts =
1526 DecodeTimestamp::FromPresentationTime(splice_timestamp);
1527 RangeList::iterator range_itr = FindExistingRangeFor(splice_dts);
1528 if (range_itr == ranges_.end())
1529 return;
1531 const DecodeTimestamp max_splice_end_dts =
1532 splice_dts + base::TimeDelta::FromMilliseconds(
1533 AudioSplicer::kCrossfadeDurationInMilliseconds);
1535 // Find all buffers involved before the splice point.
1536 BufferQueue pre_splice_buffers;
1537 if (!(*range_itr)->GetBuffersInRange(
1538 splice_dts, max_splice_end_dts, &pre_splice_buffers)) {
1539 return;
1542 // If there are gaps in the timeline, it's possible that we only find buffers
1543 // after the splice point but within the splice range. For simplicity, we do
1544 // not generate splice frames in this case.
1546 // We also do not want to generate splices if the first new buffer replaces an
1547 // existing buffer exactly.
1548 if (pre_splice_buffers.front()->timestamp() >= splice_timestamp)
1549 return;
1551 // If any |pre_splice_buffers| are already splices or preroll, do not generate
1552 // a splice.
1553 for (size_t i = 0; i < pre_splice_buffers.size(); ++i) {
1554 const BufferQueue& original_splice_buffers =
1555 pre_splice_buffers[i]->splice_buffers();
1556 if (!original_splice_buffers.empty()) {
1557 DVLOG(1) << "Can't generate splice: overlapped buffers contain a "
1558 "pre-existing splice.";
1559 return;
1562 if (pre_splice_buffers[i]->preroll_buffer().get()) {
1563 DVLOG(1) << "Can't generate splice: overlapped buffers contain preroll.";
1564 return;
1568 // Don't generate splice frames which represent less than a millisecond (which
1569 // is frequently the extent of timestamp resolution for poorly encoded media)
1570 // or less than two frames (need at least two to crossfade).
1571 const base::TimeDelta splice_duration =
1572 pre_splice_buffers.back()->timestamp() +
1573 pre_splice_buffers.back()->duration() - splice_timestamp;
1574 const base::TimeDelta minimum_splice_duration = std::max(
1575 base::TimeDelta::FromMilliseconds(1),
1576 base::TimeDelta::FromSecondsD(
1577 2.0 / audio_configs_[append_config_index_].samples_per_second()));
1578 if (splice_duration < minimum_splice_duration) {
1579 DVLOG(1) << "Can't generate splice: not enough samples for crossfade; have "
1580 << splice_duration.InMicroseconds() << " us, but need "
1581 << minimum_splice_duration.InMicroseconds() << " us.";
1582 return;
1585 DVLOG(1) << "Generating splice frame @ " << new_buffers.front()->timestamp()
1586 << ", splice duration: " << splice_duration.InMicroseconds()
1587 << " us";
1588 new_buffers.front()->ConvertToSpliceBuffer(pre_splice_buffers);
1591 bool SourceBufferStream::SetPendingBuffer(
1592 scoped_refptr<StreamParserBuffer>* out_buffer) {
1593 DCHECK(out_buffer->get());
1594 DCHECK(!pending_buffer_.get());
1596 const bool have_splice_buffers = !(*out_buffer)->splice_buffers().empty();
1597 const bool have_preroll_buffer = !!(*out_buffer)->preroll_buffer().get();
1599 if (!have_splice_buffers && !have_preroll_buffer)
1600 return false;
1602 DCHECK_NE(have_splice_buffers, have_preroll_buffer);
1603 splice_buffers_index_ = 0;
1604 pending_buffer_.swap(*out_buffer);
1605 pending_buffers_complete_ = false;
1606 return true;
1609 } // namespace media