Chromium Code Reviews| 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 |