OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/filters/source_buffer_stream.h" | 5 #include "media/filters/source_buffer_stream.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <map> | 8 #include <map> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
116 // Returns the timestamp of the next buffer that will be returned from | 116 // Returns the timestamp of the next buffer that will be returned from |
117 // GetNextBuffer(), or kNoTimestamp() if the timestamp is unknown. | 117 // GetNextBuffer(), or kNoTimestamp() if the timestamp is unknown. |
118 base::TimeDelta GetNextTimestamp() const; | 118 base::TimeDelta GetNextTimestamp() const; |
119 | 119 |
120 // Returns the start timestamp of the range. | 120 // Returns the start timestamp of the range. |
121 base::TimeDelta GetStartTimestamp() const; | 121 base::TimeDelta GetStartTimestamp() const; |
122 | 122 |
123 // Returns the timestamp of the last buffer in the range. | 123 // Returns the timestamp of the last buffer in the range. |
124 base::TimeDelta GetEndTimestamp() const; | 124 base::TimeDelta GetEndTimestamp() const; |
125 | 125 |
126 // Returns true if the last buffer in the range is a keyframe. | |
127 bool IsEndKeyframe() const; | |
scherkus (not reviewing)
2013/03/11 21:23:40
EndsWithKeyframe?
acolwell GONE FROM CHROMIUM
2013/03/11 22:31:38
Removed. Method no longer needed.
| |
128 | |
126 // Returns the timestamp for the end of the buffered region in this range. | 129 // Returns the timestamp for the end of the buffered region in this range. |
127 // This is an approximation if the duration for the last buffer in the range | 130 // This is an approximation if the duration for the last buffer in the range |
128 // is unset. | 131 // is unset. |
129 base::TimeDelta GetBufferedEndTimestamp() const; | 132 base::TimeDelta GetBufferedEndTimestamp() const; |
130 | 133 |
131 // Gets the timestamp for the keyframe that is after |timestamp|. If | 134 // Gets the timestamp for the keyframe that is after |timestamp|. If |
132 // there isn't a keyframe in the range after |timestamp| then kNoTimestamp() | 135 // there isn't a keyframe in the range after |timestamp| then kNoTimestamp() |
133 // is returned. | 136 // is returned. |
134 base::TimeDelta NextKeyframeTimestamp(base::TimeDelta timestamp); | 137 base::TimeDelta NextKeyframeTimestamp(base::TimeDelta timestamp); |
135 | 138 |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
368 DCHECK(!buffers.empty()); | 371 DCHECK(!buffers.empty()); |
369 DCHECK(media_segment_start_time_ != kNoTimestamp()); | 372 DCHECK(media_segment_start_time_ != kNoTimestamp()); |
370 | 373 |
371 // New media segments must begin with a keyframe. | 374 // New media segments must begin with a keyframe. |
372 if (new_media_segment_ && !buffers.front()->IsKeyframe()) { | 375 if (new_media_segment_ && !buffers.front()->IsKeyframe()) { |
373 MEDIA_LOG(log_cb_) << "Media segment did not begin with keyframe."; | 376 MEDIA_LOG(log_cb_) << "Media segment did not begin with keyframe."; |
374 return false; | 377 return false; |
375 } | 378 } |
376 | 379 |
377 // Buffers within a media segment should be monotonically increasing. | 380 // Buffers within a media segment should be monotonically increasing. |
378 if (!IsMonotonicallyIncreasing(buffers)) { | 381 if (!IsMonotonicallyIncreasing(buffers)) |
379 MEDIA_LOG(log_cb_) << "Buffers were not monotonically increasing."; | |
380 return false; | 382 return false; |
381 } | |
382 | 383 |
383 if (media_segment_start_time_ < base::TimeDelta() || | 384 if (media_segment_start_time_ < base::TimeDelta() || |
384 buffers.front()->GetDecodeTimestamp() < base::TimeDelta()) { | 385 buffers.front()->GetDecodeTimestamp() < base::TimeDelta()) { |
385 MEDIA_LOG(log_cb_) | 386 MEDIA_LOG(log_cb_) |
386 << "Cannot append a media segment with negative timestamps."; | 387 << "Cannot append a media segment with negative timestamps."; |
387 return false; | 388 return false; |
388 } | 389 } |
389 | 390 |
390 UpdateMaxInterbufferDistance(buffers); | 391 UpdateMaxInterbufferDistance(buffers); |
391 SetConfigIds(buffers); | 392 SetConfigIds(buffers); |
392 | 393 |
393 // Save a snapshot of stream state before range modifications are made. | 394 // Save a snapshot of stream state before range modifications are made. |
394 base::TimeDelta next_buffer_timestamp = GetNextBufferTimestamp(); | 395 base::TimeDelta next_buffer_timestamp = GetNextBufferTimestamp(); |
395 BufferQueue deleted_buffers; | 396 BufferQueue deleted_buffers; |
396 | 397 |
397 RangeList::iterator range_for_new_buffers = range_for_next_append_; | 398 RangeList::iterator range_for_new_buffers = range_for_next_append_; |
398 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise, | 399 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise, |
399 // create a new range with |buffers|. | 400 // create a new range with |buffers|. |
400 if (range_for_new_buffers != ranges_.end()) { | 401 if (range_for_new_buffers != ranges_.end()) { |
401 InsertIntoExistingRange(range_for_new_buffers, buffers, &deleted_buffers); | 402 if (!InsertIntoExistingRange(range_for_new_buffers, buffers, |
403 &deleted_buffers)) { | |
404 return false; | |
405 } | |
402 } else { | 406 } else { |
403 DCHECK(new_media_segment_); | 407 DCHECK(new_media_segment_); |
404 range_for_new_buffers = | 408 range_for_new_buffers = |
405 AddToRanges(new SourceBufferRange( | 409 AddToRanges(new SourceBufferRange( |
406 buffers, media_segment_start_time_, | 410 buffers, media_segment_start_time_, |
407 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance, | 411 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance, |
408 base::Unretained(this)))); | 412 base::Unretained(this)))); |
409 } | 413 } |
410 | 414 |
411 range_for_next_append_ = range_for_new_buffers; | 415 range_for_next_append_ = range_for_new_buffers; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
470 base::TimeDelta beginning_of_buffered = | 474 base::TimeDelta beginning_of_buffered = |
471 ranges_.front()->GetStartTimestamp(); | 475 ranges_.front()->GetStartTimestamp(); |
472 return (seek_timestamp <= beginning_of_buffered && | 476 return (seek_timestamp <= beginning_of_buffered && |
473 beginning_of_buffered < kSeekToStartFudgeRoom()); | 477 beginning_of_buffered < kSeekToStartFudgeRoom()); |
474 } | 478 } |
475 | 479 |
476 bool SourceBufferStream::IsMonotonicallyIncreasing( | 480 bool SourceBufferStream::IsMonotonicallyIncreasing( |
477 const BufferQueue& buffers) const { | 481 const BufferQueue& buffers) const { |
478 DCHECK(!buffers.empty()); | 482 DCHECK(!buffers.empty()); |
479 base::TimeDelta prev_timestamp = last_appended_buffer_timestamp_; | 483 base::TimeDelta prev_timestamp = last_appended_buffer_timestamp_; |
484 bool prev_is_keyframe = false; | |
480 for (BufferQueue::const_iterator itr = buffers.begin(); | 485 for (BufferQueue::const_iterator itr = buffers.begin(); |
481 itr != buffers.end(); ++itr) { | 486 itr != buffers.end(); ++itr) { |
482 base::TimeDelta current_timestamp = (*itr)->GetDecodeTimestamp(); | 487 base::TimeDelta current_timestamp = (*itr)->GetDecodeTimestamp(); |
488 bool current_is_keyframe = (*itr)->IsKeyframe(); | |
483 DCHECK(current_timestamp != kNoTimestamp()); | 489 DCHECK(current_timestamp != kNoTimestamp()); |
484 | 490 |
485 if (prev_timestamp != kNoTimestamp() && current_timestamp < prev_timestamp) | 491 if (prev_timestamp != kNoTimestamp()) { |
486 return false; | 492 if (current_timestamp < prev_timestamp) { |
493 MEDIA_LOG(log_cb_) << "Buffers were not monotonically increasing."; | |
494 return false; | |
495 } | |
496 | |
497 if (current_timestamp == prev_timestamp && | |
498 (current_is_keyframe || prev_is_keyframe)) { | |
499 MEDIA_LOG(log_cb_) << "Invalid alt-ref frame construct detected at " | |
500 << current_timestamp.InSecondsF(); | |
501 return false; | |
502 } | |
503 } | |
487 | 504 |
488 prev_timestamp = current_timestamp; | 505 prev_timestamp = current_timestamp; |
506 prev_is_keyframe = current_is_keyframe; | |
489 } | 507 } |
490 return true; | 508 return true; |
491 } | 509 } |
492 | 510 |
493 bool SourceBufferStream::OnlySelectedRangeIsSeeked() const { | 511 bool SourceBufferStream::OnlySelectedRangeIsSeeked() const { |
494 for (RangeList::const_iterator itr = ranges_.begin(); | 512 for (RangeList::const_iterator itr = ranges_.begin(); |
495 itr != ranges_.end(); ++itr) { | 513 itr != ranges_.end(); ++itr) { |
496 if ((*itr)->HasNextBufferPosition() && (*itr) != selected_range_) | 514 if ((*itr)->HasNextBufferPosition() && (*itr) != selected_range_) |
497 return false; | 515 return false; |
498 } | 516 } |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
621 if (range_for_next_append_ != ranges_.begin()) { | 639 if (range_for_next_append_ != ranges_.begin()) { |
622 RangeList::iterator range_before_next = range_for_next_append_; | 640 RangeList::iterator range_before_next = range_for_next_append_; |
623 --range_before_next; | 641 --range_before_next; |
624 MergeWithAdjacentRangeIfNecessary(range_before_next); | 642 MergeWithAdjacentRangeIfNecessary(range_before_next); |
625 } | 643 } |
626 MergeWithAdjacentRangeIfNecessary(range_for_next_append_); | 644 MergeWithAdjacentRangeIfNecessary(range_for_next_append_); |
627 } | 645 } |
628 return bytes_freed; | 646 return bytes_freed; |
629 } | 647 } |
630 | 648 |
631 void SourceBufferStream::InsertIntoExistingRange( | 649 bool SourceBufferStream::InsertIntoExistingRange( |
632 const RangeList::iterator& range_for_new_buffers_itr, | 650 const RangeList::iterator& range_for_new_buffers_itr, |
633 const BufferQueue& new_buffers, BufferQueue* deleted_buffers) { | 651 const BufferQueue& new_buffers, BufferQueue* deleted_buffers) { |
634 DCHECK(deleted_buffers); | 652 DCHECK(deleted_buffers); |
635 | 653 |
636 SourceBufferRange* range_for_new_buffers = *range_for_new_buffers_itr; | 654 SourceBufferRange* range_for_new_buffers = *range_for_new_buffers_itr; |
637 | 655 |
638 bool temporarily_select_range = false; | 656 bool temporarily_select_range = false; |
639 if (!track_buffer_.empty()) { | 657 if (!track_buffer_.empty()) { |
640 base::TimeDelta tb_timestamp = track_buffer_.back()->GetDecodeTimestamp(); | 658 base::TimeDelta tb_timestamp = track_buffer_.back()->GetDecodeTimestamp(); |
641 base::TimeDelta seek_timestamp = FindKeyframeAfterTimestamp(tb_timestamp); | 659 base::TimeDelta seek_timestamp = FindKeyframeAfterTimestamp(tb_timestamp); |
(...skipping 17 matching lines...) Expand all Loading... | |
659 | 677 |
660 if (last_appended_buffer_timestamp_ != kNoTimestamp()) { | 678 if (last_appended_buffer_timestamp_ != kNoTimestamp()) { |
661 // Clean up the old buffers between the last appended buffer and the | 679 // Clean up the old buffers between the last appended buffer and the |
662 // beginning of |new_buffers|. | 680 // beginning of |new_buffers|. |
663 DeleteBetween( | 681 DeleteBetween( |
664 range_for_new_buffers_itr, last_appended_buffer_timestamp_, | 682 range_for_new_buffers_itr, last_appended_buffer_timestamp_, |
665 new_buffers.front()->GetDecodeTimestamp(), true, | 683 new_buffers.front()->GetDecodeTimestamp(), true, |
666 deleted_buffers); | 684 deleted_buffers); |
667 } | 685 } |
668 | 686 |
669 // If we cannot append the |new_buffers| to the end of the existing range, | 687 base::TimeDelta prev_timestamp = range_for_new_buffers->GetEndTimestamp(); |
670 // this is either a start overlap or an middle overlap. Delete the buffers | 688 bool prev_is_keyframe = range_for_new_buffers->IsEndKeyframe(); |
671 // that |new_buffers| overlaps. | 689 base::TimeDelta next_timestamp = new_buffers.front()->GetDecodeTimestamp(); |
672 if (!range_for_new_buffers->CanAppendBuffersToEnd(new_buffers)) { | 690 bool next_is_keyframe = new_buffers.front()->IsKeyframe(); |
691 bool is_valid_alt_ref = prev_timestamp == next_timestamp && | |
scherkus (not reviewing)
2013/03/11 21:23:40
how does this compare with the if block below that
acolwell GONE FROM CHROMIUM
2013/03/11 22:31:38
This identifies a valid alt-ref construct that we
| |
692 !prev_is_keyframe && !next_is_keyframe; | |
693 | |
694 // Check for invalid alt-ref frame constructs. | |
695 // A keyframe followed by a non-keyframe or | |
696 // a non-keyframe followed by a keyframe that is not | |
697 // the first frame of a media segment are errors. | |
698 if (prev_timestamp == next_timestamp && | |
699 ((prev_is_keyframe && !next_is_keyframe) || | |
700 (!new_media_segment_ && next_is_keyframe))) { | |
701 MEDIA_LOG(log_cb_) << "Invalid alt-ref frame construct detected at time " | |
702 << prev_timestamp.InSecondsF(); | |
703 return false; | |
704 } | |
705 | |
706 // If a valid alt-ref frame sequence was not detected and we cannot append the | |
707 // |new_buffers| to the end of the existing range, this is either a start | |
708 // overlap or an middle overlap. Delete the buffers that |new_buffers| | |
709 // overlaps. | |
710 if (!is_valid_alt_ref && | |
711 !range_for_new_buffers->CanAppendBuffersToEnd(new_buffers)) { | |
673 DeleteBetween( | 712 DeleteBetween( |
674 range_for_new_buffers_itr, new_buffers.front()->GetDecodeTimestamp(), | 713 range_for_new_buffers_itr, new_buffers.front()->GetDecodeTimestamp(), |
675 new_buffers.back()->GetDecodeTimestamp(), false, | 714 new_buffers.back()->GetDecodeTimestamp(), false, |
676 deleted_buffers); | 715 deleted_buffers); |
677 } | 716 } |
678 | 717 |
679 // Restore the range seek state if necessary. | 718 // Restore the range seek state if necessary. |
680 if (temporarily_select_range) | 719 if (temporarily_select_range) |
681 SetSelectedRange(NULL); | 720 SetSelectedRange(NULL); |
682 | 721 |
683 range_for_new_buffers->AppendBuffersToEnd(new_buffers); | 722 range_for_new_buffers->AppendBuffersToEnd(new_buffers); |
723 return true; | |
684 } | 724 } |
685 | 725 |
686 void SourceBufferStream::DeleteBetween( | 726 void SourceBufferStream::DeleteBetween( |
687 const RangeList::iterator& range_itr, base::TimeDelta start_timestamp, | 727 const RangeList::iterator& range_itr, base::TimeDelta start_timestamp, |
688 base::TimeDelta end_timestamp, bool is_range_exclusive, | 728 base::TimeDelta end_timestamp, bool is_range_exclusive, |
689 BufferQueue* deleted_buffers) { | 729 BufferQueue* deleted_buffers) { |
690 SourceBufferRange* new_next_range = | 730 SourceBufferRange* new_next_range = |
691 (*range_itr)->SplitRange(end_timestamp, is_range_exclusive); | 731 (*range_itr)->SplitRange(end_timestamp, is_range_exclusive); |
692 | 732 |
693 // Insert the |new_next_range| into |ranges_| after |range|. | 733 // Insert the |new_next_range| into |ranges_| after |range|. |
(...skipping 942 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1636 if (start_timestamp == kNoTimestamp()) | 1676 if (start_timestamp == kNoTimestamp()) |
1637 start_timestamp = buffers_.front()->GetDecodeTimestamp(); | 1677 start_timestamp = buffers_.front()->GetDecodeTimestamp(); |
1638 return start_timestamp; | 1678 return start_timestamp; |
1639 } | 1679 } |
1640 | 1680 |
1641 base::TimeDelta SourceBufferRange::GetEndTimestamp() const { | 1681 base::TimeDelta SourceBufferRange::GetEndTimestamp() const { |
1642 DCHECK(!buffers_.empty()); | 1682 DCHECK(!buffers_.empty()); |
1643 return buffers_.back()->GetDecodeTimestamp(); | 1683 return buffers_.back()->GetDecodeTimestamp(); |
1644 } | 1684 } |
1645 | 1685 |
1686 bool SourceBufferRange::IsEndKeyframe() const { | |
1687 DCHECK(!buffers_.empty()); | |
1688 return buffers_.back()->IsKeyframe(); | |
1689 } | |
1690 | |
1646 base::TimeDelta SourceBufferRange::GetBufferedEndTimestamp() const { | 1691 base::TimeDelta SourceBufferRange::GetBufferedEndTimestamp() const { |
1647 DCHECK(!buffers_.empty()); | 1692 DCHECK(!buffers_.empty()); |
1648 base::TimeDelta duration = buffers_.back()->GetDuration(); | 1693 base::TimeDelta duration = buffers_.back()->GetDuration(); |
1649 if (duration == kNoTimestamp() || duration == base::TimeDelta()) | 1694 if (duration == kNoTimestamp() || duration == base::TimeDelta()) |
1650 duration = GetApproximateDuration(); | 1695 duration = GetApproximateDuration(); |
1651 return GetEndTimestamp() + duration; | 1696 return GetEndTimestamp() + duration; |
1652 } | 1697 } |
1653 | 1698 |
1654 base::TimeDelta SourceBufferRange::NextKeyframeTimestamp( | 1699 base::TimeDelta SourceBufferRange::NextKeyframeTimestamp( |
1655 base::TimeDelta timestamp) { | 1700 base::TimeDelta timestamp) { |
(...skipping 29 matching lines...) Expand all Loading... | |
1685 return ComputeFudgeRoom(GetApproximateDuration()); | 1730 return ComputeFudgeRoom(GetApproximateDuration()); |
1686 } | 1731 } |
1687 | 1732 |
1688 base::TimeDelta SourceBufferRange::GetApproximateDuration() const { | 1733 base::TimeDelta SourceBufferRange::GetApproximateDuration() const { |
1689 base::TimeDelta max_interbuffer_distance = interbuffer_distance_cb_.Run(); | 1734 base::TimeDelta max_interbuffer_distance = interbuffer_distance_cb_.Run(); |
1690 DCHECK(max_interbuffer_distance != kNoTimestamp()); | 1735 DCHECK(max_interbuffer_distance != kNoTimestamp()); |
1691 return max_interbuffer_distance; | 1736 return max_interbuffer_distance; |
1692 } | 1737 } |
1693 | 1738 |
1694 } // namespace media | 1739 } // namespace media |
OLD | NEW |