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 #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_gc) { | |
| 700 DVLOG(4) << __func__ << " level=" << memory_pressure_level; | |
| 701 memory_pressure_level_ = memory_pressure_level; | |
| 702 | |
| 703 // The new value of |memory_pressure_level_| updated set above will take | |
| 704 // effect on the next SourceBuffer append operation. But if we are notified | |
|
DaleCurtis
2017/01/26 23:07:37
Comment talks about critical but if force is enabl
servolk
2017/01/27 00:52:13
Updated the comment and moved it closer to where w
| |
| 705 // that memory pressure is critical, we might want to perform a GC right away, | |
| 706 // to release some memory immediately. Strictly speaking MSE apps expect | |
| 707 // buffered ranges only at well-defined points, like SourceBuffer append | |
| 708 // operation, and may not expect this. But it might still be better than being | |
| 709 // killed due to OOM, so might be worth the risk. | |
| 710 if (force_gc) { | |
| 711 GarbageCollectIfNeeded(media_time, 0); | |
| 712 } | |
| 713 } | |
| 714 | |
| 695 bool SourceBufferStream::GarbageCollectIfNeeded(DecodeTimestamp media_time, | 715 bool SourceBufferStream::GarbageCollectIfNeeded(DecodeTimestamp media_time, |
| 696 size_t newDataSize) { | 716 size_t newDataSize) { |
| 697 DCHECK(media_time != kNoDecodeTimestamp()); | 717 DCHECK(media_time != kNoDecodeTimestamp()); |
| 698 // Garbage collection should only happen before/during appending new data, | 718 // Garbage collection should only happen before/during appending new data, |
| 699 // which should not happen in end-of-stream state. | 719 // which should not happen in end-of-stream state. Unless we also allow GC to |
| 700 DCHECK(!end_of_stream_); | 720 // happen on memory pressure notifications, which might happen even in EOS |
| 721 // state. | |
| 722 if (!base::FeatureList::IsEnabled(kReduceMSEBuffersOnMemoryPressure)) { | |
|
DaleCurtis
2017/01/26 23:08:42
Also drop {} from single line if statements (here
servolk
2017/01/27 00:52:13
Done.
| |
| 723 DCHECK(!end_of_stream_); | |
| 724 } | |
| 701 // Compute size of |ranges_|. | 725 // Compute size of |ranges_|. |
| 702 size_t ranges_size = GetBufferedSize(); | 726 size_t ranges_size = GetBufferedSize(); |
| 703 | 727 |
| 704 // Sanity and overflow checks | 728 // Sanity and overflow checks |
| 705 if ((newDataSize > memory_limit_) || | 729 if ((newDataSize > memory_limit_) || |
| 706 (ranges_size + newDataSize < ranges_size)) { | 730 (ranges_size + newDataSize < ranges_size)) { |
| 707 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_garbage_collect_algorithm_logs_, | 731 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_garbage_collect_algorithm_logs_, |
| 708 kMaxGarbageCollectAlgorithmWarningLogs) | 732 kMaxGarbageCollectAlgorithmWarningLogs) |
| 709 << GetStreamTypeName() << " stream: " | 733 << GetStreamTypeName() << " stream: " |
| 710 << "new append of newDataSize=" << newDataSize | 734 << "new append of newDataSize=" << newDataSize |
| 711 << " bytes exceeds memory_limit_=" << memory_limit_ | 735 << " bytes exceeds memory_limit_=" << memory_limit_ |
| 712 << ", currently buffered ranges_size=" << ranges_size; | 736 << ", currently buffered ranges_size=" << ranges_size; |
| 713 return false; | 737 return false; |
| 714 } | 738 } |
| 715 | 739 |
| 740 size_t effective_memory_limit = memory_limit_; | |
| 741 if (base::FeatureList::IsEnabled(kReduceMSEBuffersOnMemoryPressure)) { | |
| 742 switch (memory_pressure_level_) { | |
| 743 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE: | |
| 744 effective_memory_limit = memory_limit_ / 2; | |
| 745 break; | |
| 746 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL: | |
| 747 effective_memory_limit = 0; | |
| 748 break; | |
| 749 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE: | |
| 750 break; | |
| 751 } | |
| 752 } | |
| 753 | |
| 716 // Return if we're under or at the memory limit. | 754 // Return if we're under or at the memory limit. |
| 717 if (ranges_size + newDataSize <= memory_limit_) | 755 if (ranges_size + newDataSize <= effective_memory_limit) |
| 718 return true; | 756 return true; |
| 719 | 757 |
| 720 size_t bytes_to_free = ranges_size + newDataSize - memory_limit_; | 758 size_t bytes_over_hard_memory_limit = 0; |
| 759 if (ranges_size + newDataSize > memory_limit_) | |
| 760 bytes_over_hard_memory_limit = ranges_size + newDataSize - memory_limit_; | |
| 761 | |
| 762 size_t bytes_to_free = ranges_size + newDataSize - effective_memory_limit; | |
| 721 | 763 |
| 722 DVLOG(2) << __func__ << " " << GetStreamTypeName() | 764 DVLOG(2) << __func__ << " " << GetStreamTypeName() |
| 723 << ": Before GC media_time=" << media_time.InSecondsF() | 765 << ": Before GC media_time=" << media_time.InSecondsF() |
| 724 << " ranges_=" << RangesToString(ranges_) | 766 << " ranges_=" << RangesToString(ranges_) |
| 725 << " seek_pending_=" << seek_pending_ | 767 << " seek_pending_=" << seek_pending_ |
| 726 << " ranges_size=" << ranges_size << " newDataSize=" << newDataSize | 768 << " ranges_size=" << ranges_size << " newDataSize=" << newDataSize |
| 727 << " memory_limit_=" << memory_limit_ | 769 << " memory_limit_=" << memory_limit_ |
| 770 << " effective_memory_limit=" << effective_memory_limit | |
| 728 << " last_appended_buffer_timestamp_=" | 771 << " last_appended_buffer_timestamp_=" |
| 729 << last_appended_buffer_timestamp_.InSecondsF(); | 772 << last_appended_buffer_timestamp_.InSecondsF(); |
| 730 | 773 |
| 731 if (selected_range_ && !seek_pending_ && | 774 if (selected_range_ && !seek_pending_ && |
| 732 media_time > selected_range_->GetBufferedEndTimestamp()) { | 775 media_time > selected_range_->GetBufferedEndTimestamp()) { |
| 733 // Strictly speaking |media_time| (taken from HTMLMediaElement::currentTime) | 776 // Strictly speaking |media_time| (taken from HTMLMediaElement::currentTime) |
| 734 // should always be in the buffered ranges, but media::Pipeline uses audio | 777 // should always be in the buffered ranges, but media::Pipeline uses audio |
| 735 // stream as the main time source, when audio is present. | 778 // stream as the main time source, when audio is present. |
| 736 // In cases when audio and video streams have different buffered ranges, the | 779 // 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 | 780 // |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) { | 870 if (bytes_freed < bytes_to_free) { |
| 828 size_t back = FreeBuffers(bytes_to_free - bytes_freed, media_time, true); | 871 size_t back = FreeBuffers(bytes_to_free - bytes_freed, media_time, true); |
| 829 DVLOG(3) << __func__ << " Removed " << back | 872 DVLOG(3) << __func__ << " Removed " << back |
| 830 << " bytes from the back. ranges_=" << RangesToString(ranges_); | 873 << " bytes from the back. ranges_=" << RangesToString(ranges_); |
| 831 bytes_freed += back; | 874 bytes_freed += back; |
| 832 } | 875 } |
| 833 | 876 |
| 834 DVLOG(2) << __func__ << " " << GetStreamTypeName() | 877 DVLOG(2) << __func__ << " " << GetStreamTypeName() |
| 835 << ": After GC bytes_to_free=" << bytes_to_free | 878 << ": After GC bytes_to_free=" << bytes_to_free |
| 836 << " bytes_freed=" << bytes_freed | 879 << " bytes_freed=" << bytes_freed |
| 880 << " bytes_over_hard_memory_limit=" << bytes_over_hard_memory_limit | |
| 837 << " ranges_=" << RangesToString(ranges_); | 881 << " ranges_=" << RangesToString(ranges_); |
| 838 | 882 |
| 839 return bytes_freed >= bytes_to_free; | 883 return bytes_freed >= bytes_over_hard_memory_limit; |
| 840 } | 884 } |
| 841 | 885 |
| 842 size_t SourceBufferStream::FreeBuffersAfterLastAppended( | 886 size_t SourceBufferStream::FreeBuffersAfterLastAppended( |
| 843 size_t total_bytes_to_free, DecodeTimestamp media_time) { | 887 size_t total_bytes_to_free, DecodeTimestamp media_time) { |
| 844 DVLOG(4) << __func__ << " last_appended_buffer_timestamp_=" | 888 DVLOG(4) << __func__ << " last_appended_buffer_timestamp_=" |
| 845 << last_appended_buffer_timestamp_.InSecondsF() | 889 << last_appended_buffer_timestamp_.InSecondsF() |
| 846 << " media_time=" << media_time.InSecondsF(); | 890 << " media_time=" << media_time.InSecondsF(); |
| 847 | 891 |
| 848 DecodeTimestamp remove_range_start = last_appended_buffer_timestamp_; | 892 DecodeTimestamp remove_range_start = last_appended_buffer_timestamp_; |
| 849 if (last_appended_buffer_is_keyframe_) | 893 if (last_appended_buffer_is_keyframe_) |
| (...skipping 907 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1757 | 1801 |
| 1758 if (!have_preroll_buffer) | 1802 if (!have_preroll_buffer) |
| 1759 return false; | 1803 return false; |
| 1760 | 1804 |
| 1761 pending_buffer_.swap(*out_buffer); | 1805 pending_buffer_.swap(*out_buffer); |
| 1762 pending_buffers_complete_ = false; | 1806 pending_buffers_complete_ = false; |
| 1763 return true; | 1807 return true; |
| 1764 } | 1808 } |
| 1765 | 1809 |
| 1766 } // namespace media | 1810 } // namespace media |
| OLD | NEW |