Chromium Code Reviews| Index: media/filters/chunk_demuxer_unittest.cc |
| diff --git a/media/filters/chunk_demuxer_unittest.cc b/media/filters/chunk_demuxer_unittest.cc |
| index 3d99e3d4fd353920b285e7d36fc01f8c2cf47375..eaab7d89d429b1b3f299f6b7d292d44e58c05718 100644 |
| --- a/media/filters/chunk_demuxer_unittest.cc |
| +++ b/media/filters/chunk_demuxer_unittest.cc |
| @@ -3334,7 +3334,7 @@ TEST_F(ChunkDemuxerTest, SetMemoryLimitType) { |
| // Set different memory limits for audio and video. |
| demuxer_->SetMemoryLimits(DemuxerStream::AUDIO, 10 * kBlockSize); |
| - demuxer_->SetMemoryLimits(DemuxerStream::VIDEO, 5 * kBlockSize); |
| + demuxer_->SetMemoryLimits(DemuxerStream::VIDEO, 5 * kBlockSize + 1); |
| base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(1000); |
| @@ -3342,6 +3342,10 @@ TEST_F(ChunkDemuxerTest, SetMemoryLimitType) { |
| AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 0, 10); |
| AppendSingleStreamCluster(kSourceId, kVideoTrackNum, 0, 5); |
| + // We should be right at buffer limit, should pass |
| + EXPECT_TRUE(demuxer_->EvictCodedFrames( |
| + kSourceId, base::TimeDelta::FromMilliseconds(0), 0)); |
| + |
| CheckExpectedRanges(DemuxerStream::AUDIO, "{ [0,230) }"); |
| CheckExpectedRanges(DemuxerStream::VIDEO, "{ [0,165) }"); |
| @@ -3354,6 +3358,9 @@ TEST_F(ChunkDemuxerTest, SetMemoryLimitType) { |
| AppendSingleStreamCluster(kSourceId, kVideoTrackNum, |
| seek_time.InMilliseconds(), 5); |
| + // We should delete first append, and be exactly at buffer limit |
| + EXPECT_TRUE(demuxer_->EvictCodedFrames(kSourceId, seek_time, 0)); |
| + |
| // Verify that the old data, and nothing more, has been garbage collected. |
| CheckExpectedRanges(DemuxerStream::AUDIO, "{ [1000,1230) }"); |
| CheckExpectedRanges(DemuxerStream::VIDEO, "{ [1000,1165) }"); |
| @@ -3375,31 +3382,72 @@ TEST_F(ChunkDemuxerTest, GCDuringSeek) { |
| seek_time1.InMilliseconds(), 5); |
| CheckExpectedRanges(kSourceId, "{ [1000,1115) }"); |
| + // We are under memory limit, so Evict should be a no-op. |
| + EXPECT_TRUE(demuxer_->EvictCodedFrames(kSourceId, seek_time1, 0)); |
| + CheckExpectedRanges(kSourceId, "{ [1000,1115) }"); |
| + |
| // Signal that the second seek is starting. |
| demuxer_->StartWaitingForSeek(seek_time2); |
| - // Append data to satisfy the second seek. This append triggers |
| - // the garbage collection logic since we set the memory limit to |
| - // 5 blocks. |
| + // Append data to satisfy the second seek. |
| AppendSingleStreamCluster(kSourceId, kAudioTrackNum, |
| seek_time2.InMilliseconds(), 5); |
| + CheckExpectedRanges(kSourceId, "{ [500,615) [1000,1115) }"); |
| - // Verify that the buffers that cover |seek_time2| do not get |
| - // garbage collected. |
| + // We are now over our memory usage limit. We have just seeked to |seek_time2| |
| + // so data around 500ms position should be preserved, while the previous |
| + // append at 1000ms should be removed. |
| + EXPECT_TRUE(demuxer_->EvictCodedFrames(kSourceId, seek_time2, 0)); |
| CheckExpectedRanges(kSourceId, "{ [500,615) }"); |
| // Complete the seek. |
| demuxer_->Seek(seek_time2, NewExpectedStatusCB(PIPELINE_OK)); |
| - |
| - // Append more data and make sure that the blocks for |seek_time2| |
| - // don't get removed. |
| - // |
| - // NOTE: The current GC algorithm tries to preserve the GOP at the |
| - // current position as well as the last appended GOP. This is |
| - // why there are 2 ranges in the expectations. |
| + // Append more data and make sure that we preserve both the buffered range |
| + // around |seek_time2|, because that's the current playback position, |
| + // and the newly appended range, since this is the most recent append. |
| AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 700, 5); |
| - CheckExpectedRanges(kSourceId, "{ [500,592) [792,815) }"); |
| + EXPECT_FALSE(demuxer_->EvictCodedFrames(kSourceId, seek_time2, 0)); |
| + CheckExpectedRanges(kSourceId, "{ [500,615) [700,815) }"); |
| +} |
| + |
| +TEST_F(ChunkDemuxerTest, GCKeepPlayhead) { |
| + ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); |
| + |
| + demuxer_->SetMemoryLimits(DemuxerStream::AUDIO, 5 * kBlockSize); |
| + |
| + // Append data at the start that can be garbage collected: |
| + AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 0, 10); |
| + CheckExpectedRanges(kSourceId, "{ [0,230) }"); |
| + |
| + // We expect garbage collection to fail, as we don't want to spontaneously |
| + // create gaps in source buffer stream. Gaps could break playback for many |
| + // clients, who don't bother to check ranges after append. |
| + EXPECT_FALSE(demuxer_->EvictCodedFrames( |
| + kSourceId, base::TimeDelta::FromMilliseconds(0), 0)); |
| + CheckExpectedRanges(kSourceId, "{ [0,230) }"); |
| + |
| + // Increase media_time a bit, this will allow some data to be collected, but |
| + // we are still over memory usage limit. |
| + base::TimeDelta seek_time1 = base::TimeDelta::FromMilliseconds(23*2); |
| + Seek(seek_time1); |
| + EXPECT_FALSE(demuxer_->EvictCodedFrames(kSourceId, seek_time1, 0)); |
| + CheckExpectedRanges(kSourceId, "{ [46,230) }"); |
| + |
| + base::TimeDelta seek_time2 = base::TimeDelta::FromMilliseconds(23*4); |
| + Seek(seek_time2); |
| + EXPECT_FALSE(demuxer_->EvictCodedFrames(kSourceId, seek_time2, 0)); |
| + CheckExpectedRanges(kSourceId, "{ [92,230) }"); |
| + |
| + // media_time has progressed to a point where we can collect enough data to |
| + // be under memory limit, so Evict should return true. |
| + base::TimeDelta seek_time3 = base::TimeDelta::FromMilliseconds(23*6); |
| + Seek(seek_time3); |
| + EXPECT_TRUE(demuxer_->EvictCodedFrames(kSourceId, seek_time3, 0)); |
| + // Strictly speaking the current playback time is 23*6==138ms, so we could |
| + // release data up to 138ms, but we only release as much data as necessary |
| + // to bring memory usage under the limit, so we release only up to 115ms. |
| + CheckExpectedRanges(kSourceId, "{ [115,230) }"); |
| } |
| TEST_F(ChunkDemuxerTest, AppendWindow_Video) { |
| @@ -3754,4 +3802,48 @@ TEST_F(ChunkDemuxerTest, CuesBetweenClusters) { |
| CheckExpectedRanges(kSourceId, "{ [0,115) }"); |
| } |
| +TEST_F(ChunkDemuxerTest, EvictCodedFramesTest) { |
|
wolenetz
2015/08/21 18:15:57
Please update this test to expose the problem with
|
| + ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); |
| + demuxer_->SetMemoryLimits(DemuxerStream::AUDIO, 10 * kBlockSize); |
| + demuxer_->SetMemoryLimits(DemuxerStream::VIDEO, 10 * kBlockSize); |
| + DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO); |
| + DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO); |
| + |
| + // Append 8 blocks (80 bytes) of data to each stream |
| + AppendMuxedCluster( |
| + MuxedStreamInfo(kAudioTrackNum, "0K 20K 40K 60K 80K 100K 120K 140K"), |
| + MuxedStreamInfo(kVideoTrackNum, "0K 30 60 90 120K 150 180 210K")); |
| + CheckExpectedBuffers(audio_stream, "0K 20K 40K 60K 80K 100K 120K 140K"); |
| + CheckExpectedBuffers(video_stream, "0K 30 60 90 120K 150 180 210K"); |
| + |
| + // If we want to append 80 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::TimeDelta::FromMilliseconds(0), |
| + 80)); |
| + // EvictCodedFrames has failed, so data should be unchanged. |
| + Seek(base::TimeDelta::FromMilliseconds(0)); |
| + CheckExpectedBuffers(audio_stream, "0K 20K 40K 60K 80K 100K 120K 140K"); |
| + CheckExpectedBuffers(video_stream, "0K 30 60 90 120K 150 180 210K"); |
| + |
| + // But if we pretend that playback position has moved to 100ms, that allows |
| + // EvictCodedFrames to garbage-collect enough data to succeed. |
| + ASSERT_TRUE(demuxer_->EvictCodedFrames(kSourceId, |
| + base::TimeDelta::FromMilliseconds(120), |
| + 80)); |
| + // EvictCodedFrames will remove some data from the front of both buffers. |
| + Seek(base::TimeDelta::FromMilliseconds(0)); |
| + // Audio stream had 8 buffers, memory limit is 10, we told EvictCodedFrames |
| + // that the new data size is 8 blocks muxed. Since we have equal amounts of |
| + // audio and video data size, EvictCodedFrames assumes the new data is 4 audio |
| + // blocks and 4 video blocks. It will remove 2 audio blocks, since that's |
| + // enough to accomodate 4 newly appended audio blocks and still stay under the |
| + // 10 block memory limit. |
| + CheckExpectedBuffers(audio_stream, "40K 60K 80K 100K 120K 140K"); |
| + // For video stream EvictCodedFrames removes GOP at a time, so the whole first |
| + // GOP will be removed. |
| + CheckExpectedBuffers(video_stream, "120K 150 180 210K"); |
| +} |
| + |
| } // namespace media |