Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1060)

Side by Side Diff: media/filters/source_buffer_stream.cc

Issue 2605993002: Experiment with more aggressive MSE GC on memory pressure (Closed)
Patch Set: Don't create mem pressure listener when the feature is disabled Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 DVLOG(4) << __func__ << " level=" << memory_pressure_level;
700 memory_pressure_level_ = memory_pressure_level;
701
702 // The new value of |memory_pressure_level_| updated set above will take
703 // effect on the next SourceBuffer append operation. But if we are notified
704 // that memory pressure is critical, we might want to perform a GC right away,
705 // to release some memory immediately. Strictly speaking MSE apps expect
706 // buffered ranges only at well-defined points, like SourceBuffer append
707 // operation, and may not expect this. But it might still be better than being
708 // killed due to OOM, so might be worth the risk.
709 if (base::FeatureList::IsEnabled(kMSEInstantGCOnMemoryPressure) &&
710 memory_pressure_level ==
711 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) {
712 GarbageCollectIfNeeded(media_time, 0);
713 }
714 }
715
695 bool SourceBufferStream::GarbageCollectIfNeeded(DecodeTimestamp media_time, 716 bool SourceBufferStream::GarbageCollectIfNeeded(DecodeTimestamp media_time,
696 size_t newDataSize) { 717 size_t newDataSize) {
697 DCHECK(media_time != kNoDecodeTimestamp()); 718 DCHECK(media_time != kNoDecodeTimestamp());
698 // Garbage collection should only happen before/during appending new data, 719 // Garbage collection should only happen before/during appending new data,
699 // which should not happen in end-of-stream state. 720 // which should not happen in end-of-stream state. Unless we also allow GC to
700 DCHECK(!end_of_stream_); 721 // happen on memory pressure notifications, which might happen even in EOS
722 // state.
723 if (!base::FeatureList::IsEnabled(kMSEInstantGCOnMemoryPressure)) {
724 DCHECK(!end_of_stream_);
725 }
701 // Compute size of |ranges_|. 726 // Compute size of |ranges_|.
702 size_t ranges_size = GetBufferedSize(); 727 size_t ranges_size = GetBufferedSize();
703 728
704 // Sanity and overflow checks 729 // Sanity and overflow checks
705 if ((newDataSize > memory_limit_) || 730 if ((newDataSize > memory_limit_) ||
706 (ranges_size + newDataSize < ranges_size)) { 731 (ranges_size + newDataSize < ranges_size)) {
707 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_garbage_collect_algorithm_logs_, 732 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_garbage_collect_algorithm_logs_,
708 kMaxGarbageCollectAlgorithmWarningLogs) 733 kMaxGarbageCollectAlgorithmWarningLogs)
709 << GetStreamTypeName() << " stream: " 734 << GetStreamTypeName() << " stream: "
710 << "new append of newDataSize=" << newDataSize 735 << "new append of newDataSize=" << newDataSize
711 << " bytes exceeds memory_limit_=" << memory_limit_ 736 << " bytes exceeds memory_limit_=" << memory_limit_
712 << ", currently buffered ranges_size=" << ranges_size; 737 << ", currently buffered ranges_size=" << ranges_size;
713 return false; 738 return false;
714 } 739 }
715 740
741 size_t effective_memory_limit = memory_limit_;
742 if (base::FeatureList::IsEnabled(kReduceMSEBuffersOnMemoryPressure)) {
743 switch (memory_pressure_level_) {
744 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
745 effective_memory_limit = memory_limit_ / 2;
746 break;
747 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
748 effective_memory_limit = 0;
749 break;
750 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
chcunningham 2017/01/25 03:47:15 Maybe no-op is fine, but what made you decide not
servolk 2017/01/25 18:06:47 Tbh I'm not sure what you mean by 'restore the mem
chcunningham 2017/01/25 22:21:57 My bad. I overlooked the local variable. Seems it
servolk 2017/01/26 18:10:14 Acknowledged.
751 break;
752 }
753 }
754
716 // Return if we're under or at the memory limit. 755 // Return if we're under or at the memory limit.
717 if (ranges_size + newDataSize <= memory_limit_) 756 if (ranges_size + newDataSize <= effective_memory_limit)
718 return true; 757 return true;
719 758
720 size_t bytes_to_free = ranges_size + newDataSize - memory_limit_; 759 size_t bytes_over_hard_memory_limit = 0;
760 if (ranges_size + newDataSize > memory_limit_)
761 bytes_over_hard_memory_limit = ranges_size + newDataSize - memory_limit_;
762
763 size_t bytes_to_free = ranges_size + newDataSize - effective_memory_limit;
721 764
722 DVLOG(2) << __func__ << " " << GetStreamTypeName() 765 DVLOG(2) << __func__ << " " << GetStreamTypeName()
723 << ": Before GC media_time=" << media_time.InSecondsF() 766 << ": Before GC media_time=" << media_time.InSecondsF()
724 << " ranges_=" << RangesToString(ranges_) 767 << " ranges_=" << RangesToString(ranges_)
725 << " seek_pending_=" << seek_pending_ 768 << " seek_pending_=" << seek_pending_
726 << " ranges_size=" << ranges_size << " newDataSize=" << newDataSize 769 << " ranges_size=" << ranges_size << " newDataSize=" << newDataSize
727 << " memory_limit_=" << memory_limit_ 770 << " memory_limit_=" << memory_limit_
771 << " effective_memory_limit=" << effective_memory_limit
728 << " last_appended_buffer_timestamp_=" 772 << " last_appended_buffer_timestamp_="
729 << last_appended_buffer_timestamp_.InSecondsF(); 773 << last_appended_buffer_timestamp_.InSecondsF();
730 774
731 if (selected_range_ && !seek_pending_ && 775 if (selected_range_ && !seek_pending_ &&
732 media_time > selected_range_->GetBufferedEndTimestamp()) { 776 media_time > selected_range_->GetBufferedEndTimestamp()) {
733 // Strictly speaking |media_time| (taken from HTMLMediaElement::currentTime) 777 // Strictly speaking |media_time| (taken from HTMLMediaElement::currentTime)
734 // should always be in the buffered ranges, but media::Pipeline uses audio 778 // should always be in the buffered ranges, but media::Pipeline uses audio
735 // stream as the main time source, when audio is present. 779 // stream as the main time source, when audio is present.
736 // In cases when audio and video streams have different buffered ranges, the 780 // 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 781 // |media_time| value might be slightly outside of the video stream buffered
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
827 if (bytes_freed < bytes_to_free) { 871 if (bytes_freed < bytes_to_free) {
828 size_t back = FreeBuffers(bytes_to_free - bytes_freed, media_time, true); 872 size_t back = FreeBuffers(bytes_to_free - bytes_freed, media_time, true);
829 DVLOG(3) << __func__ << " Removed " << back 873 DVLOG(3) << __func__ << " Removed " << back
830 << " bytes from the back. ranges_=" << RangesToString(ranges_); 874 << " bytes from the back. ranges_=" << RangesToString(ranges_);
831 bytes_freed += back; 875 bytes_freed += back;
832 } 876 }
833 877
834 DVLOG(2) << __func__ << " " << GetStreamTypeName() 878 DVLOG(2) << __func__ << " " << GetStreamTypeName()
835 << ": After GC bytes_to_free=" << bytes_to_free 879 << ": After GC bytes_to_free=" << bytes_to_free
836 << " bytes_freed=" << bytes_freed 880 << " bytes_freed=" << bytes_freed
881 << " bytes_over_hard_memory_limit=" << bytes_over_hard_memory_limit
837 << " ranges_=" << RangesToString(ranges_); 882 << " ranges_=" << RangesToString(ranges_);
838 883
839 return bytes_freed >= bytes_to_free; 884 return bytes_freed >= bytes_over_hard_memory_limit;
840 } 885 }
841 886
842 size_t SourceBufferStream::FreeBuffersAfterLastAppended( 887 size_t SourceBufferStream::FreeBuffersAfterLastAppended(
843 size_t total_bytes_to_free, DecodeTimestamp media_time) { 888 size_t total_bytes_to_free, DecodeTimestamp media_time) {
844 DVLOG(4) << __func__ << " last_appended_buffer_timestamp_=" 889 DVLOG(4) << __func__ << " last_appended_buffer_timestamp_="
845 << last_appended_buffer_timestamp_.InSecondsF() 890 << last_appended_buffer_timestamp_.InSecondsF()
846 << " media_time=" << media_time.InSecondsF(); 891 << " media_time=" << media_time.InSecondsF();
847 892
848 DecodeTimestamp remove_range_start = last_appended_buffer_timestamp_; 893 DecodeTimestamp remove_range_start = last_appended_buffer_timestamp_;
849 if (last_appended_buffer_is_keyframe_) 894 if (last_appended_buffer_is_keyframe_)
(...skipping 907 matching lines...) Expand 10 before | Expand all | Expand 10 after
1757 1802
1758 if (!have_preroll_buffer) 1803 if (!have_preroll_buffer)
1759 return false; 1804 return false;
1760 1805
1761 pending_buffer_.swap(*out_buffer); 1806 pending_buffer_.swap(*out_buffer);
1762 pending_buffers_complete_ = false; 1807 pending_buffers_complete_ = false;
1763 return true; 1808 return true;
1764 } 1809 }
1765 1810
1766 } // namespace media 1811 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698