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 #include <sstream> | 9 #include <sstream> |
10 | 10 |
(...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
612 } | 612 } |
613 | 613 |
614 bool SourceBufferStream::GarbageCollectIfNeeded(DecodeTimestamp media_time, | 614 bool SourceBufferStream::GarbageCollectIfNeeded(DecodeTimestamp media_time, |
615 size_t newDataSize) { | 615 size_t newDataSize) { |
616 DCHECK(media_time != kNoDecodeTimestamp()); | 616 DCHECK(media_time != kNoDecodeTimestamp()); |
617 // Compute size of |ranges_|. | 617 // Compute size of |ranges_|. |
618 size_t ranges_size = GetBufferedSize(); | 618 size_t ranges_size = GetBufferedSize(); |
619 | 619 |
620 // Sanity and overflow checks | 620 // Sanity and overflow checks |
621 if ((newDataSize > memory_limit_) || | 621 if ((newDataSize > memory_limit_) || |
622 (ranges_size + newDataSize < ranges_size)) | 622 (ranges_size + newDataSize < ranges_size)) { |
623 LOG(WARNING) << "GarbageCollectIfNeeded: memory_limit_=" << memory_limit_ | |
wolenetz
2015/09/17 18:57:54
Please change to LIMITED_MEDIA_LOG(DEBUG...), so c
servolk
2015/09/18 01:29:28
Done.
| |
624 << " ranges_size=" << ranges_size << " newDataSize=" | |
625 << newDataSize; | |
623 return false; | 626 return false; |
627 } | |
624 | 628 |
625 // Return if we're under or at the memory limit. | 629 // Return if we're under or at the memory limit. |
626 if (ranges_size + newDataSize <= memory_limit_) | 630 if (ranges_size + newDataSize <= memory_limit_) |
627 return true; | 631 return true; |
628 | 632 |
629 size_t bytes_to_free = ranges_size + newDataSize - memory_limit_; | 633 size_t bytes_to_free = ranges_size + newDataSize - memory_limit_; |
630 | 634 |
635 // If media_time is not within one of the currently buffered ranges, then we | |
636 // likely have a pending seek and we should allow GC to remove data more | |
637 // aggressively for the upcoming append to allow seeking to proceed. | |
638 bool seek_pending = true; | |
639 for (auto& r : ranges_) { | |
wolenetz
2015/09/17 18:57:54
Bear with me. I think the tl;dr is this is ok.
I
servolk
2015/09/18 01:29:28
Wait, as far as I understand GOP handling is alrea
| |
640 if (media_time >= r->GetStartTimestamp() && | |
641 media_time <= r->GetEndTimestamp()) { | |
642 seek_pending = false; | |
643 break; | |
644 } | |
645 } | |
646 | |
631 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName() << ": Before GC" | 647 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName() << ": Before GC" |
632 << " media_time=" << media_time.InSecondsF() | 648 << " media_time=" << media_time.InSecondsF() |
633 << " ranges_=" << RangesToString(ranges_) | 649 << " ranges_=" << RangesToString(ranges_) |
650 << " seek_pending=" << seek_pending | |
634 << " ranges_size=" << ranges_size | 651 << " ranges_size=" << ranges_size |
635 << " newDataSize=" << newDataSize | 652 << " newDataSize=" << newDataSize |
636 << " memory_limit_=" << memory_limit_ | 653 << " memory_limit_=" << memory_limit_ |
637 << " last_appended_buffer_timestamp_=" | 654 << " last_appended_buffer_timestamp_=" |
638 << last_appended_buffer_timestamp_.InSecondsF(); | 655 << last_appended_buffer_timestamp_.InSecondsF(); |
639 | 656 |
640 size_t bytes_freed = 0; | 657 size_t bytes_freed = 0; |
641 | 658 |
642 // If last appended buffer position was earlier than the current playback time | 659 // If last appended buffer position was earlier than the current playback time |
643 // then try deleting data between last append and current media_time. | 660 // then try deleting data between last append and current media_time. |
644 if (last_appended_buffer_timestamp_ != kNoDecodeTimestamp() && | 661 if (last_appended_buffer_timestamp_ != kNoDecodeTimestamp() && |
645 last_appended_buffer_timestamp_ < media_time) { | 662 last_appended_buffer_timestamp_ < media_time) { |
646 size_t between = FreeBuffersAfterLastAppended(bytes_to_free, media_time); | 663 size_t between = FreeBuffersAfterLastAppended(bytes_to_free, media_time); |
647 DVLOG(3) << __FUNCTION__ << " FreeBuffersAfterLastAppended " | 664 DVLOG(3) << __FUNCTION__ << " FreeBuffersAfterLastAppended " |
648 << " released " << between << " bytes" | 665 << " released " << between << " bytes" |
649 << " ranges_=" << RangesToString(ranges_); | 666 << " ranges_=" << RangesToString(ranges_); |
650 bytes_freed += between; | 667 bytes_freed += between; |
651 | 668 |
652 // If the last append happened before the current playback position | 669 // Some players start appending data at the new seek target position before |
653 // |media_time|, then JS player is probably preparing to seek back and we | 670 // actually initiating the seek operation (i.e. they try to improve seek |
654 // should try to preserve all most recently appended data (which is in | 671 // performance by prebuffering some data at the seek target position and |
655 // range_for_next_append_) from being removed by GC (see crbug.com/440173) | 672 // initiating seek once enough data is pre-buffered. In those cases we'll |
656 if (range_for_next_append_ != ranges_.end()) { | 673 // see that data is being appended at some new position, but |media_time| is |
674 // still going to be in some buffered range and the logic for detecting | |
675 // |pending_seek| is not going to work. In this situation we need to try | |
676 // preserving the most recently appended data, i.e. data belonging to the | |
677 // same buffered range as the most recent append. | |
678 if (range_for_next_append_ != ranges_.end() && !seek_pending) { | |
657 DCHECK((*range_for_next_append_)->GetStartTimestamp() <= media_time); | 679 DCHECK((*range_for_next_append_)->GetStartTimestamp() <= media_time); |
658 media_time = (*range_for_next_append_)->GetStartTimestamp(); | 680 media_time = (*range_for_next_append_)->GetStartTimestamp(); |
659 } | 681 } |
660 } | 682 } |
661 | 683 |
684 // If there is an unsatisfied pending seek, we can safely remove all data that | |
685 // is earlier than seek target, then remove from the back until we reach the | |
686 // most recently appended GOP and then remove from the front if we still don't | |
687 // have enough space for the upcoming append. | |
688 if (bytes_freed < bytes_to_free && seek_pending) { | |
689 DCHECK(!ranges_.empty()); | |
690 // All data earlier than the seek target |media_time| can be removed safely | |
691 size_t front = FreeBuffers(bytes_to_free - bytes_freed, media_time, false); | |
692 DVLOG(3) << __FUNCTION__ << " Removed " << front << " bytes from the" | |
693 << " front. ranges_=" << RangesToString(ranges_); | |
694 bytes_freed += front; | |
695 | |
696 // If removing data earlier than |media_time| didn't free up enough space, | |
697 // then try deleting from the back until we reach most recently appended GOP | |
698 if (bytes_freed < bytes_to_free) { | |
699 size_t back = FreeBuffers(bytes_to_free - bytes_freed, media_time, true); | |
700 DVLOG(3) << __FUNCTION__ << " Removed " << back << " bytes from the back" | |
701 << " ranges_=" << RangesToString(ranges_); | |
702 bytes_freed += back; | |
703 } | |
704 | |
705 // If even that wasn't enough, then try greedily deleting from the front, | |
706 // that should allow us to remove as much data as necessary to succeed. | |
707 if (bytes_freed < bytes_to_free) { | |
708 size_t front2 = FreeBuffers(bytes_to_free - bytes_freed, | |
709 ranges_.back()->GetEndTimestamp(), false); | |
710 DVLOG(3) << __FUNCTION__ << " Removed " << front << " bytes from the" | |
711 << " front. ranges_=" << RangesToString(ranges_); | |
712 bytes_freed += front2; | |
713 } | |
714 DCHECK(bytes_freed >= bytes_to_free); | |
715 } | |
716 | |
662 // Try removing data from the front of the SourceBuffer up to |media_time| | 717 // Try removing data from the front of the SourceBuffer up to |media_time| |
663 // position. | 718 // position. |
664 if (bytes_freed < bytes_to_free) { | 719 if (bytes_freed < bytes_to_free) { |
665 size_t front = FreeBuffers(bytes_to_free - bytes_freed, media_time, false); | 720 size_t front = FreeBuffers(bytes_to_free - bytes_freed, media_time, false); |
666 DVLOG(3) << __FUNCTION__ << " Removed " << front << " bytes from the front" | 721 DVLOG(3) << __FUNCTION__ << " Removed " << front << " bytes from the" |
667 << " ranges_=" << RangesToString(ranges_); | 722 << " front. ranges_=" << RangesToString(ranges_); |
668 bytes_freed += front; | 723 bytes_freed += front; |
669 } | 724 } |
670 | 725 |
671 // Try removing data from the back of the SourceBuffer, until we reach the | 726 // Try removing data from the back of the SourceBuffer, until we reach the |
672 // most recent append position. | 727 // most recent append position. |
673 if (bytes_freed < bytes_to_free) { | 728 if (bytes_freed < bytes_to_free) { |
674 size_t back = FreeBuffers(bytes_to_free - bytes_freed, media_time, true); | 729 size_t back = FreeBuffers(bytes_to_free - bytes_freed, media_time, true); |
675 DVLOG(3) << __FUNCTION__ << " Removed " << back << " bytes from the back" | 730 DVLOG(3) << __FUNCTION__ << " Removed " << back << " bytes from the back." |
676 << " ranges_=" << RangesToString(ranges_); | 731 << " ranges_=" << RangesToString(ranges_); |
677 bytes_freed += back; | 732 bytes_freed += back; |
678 } | 733 } |
679 | 734 |
680 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName() << ": After GC" | 735 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName() << ": After GC" |
681 << " bytes_to_free=" << bytes_to_free | 736 << " bytes_to_free=" << bytes_to_free |
682 << " bytes_freed=" << bytes_freed | 737 << " bytes_freed=" << bytes_freed |
683 << " ranges_=" << RangesToString(ranges_); | 738 << " ranges_=" << RangesToString(ranges_); |
684 | 739 |
685 return bytes_freed >= bytes_to_free; | 740 return bytes_freed >= bytes_to_free; |
(...skipping 1045 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1731 return false; | 1786 return false; |
1732 | 1787 |
1733 DCHECK_NE(have_splice_buffers, have_preroll_buffer); | 1788 DCHECK_NE(have_splice_buffers, have_preroll_buffer); |
1734 splice_buffers_index_ = 0; | 1789 splice_buffers_index_ = 0; |
1735 pending_buffer_.swap(*out_buffer); | 1790 pending_buffer_.swap(*out_buffer); |
1736 pending_buffers_complete_ = false; | 1791 pending_buffers_complete_ = false; |
1737 return true; | 1792 return true; |
1738 } | 1793 } |
1739 | 1794 |
1740 } // namespace media | 1795 } // namespace media |
OLD | NEW |