| 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 #include <string> | 10 #include <string> |
| 11 | 11 |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/logging.h" | 13 #include "base/logging.h" |
| 14 #include "base/trace_event/trace_event.h" | 14 #include "base/trace_event/trace_event.h" |
| 15 #include "media/base/media_switches.h" |
| 15 #include "media/base/timestamp_constants.h" | 16 #include "media/base/timestamp_constants.h" |
| 16 #include "media/filters/source_buffer_platform.h" | 17 #include "media/filters/source_buffer_platform.h" |
| 17 #include "media/filters/source_buffer_range.h" | 18 #include "media/filters/source_buffer_range.h" |
| 18 | 19 |
| 19 namespace media { | 20 namespace media { |
| 20 | 21 |
| 21 namespace { | 22 namespace { |
| 22 | 23 |
| 23 // An arbitrarily-chosen number to estimate the duration of a buffer if none is | 24 // 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 // set and there's not enough information to get a better estimate. |
| (...skipping 660 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 685 } | 686 } |
| 686 } | 687 } |
| 687 | 688 |
| 688 void SourceBufferStream::SetConfigIds(const BufferQueue& buffers) { | 689 void SourceBufferStream::SetConfigIds(const BufferQueue& buffers) { |
| 689 for (BufferQueue::const_iterator itr = buffers.begin(); | 690 for (BufferQueue::const_iterator itr = buffers.begin(); |
| 690 itr != buffers.end(); ++itr) { | 691 itr != buffers.end(); ++itr) { |
| 691 (*itr)->SetConfigId(append_config_index_); | 692 (*itr)->SetConfigId(append_config_index_); |
| 692 } | 693 } |
| 693 } | 694 } |
| 694 | 695 |
| 696 void SourceBufferStream::OnMemoryPressure( |
| 697 DecodeTimestamp media_time, |
| 698 base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level, |
| 699 bool force_instant_gc) { |
| 700 DVLOG(4) << __func__ << " level=" << memory_pressure_level; |
| 701 memory_pressure_level_ = memory_pressure_level; |
| 702 |
| 703 if (force_instant_gc) |
| 704 GarbageCollectIfNeeded(media_time, 0); |
| 705 } |
| 706 |
| 695 bool SourceBufferStream::GarbageCollectIfNeeded(DecodeTimestamp media_time, | 707 bool SourceBufferStream::GarbageCollectIfNeeded(DecodeTimestamp media_time, |
| 696 size_t newDataSize) { | 708 size_t newDataSize) { |
| 697 DCHECK(media_time != kNoDecodeTimestamp()); | 709 DCHECK(media_time != kNoDecodeTimestamp()); |
| 698 // Garbage collection should only happen before/during appending new data, | 710 // Garbage collection should only happen before/during appending new data, |
| 699 // which should not happen in end-of-stream state. | 711 // which should not happen in end-of-stream state. Unless we also allow GC to |
| 700 DCHECK(!end_of_stream_); | 712 // happen on memory pressure notifications, which might happen even in EOS |
| 713 // state. |
| 714 if (!base::FeatureList::IsEnabled(kMemoryPressureBasedSourceBufferGC)) |
| 715 DCHECK(!end_of_stream_); |
| 701 // Compute size of |ranges_|. | 716 // Compute size of |ranges_|. |
| 702 size_t ranges_size = GetBufferedSize(); | 717 size_t ranges_size = GetBufferedSize(); |
| 703 | 718 |
| 704 // Sanity and overflow checks | 719 // Sanity and overflow checks |
| 705 if ((newDataSize > memory_limit_) || | 720 if ((newDataSize > memory_limit_) || |
| 706 (ranges_size + newDataSize < ranges_size)) { | 721 (ranges_size + newDataSize < ranges_size)) { |
| 707 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_garbage_collect_algorithm_logs_, | 722 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_garbage_collect_algorithm_logs_, |
| 708 kMaxGarbageCollectAlgorithmWarningLogs) | 723 kMaxGarbageCollectAlgorithmWarningLogs) |
| 709 << GetStreamTypeName() << " stream: " | 724 << GetStreamTypeName() << " stream: " |
| 710 << "new append of newDataSize=" << newDataSize | 725 << "new append of newDataSize=" << newDataSize |
| 711 << " bytes exceeds memory_limit_=" << memory_limit_ | 726 << " bytes exceeds memory_limit_=" << memory_limit_ |
| 712 << ", currently buffered ranges_size=" << ranges_size; | 727 << ", currently buffered ranges_size=" << ranges_size; |
| 713 return false; | 728 return false; |
| 714 } | 729 } |
| 715 | 730 |
| 731 size_t effective_memory_limit = memory_limit_; |
| 732 if (base::FeatureList::IsEnabled(kMemoryPressureBasedSourceBufferGC)) { |
| 733 switch (memory_pressure_level_) { |
| 734 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE: |
| 735 effective_memory_limit = memory_limit_ / 2; |
| 736 break; |
| 737 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL: |
| 738 effective_memory_limit = 0; |
| 739 break; |
| 740 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE: |
| 741 break; |
| 742 } |
| 743 } |
| 744 |
| 716 // Return if we're under or at the memory limit. | 745 // Return if we're under or at the memory limit. |
| 717 if (ranges_size + newDataSize <= memory_limit_) | 746 if (ranges_size + newDataSize <= effective_memory_limit) |
| 718 return true; | 747 return true; |
| 719 | 748 |
| 720 size_t bytes_to_free = ranges_size + newDataSize - memory_limit_; | 749 size_t bytes_over_hard_memory_limit = 0; |
| 750 if (ranges_size + newDataSize > memory_limit_) |
| 751 bytes_over_hard_memory_limit = ranges_size + newDataSize - memory_limit_; |
| 752 |
| 753 size_t bytes_to_free = ranges_size + newDataSize - effective_memory_limit; |
| 721 | 754 |
| 722 DVLOG(2) << __func__ << " " << GetStreamTypeName() | 755 DVLOG(2) << __func__ << " " << GetStreamTypeName() |
| 723 << ": Before GC media_time=" << media_time.InSecondsF() | 756 << ": Before GC media_time=" << media_time.InSecondsF() |
| 724 << " ranges_=" << RangesToString(ranges_) | 757 << " ranges_=" << RangesToString(ranges_) |
| 725 << " seek_pending_=" << seek_pending_ | 758 << " seek_pending_=" << seek_pending_ |
| 726 << " ranges_size=" << ranges_size << " newDataSize=" << newDataSize | 759 << " ranges_size=" << ranges_size << " newDataSize=" << newDataSize |
| 727 << " memory_limit_=" << memory_limit_ | 760 << " memory_limit_=" << memory_limit_ |
| 761 << " effective_memory_limit=" << effective_memory_limit |
| 728 << " last_appended_buffer_timestamp_=" | 762 << " last_appended_buffer_timestamp_=" |
| 729 << last_appended_buffer_timestamp_.InSecondsF(); | 763 << last_appended_buffer_timestamp_.InSecondsF(); |
| 730 | 764 |
| 731 if (selected_range_ && !seek_pending_ && | 765 if (selected_range_ && !seek_pending_ && |
| 732 media_time > selected_range_->GetBufferedEndTimestamp()) { | 766 media_time > selected_range_->GetBufferedEndTimestamp()) { |
| 733 // Strictly speaking |media_time| (taken from HTMLMediaElement::currentTime) | 767 // Strictly speaking |media_time| (taken from HTMLMediaElement::currentTime) |
| 734 // should always be in the buffered ranges, but media::Pipeline uses audio | 768 // should always be in the buffered ranges, but media::Pipeline uses audio |
| 735 // stream as the main time source, when audio is present. | 769 // stream as the main time source, when audio is present. |
| 736 // In cases when audio and video streams have different buffered ranges, the | 770 // In cases when audio and video streams have different buffered ranges, the |
| 737 // |media_time| value might be slightly outside of the video stream buffered | 771 // |media_time| value might be slightly outside of the video stream buffered |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 827 if (bytes_freed < bytes_to_free) { | 861 if (bytes_freed < bytes_to_free) { |
| 828 size_t back = FreeBuffers(bytes_to_free - bytes_freed, media_time, true); | 862 size_t back = FreeBuffers(bytes_to_free - bytes_freed, media_time, true); |
| 829 DVLOG(3) << __func__ << " Removed " << back | 863 DVLOG(3) << __func__ << " Removed " << back |
| 830 << " bytes from the back. ranges_=" << RangesToString(ranges_); | 864 << " bytes from the back. ranges_=" << RangesToString(ranges_); |
| 831 bytes_freed += back; | 865 bytes_freed += back; |
| 832 } | 866 } |
| 833 | 867 |
| 834 DVLOG(2) << __func__ << " " << GetStreamTypeName() | 868 DVLOG(2) << __func__ << " " << GetStreamTypeName() |
| 835 << ": After GC bytes_to_free=" << bytes_to_free | 869 << ": After GC bytes_to_free=" << bytes_to_free |
| 836 << " bytes_freed=" << bytes_freed | 870 << " bytes_freed=" << bytes_freed |
| 871 << " bytes_over_hard_memory_limit=" << bytes_over_hard_memory_limit |
| 837 << " ranges_=" << RangesToString(ranges_); | 872 << " ranges_=" << RangesToString(ranges_); |
| 838 | 873 |
| 839 return bytes_freed >= bytes_to_free; | 874 return bytes_freed >= bytes_over_hard_memory_limit; |
| 840 } | 875 } |
| 841 | 876 |
| 842 size_t SourceBufferStream::FreeBuffersAfterLastAppended( | 877 size_t SourceBufferStream::FreeBuffersAfterLastAppended( |
| 843 size_t total_bytes_to_free, DecodeTimestamp media_time) { | 878 size_t total_bytes_to_free, DecodeTimestamp media_time) { |
| 844 DVLOG(4) << __func__ << " last_appended_buffer_timestamp_=" | 879 DVLOG(4) << __func__ << " last_appended_buffer_timestamp_=" |
| 845 << last_appended_buffer_timestamp_.InSecondsF() | 880 << last_appended_buffer_timestamp_.InSecondsF() |
| 846 << " media_time=" << media_time.InSecondsF(); | 881 << " media_time=" << media_time.InSecondsF(); |
| 847 | 882 |
| 848 DecodeTimestamp remove_range_start = last_appended_buffer_timestamp_; | 883 DecodeTimestamp remove_range_start = last_appended_buffer_timestamp_; |
| 849 if (last_appended_buffer_is_keyframe_) | 884 if (last_appended_buffer_is_keyframe_) |
| (...skipping 907 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1757 | 1792 |
| 1758 if (!have_preroll_buffer) | 1793 if (!have_preroll_buffer) |
| 1759 return false; | 1794 return false; |
| 1760 | 1795 |
| 1761 pending_buffer_.swap(*out_buffer); | 1796 pending_buffer_.swap(*out_buffer); |
| 1762 pending_buffers_complete_ = false; | 1797 pending_buffers_complete_ = false; |
| 1763 return true; | 1798 return true; |
| 1764 } | 1799 } |
| 1765 | 1800 |
| 1766 } // namespace media | 1801 } // namespace media |
| OLD | NEW |