[MD settings] moving attached() code
[chromium-blink-merge.git] / media / filters / source_buffer_stream.cc
blobe17a4f1c91952b64cf280a9777404e4adeec71d2
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/base/timestamp_constants.h"
16 #include "media/filters/source_buffer_platform.h"
17 #include "media/filters/source_buffer_range.h"
19 namespace media {
21 namespace {
23 // An arbitrarily-chosen number to estimate the duration of a buffer if none is
24 // set and there's not enough information to get a better estimate.
25 const int kDefaultBufferDurationInMs = 125;
27 // Limit the number of MEDIA_LOG() logs for splice buffer generation warnings
28 // and successes. Though these values are high enough to possibly exhaust the
29 // media internals event cache (along with other events), these logs are
30 // important for debugging splice generation.
31 const int kMaxSpliceGenerationWarningLogs = 50;
32 const int kMaxSpliceGenerationSuccessLogs = 20;
34 // Limit the number of MEDIA_LOG() logs for track buffer time gaps.
35 const int kMaxTrackBufferGapWarningLogs = 20;
37 // Helper method that returns true if |ranges| is sorted in increasing order,
38 // false otherwise.
39 bool IsRangeListSorted(const std::list<media::SourceBufferRange*>& ranges) {
40 DecodeTimestamp prev = kNoDecodeTimestamp();
41 for (std::list<SourceBufferRange*>::const_iterator itr =
42 ranges.begin(); itr != ranges.end(); ++itr) {
43 if (prev != kNoDecodeTimestamp() && prev >= (*itr)->GetStartTimestamp())
44 return false;
45 prev = (*itr)->GetEndTimestamp();
47 return true;
50 // Returns an estimate of how far from the beginning or end of a range a buffer
51 // can be to still be considered in the range, given the |approximate_duration|
52 // of a buffer in the stream.
53 // TODO(wolenetz): Once all stream parsers emit accurate frame durations, use
54 // logic like FrameProcessor (2*last_frame_duration + last_decode_timestamp)
55 // instead of an overall maximum interbuffer delta for range discontinuity
56 // detection, and adjust similarly for splice frame discontinuity detection.
57 // See http://crbug.com/351489 and http://crbug.com/351166.
58 base::TimeDelta ComputeFudgeRoom(base::TimeDelta approximate_duration) {
59 // Because we do not know exactly when is the next timestamp, any buffer
60 // that starts within 2x the approximate duration of a buffer is considered
61 // within this range.
62 return 2 * approximate_duration;
65 // The amount of time the beginning of the buffered data can differ from the
66 // start time in order to still be considered the start of stream.
67 base::TimeDelta kSeekToStartFudgeRoom() {
68 return base::TimeDelta::FromMilliseconds(1000);
71 // Helper method for logging, converts a range into a readable string.
72 std::string RangeToString(const SourceBufferRange& range) {
73 if (range.size_in_bytes() == 0) {
74 return "[]";
76 std::stringstream ss;
77 ss << "[" << range.GetStartTimestamp().InSecondsF()
78 << ";" << range.GetEndTimestamp().InSecondsF()
79 << "(" << range.GetBufferedEndTimestamp().InSecondsF() << ")]";
80 return ss.str();
83 // Helper method for logging, converts a set of ranges into a readable string.
84 std::string RangesToString(const SourceBufferStream::RangeList& ranges) {
85 if (ranges.empty())
86 return "<EMPTY>";
88 std::stringstream ss;
89 for (const auto* range_ptr : ranges) {
90 if (range_ptr != ranges.front())
91 ss << " ";
92 ss << RangeToString(*range_ptr);
94 return ss.str();
97 std::string BufferQueueToLogString(
98 const SourceBufferStream::BufferQueue& buffers) {
99 std::stringstream result;
100 if (buffers.front()->GetDecodeTimestamp().InMicroseconds() ==
101 buffers.front()->timestamp().InMicroseconds() &&
102 buffers.back()->GetDecodeTimestamp().InMicroseconds() ==
103 buffers.back()->timestamp().InMicroseconds()) {
104 result << "dts/pts=[" << buffers.front()->timestamp().InSecondsF() << ";"
105 << buffers.back()->timestamp().InSecondsF() << "(last frame dur="
106 << buffers.back()->duration().InSecondsF() << ")]";
107 } else {
108 result << "dts=[" << buffers.front()->GetDecodeTimestamp().InSecondsF()
109 << ";" << buffers.back()->GetDecodeTimestamp().InSecondsF()
110 << "] pts=[" << buffers.front()->timestamp().InSecondsF() << ";"
111 << buffers.back()->timestamp().InSecondsF() << "(last frame dur="
112 << buffers.back()->duration().InSecondsF() << ")]";
114 return result.str();
117 SourceBufferRange::GapPolicy TypeToGapPolicy(SourceBufferStream::Type type) {
118 switch (type) {
119 case SourceBufferStream::kAudio:
120 case SourceBufferStream::kVideo:
121 return SourceBufferRange::NO_GAPS_ALLOWED;
122 case SourceBufferStream::kText:
123 return SourceBufferRange::ALLOW_GAPS;
126 NOTREACHED();
127 return SourceBufferRange::NO_GAPS_ALLOWED;
130 } // namespace
132 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config,
133 const scoped_refptr<MediaLog>& media_log,
134 bool splice_frames_enabled)
135 : media_log_(media_log),
136 seek_buffer_timestamp_(kNoTimestamp()),
137 media_segment_start_time_(kNoDecodeTimestamp()),
138 range_for_next_append_(ranges_.end()),
139 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
140 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
141 max_interbuffer_distance_(kNoTimestamp()),
142 memory_limit_(kSourceBufferAudioMemoryLimit),
143 splice_frames_enabled_(splice_frames_enabled) {
144 DCHECK(audio_config.IsValidConfig());
145 audio_configs_.push_back(audio_config);
148 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config,
149 const scoped_refptr<MediaLog>& media_log,
150 bool splice_frames_enabled)
151 : media_log_(media_log),
152 seek_buffer_timestamp_(kNoTimestamp()),
153 media_segment_start_time_(kNoDecodeTimestamp()),
154 range_for_next_append_(ranges_.end()),
155 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
156 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
157 max_interbuffer_distance_(kNoTimestamp()),
158 memory_limit_(kSourceBufferVideoMemoryLimit),
159 splice_frames_enabled_(splice_frames_enabled) {
160 DCHECK(video_config.IsValidConfig());
161 video_configs_.push_back(video_config);
164 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config,
165 const scoped_refptr<MediaLog>& media_log,
166 bool splice_frames_enabled)
167 : media_log_(media_log),
168 text_track_config_(text_config),
169 seek_buffer_timestamp_(kNoTimestamp()),
170 media_segment_start_time_(kNoDecodeTimestamp()),
171 range_for_next_append_(ranges_.end()),
172 last_appended_buffer_timestamp_(kNoDecodeTimestamp()),
173 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
174 max_interbuffer_distance_(kNoTimestamp()),
175 memory_limit_(kSourceBufferAudioMemoryLimit),
176 splice_frames_enabled_(splice_frames_enabled) {}
178 SourceBufferStream::~SourceBufferStream() {
179 while (!ranges_.empty()) {
180 delete ranges_.front();
181 ranges_.pop_front();
185 void SourceBufferStream::OnNewMediaSegment(
186 DecodeTimestamp media_segment_start_time) {
187 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
188 << " (" << media_segment_start_time.InSecondsF() << ")";
189 DCHECK(!end_of_stream_);
190 media_segment_start_time_ = media_segment_start_time;
191 new_media_segment_ = true;
193 RangeList::iterator last_range = range_for_next_append_;
194 range_for_next_append_ = FindExistingRangeFor(media_segment_start_time);
196 // Only reset |last_appended_buffer_timestamp_| if this new media segment is
197 // not adjacent to the previous media segment appended to the stream.
198 if (range_for_next_append_ == ranges_.end() ||
199 !AreAdjacentInSequence(last_appended_buffer_timestamp_,
200 media_segment_start_time)) {
201 last_appended_buffer_timestamp_ = kNoDecodeTimestamp();
202 last_appended_buffer_is_keyframe_ = false;
203 DVLOG(3) << __FUNCTION__ << " next appended buffers will be in a new range";
204 } else if (last_range != ranges_.end()) {
205 DCHECK(last_range == range_for_next_append_);
206 DVLOG(3) << __FUNCTION__ << " next appended buffers will continue range "
207 << "unless intervening remove makes discontinuity";
211 bool SourceBufferStream::Append(const BufferQueue& buffers) {
212 TRACE_EVENT2("media", "SourceBufferStream::Append",
213 "stream type", GetStreamTypeName(),
214 "buffers to append", buffers.size());
216 DCHECK(!buffers.empty());
217 DCHECK(media_segment_start_time_ != kNoDecodeTimestamp());
218 DCHECK(media_segment_start_time_ <= buffers.front()->GetDecodeTimestamp());
219 DCHECK(!end_of_stream_);
221 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
222 << ": buffers " << BufferQueueToLogString(buffers);
224 // New media segments must begin with a keyframe.
225 // TODO(wolenetz): Relax this requirement. See http://crbug.com/229412.
226 if (new_media_segment_ && !buffers.front()->is_key_frame()) {
227 MEDIA_LOG(ERROR, media_log_) << "Media segment did not begin with key "
228 "frame. Support for such segments will be "
229 "available in a future version. Please see "
230 "https://crbug.com/229412.";
231 return false;
234 // Buffers within a media segment should be monotonically increasing.
235 if (!IsMonotonicallyIncreasing(buffers))
236 return false;
238 if (media_segment_start_time_ < DecodeTimestamp() ||
239 buffers.front()->GetDecodeTimestamp() < DecodeTimestamp()) {
240 MEDIA_LOG(ERROR, media_log_)
241 << "Cannot append a media segment with negative timestamps.";
242 return false;
245 if (!IsNextTimestampValid(buffers.front()->GetDecodeTimestamp(),
246 buffers.front()->is_key_frame())) {
247 const DecodeTimestamp& dts = buffers.front()->GetDecodeTimestamp();
248 MEDIA_LOG(ERROR, media_log_)
249 << "Invalid same timestamp construct detected at"
250 << " time " << dts.InSecondsF();
252 return false;
255 UpdateMaxInterbufferDistance(buffers);
256 SetConfigIds(buffers);
258 // Save a snapshot of stream state before range modifications are made.
259 DecodeTimestamp next_buffer_timestamp = GetNextBufferTimestamp();
260 BufferQueue deleted_buffers;
262 PrepareRangesForNextAppend(buffers, &deleted_buffers);
264 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise,
265 // create a new range with |buffers|.
266 if (range_for_next_append_ != ranges_.end()) {
267 (*range_for_next_append_)->AppendBuffersToEnd(buffers);
268 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp();
269 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame();
270 } else {
271 DecodeTimestamp new_range_start_time = std::min(
272 media_segment_start_time_, buffers.front()->GetDecodeTimestamp());
273 const BufferQueue* buffers_for_new_range = &buffers;
274 BufferQueue trimmed_buffers;
276 // If the new range is not being created because of a new media
277 // segment, then we must make sure that we start with a key frame.
278 // This can happen if the GOP in the previous append gets destroyed
279 // by a Remove() call.
280 if (!new_media_segment_) {
281 BufferQueue::const_iterator itr = buffers.begin();
283 // Scan past all the non-key-frames.
284 while (itr != buffers.end() && !(*itr)->is_key_frame()) {
285 ++itr;
288 // If we didn't find a key frame, then update the last appended
289 // buffer state and return.
290 if (itr == buffers.end()) {
291 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp();
292 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame();
293 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
294 << ": new buffers in the middle of media segment depend on"
295 "keyframe that has been removed, and contain no keyframes."
296 "Skipping further processing.";
297 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
298 << ": done. ranges_=" << RangesToString(ranges_);
299 return true;
300 } else if (itr != buffers.begin()) {
301 // Copy the first key frame and everything after it into
302 // |trimmed_buffers|.
303 trimmed_buffers.assign(itr, buffers.end());
304 buffers_for_new_range = &trimmed_buffers;
307 new_range_start_time =
308 buffers_for_new_range->front()->GetDecodeTimestamp();
311 range_for_next_append_ =
312 AddToRanges(new SourceBufferRange(
313 TypeToGapPolicy(GetType()),
314 *buffers_for_new_range, new_range_start_time,
315 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance,
316 base::Unretained(this))));
317 last_appended_buffer_timestamp_ =
318 buffers_for_new_range->back()->GetDecodeTimestamp();
319 last_appended_buffer_is_keyframe_ =
320 buffers_for_new_range->back()->is_key_frame();
323 new_media_segment_ = false;
325 MergeWithAdjacentRangeIfNecessary(range_for_next_append_);
327 // Seek to try to fulfill a previous call to Seek().
328 if (seek_pending_) {
329 DCHECK(!selected_range_);
330 DCHECK(deleted_buffers.empty());
331 Seek(seek_buffer_timestamp_);
334 if (!deleted_buffers.empty()) {
335 DecodeTimestamp start_of_deleted =
336 deleted_buffers.front()->GetDecodeTimestamp();
338 DCHECK(track_buffer_.empty() ||
339 track_buffer_.back()->GetDecodeTimestamp() < start_of_deleted)
340 << "decode timestamp "
341 << track_buffer_.back()->GetDecodeTimestamp().InSecondsF() << " sec"
342 << ", start_of_deleted " << start_of_deleted.InSecondsF()<< " sec";
344 track_buffer_.insert(track_buffer_.end(), deleted_buffers.begin(),
345 deleted_buffers.end());
346 DVLOG(3) << __FUNCTION__ << " " << GetStreamTypeName() << " Added "
347 << deleted_buffers.size()
348 << " buffers to track buffer. TB size is now "
349 << track_buffer_.size();
350 } else {
351 DVLOG(3) << __FUNCTION__ << " " << GetStreamTypeName()
352 << " No deleted buffers for track buffer";
355 // Prune any extra buffers in |track_buffer_| if new keyframes
356 // are appended to the range covered by |track_buffer_|.
357 if (!track_buffer_.empty()) {
358 DecodeTimestamp keyframe_timestamp =
359 FindKeyframeAfterTimestamp(track_buffer_.front()->GetDecodeTimestamp());
360 if (keyframe_timestamp != kNoDecodeTimestamp())
361 PruneTrackBuffer(keyframe_timestamp);
364 SetSelectedRangeIfNeeded(next_buffer_timestamp);
366 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
367 << ": done. ranges_=" << RangesToString(ranges_);
368 DCHECK(IsRangeListSorted(ranges_));
369 DCHECK(OnlySelectedRangeIsSeeked());
370 return true;
373 void SourceBufferStream::Remove(base::TimeDelta start, base::TimeDelta end,
374 base::TimeDelta duration) {
375 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
376 << " (" << start.InSecondsF() << ", " << end.InSecondsF()
377 << ", " << duration.InSecondsF() << ")";
378 DCHECK(start >= base::TimeDelta()) << start.InSecondsF();
379 DCHECK(start < end) << "start " << start.InSecondsF()
380 << " end " << end.InSecondsF();
381 DCHECK(duration != kNoTimestamp());
383 DecodeTimestamp start_dts = DecodeTimestamp::FromPresentationTime(start);
384 DecodeTimestamp end_dts = DecodeTimestamp::FromPresentationTime(end);
385 DecodeTimestamp remove_end_timestamp =
386 DecodeTimestamp::FromPresentationTime(duration);
387 DecodeTimestamp keyframe_timestamp = FindKeyframeAfterTimestamp(end_dts);
388 if (keyframe_timestamp != kNoDecodeTimestamp()) {
389 remove_end_timestamp = keyframe_timestamp;
390 } else if (end_dts < remove_end_timestamp) {
391 remove_end_timestamp = end_dts;
394 BufferQueue deleted_buffers;
395 RemoveInternal(start_dts, remove_end_timestamp, false, &deleted_buffers);
397 if (!deleted_buffers.empty()) {
398 // Buffers for the current position have been removed.
399 SetSelectedRangeIfNeeded(deleted_buffers.front()->GetDecodeTimestamp());
400 if (last_output_buffer_timestamp_ == kNoDecodeTimestamp()) {
401 // We just removed buffers for the current playback position for this
402 // stream, yet we also had output no buffer since the last Seek.
403 // Re-seek to prevent stall.
404 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
405 << ": re-seeking to " << seek_buffer_timestamp_
406 << " to prevent stall if this time becomes buffered again";
407 Seek(seek_buffer_timestamp_);
412 void SourceBufferStream::RemoveInternal(DecodeTimestamp start,
413 DecodeTimestamp end,
414 bool exclude_start,
415 BufferQueue* deleted_buffers) {
416 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName() << " ("
417 << start.InSecondsF() << ", " << end.InSecondsF() << ", "
418 << exclude_start << ")";
419 DVLOG(3) << __FUNCTION__ << " " << GetStreamTypeName()
420 << ": before remove ranges_=" << RangesToString(ranges_);
422 DCHECK(start >= DecodeTimestamp());
423 DCHECK(start < end) << "start " << start.InSecondsF()
424 << " end " << end.InSecondsF();
425 DCHECK(deleted_buffers);
427 RangeList::iterator itr = ranges_.begin();
429 while (itr != ranges_.end()) {
430 SourceBufferRange* range = *itr;
431 if (range->GetStartTimestamp() >= end)
432 break;
434 // Split off any remaining GOPs starting at or after |end| and add it to
435 // |ranges_|.
436 SourceBufferRange* new_range = range->SplitRange(end);
437 if (new_range) {
438 itr = ranges_.insert(++itr, new_range);
439 --itr;
441 // Update the selected range if the next buffer position was transferred
442 // to |new_range|.
443 if (new_range->HasNextBufferPosition())
444 SetSelectedRange(new_range);
447 // Truncate the current range so that it only contains data before
448 // the removal range.
449 BufferQueue saved_buffers;
450 bool delete_range = range->TruncateAt(start, &saved_buffers, exclude_start);
452 // Check to see if the current playback position was removed and
453 // update the selected range appropriately.
454 if (!saved_buffers.empty()) {
455 DCHECK(!range->HasNextBufferPosition());
456 DCHECK(deleted_buffers->empty());
458 *deleted_buffers = saved_buffers;
461 if (range == selected_range_ && !range->HasNextBufferPosition())
462 SetSelectedRange(NULL);
464 // If the current range now is completely covered by the removal
465 // range then delete it and move on.
466 if (delete_range) {
467 DeleteAndRemoveRange(&itr);
468 continue;
471 // Clear |range_for_next_append_| if we determine that the removal
472 // operation makes it impossible for the next append to be added
473 // to the current range.
474 if (range_for_next_append_ != ranges_.end() &&
475 *range_for_next_append_ == range &&
476 last_appended_buffer_timestamp_ != kNoDecodeTimestamp()) {
477 DecodeTimestamp potential_next_append_timestamp =
478 last_appended_buffer_timestamp_ +
479 base::TimeDelta::FromInternalValue(1);
481 if (!range->BelongsToRange(potential_next_append_timestamp)) {
482 DVLOG(1) << "Resetting range_for_next_append_ since the next append"
483 << " can't add to the current range.";
484 range_for_next_append_ =
485 FindExistingRangeFor(potential_next_append_timestamp);
489 // Move on to the next range.
490 ++itr;
493 DVLOG(3) << __FUNCTION__ << " " << GetStreamTypeName()
494 << ": after remove ranges_=" << RangesToString(ranges_);
496 DCHECK(IsRangeListSorted(ranges_));
497 DCHECK(OnlySelectedRangeIsSeeked());
500 void SourceBufferStream::ResetSeekState() {
501 SetSelectedRange(NULL);
502 track_buffer_.clear();
503 config_change_pending_ = false;
504 last_output_buffer_timestamp_ = kNoDecodeTimestamp();
505 just_exhausted_track_buffer_ = false;
506 splice_buffers_index_ = 0;
507 pending_buffer_ = NULL;
508 pending_buffers_complete_ = false;
511 bool SourceBufferStream::ShouldSeekToStartOfBuffered(
512 base::TimeDelta seek_timestamp) const {
513 if (ranges_.empty())
514 return false;
515 base::TimeDelta beginning_of_buffered =
516 ranges_.front()->GetStartTimestamp().ToPresentationTime();
517 return (seek_timestamp <= beginning_of_buffered &&
518 beginning_of_buffered < kSeekToStartFudgeRoom());
521 bool SourceBufferStream::IsMonotonicallyIncreasing(
522 const BufferQueue& buffers) const {
523 DCHECK(!buffers.empty());
524 DecodeTimestamp prev_timestamp = last_appended_buffer_timestamp_;
525 bool prev_is_keyframe = last_appended_buffer_is_keyframe_;
526 for (BufferQueue::const_iterator itr = buffers.begin();
527 itr != buffers.end(); ++itr) {
528 DecodeTimestamp current_timestamp = (*itr)->GetDecodeTimestamp();
529 bool current_is_keyframe = (*itr)->is_key_frame();
530 DCHECK(current_timestamp != kNoDecodeTimestamp());
531 DCHECK((*itr)->duration() >= base::TimeDelta())
532 << "Packet with invalid duration."
533 << " pts " << (*itr)->timestamp().InSecondsF()
534 << " dts " << (*itr)->GetDecodeTimestamp().InSecondsF()
535 << " dur " << (*itr)->duration().InSecondsF();
537 if (prev_timestamp != kNoDecodeTimestamp()) {
538 if (current_timestamp < prev_timestamp) {
539 MEDIA_LOG(ERROR, media_log_)
540 << "Buffers did not monotonically increase.";
541 return false;
544 if (current_timestamp == prev_timestamp &&
545 !SourceBufferRange::AllowSameTimestamp(prev_is_keyframe,
546 current_is_keyframe)) {
547 MEDIA_LOG(ERROR, media_log_) << "Unexpected combination of buffers with"
548 << " the same timestamp detected at "
549 << current_timestamp.InSecondsF();
550 return false;
554 prev_timestamp = current_timestamp;
555 prev_is_keyframe = current_is_keyframe;
557 return true;
560 bool SourceBufferStream::IsNextTimestampValid(
561 DecodeTimestamp next_timestamp, bool next_is_keyframe) const {
562 return (last_appended_buffer_timestamp_ != next_timestamp) ||
563 new_media_segment_ ||
564 SourceBufferRange::AllowSameTimestamp(last_appended_buffer_is_keyframe_,
565 next_is_keyframe);
569 bool SourceBufferStream::OnlySelectedRangeIsSeeked() const {
570 for (RangeList::const_iterator itr = ranges_.begin();
571 itr != ranges_.end(); ++itr) {
572 if ((*itr)->HasNextBufferPosition() && (*itr) != selected_range_)
573 return false;
575 return !selected_range_ || selected_range_->HasNextBufferPosition();
578 void SourceBufferStream::UpdateMaxInterbufferDistance(
579 const BufferQueue& buffers) {
580 DCHECK(!buffers.empty());
581 DecodeTimestamp prev_timestamp = last_appended_buffer_timestamp_;
582 for (BufferQueue::const_iterator itr = buffers.begin();
583 itr != buffers.end(); ++itr) {
584 DecodeTimestamp current_timestamp = (*itr)->GetDecodeTimestamp();
585 DCHECK(current_timestamp != kNoDecodeTimestamp());
587 base::TimeDelta interbuffer_distance = (*itr)->duration();
588 DCHECK(interbuffer_distance >= base::TimeDelta());
590 if (prev_timestamp != kNoDecodeTimestamp()) {
591 interbuffer_distance =
592 std::max(current_timestamp - prev_timestamp, interbuffer_distance);
595 if (interbuffer_distance > base::TimeDelta()) {
596 if (max_interbuffer_distance_ == kNoTimestamp()) {
597 max_interbuffer_distance_ = interbuffer_distance;
598 } else {
599 max_interbuffer_distance_ =
600 std::max(max_interbuffer_distance_, interbuffer_distance);
603 prev_timestamp = current_timestamp;
607 void SourceBufferStream::SetConfigIds(const BufferQueue& buffers) {
608 for (BufferQueue::const_iterator itr = buffers.begin();
609 itr != buffers.end(); ++itr) {
610 (*itr)->SetConfigId(append_config_index_);
614 bool SourceBufferStream::GarbageCollectIfNeeded(DecodeTimestamp media_time,
615 size_t newDataSize) {
616 DCHECK(media_time != kNoDecodeTimestamp());
617 // Compute size of |ranges_|.
618 size_t ranges_size = GetBufferedSize();
620 // Sanity and overflow checks
621 if ((newDataSize > memory_limit_) ||
622 (ranges_size + newDataSize < ranges_size))
623 return false;
625 // Return if we're under or at the memory limit.
626 if (ranges_size + newDataSize <= memory_limit_)
627 return true;
629 size_t bytes_to_free = ranges_size + newDataSize - memory_limit_;
631 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName() << ": Before GC"
632 << " media_time=" << media_time.InSecondsF()
633 << " ranges_=" << RangesToString(ranges_)
634 << " ranges_size=" << ranges_size
635 << " newDataSize=" << newDataSize
636 << " memory_limit_=" << memory_limit_
637 << " last_appended_buffer_timestamp_="
638 << last_appended_buffer_timestamp_.InSecondsF();
640 size_t bytes_freed = 0;
642 // If last appended buffer position was earlier than the current playback time
643 // then try deleting data between last append and current media_time.
644 if (last_appended_buffer_timestamp_ != kNoDecodeTimestamp() &&
645 last_appended_buffer_timestamp_ < media_time) {
646 size_t between = FreeBuffersAfterLastAppended(bytes_to_free, media_time);
647 DVLOG(3) << __FUNCTION__ << " FreeBuffersAfterLastAppended "
648 << " released " << between << " bytes"
649 << " ranges_=" << RangesToString(ranges_);
650 bytes_freed += between;
652 // If the last append happened before the current playback position
653 // |media_time|, then JS player is probably preparing to seek back and we
654 // should try to preserve all most recently appended data (which is in
655 // range_for_next_append_) from being removed by GC (see crbug.com/440173)
656 if (range_for_next_append_ != ranges_.end()) {
657 DCHECK((*range_for_next_append_)->GetStartTimestamp() <= media_time);
658 media_time = (*range_for_next_append_)->GetStartTimestamp();
662 // Try removing data from the front of the SourceBuffer up to |media_time|
663 // position.
664 if (bytes_freed < bytes_to_free) {
665 size_t front = FreeBuffers(bytes_to_free - bytes_freed, media_time, false);
666 DVLOG(3) << __FUNCTION__ << " Removed " << front << " bytes from the front"
667 << " ranges_=" << RangesToString(ranges_);
668 bytes_freed += front;
671 // Try removing data from the back of the SourceBuffer, until we reach the
672 // most recent append position.
673 if (bytes_freed < bytes_to_free) {
674 size_t back = FreeBuffers(bytes_to_free - bytes_freed, media_time, true);
675 DVLOG(3) << __FUNCTION__ << " Removed " << back << " bytes from the back"
676 << " ranges_=" << RangesToString(ranges_);
677 bytes_freed += back;
680 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName() << ": After GC"
681 << " bytes_to_free=" << bytes_to_free
682 << " bytes_freed=" << bytes_freed
683 << " ranges_=" << RangesToString(ranges_);
685 return bytes_freed >= bytes_to_free;
688 size_t SourceBufferStream::FreeBuffersAfterLastAppended(
689 size_t total_bytes_to_free, DecodeTimestamp media_time) {
690 DVLOG(4) << __FUNCTION__ << " last_appended_buffer_timestamp_="
691 << last_appended_buffer_timestamp_.InSecondsF()
692 << " media_time=" << media_time.InSecondsF();
694 DecodeTimestamp remove_range_start = last_appended_buffer_timestamp_;
695 if (last_appended_buffer_is_keyframe_)
696 remove_range_start += GetMaxInterbufferDistance();
698 DecodeTimestamp remove_range_start_keyframe = FindKeyframeAfterTimestamp(
699 remove_range_start);
700 if (remove_range_start_keyframe != kNoDecodeTimestamp())
701 remove_range_start = remove_range_start_keyframe;
702 if (remove_range_start >= media_time)
703 return 0;
705 DecodeTimestamp remove_range_end;
706 size_t bytes_freed = GetRemovalRange(remove_range_start,
707 media_time,
708 total_bytes_to_free,
709 &remove_range_end);
710 if (bytes_freed > 0) {
711 DVLOG(4) << __FUNCTION__ << " removing ["
712 << remove_range_start.ToPresentationTime().InSecondsF() << ";"
713 << remove_range_end.ToPresentationTime().InSecondsF() << "]";
714 Remove(remove_range_start.ToPresentationTime(),
715 remove_range_end.ToPresentationTime(),
716 media_time.ToPresentationTime());
719 return bytes_freed;
722 size_t SourceBufferStream::GetRemovalRange(
723 DecodeTimestamp start_timestamp, DecodeTimestamp end_timestamp,
724 size_t total_bytes_to_free, DecodeTimestamp* removal_end_timestamp) {
725 DCHECK(start_timestamp >= DecodeTimestamp()) << start_timestamp.InSecondsF();
726 DCHECK(start_timestamp < end_timestamp)
727 << "start " << start_timestamp.InSecondsF()
728 << ", end " << end_timestamp.InSecondsF();
730 size_t bytes_freed = 0;
732 for (RangeList::iterator itr = ranges_.begin();
733 itr != ranges_.end() && bytes_freed < total_bytes_to_free; ++itr) {
734 SourceBufferRange* range = *itr;
735 if (range->GetStartTimestamp() >= end_timestamp)
736 break;
737 if (range->GetEndTimestamp() < start_timestamp)
738 continue;
740 size_t bytes_to_free = total_bytes_to_free - bytes_freed;
741 size_t bytes_removed = range->GetRemovalGOP(
742 start_timestamp, end_timestamp, bytes_to_free, removal_end_timestamp);
743 bytes_freed += bytes_removed;
745 return bytes_freed;
748 size_t SourceBufferStream::FreeBuffers(size_t total_bytes_to_free,
749 DecodeTimestamp media_time,
750 bool reverse_direction) {
751 TRACE_EVENT2("media", "SourceBufferStream::FreeBuffers",
752 "total bytes to free", total_bytes_to_free,
753 "reverse direction", reverse_direction);
755 DCHECK_GT(total_bytes_to_free, 0u);
756 size_t bytes_freed = 0;
758 // This range will save the last GOP appended to |range_for_next_append_|
759 // if the buffers surrounding it get deleted during garbage collection.
760 SourceBufferRange* new_range_for_append = NULL;
762 while (!ranges_.empty() && bytes_freed < total_bytes_to_free) {
763 SourceBufferRange* current_range = NULL;
764 BufferQueue buffers;
765 size_t bytes_deleted = 0;
767 if (reverse_direction) {
768 current_range = ranges_.back();
769 DVLOG(5) << "current_range=" << RangeToString(*current_range);
770 if (current_range->LastGOPContainsNextBufferPosition()) {
771 DCHECK_EQ(current_range, selected_range_);
772 DVLOG(5) << "current_range contains next read position, stopping GC";
773 break;
775 DVLOG(5) << "Deleting GOP from back: " << RangeToString(*current_range);
776 bytes_deleted = current_range->DeleteGOPFromBack(&buffers);
777 } else {
778 current_range = ranges_.front();
779 DVLOG(5) << "current_range=" << RangeToString(*current_range);
780 if (!current_range->FirstGOPEarlierThanMediaTime(media_time)) {
781 // We have removed all data up to the GOP that contains current playback
782 // position, we can't delete any further.
783 DVLOG(5) << "current_range contains playback position, stopping GC";
784 break;
786 DVLOG(4) << "Deleting GOP from front: " << RangeToString(*current_range);
787 bytes_deleted = current_range->DeleteGOPFromFront(&buffers);
790 // Check to see if we've just deleted the GOP that was last appended.
791 DecodeTimestamp end_timestamp = buffers.back()->GetDecodeTimestamp();
792 if (end_timestamp == last_appended_buffer_timestamp_) {
793 DCHECK(last_appended_buffer_timestamp_ != kNoDecodeTimestamp());
794 DCHECK(!new_range_for_append);
796 // Create a new range containing these buffers.
797 new_range_for_append = new SourceBufferRange(
798 TypeToGapPolicy(GetType()),
799 buffers, kNoDecodeTimestamp(),
800 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance,
801 base::Unretained(this)));
802 range_for_next_append_ = ranges_.end();
803 } else {
804 bytes_freed += bytes_deleted;
807 if (current_range->size_in_bytes() == 0) {
808 DCHECK_NE(current_range, selected_range_);
809 DCHECK(range_for_next_append_ == ranges_.end() ||
810 *range_for_next_append_ != current_range);
811 delete current_range;
812 reverse_direction ? ranges_.pop_back() : ranges_.pop_front();
815 if (reverse_direction && new_range_for_append) {
816 // We don't want to delete any further, or we'll be creating gaps
817 break;
821 // Insert |new_range_for_append| into |ranges_|, if applicable.
822 if (new_range_for_append) {
823 range_for_next_append_ = AddToRanges(new_range_for_append);
824 DCHECK(range_for_next_append_ != ranges_.end());
826 // Check to see if we need to merge |new_range_for_append| with the range
827 // before or after it. |new_range_for_append| is created whenever the last
828 // GOP appended is encountered, regardless of whether any buffers after it
829 // are ultimately deleted. Merging is necessary if there were no buffers
830 // (or very few buffers) deleted after creating |new_range_for_append|.
831 if (range_for_next_append_ != ranges_.begin()) {
832 RangeList::iterator range_before_next = range_for_next_append_;
833 --range_before_next;
834 MergeWithAdjacentRangeIfNecessary(range_before_next);
836 MergeWithAdjacentRangeIfNecessary(range_for_next_append_);
838 return bytes_freed;
841 void SourceBufferStream::PrepareRangesForNextAppend(
842 const BufferQueue& new_buffers, BufferQueue* deleted_buffers) {
843 DCHECK(deleted_buffers);
845 bool temporarily_select_range = false;
846 if (!track_buffer_.empty()) {
847 DecodeTimestamp tb_timestamp = track_buffer_.back()->GetDecodeTimestamp();
848 DecodeTimestamp seek_timestamp = FindKeyframeAfterTimestamp(tb_timestamp);
849 if (seek_timestamp != kNoDecodeTimestamp() &&
850 seek_timestamp < new_buffers.front()->GetDecodeTimestamp() &&
851 range_for_next_append_ != ranges_.end() &&
852 (*range_for_next_append_)->BelongsToRange(seek_timestamp)) {
853 DCHECK(tb_timestamp < seek_timestamp);
854 DCHECK(!selected_range_);
855 DCHECK(!(*range_for_next_append_)->HasNextBufferPosition());
857 // If there are GOPs between the end of the track buffer and the
858 // beginning of the new buffers, then temporarily seek the range
859 // so that the buffers between these two times will be deposited in
860 // |deleted_buffers| as if they were part of the current playback
861 // position.
862 // TODO(acolwell): Figure out a more elegant way to do this.
863 SeekAndSetSelectedRange(*range_for_next_append_, seek_timestamp);
864 temporarily_select_range = true;
868 // Handle splices between the existing buffers and the new buffers. If a
869 // splice is generated the timestamp and duration of the first buffer in
870 // |new_buffers| will be modified.
871 if (splice_frames_enabled_)
872 GenerateSpliceFrame(new_buffers);
874 DecodeTimestamp prev_timestamp = last_appended_buffer_timestamp_;
875 bool prev_is_keyframe = last_appended_buffer_is_keyframe_;
876 DecodeTimestamp next_timestamp = new_buffers.front()->GetDecodeTimestamp();
877 bool next_is_keyframe = new_buffers.front()->is_key_frame();
879 if (prev_timestamp != kNoDecodeTimestamp() &&
880 prev_timestamp != next_timestamp) {
881 // Clean up the old buffers between the last appended buffer and the
882 // beginning of |new_buffers|.
883 RemoveInternal(prev_timestamp, next_timestamp, true, deleted_buffers);
886 // Make the delete range exclusive if we are dealing with an allowed same
887 // timestamp situation. This prevents the first buffer in the current append
888 // from deleting the last buffer in the previous append if both buffers
889 // have the same timestamp.
891 // The delete range should never be exclusive if a splice frame was generated
892 // because we don't generate splice frames for same timestamp situations.
893 DCHECK(new_buffers.front()->splice_timestamp() !=
894 new_buffers.front()->timestamp());
895 const bool exclude_start =
896 new_buffers.front()->splice_buffers().empty() &&
897 prev_timestamp == next_timestamp &&
898 SourceBufferRange::AllowSameTimestamp(prev_is_keyframe, next_is_keyframe);
900 // Delete the buffers that |new_buffers| overlaps.
901 DecodeTimestamp start = new_buffers.front()->GetDecodeTimestamp();
902 DecodeTimestamp end = new_buffers.back()->GetDecodeTimestamp();
903 base::TimeDelta duration = new_buffers.back()->duration();
905 // Set end time for remove to include the duration of last buffer. If the
906 // duration is estimated, use 1 microsecond instead to ensure frames are not
907 // accidentally removed due to over-estimation.
908 if (duration != kNoTimestamp() && duration > base::TimeDelta() &&
909 !new_buffers.back()->is_duration_estimated()) {
910 end += duration;
911 } else {
912 // TODO(chcunningham): Emit warning when 0ms durations are not expected.
913 // http://crbug.com/312836
914 end += base::TimeDelta::FromInternalValue(1);
917 RemoveInternal(start, end, exclude_start, deleted_buffers);
919 // Restore the range seek state if necessary.
920 if (temporarily_select_range)
921 SetSelectedRange(NULL);
924 bool SourceBufferStream::AreAdjacentInSequence(
925 DecodeTimestamp first_timestamp, DecodeTimestamp second_timestamp) const {
926 return first_timestamp < second_timestamp &&
927 second_timestamp <=
928 first_timestamp + ComputeFudgeRoom(GetMaxInterbufferDistance());
931 void SourceBufferStream::PruneTrackBuffer(const DecodeTimestamp timestamp) {
932 // If we don't have the next timestamp, we don't have anything to delete.
933 if (timestamp == kNoDecodeTimestamp())
934 return;
936 while (!track_buffer_.empty() &&
937 track_buffer_.back()->GetDecodeTimestamp() >= timestamp) {
938 track_buffer_.pop_back();
940 DVLOG(3) << __FUNCTION__ << " " << GetStreamTypeName()
941 << " Removed all buffers with DTS >= " << timestamp.InSecondsF()
942 << ". New track buffer size:" << track_buffer_.size();
945 void SourceBufferStream::MergeWithAdjacentRangeIfNecessary(
946 const RangeList::iterator& range_with_new_buffers_itr) {
947 DCHECK(range_with_new_buffers_itr != ranges_.end());
949 SourceBufferRange* range_with_new_buffers = *range_with_new_buffers_itr;
950 RangeList::iterator next_range_itr = range_with_new_buffers_itr;
951 ++next_range_itr;
953 if (next_range_itr == ranges_.end() ||
954 !range_with_new_buffers->CanAppendRangeToEnd(**next_range_itr)) {
955 return;
958 bool transfer_current_position = selected_range_ == *next_range_itr;
959 DVLOG(3) << __FUNCTION__ << " " << GetStreamTypeName()
960 << " merging " << RangeToString(*range_with_new_buffers)
961 << " into " << RangeToString(**next_range_itr);
962 range_with_new_buffers->AppendRangeToEnd(**next_range_itr,
963 transfer_current_position);
964 // Update |selected_range_| pointer if |range| has become selected after
965 // merges.
966 if (transfer_current_position)
967 SetSelectedRange(range_with_new_buffers);
969 if (next_range_itr == range_for_next_append_)
970 range_for_next_append_ = range_with_new_buffers_itr;
972 DeleteAndRemoveRange(&next_range_itr);
975 void SourceBufferStream::Seek(base::TimeDelta timestamp) {
976 DCHECK(timestamp >= base::TimeDelta());
977 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
978 << " (" << timestamp.InSecondsF() << ")";
979 ResetSeekState();
981 seek_buffer_timestamp_ = timestamp;
982 seek_pending_ = true;
984 if (ShouldSeekToStartOfBuffered(timestamp)) {
985 ranges_.front()->SeekToStart();
986 SetSelectedRange(ranges_.front());
987 seek_pending_ = false;
988 return;
991 DecodeTimestamp seek_dts = DecodeTimestamp::FromPresentationTime(timestamp);
993 RangeList::iterator itr = ranges_.end();
994 for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
995 if ((*itr)->CanSeekTo(seek_dts))
996 break;
999 if (itr == ranges_.end())
1000 return;
1002 SeekAndSetSelectedRange(*itr, seek_dts);
1003 seek_pending_ = false;
1006 bool SourceBufferStream::IsSeekPending() const {
1007 return seek_pending_ && !IsEndOfStreamReached();
1010 void SourceBufferStream::OnSetDuration(base::TimeDelta duration) {
1011 DecodeTimestamp duration_dts =
1012 DecodeTimestamp::FromPresentationTime(duration);
1013 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
1014 << " (" << duration.InSecondsF() << ")";
1016 RangeList::iterator itr = ranges_.end();
1017 for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
1018 if ((*itr)->GetEndTimestamp() > duration_dts)
1019 break;
1021 if (itr == ranges_.end())
1022 return;
1024 // Need to partially truncate this range.
1025 if ((*itr)->GetStartTimestamp() < duration_dts) {
1026 bool delete_range = (*itr)->TruncateAt(duration_dts, NULL, false);
1027 if ((*itr == selected_range_) && !selected_range_->HasNextBufferPosition())
1028 SetSelectedRange(NULL);
1030 if (delete_range) {
1031 DeleteAndRemoveRange(&itr);
1032 } else {
1033 ++itr;
1037 // Delete all ranges that begin after |duration_dts|.
1038 while (itr != ranges_.end()) {
1039 // If we're about to delete the selected range, also reset the seek state.
1040 DCHECK((*itr)->GetStartTimestamp() >= duration_dts);
1041 if (*itr == selected_range_)
1042 ResetSeekState();
1043 DeleteAndRemoveRange(&itr);
1047 SourceBufferStream::Status SourceBufferStream::GetNextBuffer(
1048 scoped_refptr<StreamParserBuffer>* out_buffer) {
1049 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName();
1050 if (!pending_buffer_.get()) {
1051 const SourceBufferStream::Status status = GetNextBufferInternal(out_buffer);
1052 if (status != SourceBufferStream::kSuccess ||
1053 !SetPendingBuffer(out_buffer)) {
1054 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName()
1055 << ": no pending buffer, returning status " << status;
1056 return status;
1060 if (!pending_buffer_->splice_buffers().empty()) {
1061 const SourceBufferStream::Status status =
1062 HandleNextBufferWithSplice(out_buffer);
1063 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName()
1064 << ": handled next buffer with splice, returning status "
1065 << status;
1066 return status;
1069 DCHECK(pending_buffer_->preroll_buffer().get());
1071 const SourceBufferStream::Status status =
1072 HandleNextBufferWithPreroll(out_buffer);
1073 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName()
1074 << ": handled next buffer with preroll, returning status "
1075 << status;
1076 return status;
1079 SourceBufferStream::Status SourceBufferStream::HandleNextBufferWithSplice(
1080 scoped_refptr<StreamParserBuffer>* out_buffer) {
1081 const BufferQueue& splice_buffers = pending_buffer_->splice_buffers();
1082 const size_t last_splice_buffer_index = splice_buffers.size() - 1;
1084 // Are there any splice buffers left to hand out? The last buffer should be
1085 // handed out separately since it represents the first post-splice buffer.
1086 if (splice_buffers_index_ < last_splice_buffer_index) {
1087 // Account for config changes which occur between fade out buffers.
1088 if (current_config_index_ !=
1089 splice_buffers[splice_buffers_index_]->GetConfigId()) {
1090 config_change_pending_ = true;
1091 DVLOG(1) << "Config change (splice buffer config ID does not match).";
1092 return SourceBufferStream::kConfigChange;
1095 // Every pre splice buffer must have the same splice_timestamp().
1096 DCHECK(pending_buffer_->splice_timestamp() ==
1097 splice_buffers[splice_buffers_index_]->splice_timestamp());
1099 // No pre splice buffers should have preroll.
1100 DCHECK(!splice_buffers[splice_buffers_index_]->preroll_buffer().get());
1102 *out_buffer = splice_buffers[splice_buffers_index_++];
1103 return SourceBufferStream::kSuccess;
1106 // Did we hand out the last pre-splice buffer on the previous call?
1107 if (!pending_buffers_complete_) {
1108 DCHECK_EQ(splice_buffers_index_, last_splice_buffer_index);
1109 pending_buffers_complete_ = true;
1110 config_change_pending_ = true;
1111 DVLOG(1) << "Config change (forced for fade in of splice frame).";
1112 return SourceBufferStream::kConfigChange;
1115 // All pre-splice buffers have been handed out and a config change completed,
1116 // so hand out the final buffer for fade in. Because a config change is
1117 // always issued prior to handing out this buffer, any changes in config id
1118 // have been inherently handled.
1119 DCHECK(pending_buffers_complete_);
1120 DCHECK_EQ(splice_buffers_index_, splice_buffers.size() - 1);
1121 DCHECK(splice_buffers.back()->splice_timestamp() == kNoTimestamp());
1122 *out_buffer = splice_buffers.back();
1123 pending_buffer_ = NULL;
1125 // If the last splice buffer has preroll, hand off to the preroll handler.
1126 return SetPendingBuffer(out_buffer) ? HandleNextBufferWithPreroll(out_buffer)
1127 : SourceBufferStream::kSuccess;
1130 SourceBufferStream::Status SourceBufferStream::HandleNextBufferWithPreroll(
1131 scoped_refptr<StreamParserBuffer>* out_buffer) {
1132 // Any config change should have already been handled.
1133 DCHECK_EQ(current_config_index_, pending_buffer_->GetConfigId());
1135 // Check if the preroll buffer has already been handed out.
1136 if (!pending_buffers_complete_) {
1137 pending_buffers_complete_ = true;
1138 *out_buffer = pending_buffer_->preroll_buffer();
1139 return SourceBufferStream::kSuccess;
1142 // Preroll complete, hand out the final buffer.
1143 *out_buffer = pending_buffer_;
1144 pending_buffer_ = NULL;
1145 return SourceBufferStream::kSuccess;
1148 SourceBufferStream::Status SourceBufferStream::GetNextBufferInternal(
1149 scoped_refptr<StreamParserBuffer>* out_buffer) {
1150 CHECK(!config_change_pending_);
1152 if (!track_buffer_.empty()) {
1153 DCHECK(!selected_range_);
1154 scoped_refptr<StreamParserBuffer>& next_buffer = track_buffer_.front();
1156 // If the next buffer is an audio splice frame, the next effective config id
1157 // comes from the first splice buffer.
1158 if (next_buffer->GetSpliceBufferConfigId(0) != current_config_index_) {
1159 config_change_pending_ = true;
1160 DVLOG(1) << "Config change (track buffer config ID does not match).";
1161 return kConfigChange;
1164 DVLOG(3) << __FUNCTION__ << " Next buffer coming from track_buffer_";
1165 *out_buffer = next_buffer;
1166 track_buffer_.pop_front();
1167 WarnIfTrackBufferExhaustionSkipsForward(*out_buffer);
1168 last_output_buffer_timestamp_ = (*out_buffer)->GetDecodeTimestamp();
1170 // If the track buffer becomes empty, then try to set the selected range
1171 // based on the timestamp of this buffer being returned.
1172 if (track_buffer_.empty()) {
1173 just_exhausted_track_buffer_ = true;
1174 SetSelectedRangeIfNeeded(last_output_buffer_timestamp_);
1177 return kSuccess;
1180 DCHECK(track_buffer_.empty());
1181 if (!selected_range_ || !selected_range_->HasNextBuffer()) {
1182 if (IsEndOfStreamReached()) {
1183 return kEndOfStream;
1185 DVLOG(3) << __FUNCTION__ << " " << GetStreamTypeName()
1186 << ": returning kNeedBuffer "
1187 << (selected_range_ ? "(selected range has no next buffer)"
1188 : "(no selected range)");
1189 return kNeedBuffer;
1192 if (selected_range_->GetNextConfigId() != current_config_index_) {
1193 config_change_pending_ = true;
1194 DVLOG(1) << "Config change (selected range config ID does not match).";
1195 return kConfigChange;
1198 CHECK(selected_range_->GetNextBuffer(out_buffer));
1199 WarnIfTrackBufferExhaustionSkipsForward(*out_buffer);
1200 last_output_buffer_timestamp_ = (*out_buffer)->GetDecodeTimestamp();
1201 return kSuccess;
1204 void SourceBufferStream::WarnIfTrackBufferExhaustionSkipsForward(
1205 const scoped_refptr<StreamParserBuffer>& next_buffer) {
1206 if (!just_exhausted_track_buffer_)
1207 return;
1209 just_exhausted_track_buffer_ = false;
1210 DCHECK(next_buffer->is_key_frame());
1211 DecodeTimestamp next_output_buffer_timestamp =
1212 next_buffer->GetDecodeTimestamp();
1213 base::TimeDelta delta =
1214 next_output_buffer_timestamp - last_output_buffer_timestamp_;
1215 DCHECK_GE(delta, base::TimeDelta());
1216 if (delta > GetMaxInterbufferDistance()) {
1217 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_track_buffer_gap_warning_logs_,
1218 kMaxTrackBufferGapWarningLogs)
1219 << "Media append that overlapped current playback position caused time "
1220 "gap in playing "
1221 << GetStreamTypeName() << " stream because the next keyframe is "
1222 << delta.InMilliseconds() << "ms beyond last overlapped frame. Media "
1223 "may appear temporarily frozen.";
1227 DecodeTimestamp SourceBufferStream::GetNextBufferTimestamp() {
1228 if (!track_buffer_.empty())
1229 return track_buffer_.front()->GetDecodeTimestamp();
1231 if (!selected_range_)
1232 return kNoDecodeTimestamp();
1234 DCHECK(selected_range_->HasNextBufferPosition());
1235 return selected_range_->GetNextTimestamp();
1238 SourceBufferStream::RangeList::iterator
1239 SourceBufferStream::FindExistingRangeFor(DecodeTimestamp start_timestamp) {
1240 for (RangeList::iterator itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
1241 if ((*itr)->BelongsToRange(start_timestamp))
1242 return itr;
1244 return ranges_.end();
1247 SourceBufferStream::RangeList::iterator
1248 SourceBufferStream::AddToRanges(SourceBufferRange* new_range) {
1249 DecodeTimestamp start_timestamp = new_range->GetStartTimestamp();
1250 RangeList::iterator itr = ranges_.end();
1251 for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
1252 if ((*itr)->GetStartTimestamp() > start_timestamp)
1253 break;
1255 return ranges_.insert(itr, new_range);
1258 SourceBufferStream::RangeList::iterator
1259 SourceBufferStream::GetSelectedRangeItr() {
1260 DCHECK(selected_range_);
1261 RangeList::iterator itr = ranges_.end();
1262 for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
1263 if (*itr == selected_range_)
1264 break;
1266 DCHECK(itr != ranges_.end());
1267 return itr;
1270 void SourceBufferStream::SeekAndSetSelectedRange(
1271 SourceBufferRange* range, DecodeTimestamp seek_timestamp) {
1272 if (range)
1273 range->Seek(seek_timestamp);
1274 SetSelectedRange(range);
1277 void SourceBufferStream::SetSelectedRange(SourceBufferRange* range) {
1278 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() << ": "
1279 << selected_range_ << " "
1280 << (selected_range_ ? RangeToString(*selected_range_) : "")
1281 << " -> " << range << " " << (range ? RangeToString(*range) : "");
1282 if (selected_range_)
1283 selected_range_->ResetNextBufferPosition();
1284 DCHECK(!range || range->HasNextBufferPosition());
1285 selected_range_ = range;
1288 Ranges<base::TimeDelta> SourceBufferStream::GetBufferedTime() const {
1289 Ranges<base::TimeDelta> ranges;
1290 for (RangeList::const_iterator itr = ranges_.begin();
1291 itr != ranges_.end(); ++itr) {
1292 ranges.Add((*itr)->GetStartTimestamp().ToPresentationTime(),
1293 (*itr)->GetBufferedEndTimestamp().ToPresentationTime());
1295 return ranges;
1298 base::TimeDelta SourceBufferStream::GetBufferedDuration() const {
1299 if (ranges_.empty())
1300 return base::TimeDelta();
1302 return ranges_.back()->GetBufferedEndTimestamp().ToPresentationTime();
1305 size_t SourceBufferStream::GetBufferedSize() const {
1306 size_t ranges_size = 0;
1307 for (const auto& range : ranges_)
1308 ranges_size += range->size_in_bytes();
1309 return ranges_size;
1312 void SourceBufferStream::MarkEndOfStream() {
1313 DCHECK(!end_of_stream_);
1314 end_of_stream_ = true;
1317 void SourceBufferStream::UnmarkEndOfStream() {
1318 DCHECK(end_of_stream_);
1319 end_of_stream_ = false;
1322 bool SourceBufferStream::IsEndOfStreamReached() const {
1323 if (!end_of_stream_ || !track_buffer_.empty())
1324 return false;
1326 if (ranges_.empty())
1327 return true;
1329 if (seek_pending_) {
1330 base::TimeDelta last_range_end_time =
1331 ranges_.back()->GetBufferedEndTimestamp().ToPresentationTime();
1332 return seek_buffer_timestamp_ >= last_range_end_time;
1335 if (!selected_range_)
1336 return true;
1338 return selected_range_ == ranges_.back();
1341 const AudioDecoderConfig& SourceBufferStream::GetCurrentAudioDecoderConfig() {
1342 if (config_change_pending_)
1343 CompleteConfigChange();
1344 return audio_configs_[current_config_index_];
1347 const VideoDecoderConfig& SourceBufferStream::GetCurrentVideoDecoderConfig() {
1348 if (config_change_pending_)
1349 CompleteConfigChange();
1350 return video_configs_[current_config_index_];
1353 const TextTrackConfig& SourceBufferStream::GetCurrentTextTrackConfig() {
1354 return text_track_config_;
1357 base::TimeDelta SourceBufferStream::GetMaxInterbufferDistance() const {
1358 if (max_interbuffer_distance_ == kNoTimestamp())
1359 return base::TimeDelta::FromMilliseconds(kDefaultBufferDurationInMs);
1360 return max_interbuffer_distance_;
1363 bool SourceBufferStream::UpdateAudioConfig(const AudioDecoderConfig& config) {
1364 DCHECK(!audio_configs_.empty());
1365 DCHECK(video_configs_.empty());
1366 DVLOG(3) << "UpdateAudioConfig.";
1368 if (audio_configs_[0].codec() != config.codec()) {
1369 MEDIA_LOG(ERROR, media_log_) << "Audio codec changes not allowed.";
1370 return false;
1373 if (audio_configs_[0].is_encrypted() != config.is_encrypted()) {
1374 MEDIA_LOG(ERROR, media_log_) << "Audio encryption changes not allowed.";
1375 return false;
1378 // Check to see if the new config matches an existing one.
1379 for (size_t i = 0; i < audio_configs_.size(); ++i) {
1380 if (config.Matches(audio_configs_[i])) {
1381 append_config_index_ = i;
1382 return true;
1386 // No matches found so let's add this one to the list.
1387 append_config_index_ = audio_configs_.size();
1388 DVLOG(2) << "New audio config - index: " << append_config_index_;
1389 audio_configs_.resize(audio_configs_.size() + 1);
1390 audio_configs_[append_config_index_] = config;
1391 return true;
1394 bool SourceBufferStream::UpdateVideoConfig(const VideoDecoderConfig& config) {
1395 DCHECK(!video_configs_.empty());
1396 DCHECK(audio_configs_.empty());
1397 DVLOG(3) << "UpdateVideoConfig.";
1399 if (video_configs_[0].codec() != config.codec()) {
1400 MEDIA_LOG(ERROR, media_log_) << "Video codec changes not allowed.";
1401 return false;
1404 if (video_configs_[0].is_encrypted() != config.is_encrypted()) {
1405 MEDIA_LOG(ERROR, media_log_) << "Video encryption changes not allowed.";
1406 return false;
1409 // Check to see if the new config matches an existing one.
1410 for (size_t i = 0; i < video_configs_.size(); ++i) {
1411 if (config.Matches(video_configs_[i])) {
1412 append_config_index_ = i;
1413 return true;
1417 // No matches found so let's add this one to the list.
1418 append_config_index_ = video_configs_.size();
1419 DVLOG(2) << "New video config - index: " << append_config_index_;
1420 video_configs_.resize(video_configs_.size() + 1);
1421 video_configs_[append_config_index_] = config;
1422 return true;
1425 void SourceBufferStream::CompleteConfigChange() {
1426 config_change_pending_ = false;
1428 if (pending_buffer_.get()) {
1429 current_config_index_ =
1430 pending_buffer_->GetSpliceBufferConfigId(splice_buffers_index_);
1431 return;
1434 if (!track_buffer_.empty()) {
1435 current_config_index_ = track_buffer_.front()->GetSpliceBufferConfigId(0);
1436 return;
1439 if (selected_range_ && selected_range_->HasNextBuffer())
1440 current_config_index_ = selected_range_->GetNextConfigId();
1443 void SourceBufferStream::SetSelectedRangeIfNeeded(
1444 const DecodeTimestamp timestamp) {
1445 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName()
1446 << "(" << timestamp.InSecondsF() << ")";
1448 if (selected_range_) {
1449 DCHECK(track_buffer_.empty());
1450 return;
1453 if (!track_buffer_.empty()) {
1454 DCHECK(!selected_range_);
1455 return;
1458 DecodeTimestamp start_timestamp = timestamp;
1460 // If the next buffer timestamp is not known then use a timestamp just after
1461 // the timestamp on the last buffer returned by GetNextBuffer().
1462 if (start_timestamp == kNoDecodeTimestamp()) {
1463 if (last_output_buffer_timestamp_ == kNoDecodeTimestamp()) {
1464 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName()
1465 << " no previous output timestamp";
1466 return;
1469 start_timestamp = last_output_buffer_timestamp_ +
1470 base::TimeDelta::FromInternalValue(1);
1473 DecodeTimestamp seek_timestamp =
1474 FindNewSelectedRangeSeekTimestamp(start_timestamp);
1476 // If we don't have buffered data to seek to, then return.
1477 if (seek_timestamp == kNoDecodeTimestamp()) {
1478 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName()
1479 << " couldn't find new selected range seek timestamp";
1480 return;
1483 DCHECK(track_buffer_.empty());
1484 SeekAndSetSelectedRange(*FindExistingRangeFor(seek_timestamp),
1485 seek_timestamp);
1488 DecodeTimestamp SourceBufferStream::FindNewSelectedRangeSeekTimestamp(
1489 const DecodeTimestamp start_timestamp) {
1490 DCHECK(start_timestamp != kNoDecodeTimestamp());
1491 DCHECK(start_timestamp >= DecodeTimestamp());
1493 RangeList::iterator itr = ranges_.begin();
1495 for (; itr != ranges_.end(); ++itr) {
1496 if ((*itr)->GetEndTimestamp() >= start_timestamp) {
1497 break;
1501 if (itr == ranges_.end()) {
1502 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName()
1503 << " no buffered data for dts=" << start_timestamp.InSecondsF();
1504 return kNoDecodeTimestamp();
1507 // First check for a keyframe timestamp >= |start_timestamp|
1508 // in the current range.
1509 DecodeTimestamp keyframe_timestamp =
1510 (*itr)->NextKeyframeTimestamp(start_timestamp);
1512 if (keyframe_timestamp != kNoDecodeTimestamp())
1513 return keyframe_timestamp;
1515 // If a keyframe was not found then look for a keyframe that is
1516 // "close enough" in the current or next range.
1517 DecodeTimestamp end_timestamp =
1518 start_timestamp + ComputeFudgeRoom(GetMaxInterbufferDistance());
1519 DCHECK(start_timestamp < end_timestamp);
1521 // Make sure the current range doesn't start beyond |end_timestamp|.
1522 if ((*itr)->GetStartTimestamp() >= end_timestamp)
1523 return kNoDecodeTimestamp();
1525 keyframe_timestamp = (*itr)->KeyframeBeforeTimestamp(end_timestamp);
1527 // Check to see if the keyframe is within the acceptable range
1528 // (|start_timestamp|, |end_timestamp|].
1529 if (keyframe_timestamp != kNoDecodeTimestamp() &&
1530 start_timestamp < keyframe_timestamp &&
1531 keyframe_timestamp <= end_timestamp) {
1532 return keyframe_timestamp;
1535 // If |end_timestamp| is within this range, then no other checks are
1536 // necessary.
1537 if (end_timestamp <= (*itr)->GetEndTimestamp())
1538 return kNoDecodeTimestamp();
1540 // Move on to the next range.
1541 ++itr;
1543 // Return early if the next range does not contain |end_timestamp|.
1544 if (itr == ranges_.end() || (*itr)->GetStartTimestamp() >= end_timestamp)
1545 return kNoDecodeTimestamp();
1547 keyframe_timestamp = (*itr)->KeyframeBeforeTimestamp(end_timestamp);
1549 // Check to see if the keyframe is within the acceptable range
1550 // (|start_timestamp|, |end_timestamp|].
1551 if (keyframe_timestamp != kNoDecodeTimestamp() &&
1552 start_timestamp < keyframe_timestamp &&
1553 keyframe_timestamp <= end_timestamp) {
1554 return keyframe_timestamp;
1557 return kNoDecodeTimestamp();
1560 DecodeTimestamp SourceBufferStream::FindKeyframeAfterTimestamp(
1561 const DecodeTimestamp timestamp) {
1562 DCHECK(timestamp != kNoDecodeTimestamp());
1564 RangeList::iterator itr = FindExistingRangeFor(timestamp);
1566 if (itr == ranges_.end())
1567 return kNoDecodeTimestamp();
1569 // First check for a keyframe timestamp >= |timestamp|
1570 // in the current range.
1571 return (*itr)->NextKeyframeTimestamp(timestamp);
1574 std::string SourceBufferStream::GetStreamTypeName() const {
1575 switch (GetType()) {
1576 case kAudio:
1577 return "AUDIO";
1578 case kVideo:
1579 return "VIDEO";
1580 case kText:
1581 return "TEXT";
1583 NOTREACHED();
1584 return "";
1587 SourceBufferStream::Type SourceBufferStream::GetType() const {
1588 if (!audio_configs_.empty())
1589 return kAudio;
1590 if (!video_configs_.empty())
1591 return kVideo;
1592 DCHECK_NE(text_track_config_.kind(), kTextNone);
1593 return kText;
1596 void SourceBufferStream::DeleteAndRemoveRange(RangeList::iterator* itr) {
1597 DVLOG(1) << __FUNCTION__;
1599 DCHECK(*itr != ranges_.end());
1600 if (**itr == selected_range_) {
1601 DVLOG(1) << __FUNCTION__ << " deleting selected range.";
1602 SetSelectedRange(NULL);
1605 if (*itr == range_for_next_append_) {
1606 DVLOG(1) << __FUNCTION__ << " deleting range_for_next_append_.";
1607 range_for_next_append_ = ranges_.end();
1608 last_appended_buffer_timestamp_ = kNoDecodeTimestamp();
1609 last_appended_buffer_is_keyframe_ = false;
1612 delete **itr;
1613 *itr = ranges_.erase(*itr);
1616 void SourceBufferStream::GenerateSpliceFrame(const BufferQueue& new_buffers) {
1617 DCHECK(!new_buffers.empty());
1619 // Splice frames are only supported for audio.
1620 if (GetType() != kAudio)
1621 return;
1623 // Find the overlapped range (if any).
1624 const base::TimeDelta splice_timestamp = new_buffers.front()->timestamp();
1625 const DecodeTimestamp splice_dts =
1626 DecodeTimestamp::FromPresentationTime(splice_timestamp);
1627 RangeList::iterator range_itr = FindExistingRangeFor(splice_dts);
1628 if (range_itr == ranges_.end())
1629 return;
1631 const DecodeTimestamp max_splice_end_dts =
1632 splice_dts + base::TimeDelta::FromMilliseconds(
1633 AudioSplicer::kCrossfadeDurationInMilliseconds);
1635 // Find all buffers involved before the splice point.
1636 BufferQueue pre_splice_buffers;
1637 if (!(*range_itr)->GetBuffersInRange(
1638 splice_dts, max_splice_end_dts, &pre_splice_buffers)) {
1639 return;
1642 // If there are gaps in the timeline, it's possible that we only find buffers
1643 // after the splice point but within the splice range. For simplicity, we do
1644 // not generate splice frames in this case.
1646 // We also do not want to generate splices if the first new buffer replaces an
1647 // existing buffer exactly.
1648 if (pre_splice_buffers.front()->timestamp() >= splice_timestamp) {
1649 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_splice_generation_warning_logs_,
1650 kMaxSpliceGenerationWarningLogs)
1651 << "Skipping splice frame generation: first new buffer at "
1652 << splice_timestamp.InMicroseconds()
1653 << "us begins at or before existing buffer at "
1654 << pre_splice_buffers.front()->timestamp().InMicroseconds() << "us.";
1655 DVLOG(1) << "Skipping splice: overlapped buffers begin at or after the "
1656 "first new buffer.";
1657 return;
1660 // If any |pre_splice_buffers| are already splices or preroll, do not generate
1661 // a splice.
1662 for (size_t i = 0; i < pre_splice_buffers.size(); ++i) {
1663 const BufferQueue& original_splice_buffers =
1664 pre_splice_buffers[i]->splice_buffers();
1665 if (!original_splice_buffers.empty()) {
1666 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_splice_generation_warning_logs_,
1667 kMaxSpliceGenerationWarningLogs)
1668 << "Skipping splice frame generation: overlapped buffers at "
1669 << pre_splice_buffers[i]->timestamp().InMicroseconds()
1670 << "us are in a previously buffered splice.";
1671 DVLOG(1) << "Can't generate splice: overlapped buffers contain a "
1672 "pre-existing splice.";
1673 return;
1676 if (pre_splice_buffers[i]->preroll_buffer().get()) {
1677 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_splice_generation_warning_logs_,
1678 kMaxSpliceGenerationWarningLogs)
1679 << "Skipping splice frame generation: overlapped buffers at "
1680 << pre_splice_buffers[i]->timestamp().InMicroseconds()
1681 << "us contain preroll.";
1682 DVLOG(1) << "Can't generate splice: overlapped buffers contain preroll.";
1683 return;
1687 // Don't generate splice frames which represent less than a millisecond (which
1688 // is frequently the extent of timestamp resolution for poorly encoded media)
1689 // or less than two samples (need at least two to crossfade).
1690 const base::TimeDelta splice_duration =
1691 pre_splice_buffers.back()->timestamp() +
1692 pre_splice_buffers.back()->duration() - splice_timestamp;
1693 const base::TimeDelta minimum_splice_duration = std::max(
1694 base::TimeDelta::FromMilliseconds(1),
1695 base::TimeDelta::FromSecondsD(
1696 2.0 / audio_configs_[append_config_index_].samples_per_second()));
1697 if (splice_duration < minimum_splice_duration) {
1698 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_splice_generation_warning_logs_,
1699 kMaxSpliceGenerationWarningLogs)
1700 << "Skipping splice frame generation: not enough samples for splicing "
1701 "new buffer at "
1702 << splice_timestamp.InMicroseconds() << "us. Have "
1703 << splice_duration.InMicroseconds() << "us, but need "
1704 << minimum_splice_duration.InMicroseconds() << "us.";
1705 DVLOG(1) << "Can't generate splice: not enough samples for crossfade; have "
1706 << splice_duration.InMicroseconds() << "us, but need "
1707 << minimum_splice_duration.InMicroseconds() << "us.";
1708 return;
1711 DVLOG(1) << "Generating splice frame @ " << new_buffers.front()->timestamp()
1712 << ", splice duration: " << splice_duration.InMicroseconds()
1713 << " us";
1714 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_splice_generation_success_logs_,
1715 kMaxSpliceGenerationSuccessLogs)
1716 << "Generated splice of overlap duration "
1717 << splice_duration.InMicroseconds() << "us into new buffer at "
1718 << splice_timestamp.InMicroseconds() << "us.";
1719 new_buffers.front()->ConvertToSpliceBuffer(pre_splice_buffers);
1722 bool SourceBufferStream::SetPendingBuffer(
1723 scoped_refptr<StreamParserBuffer>* out_buffer) {
1724 DCHECK(out_buffer->get());
1725 DCHECK(!pending_buffer_.get());
1727 const bool have_splice_buffers = !(*out_buffer)->splice_buffers().empty();
1728 const bool have_preroll_buffer = !!(*out_buffer)->preroll_buffer().get();
1730 if (!have_splice_buffers && !have_preroll_buffer)
1731 return false;
1733 DCHECK_NE(have_splice_buffers, have_preroll_buffer);
1734 splice_buffers_index_ = 0;
1735 pending_buffer_.swap(*out_buffer);
1736 pending_buffers_complete_ = false;
1737 return true;
1740 } // namespace media