From 4912dde5aa714ead29cfcae892dd900f9f21e170 Mon Sep 17 00:00:00 2001 From: Jason Zhang Date: Wed, 3 Apr 2024 23:57:58 +0000 Subject: [PATCH] Refine Demuxer GC for low resolution videos The chunk demuxer garbage collection algorithm didn't account bookkeeping data, which uses a significant amount of memory when playing low resolution videos. For example, the reported memory usage of ChunkDemuxerTest.WebMFile_AudioOnly test was 18624 bytes. After including memory usage of 166 StreamParserBuffer instances, the new memory usage increases to 69088 bytes. Fixed: b/372965149 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5353702 (cherry picked from commit 41153e57b9e6a7ef8dd2231dfc8cab201a956913) --- media/base/decoder_buffer.cc | 24 +++++ media/base/decoder_buffer.h | 4 + media/base/decoder_buffer_queue.cc | 12 +-- media/base/decoder_buffer_queue.h | 11 ++- media/base/decoder_buffer_queue_unittest.cc | 34 ++++--- media/base/stream_parser_buffer.cc | 11 +++ media/base/stream_parser_buffer.h | 5 + media/filters/chunk_demuxer.cc | 8 +- media/filters/chunk_demuxer.h | 4 +- media/filters/chunk_demuxer_unittest.cc | 80 ++++++++++------ media/filters/ffmpeg_demuxer.cc | 2 +- media/filters/ffmpeg_demuxer.h | 2 +- media/filters/ffmpeg_demuxer_unittest.cc | 12 ++- media/filters/source_buffer_range.cc | 23 +++-- media/filters/source_buffer_range.h | 11 ++- media/filters/source_buffer_state.cc | 12 +-- media/filters/source_buffer_stream.cc | 14 +-- media/filters/source_buffer_stream.h | 4 +- .../filters/source_buffer_stream_unittest.cc | 95 ++++++++++++------- ...buffer-quota-exceeded-default-buffers.html | 4 +- 20 files changed, 237 insertions(+), 135 deletions(-) diff --git a/media/base/decoder_buffer.cc b/media/base/decoder_buffer.cc index fdc205bb8a4a..bd541d450030 100644 --- a/media/base/decoder_buffer.cc +++ b/media/base/decoder_buffer.cc @@ -289,4 +289,28 @@ void DecoderBuffer::CopySideDataFrom(const uint8_t* side_data, } } +size_t DecoderBuffer::GetMemoryUsage() const { + size_t memory_usage = sizeof(DecoderBuffer); + + if (end_of_stream()) { + return memory_usage; + } + + memory_usage += data_size(); + + // Side data and decrypt config would not change after construction. + if (side_data_size_ > 0) { + memory_usage += side_data_size_; + } + if (decrypt_config_) { + memory_usage += sizeof(DecryptConfig); + memory_usage += decrypt_config_->key_id().capacity(); + memory_usage += decrypt_config_->iv().capacity(); + memory_usage += + sizeof(SubsampleEntry) * decrypt_config_->subsamples().capacity(); + } + + return memory_usage; +} + } // namespace media diff --git a/media/base/decoder_buffer.h b/media/base/decoder_buffer.h index 27a87eb204e5..e41c822f8787 100644 --- a/media/base/decoder_buffer.h +++ b/media/base/decoder_buffer.h @@ -296,6 +296,10 @@ class MEDIA_EXPORT DecoderBuffer // Replaces any existing side data with data copied from |side_data|. void CopySideDataFrom(const uint8_t* side_data, size_t side_data_size); + // Returns total memory usage for both bookkeeping and buffered data. The + // function is added for more accurately memory management. + virtual size_t GetMemoryUsage() const; + protected: friend class base::RefCountedThreadSafe; diff --git a/media/base/decoder_buffer_queue.cc b/media/base/decoder_buffer_queue.cc index 411dc719cb54..b761c53280f6 100644 --- a/media/base/decoder_buffer_queue.cc +++ b/media/base/decoder_buffer_queue.cc @@ -11,7 +11,7 @@ namespace media { DecoderBufferQueue::DecoderBufferQueue() - : earliest_valid_timestamp_(kNoTimestamp), data_size_(0) {} + : earliest_valid_timestamp_(kNoTimestamp) {} DecoderBufferQueue::~DecoderBufferQueue() = default; @@ -21,7 +21,7 @@ void DecoderBufferQueue::Push(scoped_refptr buffer) { DCHECK(!buffer->end_of_stream()); queue_.push_back(buffer); - data_size_ += buffer->data_size(); + memory_usage_in_bytes_ += buffer->GetMemoryUsage(); // TODO(scherkus): FFmpeg returns some packets with no timestamp after // seeking. Fix and turn this into CHECK(). See http://crbug.com/162192 @@ -49,9 +49,9 @@ scoped_refptr DecoderBufferQueue::Pop() { scoped_refptr buffer = std::move(queue_.front()); queue_.pop_front(); - size_t buffer_data_size = buffer->data_size(); - DCHECK_LE(buffer_data_size, data_size_); - data_size_ -= buffer_data_size; + size_t buffer_data_size = buffer->GetMemoryUsage(); + DCHECK_LE(buffer_data_size, memory_usage_in_bytes_); + memory_usage_in_bytes_ -= buffer_data_size; if (!in_order_queue_.empty() && in_order_queue_.front() == buffer) in_order_queue_.pop_front(); @@ -61,7 +61,7 @@ scoped_refptr DecoderBufferQueue::Pop() { void DecoderBufferQueue::Clear() { queue_.clear(); - data_size_ = 0; + memory_usage_in_bytes_ = 0; in_order_queue_.clear(); earliest_valid_timestamp_ = kNoTimestamp; } diff --git a/media/base/decoder_buffer_queue.h b/media/base/decoder_buffer_queue.h index e840a98597b8..3804d23f33e7 100644 --- a/media/base/decoder_buffer_queue.h +++ b/media/base/decoder_buffer_queue.h @@ -56,8 +56,11 @@ class MEDIA_EXPORT DecoderBufferQueue { // Returns zero if the queue is empty. base::TimeDelta Duration(); - // Returns the total size of buffers inside the queue. - size_t data_size() const { return data_size_; } + // Returns the total memory occupied by this class and the buffers it holds, + // including the bookkeeping data and buffered data. For simplicity, the + // bookkeeping data of this class itself isn't included as it's relatively + // small compared to the other data. + size_t memory_usage_in_bytes() const { return memory_usage_in_bytes_; } // Returns the number of buffers in the queue. size_t queue_size() const { return queue_.size(); } @@ -73,8 +76,8 @@ class MEDIA_EXPORT DecoderBufferQueue { base::TimeDelta earliest_valid_timestamp_; - // Total size in bytes of buffers in the queue. - size_t data_size_; + // Total memory usage in bytes for buffers in the queue. + size_t memory_usage_in_bytes_ = 0; }; } // namespace media diff --git a/media/base/decoder_buffer_queue_unittest.cc b/media/base/decoder_buffer_queue_unittest.cc index 4272b142b6ff..8a44fd2bf8ab 100644 --- a/media/base/decoder_buffer_queue_unittest.cc +++ b/media/base/decoder_buffer_queue_unittest.cc @@ -32,6 +32,10 @@ static scoped_refptr CreateBuffer(int timestamp, int size) { return buffer; } +static size_t GetExpectedMemoryUsage(int number_of_buffers, int data_size) { + return number_of_buffers * sizeof(DecoderBuffer) + data_size; +} + TEST(DecoderBufferQueueTest, IsEmpty) { DecoderBufferQueue queue; EXPECT_TRUE(queue.IsEmpty()); @@ -142,28 +146,34 @@ TEST(DecoderBufferQueueTest, Duration_NoTimestamp) { EXPECT_EQ(0, queue.Duration().InSeconds()); } -TEST(DecoderBufferQueueTest, DataSize) { +TEST(DecoderBufferQueueTest, MemoryUsage) { DecoderBufferQueue queue; - EXPECT_EQ(queue.data_size(), 0u); + EXPECT_EQ(queue.memory_usage_in_bytes(), 0u); + + queue.Push(CreateBuffer(0, 0u)); + EXPECT_EQ(queue.memory_usage_in_bytes(), GetExpectedMemoryUsage(1, 0)); + + queue.Pop(); + EXPECT_EQ(queue.memory_usage_in_bytes(), 0u); - queue.Push(CreateBuffer(0, 1200u)); - EXPECT_EQ(queue.data_size(), 1200u); + queue.Push(CreateBuffer(1, 1200u)); + EXPECT_EQ(queue.memory_usage_in_bytes(), GetExpectedMemoryUsage(1, 1200)); - queue.Push(CreateBuffer(1, 1000u)); - EXPECT_EQ(queue.data_size(), 2200u); + queue.Push(CreateBuffer(2, 1000u)); + EXPECT_EQ(queue.memory_usage_in_bytes(), GetExpectedMemoryUsage(2, 2200)); queue.Pop(); - EXPECT_EQ(queue.data_size(), 1000u); + EXPECT_EQ(queue.memory_usage_in_bytes(), GetExpectedMemoryUsage(1, 1000)); - queue.Push(CreateBuffer(2, 999u)); queue.Push(CreateBuffer(3, 999u)); - EXPECT_EQ(queue.data_size(), 2998u); + queue.Push(CreateBuffer(4, 999u)); + EXPECT_EQ(queue.memory_usage_in_bytes(), GetExpectedMemoryUsage(3, 2998)); queue.Clear(); - EXPECT_EQ(queue.data_size(), 0u); + EXPECT_EQ(queue.memory_usage_in_bytes(), GetExpectedMemoryUsage(0, 0)); - queue.Push(CreateBuffer(4, 1400u)); - EXPECT_EQ(queue.data_size(), 1400u); + queue.Push(CreateBuffer(5, 1400u)); + EXPECT_EQ(queue.memory_usage_in_bytes(), GetExpectedMemoryUsage(1, 1400)); } } // namespace media diff --git a/media/base/stream_parser_buffer.cc b/media/base/stream_parser_buffer.cc index b3d75bce07f9..5f98fc000f46 100644 --- a/media/base/stream_parser_buffer.cc +++ b/media/base/stream_parser_buffer.cc @@ -140,4 +140,15 @@ void StreamParserBuffer::set_timestamp(base::TimeDelta timestamp) { preroll_buffer_->set_timestamp(timestamp); } +size_t StreamParserBuffer::GetMemoryUsage() const { + size_t memory_usage = DecoderBuffer::GetMemoryUsage() - + sizeof(DecoderBuffer) + sizeof(StreamParserBuffer); + + if (preroll_buffer_) { + memory_usage += preroll_buffer_->GetMemoryUsage(); + } + + return memory_usage; +} + } // namespace media diff --git a/media/base/stream_parser_buffer.h b/media/base/stream_parser_buffer.h index 1a9638d1a475..6bdc672fd7c8 100644 --- a/media/base/stream_parser_buffer.h +++ b/media/base/stream_parser_buffer.h @@ -182,6 +182,9 @@ class MEDIA_EXPORT StreamParserBuffer : public DecoderBuffer { // // All future timestamp, decode timestamp, config id, or track id changes to // this buffer will be applied to the preroll buffer as well. + // + // TODO(b/331652782): integrate the setter function into the constructor to + // make |preroll_buffer_| immutable. void SetPrerollBuffer(scoped_refptr preroll); scoped_refptr preroll_buffer() { return preroll_buffer_; } @@ -193,6 +196,8 @@ class MEDIA_EXPORT StreamParserBuffer : public DecoderBuffer { is_duration_estimated_ = is_estimated; } + size_t GetMemoryUsage() const override; + private: StreamParserBuffer(std::unique_ptr external_memory, bool is_key_frame, diff --git a/media/filters/chunk_demuxer.cc b/media/filters/chunk_demuxer.cc index 496729f6ae63..6b2410f99d9f 100644 --- a/media/filters/chunk_demuxer.cc +++ b/media/filters/chunk_demuxer.cc @@ -279,9 +279,9 @@ base::TimeDelta ChunkDemuxerStream::GetBufferedDuration() const { return stream_->GetBufferedDuration(); } -size_t ChunkDemuxerStream::GetBufferedSize() const { +size_t ChunkDemuxerStream::GetMemoryUsage() const { base::AutoLock auto_lock(lock_); - return stream_->GetBufferedSize(); + return stream_->GetMemoryUsage(); } void ChunkDemuxerStream::OnStartOfCodedFrameGroup(DecodeTimestamp start_dts, @@ -681,9 +681,9 @@ int64_t ChunkDemuxer::GetMemoryUsage() const { base::AutoLock auto_lock(lock_); int64_t mem = 0; for (const auto& s : audio_streams_) - mem += s->GetBufferedSize(); + mem += s->GetMemoryUsage(); for (const auto& s : video_streams_) - mem += s->GetBufferedSize(); + mem += s->GetMemoryUsage(); return mem; } diff --git a/media/filters/chunk_demuxer.h b/media/filters/chunk_demuxer.h index 99ff035f639a..49b7199e0943 100644 --- a/media/filters/chunk_demuxer.h +++ b/media/filters/chunk_demuxer.h @@ -106,8 +106,8 @@ class MEDIA_EXPORT ChunkDemuxerStream : public DemuxerStream { // Returns base::TimeDelta() if the stream has no buffered data. base::TimeDelta GetBufferedDuration() const; - // Returns the size of the buffered data in bytes. - size_t GetBufferedSize() const; + // Returns the memory usage of the buffered data in bytes. + size_t GetMemoryUsage() const; // Signal to the stream that buffers handed in through subsequent calls to // Append() belong to a coded frame group that starts at |start_pts|. diff --git a/media/filters/chunk_demuxer_unittest.cc b/media/filters/chunk_demuxer_unittest.cc index 4ead9ea28d8d..c06f38fc6212 100644 --- a/media/filters/chunk_demuxer_unittest.cc +++ b/media/filters/chunk_demuxer_unittest.cc @@ -1293,6 +1293,10 @@ class ChunkDemuxerTest : public ::testing::Test { return true; } + int64_t GetExpectedMemoryUsage(int number_of_buffers, int data_size) const { + return number_of_buffers * sizeof(StreamParserBuffer) + data_size; + } + base::test::TaskEnvironment task_environment_; StrictMock media_log_; @@ -2094,7 +2098,7 @@ TEST_F(ChunkDemuxerTest, WebMFile_AudioAndVideo) { ASSERT_TRUE(ParseWebMFile("bear-320x240.webm", buffer_timestamps, base::Milliseconds(2744))); - EXPECT_EQ(212949, demuxer_->GetMemoryUsage()); + EXPECT_EQ(GetExpectedMemoryUsage(248, 212949), demuxer_->GetMemoryUsage()); } TEST_F(ChunkDemuxerTest, WebMFile_LiveAudioAndVideo) { @@ -2116,7 +2120,7 @@ TEST_F(ChunkDemuxerTest, WebMFile_LiveAudioAndVideo) { EXPECT_EQ(StreamLiveness::kLive, audio->liveness()); DemuxerStream* video = GetStream(DemuxerStream::VIDEO); EXPECT_EQ(StreamLiveness::kLive, video->liveness()); - EXPECT_EQ(212949, demuxer_->GetMemoryUsage()); + EXPECT_EQ(GetExpectedMemoryUsage(248, 212949), demuxer_->GetMemoryUsage()); } TEST_F(ChunkDemuxerTest, WebMFile_AudioOnly) { @@ -2138,7 +2142,7 @@ TEST_F(ChunkDemuxerTest, WebMFile_AudioOnly) { ASSERT_TRUE(ParseWebMFile("bear-320x240-audio-only.webm", buffer_timestamps, base::Milliseconds(2744), HAS_AUDIO)); - EXPECT_EQ(18624, demuxer_->GetMemoryUsage()); + EXPECT_EQ(GetExpectedMemoryUsage(166, 18624), demuxer_->GetMemoryUsage()); } TEST_F(ChunkDemuxerTest, WebMFile_VideoOnly) { @@ -2159,7 +2163,7 @@ TEST_F(ChunkDemuxerTest, WebMFile_VideoOnly) { ASSERT_TRUE(ParseWebMFile("bear-320x240-video-only.webm", buffer_timestamps, base::Milliseconds(2703), HAS_VIDEO)); - EXPECT_EQ(194325, demuxer_->GetMemoryUsage()); + EXPECT_EQ(GetExpectedMemoryUsage(82, 194325), demuxer_->GetMemoryUsage()); } TEST_F(ChunkDemuxerTest, WebMFile_AltRefFrames) { @@ -3646,8 +3650,10 @@ TEST_F(ChunkDemuxerTest, SetMemoryLimitType) { ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); // Set different memory limits for audio and video. - demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, 10 * block_size_); - demuxer_->SetMemoryLimitsForTest(DemuxerStream::VIDEO, 5 * block_size_ + 1); + demuxer_->SetMemoryLimitsForTest( + DemuxerStream::AUDIO, GetExpectedMemoryUsage(10, 10 * block_size_)); + demuxer_->SetMemoryLimitsForTest( + DemuxerStream::VIDEO, GetExpectedMemoryUsage(5, 5 * block_size_) + 1); base::TimeDelta seek_time = base::Milliseconds(1000); @@ -3683,7 +3689,8 @@ TEST_F(ChunkDemuxerTest, SetMemoryLimitType) { TEST_F(ChunkDemuxerTest, GCDuringSeek_SingleRange_SeekForward) { ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); - demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, 10 * block_size_); + demuxer_->SetMemoryLimitsForTest( + DemuxerStream::AUDIO, GetExpectedMemoryUsage(10, 10 * block_size_)); // Append some data at position 1000ms AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 1000, 10); CheckExpectedRanges("{ [1000,1230) }"); @@ -3692,8 +3699,8 @@ TEST_F(ChunkDemuxerTest, GCDuringSeek_SingleRange_SeekForward) { // those frames are earlier than the seek target position. base::TimeDelta seek_time = base::Milliseconds(2000); Seek(seek_time); - EXPECT_TRUE( - demuxer_->EvictCodedFrames(kSourceId, seek_time, 5 * block_size_)); + EXPECT_TRUE(demuxer_->EvictCodedFrames( + kSourceId, seek_time, GetExpectedMemoryUsage(5, 5 * block_size_))); // Append data to complete seek operation AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 2000, 5); @@ -3702,7 +3709,8 @@ TEST_F(ChunkDemuxerTest, GCDuringSeek_SingleRange_SeekForward) { TEST_F(ChunkDemuxerTest, GCDuringSeek_SingleRange_SeekBack) { ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); - demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, 10 * block_size_); + demuxer_->SetMemoryLimitsForTest( + DemuxerStream::AUDIO, GetExpectedMemoryUsage(10, 10 * block_size_)); // Append some data at position 1000ms AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 1000, 10); CheckExpectedRanges("{ [1000,1230) }"); @@ -3712,8 +3720,8 @@ TEST_F(ChunkDemuxerTest, GCDuringSeek_SingleRange_SeekBack) { // evicted to make space for the upcoming append at seek target position. base::TimeDelta seek_time = base::TimeDelta(); Seek(seek_time); - EXPECT_TRUE( - demuxer_->EvictCodedFrames(kSourceId, seek_time, 5 * block_size_)); + EXPECT_TRUE(demuxer_->EvictCodedFrames( + kSourceId, seek_time, GetExpectedMemoryUsage(5, 5 * block_size_))); // Append data to complete seek operation AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 0, 5); @@ -3722,7 +3730,8 @@ TEST_F(ChunkDemuxerTest, GCDuringSeek_SingleRange_SeekBack) { TEST_F(ChunkDemuxerTest, GCDuringSeek_MultipleRanges_SeekForward) { ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); - demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, 10 * block_size_); + demuxer_->SetMemoryLimitsForTest( + DemuxerStream::AUDIO, GetExpectedMemoryUsage(10, 10 * block_size_)); // Append some data at position 1000ms then at 2000ms AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 1000, 5); AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 2000, 5); @@ -3732,8 +3741,8 @@ TEST_F(ChunkDemuxerTest, GCDuringSeek_MultipleRanges_SeekForward) { // those frames are earlier than the seek target position. base::TimeDelta seek_time = base::Milliseconds(3000); Seek(seek_time); - EXPECT_TRUE( - demuxer_->EvictCodedFrames(kSourceId, seek_time, 8 * block_size_)); + EXPECT_TRUE(demuxer_->EvictCodedFrames( + kSourceId, seek_time, GetExpectedMemoryUsage(8, 8 * block_size_))); // Append data to complete seek operation AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 3000, 5); @@ -3742,7 +3751,8 @@ TEST_F(ChunkDemuxerTest, GCDuringSeek_MultipleRanges_SeekForward) { TEST_F(ChunkDemuxerTest, GCDuringSeek_MultipleRanges_SeekInbetween1) { ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); - demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, 10 * block_size_); + demuxer_->SetMemoryLimitsForTest( + DemuxerStream::AUDIO, GetExpectedMemoryUsage(10, 10 * block_size_)); // Append some data at position 1000ms then at 2000ms AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 1000, 5); AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 2000, 5); @@ -3758,8 +3768,8 @@ TEST_F(ChunkDemuxerTest, GCDuringSeek_MultipleRanges_SeekInbetween1) { // the upcoming append and allow seek to proceed. base::TimeDelta seek_time = base::Milliseconds(1500); Seek(seek_time); - EXPECT_TRUE( - demuxer_->EvictCodedFrames(kSourceId, seek_time, 8 * block_size_)); + EXPECT_TRUE(demuxer_->EvictCodedFrames( + kSourceId, seek_time, GetExpectedMemoryUsage(8, 8 * block_size_))); // Append data to complete seek operation AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 1500, 5); @@ -3768,7 +3778,8 @@ TEST_F(ChunkDemuxerTest, GCDuringSeek_MultipleRanges_SeekInbetween1) { TEST_F(ChunkDemuxerTest, GCDuringSeek_MultipleRanges_SeekInbetween2) { ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); - demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, 10 * block_size_); + demuxer_->SetMemoryLimitsForTest( + DemuxerStream::AUDIO, GetExpectedMemoryUsage(10, 10 * block_size_)); // Append some data at position 2000ms first, then at 1000ms, so that the last // appended data position is in the first buffered range (that matters to the @@ -3781,8 +3792,8 @@ TEST_F(ChunkDemuxerTest, GCDuringSeek_MultipleRanges_SeekInbetween2) { // without calling Seek(), the GC algorithm should try to preserve data in the // first range, since that is most recently appended data. base::TimeDelta seek_time = base::Milliseconds(2030); - EXPECT_TRUE( - demuxer_->EvictCodedFrames(kSourceId, seek_time, 5 * block_size_)); + EXPECT_TRUE(demuxer_->EvictCodedFrames( + kSourceId, seek_time, GetExpectedMemoryUsage(5, 5 * block_size_))); AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 1500, 5); CheckExpectedRanges("{ [1000,1115) [1500,1615) }"); @@ -3790,7 +3801,8 @@ TEST_F(ChunkDemuxerTest, GCDuringSeek_MultipleRanges_SeekInbetween2) { TEST_F(ChunkDemuxerTest, GCDuringSeek_MultipleRanges_SeekBack) { ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); - demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, 10 * block_size_); + demuxer_->SetMemoryLimitsForTest( + DemuxerStream::AUDIO, GetExpectedMemoryUsage(10, 10 * block_size_)); // Append some data at position 1000ms then at 2000ms AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 1000, 5); AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 2000, 5); @@ -3800,8 +3812,8 @@ TEST_F(ChunkDemuxerTest, GCDuringSeek_MultipleRanges_SeekBack) { // those frames are earlier than the seek target position. base::TimeDelta seek_time = base::TimeDelta(); Seek(seek_time); - EXPECT_TRUE( - demuxer_->EvictCodedFrames(kSourceId, seek_time, 8 * block_size_)); + EXPECT_TRUE(demuxer_->EvictCodedFrames( + kSourceId, seek_time, GetExpectedMemoryUsage(8, 8 * block_size_))); // Append data to complete seek operation AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 0, 5); @@ -3811,7 +3823,8 @@ TEST_F(ChunkDemuxerTest, GCDuringSeek_MultipleRanges_SeekBack) { TEST_F(ChunkDemuxerTest, GCDuringSeek) { ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); - demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, 5 * block_size_); + demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, + GetExpectedMemoryUsage(5, 5 * block_size_)); base::TimeDelta seek_time1 = base::Milliseconds(1000); base::TimeDelta seek_time2 = base::Milliseconds(500); @@ -3856,7 +3869,8 @@ TEST_F(ChunkDemuxerTest, GCDuringSeek) { TEST_F(ChunkDemuxerTest, GCKeepPlayhead) { ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); - demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, 5 * block_size_); + demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, + GetExpectedMemoryUsage(5, 5 * block_size_)); // Append data at the start that can be garbage collected: AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 0, 10); @@ -4213,8 +4227,10 @@ TEST_F(ChunkDemuxerTest, CuesBetweenClusters) { TEST_F(ChunkDemuxerTest, EvictCodedFramesTest) { ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); - demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, 10 * block_size_); - demuxer_->SetMemoryLimitsForTest(DemuxerStream::VIDEO, 15 * block_size_); + demuxer_->SetMemoryLimitsForTest( + DemuxerStream::AUDIO, GetExpectedMemoryUsage(10, 10 * block_size_)); + demuxer_->SetMemoryLimitsForTest( + DemuxerStream::VIDEO, GetExpectedMemoryUsage(15, 15 * block_size_)); DemuxerStream* audio_stream = GetStream(DemuxerStream::AUDIO); DemuxerStream* video_stream = GetStream(DemuxerStream::VIDEO); @@ -4228,11 +4244,12 @@ TEST_F(ChunkDemuxerTest, EvictCodedFramesTest) { CheckExpectedBuffers(audio_stream, kAudioStreamInfo); CheckExpectedBuffers(video_stream, kVideoStreamInfo); - // If we want to append 80 more blocks of muxed a+v data and the current + // If we want to append 8 more blocks of muxed a+v data and the current // position is 0, that will fail, because EvictCodedFrames won't remove the // data after the current playback position. ASSERT_FALSE( - demuxer_->EvictCodedFrames(kSourceId, base::Milliseconds(0), 80)); + demuxer_->EvictCodedFrames(kSourceId, base::Milliseconds(0), + GetExpectedMemoryUsage(8, 8 * block_size_))); // EvictCodedFrames has failed, so data should be unchanged. Seek(base::Milliseconds(0)); CheckExpectedBuffers(audio_stream, kAudioStreamInfo); @@ -4241,7 +4258,8 @@ TEST_F(ChunkDemuxerTest, EvictCodedFramesTest) { // But if we pretend that playback position has moved to 120ms, that allows // EvictCodedFrames to garbage-collect enough data to succeed. ASSERT_TRUE( - demuxer_->EvictCodedFrames(kSourceId, base::Milliseconds(120), 80)); + demuxer_->EvictCodedFrames(kSourceId, base::Milliseconds(120), + GetExpectedMemoryUsage(8, 8 * block_size_))); Seek(base::Milliseconds(0)); // Audio stream had 8 buffers, video stream had 15. We told EvictCodedFrames diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc index d5ab57b0b41b..d6927dfa8185 100644 --- a/media/filters/ffmpeg_demuxer.cc +++ b/media/filters/ffmpeg_demuxer.cc @@ -881,7 +881,7 @@ bool FFmpegDemuxerStream::HasAvailableCapacity() { } size_t FFmpegDemuxerStream::MemoryUsage() const { - return buffer_queue_.data_size(); + return buffer_queue_.memory_usage_in_bytes(); } std::string FFmpegDemuxerStream::GetMetadata(const char* key) const { diff --git a/media/filters/ffmpeg_demuxer.h b/media/filters/ffmpeg_demuxer.h index bbc77cfa4039..518defab5c31 100644 --- a/media/filters/ffmpeg_demuxer.h +++ b/media/filters/ffmpeg_demuxer.h @@ -131,7 +131,7 @@ class MEDIA_EXPORT FFmpegDemuxerStream : public DemuxerStream { // Returns true if this stream has capacity for additional data. bool HasAvailableCapacity(); - // Returns the total buffer size FFMpegDemuxerStream is holding onto. + // Returns the total memory usage of FFMpegDemuxerStream. size_t MemoryUsage() const; TextKind GetTextKind() const; diff --git a/media/filters/ffmpeg_demuxer_unittest.cc b/media/filters/ffmpeg_demuxer_unittest.cc index 8e468977ffd8..eb7d311a1b49 100644 --- a/media/filters/ffmpeg_demuxer_unittest.cc +++ b/media/filters/ffmpeg_demuxer_unittest.cc @@ -334,6 +334,10 @@ class FFmpegDemuxerTest : public testing::Test { event.RunAndWaitForStatus(PIPELINE_OK); } + int64_t GetExpectedMemoryUsage(int number_of_buffers, int data_size) const { + return number_of_buffers * sizeof(DecoderBuffer) + data_size; + } + private: void CreateDemuxerInternal(const std::string& name, MediaLog* media_log) { CHECK(!demuxer_); @@ -541,7 +545,7 @@ TEST_F(FFmpegDemuxerTest, Read_Audio) { DemuxerStream* audio = GetStream(DemuxerStream::AUDIO); Read(audio, FROM_HERE, 29, 0, true); Read(audio, FROM_HERE, 27, 3000, true); - EXPECT_EQ(166866, demuxer_->GetMemoryUsage()); + EXPECT_EQ(GetExpectedMemoryUsage(182, 166866), demuxer_->GetMemoryUsage()); } TEST_F(FFmpegDemuxerTest, Read_Video) { @@ -553,7 +557,7 @@ TEST_F(FFmpegDemuxerTest, Read_Video) { DemuxerStream* video = GetStream(DemuxerStream::VIDEO); Read(video, FROM_HERE, 22084, 0, true); Read(video, FROM_HERE, 1057, 33000, false); - EXPECT_EQ(148778, demuxer_->GetMemoryUsage()); + EXPECT_EQ(GetExpectedMemoryUsage(193, 148778), demuxer_->GetMemoryUsage()); } TEST_F(FFmpegDemuxerTest, SeekInitialized_NoVideoStartTime) { @@ -1740,7 +1744,7 @@ TEST_F(FFmpegDemuxerTest, MultitrackMemoryUsage) { // the first audio and the first video stream are enabled, so the memory usage // shouldn't be too high. Read(audio, FROM_HERE, 304, 0, true); - EXPECT_EQ(22134, demuxer_->GetMemoryUsage()); + EXPECT_EQ(GetExpectedMemoryUsage(152, 22134), demuxer_->GetMemoryUsage()); // Now enable all demuxer streams in the file and perform another read, this // will buffer the data for additional streams and memory usage will increase. @@ -1753,7 +1757,7 @@ TEST_F(FFmpegDemuxerTest, MultitrackMemoryUsage) { // With newly enabled demuxer streams the amount of memory used by the demuxer // is much higher. - EXPECT_EQ(156011, demuxer_->GetMemoryUsage()); + EXPECT_EQ(GetExpectedMemoryUsage(896, 156011), demuxer_->GetMemoryUsage()); } TEST_F(FFmpegDemuxerTest, SeekOnVideoTrackChangeWontSeekIfEmpty) { diff --git a/media/filters/source_buffer_range.cc b/media/filters/source_buffer_range.cc index 07ec131726b1..bd3d2b5720ea 100644 --- a/media/filters/source_buffer_range.cc +++ b/media/filters/source_buffer_range.cc @@ -22,7 +22,6 @@ SourceBufferRange::SourceBufferRange( : gap_policy_(gap_policy), next_buffer_index_(-1), interbuffer_distance_cb_(std::move(interbuffer_distance_cb)), - size_in_bytes_(0), range_start_pts_(range_start_pts), keyframe_map_index_base_(0) { DVLOG(3) << __func__; @@ -122,7 +121,7 @@ void SourceBufferRange::AppendBuffersToEnd( buffers_.push_back(*itr); UpdateEndTime(*itr); - size_in_bytes_ += (*itr)->data_size(); + memory_usage_in_bytes_ += (*itr)->GetMemoryUsage(); if ((*itr)->is_key_frame()) { keyframe_map_.insert(std::make_pair( @@ -331,9 +330,9 @@ size_t SourceBufferRange::DeleteGOPFromFront(BufferQueue* deleted_buffers) { // Delete buffers from the beginning of the buffered range up until (but not // including) the next keyframe. for (int i = 0; i < end_index; i++) { - size_t bytes_deleted = buffers_.front()->data_size(); - DCHECK_GE(size_in_bytes_, bytes_deleted); - size_in_bytes_ -= bytes_deleted; + size_t bytes_deleted = buffers_.front()->GetMemoryUsage(); + DCHECK_GE(memory_usage_in_bytes_, bytes_deleted); + memory_usage_in_bytes_ -= bytes_deleted; total_bytes_deleted += bytes_deleted; deleted_buffers->push_back(buffers_.front()); buffers_.pop_front(); @@ -381,9 +380,9 @@ size_t SourceBufferRange::DeleteGOPFromBack(BufferQueue* deleted_buffers) { size_t total_bytes_deleted = 0; while (buffers_.size() != goal_size) { - size_t bytes_deleted = buffers_.back()->data_size(); - DCHECK_GE(size_in_bytes_, bytes_deleted); - size_in_bytes_ -= bytes_deleted; + size_t bytes_deleted = buffers_.back()->GetMemoryUsage(); + DCHECK_GE(memory_usage_in_bytes_, bytes_deleted); + memory_usage_in_bytes_ -= bytes_deleted; total_bytes_deleted += bytes_deleted; // We're removing buffers from the back, so push each removed buffer to the // front of |deleted_buffers| so that |deleted_buffers| are in nondecreasing @@ -432,7 +431,7 @@ size_t SourceBufferRange::GetRemovalGOP( BufferQueue::const_iterator next_gop_start = buffers_.begin() + next_gop_index; for (; buffer_itr != next_gop_start; ++buffer_itr) { - gop_size += (*buffer_itr)->data_size(); + gop_size += (*buffer_itr)->GetMemoryUsage(); } bytes_removed += gop_size; @@ -706,9 +705,9 @@ void SourceBufferRange::FreeBufferRange( const BufferQueue::const_iterator& ending_point) { for (BufferQueue::const_iterator itr = starting_point; itr != ending_point; ++itr) { - size_t itr_data_size = static_cast((*itr)->data_size()); - DCHECK_GE(size_in_bytes_, itr_data_size); - size_in_bytes_ -= itr_data_size; + size_t itr_data_size = static_cast((*itr)->GetMemoryUsage()); + DCHECK_GE(memory_usage_in_bytes_, itr_data_size); + memory_usage_in_bytes_ -= itr_data_size; } buffers_.erase(starting_point, ending_point); } diff --git a/media/filters/source_buffer_range.h b/media/filters/source_buffer_range.h index f6d36ec992cd..916d189f90bf 100644 --- a/media/filters/source_buffer_range.h +++ b/media/filters/source_buffer_range.h @@ -247,7 +247,8 @@ class MEDIA_EXPORT SourceBufferRange { base::TimeDelta end, BufferQueue* buffers) const; - size_t size_in_bytes() const { return size_in_bytes_; } + // Returns the memory usage of the buffered data in bytes. + size_t GetMemoryUsage() const { return memory_usage_in_bytes_; } private: // Friend of private is only for IsNextInPresentationSequence testing. @@ -263,8 +264,8 @@ class MEDIA_EXPORT SourceBufferRange { void AdjustEstimatedDurationForNewAppend(const BufferQueue& new_buffers); // Frees the buffers in |buffers_| from [|start_point|,|ending_point|) and - // updates the |size_in_bytes_| accordingly. Note, this does not update - // |keyframe_map_|. + // updates the |memory_usage_in_bytes_| accordingly. Note, this does not + // update |keyframe_map_|. void FreeBufferRange(const BufferQueue::const_iterator& starting_point, const BufferQueue::const_iterator& ending_point); @@ -373,8 +374,8 @@ class MEDIA_EXPORT SourceBufferRange { // Called to get the largest interbuffer distance seen so far in the stream. InterbufferDistanceCB interbuffer_distance_cb_; - // Stores the amount of memory taken up by the data in |buffers_|. - size_t size_in_bytes_; + // Stores the amount of memory taken up to store |buffers_|. + size_t memory_usage_in_bytes_ = 0; // If the first buffer in this range is the beginning of a coded frame group, // |range_start_pts_| is the presentation time when the coded frame group diff --git a/media/filters/source_buffer_state.cc b/media/filters/source_buffer_state.cc index ca3c451bdd51..96829c063583 100644 --- a/media/filters/source_buffer_state.cc +++ b/media/filters/source_buffer_state.cc @@ -301,11 +301,11 @@ bool SourceBufferState::EvictCodedFrames(base::TimeDelta media_time, size_t newDataSize) { size_t total_buffered_size = 0; for (const auto& it : audio_streams_) - total_buffered_size += it.second->GetBufferedSize(); + total_buffered_size += it.second->GetMemoryUsage(); for (const auto& it : video_streams_) - total_buffered_size += it.second->GetBufferedSize(); + total_buffered_size += it.second->GetMemoryUsage(); for (const auto& it : text_streams_) - total_buffered_size += it.second->GetBufferedSize(); + total_buffered_size += it.second->GetMemoryUsage(); DVLOG(3) << __func__ << " media_time=" << media_time.InSecondsF() << " newDataSize=" << newDataSize @@ -316,7 +316,7 @@ bool SourceBufferState::EvictCodedFrames(base::TimeDelta media_time, bool success = true; for (const auto& it : audio_streams_) { - uint64_t curr_size = it.second->GetBufferedSize(); + uint64_t curr_size = it.second->GetMemoryUsage(); if (curr_size == 0) continue; uint64_t estimated_new_size = newDataSize * curr_size / total_buffered_size; @@ -325,7 +325,7 @@ bool SourceBufferState::EvictCodedFrames(base::TimeDelta media_time, media_time, static_cast(estimated_new_size)); } for (const auto& it : video_streams_) { - uint64_t curr_size = it.second->GetBufferedSize(); + uint64_t curr_size = it.second->GetMemoryUsage(); if (curr_size == 0) continue; uint64_t estimated_new_size = newDataSize * curr_size / total_buffered_size; @@ -334,7 +334,7 @@ bool SourceBufferState::EvictCodedFrames(base::TimeDelta media_time, media_time, static_cast(estimated_new_size)); } for (const auto& it : text_streams_) { - uint64_t curr_size = it.second->GetBufferedSize(); + uint64_t curr_size = it.second->GetMemoryUsage(); if (curr_size == 0) continue; uint64_t estimated_new_size = newDataSize * curr_size / total_buffered_size; diff --git a/media/filters/source_buffer_stream.cc b/media/filters/source_buffer_stream.cc index d7412584df88..55347c869b26 100644 --- a/media/filters/source_buffer_stream.cc +++ b/media/filters/source_buffer_stream.cc @@ -86,7 +86,7 @@ std::string StatusToString(const SourceBufferStreamStatus& status) { // Helper method for logging, converts a range into a readable string. std::string RangeToString(const SourceBufferRange& range) { - if (range.size_in_bytes() == 0) { + if (range.GetMemoryUsage() == 0) { return "[]"; } std::stringstream ss; @@ -785,7 +785,7 @@ bool SourceBufferStream::GarbageCollectIfNeeded(base::TimeDelta media_time, if (!base::FeatureList::IsEnabled(kMemoryPressureBasedSourceBufferGC)) DCHECK(!end_of_stream_); // Compute size of |ranges_|. - size_t ranges_size = GetBufferedSize(); + size_t ranges_size = GetMemoryUsage(); // Sanity and overflow checks if ((newDataSize > memory_limit_) || @@ -1082,7 +1082,7 @@ size_t SourceBufferStream::FreeBuffers(size_t total_bytes_to_free, bytes_freed += bytes_deleted; } - if (current_range->size_in_bytes() == 0) { + if (current_range->GetMemoryUsage() == 0) { DCHECK_NE(current_range, selected_range_); DCHECK(range_for_next_append_ == ranges_.end() || range_for_next_append_->get() != current_range); @@ -1745,11 +1745,11 @@ base::TimeDelta SourceBufferStream::GetBufferedDuration() const { return ranges_.back()->GetBufferedEndTimestamp(); } -size_t SourceBufferStream::GetBufferedSize() const { - size_t ranges_size = 0; +size_t SourceBufferStream::GetMemoryUsage() const { + size_t memory_usage = 0; for (const auto& range_ptr : ranges_) - ranges_size += range_ptr->size_in_bytes(); - return ranges_size; + memory_usage += range_ptr->GetMemoryUsage(); + return memory_usage; } void SourceBufferStream::MarkEndOfStream() { diff --git a/media/filters/source_buffer_stream.h b/media/filters/source_buffer_stream.h index 8a89cc494867..19849e85b683 100644 --- a/media/filters/source_buffer_stream.h +++ b/media/filters/source_buffer_stream.h @@ -147,8 +147,8 @@ class MEDIA_EXPORT SourceBufferStream { // then base::TimeDelta() is returned. base::TimeDelta GetBufferedDuration() const; - // Returns the size of the buffered data in bytes. - size_t GetBufferedSize() const; + // Returns the memory usage of the buffered data in bytes. + size_t GetMemoryUsage() const; // Notifies this object that end of stream has been signalled. void MarkEndOfStream(); diff --git a/media/filters/source_buffer_stream_unittest.cc b/media/filters/source_buffer_stream_unittest.cc index 81af440b4dbf..4c127e60f934 100644 --- a/media/filters/source_buffer_stream_unittest.cc +++ b/media/filters/source_buffer_stream_unittest.cc @@ -85,7 +85,7 @@ class SourceBufferStreamTest : public testing::Test { } void SetMemoryLimit(size_t buffers_of_data) { - stream_->set_memory_limit(buffers_of_data * kDataSize); + stream_->set_memory_limit(buffers_of_data * GetMemoryUsagePerBuffer()); } void SetStreamInfo(int frames_per_second, int keyframes_per_second) { @@ -430,6 +430,10 @@ class SourceBufferStreamTest : public testing::Test { << "\nActual: " << actual.AsHumanReadableString(); } + int GetMemoryUsagePerBuffer() const { + return kDataSize + sizeof(StreamParserBuffer); + } + base::TimeDelta frame_duration() const { return frame_duration_; } StrictMock media_log_; @@ -2599,7 +2603,8 @@ TEST_F(SourceBufferStreamTest, // GOP in that first range. Neither can it collect the last appended GOP // (which is the entire second range), so GC should return false since it // couldn't collect enough. - EXPECT_FALSE(GarbageCollect(base::Milliseconds(95), 7)); + EXPECT_FALSE( + GarbageCollect(base::Milliseconds(95), 7 * GetMemoryUsagePerBuffer())); CheckExpectedRangesByTimestamp("{ [50,100) [1000,1050) }"); } @@ -3261,45 +3266,53 @@ TEST_F(SourceBufferStreamTest, GetRemovalRange_BytesToFree) { EXPECT_EQ(0, bytes_removed); // Smaller than the size of GOP. - bytes_removed = GetRemovalRangeInMs(300, 1080, 1, &remove_range_end); + bytes_removed = GetRemovalRangeInMs(300, 1080, GetMemoryUsagePerBuffer(), + &remove_range_end); EXPECT_EQ(390, remove_range_end); // Remove as the size of GOP. - EXPECT_EQ(3, bytes_removed); + EXPECT_EQ(3 * GetMemoryUsagePerBuffer(), bytes_removed); // The same size with a GOP. - bytes_removed = GetRemovalRangeInMs(300, 1080, 3, &remove_range_end); + bytes_removed = GetRemovalRangeInMs(300, 1080, 3 * GetMemoryUsagePerBuffer(), + &remove_range_end); EXPECT_EQ(390, remove_range_end); - EXPECT_EQ(3, bytes_removed); + EXPECT_EQ(3 * GetMemoryUsagePerBuffer(), bytes_removed); // The same size with a range. - bytes_removed = GetRemovalRangeInMs(300, 1080, 6, &remove_range_end); + bytes_removed = GetRemovalRangeInMs(300, 1080, 6 * GetMemoryUsagePerBuffer(), + &remove_range_end); EXPECT_EQ(480, remove_range_end); - EXPECT_EQ(6, bytes_removed); + EXPECT_EQ(6 * GetMemoryUsagePerBuffer(), bytes_removed); // A frame larger than a range. - bytes_removed = GetRemovalRangeInMs(300, 1080, 7, &remove_range_end); + bytes_removed = GetRemovalRangeInMs(300, 1080, 7 * GetMemoryUsagePerBuffer(), + &remove_range_end); EXPECT_EQ(690, remove_range_end); - EXPECT_EQ(9, bytes_removed); + EXPECT_EQ(9 * GetMemoryUsagePerBuffer(), bytes_removed); // The same size with two ranges. - bytes_removed = GetRemovalRangeInMs(300, 1080, 12, &remove_range_end); + bytes_removed = GetRemovalRangeInMs(300, 1080, 12 * GetMemoryUsagePerBuffer(), + &remove_range_end); EXPECT_EQ(780, remove_range_end); - EXPECT_EQ(12, bytes_removed); + EXPECT_EQ(12 * GetMemoryUsagePerBuffer(), bytes_removed); // Larger than two ranges. - bytes_removed = GetRemovalRangeInMs(300, 1080, 14, &remove_range_end); + bytes_removed = GetRemovalRangeInMs(300, 1080, 14 * GetMemoryUsagePerBuffer(), + &remove_range_end); EXPECT_EQ(990, remove_range_end); - EXPECT_EQ(15, bytes_removed); + EXPECT_EQ(15 * GetMemoryUsagePerBuffer(), bytes_removed); // The same size with the whole ranges. - bytes_removed = GetRemovalRangeInMs(300, 1080, 18, &remove_range_end); + bytes_removed = GetRemovalRangeInMs(300, 1080, 18 * GetMemoryUsagePerBuffer(), + &remove_range_end); EXPECT_EQ(1080, remove_range_end); - EXPECT_EQ(18, bytes_removed); + EXPECT_EQ(18 * GetMemoryUsagePerBuffer(), bytes_removed); // Larger than the whole ranges. - bytes_removed = GetRemovalRangeInMs(300, 1080, 20, &remove_range_end); + bytes_removed = GetRemovalRangeInMs(300, 1080, 20 * GetMemoryUsagePerBuffer(), + &remove_range_end); EXPECT_EQ(1080, remove_range_end); - EXPECT_EQ(18, bytes_removed); + EXPECT_EQ(18 * GetMemoryUsagePerBuffer(), bytes_removed); } TEST_F(SourceBufferStreamTest, GetRemovalRange_Range) { @@ -3318,54 +3331,64 @@ TEST_F(SourceBufferStreamTest, GetRemovalRange_Range) { int bytes_removed = -1; // Within a GOP and no keyframe. - bytes_removed = GetRemovalRangeInMs(630, 660, 20, &remove_range_end); + bytes_removed = GetRemovalRangeInMs(630, 660, 20 * GetMemoryUsagePerBuffer(), + &remove_range_end); EXPECT_EQ(-1, remove_range_end); EXPECT_EQ(0, bytes_removed); // Across a GOP and no keyframe. - bytes_removed = GetRemovalRangeInMs(630, 750, 20, &remove_range_end); + bytes_removed = GetRemovalRangeInMs(630, 750, 20 * GetMemoryUsagePerBuffer(), + &remove_range_end); EXPECT_EQ(-1, remove_range_end); EXPECT_EQ(0, bytes_removed); // The same size with a range. - bytes_removed = GetRemovalRangeInMs(600, 780, 20, &remove_range_end); + bytes_removed = GetRemovalRangeInMs(600, 780, 20 * GetMemoryUsagePerBuffer(), + &remove_range_end); EXPECT_EQ(780, remove_range_end); - EXPECT_EQ(6, bytes_removed); + EXPECT_EQ(6 * GetMemoryUsagePerBuffer(), bytes_removed); // One frame larger than a range. - bytes_removed = GetRemovalRangeInMs(570, 810, 20, &remove_range_end); + bytes_removed = GetRemovalRangeInMs(570, 810, 20 * GetMemoryUsagePerBuffer(), + &remove_range_end); EXPECT_EQ(780, remove_range_end); - EXPECT_EQ(6, bytes_removed); + EXPECT_EQ(6 * GetMemoryUsagePerBuffer(), bytes_removed); // Facing the other ranges. - bytes_removed = GetRemovalRangeInMs(480, 900, 20, &remove_range_end); + bytes_removed = GetRemovalRangeInMs(480, 900, 20 * GetMemoryUsagePerBuffer(), + &remove_range_end); EXPECT_EQ(780, remove_range_end); - EXPECT_EQ(6, bytes_removed); + EXPECT_EQ(6 * GetMemoryUsagePerBuffer(), bytes_removed); // In the midle of the other ranges, but not including any GOP. - bytes_removed = GetRemovalRangeInMs(420, 960, 20, &remove_range_end); + bytes_removed = GetRemovalRangeInMs(420, 960, 20 * GetMemoryUsagePerBuffer(), + &remove_range_end); EXPECT_EQ(780, remove_range_end); - EXPECT_EQ(6, bytes_removed); + EXPECT_EQ(6 * GetMemoryUsagePerBuffer(), bytes_removed); // In the middle of the other ranges. - bytes_removed = GetRemovalRangeInMs(390, 990, 20, &remove_range_end); + bytes_removed = GetRemovalRangeInMs(390, 990, 20 * GetMemoryUsagePerBuffer(), + &remove_range_end); EXPECT_EQ(990, remove_range_end); - EXPECT_EQ(12, bytes_removed); + EXPECT_EQ(12 * GetMemoryUsagePerBuffer(), bytes_removed); // A frame smaller than the whole ranges. - bytes_removed = GetRemovalRangeInMs(330, 1050, 20, &remove_range_end); + bytes_removed = GetRemovalRangeInMs(330, 1050, 20 * GetMemoryUsagePerBuffer(), + &remove_range_end); EXPECT_EQ(990, remove_range_end); - EXPECT_EQ(12, bytes_removed); + EXPECT_EQ(12 * GetMemoryUsagePerBuffer(), bytes_removed); // The same with the whole ranges. - bytes_removed = GetRemovalRangeInMs(300, 1080, 20, &remove_range_end); + bytes_removed = GetRemovalRangeInMs(300, 1080, 20 * GetMemoryUsagePerBuffer(), + &remove_range_end); EXPECT_EQ(1080, remove_range_end); - EXPECT_EQ(18, bytes_removed); + EXPECT_EQ(18 * GetMemoryUsagePerBuffer(), bytes_removed); // Larger than the whole ranges. - bytes_removed = GetRemovalRangeInMs(270, 1110, 20, &remove_range_end); + bytes_removed = GetRemovalRangeInMs(270, 1110, 20 * GetMemoryUsagePerBuffer(), + &remove_range_end); EXPECT_EQ(1080, remove_range_end); - EXPECT_EQ(18, bytes_removed); + EXPECT_EQ(18 * GetMemoryUsagePerBuffer(), bytes_removed); } TEST_F(SourceBufferStreamTest, IsNextBufferConfigChanged) { diff --git a/third_party/blink/web_tests/http/tests/media/media-source/stream_memory_tests/mediasource-appendbuffer-quota-exceeded-default-buffers.html b/third_party/blink/web_tests/http/tests/media/media-source/stream_memory_tests/mediasource-appendbuffer-quota-exceeded-default-buffers.html index 2e704f6478d9..0b9a7d7f42e7 100644 --- a/third_party/blink/web_tests/http/tests/media/media-source/stream_memory_tests/mediasource-appendbuffer-quota-exceeded-default-buffers.html +++ b/third_party/blink/web_tests/http/tests/media/media-source/stream_memory_tests/mediasource-appendbuffer-quota-exceeded-default-buffers.html @@ -12,8 +12,8 @@ var subType = MediaSourceUtil.getSubType(MediaSourceUtil.AUDIO_ONLY_TYPE); var mediaDataManifest = subType + '/test-a-5min-44100Hz-1ch-manifest.json'; MediaSourceUtil.fillUpSourceBuffer(test, mediaSource, mediaDataManifest, function (appendedDataSize) { // onBufferFull - assert_greater_than(appendedDataSize, 12 * 1048576, "Appended more than 12MB of data"); - assert_less_than(appendedDataSize, 14 * 1048576, "Appended less than 14MB of data"); + assert_greater_than(appendedDataSize, 2 * 1048576, "Appended more than 2MB of data"); + assert_less_than(appendedDataSize, 3 * 1048576, "Appended less than 3MB of data"); test.done(); }); }, 'Appending data repeatedly should fill up the buffer and throw a QuotaExceededError when buffer is full.');