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

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

Issue 1008463002: Fix MSE GC, make it less aggressive, more spec-compliant (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Added overflow check to sanity checks and use CHECK instead of DCHECK Created 5 years, 4 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 <algorithm> 5 #include <algorithm>
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/message_loop/message_loop.h" 8 #include "base/message_loop/message_loop.h"
9 #include "base/strings/string_number_conversions.h" 9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/string_split.h" 10 #include "base/strings/string_split.h"
(...skipping 3316 matching lines...) Expand 10 before | Expand all | Expand 10 after
3327 3327
3328 // Append data to satisfy the seek. 3328 // Append data to satisfy the seek.
3329 AppendCluster(seek_time.InMilliseconds(), 10); 3329 AppendCluster(seek_time.InMilliseconds(), 10);
3330 } 3330 }
3331 3331
3332 TEST_F(ChunkDemuxerTest, SetMemoryLimitType) { 3332 TEST_F(ChunkDemuxerTest, SetMemoryLimitType) {
3333 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 3333 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
3334 3334
3335 // Set different memory limits for audio and video. 3335 // Set different memory limits for audio and video.
3336 demuxer_->SetMemoryLimits(DemuxerStream::AUDIO, 10 * kBlockSize); 3336 demuxer_->SetMemoryLimits(DemuxerStream::AUDIO, 10 * kBlockSize);
3337 demuxer_->SetMemoryLimits(DemuxerStream::VIDEO, 5 * kBlockSize); 3337 demuxer_->SetMemoryLimits(DemuxerStream::VIDEO, 5 * kBlockSize + 1);
3338 3338
3339 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(1000); 3339 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(1000);
3340 3340
3341 // Append data at the start that can be garbage collected: 3341 // Append data at the start that can be garbage collected:
3342 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 0, 10); 3342 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 0, 10);
3343 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, 0, 5); 3343 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, 0, 5);
3344 3344
3345 // We should be right at buffer limit, should pass
3346 EXPECT_TRUE(demuxer_->EvictCodedFrames(
3347 kSourceId, base::TimeDelta::FromMilliseconds(0), 0));
3348
3345 CheckExpectedRanges(DemuxerStream::AUDIO, "{ [0,230) }"); 3349 CheckExpectedRanges(DemuxerStream::AUDIO, "{ [0,230) }");
3346 CheckExpectedRanges(DemuxerStream::VIDEO, "{ [0,165) }"); 3350 CheckExpectedRanges(DemuxerStream::VIDEO, "{ [0,165) }");
3347 3351
3348 // Seek so we can garbage collect the data appended above. 3352 // Seek so we can garbage collect the data appended above.
3349 Seek(seek_time); 3353 Seek(seek_time);
3350 3354
3351 // Append data at seek_time. 3355 // Append data at seek_time.
3352 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 3356 AppendSingleStreamCluster(kSourceId, kAudioTrackNum,
3353 seek_time.InMilliseconds(), 10); 3357 seek_time.InMilliseconds(), 10);
3354 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, 3358 AppendSingleStreamCluster(kSourceId, kVideoTrackNum,
3355 seek_time.InMilliseconds(), 5); 3359 seek_time.InMilliseconds(), 5);
3356 3360
3361 // We should delete first append, and be exactly at buffer limit
3362 EXPECT_TRUE(demuxer_->EvictCodedFrames(kSourceId, seek_time, 0));
3363
3357 // Verify that the old data, and nothing more, has been garbage collected. 3364 // Verify that the old data, and nothing more, has been garbage collected.
3358 CheckExpectedRanges(DemuxerStream::AUDIO, "{ [1000,1230) }"); 3365 CheckExpectedRanges(DemuxerStream::AUDIO, "{ [1000,1230) }");
3359 CheckExpectedRanges(DemuxerStream::VIDEO, "{ [1000,1165) }"); 3366 CheckExpectedRanges(DemuxerStream::VIDEO, "{ [1000,1165) }");
3360 } 3367 }
3361 3368
3362 TEST_F(ChunkDemuxerTest, GCDuringSeek) { 3369 TEST_F(ChunkDemuxerTest, GCDuringSeek) {
3363 ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); 3370 ASSERT_TRUE(InitDemuxer(HAS_AUDIO));
3364 3371
3365 demuxer_->SetMemoryLimits(DemuxerStream::AUDIO, 5 * kBlockSize); 3372 demuxer_->SetMemoryLimits(DemuxerStream::AUDIO, 5 * kBlockSize);
3366 3373
3367 base::TimeDelta seek_time1 = base::TimeDelta::FromMilliseconds(1000); 3374 base::TimeDelta seek_time1 = base::TimeDelta::FromMilliseconds(1000);
3368 base::TimeDelta seek_time2 = base::TimeDelta::FromMilliseconds(500); 3375 base::TimeDelta seek_time2 = base::TimeDelta::FromMilliseconds(500);
3369 3376
3370 // Initiate a seek to |seek_time1|. 3377 // Initiate a seek to |seek_time1|.
3371 Seek(seek_time1); 3378 Seek(seek_time1);
3372 3379
3373 // Append data to satisfy the first seek request. 3380 // Append data to satisfy the first seek request.
3374 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 3381 AppendSingleStreamCluster(kSourceId, kAudioTrackNum,
3375 seek_time1.InMilliseconds(), 5); 3382 seek_time1.InMilliseconds(), 5);
3376 CheckExpectedRanges(kSourceId, "{ [1000,1115) }"); 3383 CheckExpectedRanges(kSourceId, "{ [1000,1115) }");
3377 3384
3385 // We are under memory limit, so Evict should be a no-op.
3386 EXPECT_TRUE(demuxer_->EvictCodedFrames(kSourceId, seek_time1, 0));
3387 CheckExpectedRanges(kSourceId, "{ [1000,1115) }");
3388
3378 // Signal that the second seek is starting. 3389 // Signal that the second seek is starting.
3379 demuxer_->StartWaitingForSeek(seek_time2); 3390 demuxer_->StartWaitingForSeek(seek_time2);
3380 3391
3381 // Append data to satisfy the second seek. This append triggers 3392 // Append data to satisfy the second seek.
3382 // the garbage collection logic since we set the memory limit to
3383 // 5 blocks.
3384 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 3393 AppendSingleStreamCluster(kSourceId, kAudioTrackNum,
3385 seek_time2.InMilliseconds(), 5); 3394 seek_time2.InMilliseconds(), 5);
3395 CheckExpectedRanges(kSourceId, "{ [500,615) [1000,1115) }");
3386 3396
3387 // Verify that the buffers that cover |seek_time2| do not get 3397 // We are now over our memory usage limit. We have just seeked to |seek_time2|
3388 // garbage collected. 3398 // so data around 500ms position should be preserved, while the previous
3399 // append at 1000ms should be removed.
3400 EXPECT_TRUE(demuxer_->EvictCodedFrames(kSourceId, seek_time2, 0));
3389 CheckExpectedRanges(kSourceId, "{ [500,615) }"); 3401 CheckExpectedRanges(kSourceId, "{ [500,615) }");
3390 3402
3391 // Complete the seek. 3403 // Complete the seek.
3392 demuxer_->Seek(seek_time2, NewExpectedStatusCB(PIPELINE_OK)); 3404 demuxer_->Seek(seek_time2, NewExpectedStatusCB(PIPELINE_OK));
3393 3405
3406 // Append more data and make sure that we preserve both the buffered range
3407 // around |seek_time2|, because that's the current playback position,
3408 // and the newly appended range, since this is the most recent append.
3409 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 700, 5);
3410 EXPECT_FALSE(demuxer_->EvictCodedFrames(kSourceId, seek_time2, 0));
3411 CheckExpectedRanges(kSourceId, "{ [500,615) [700,815) }");
3412 }
3394 3413
3395 // Append more data and make sure that the blocks for |seek_time2| 3414 TEST_F(ChunkDemuxerTest, GCKeepPlayhead) {
3396 // don't get removed. 3415 ASSERT_TRUE(InitDemuxer(HAS_AUDIO));
3397 // 3416
3398 // NOTE: The current GC algorithm tries to preserve the GOP at the 3417 demuxer_->SetMemoryLimits(DemuxerStream::AUDIO, 5 * kBlockSize);
3399 // current position as well as the last appended GOP. This is 3418
3400 // why there are 2 ranges in the expectations. 3419 // Append data at the start that can be garbage collected:
3401 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 700, 5); 3420 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 0, 10);
3402 CheckExpectedRanges(kSourceId, "{ [500,592) [792,815) }"); 3421 CheckExpectedRanges(kSourceId, "{ [0,230) }");
3422
3423 // We expect garbage collection to fail, as we don't want to spontaneously
3424 // create gaps in source buffer stream. Gaps could break playback for many
3425 // clients, who don't bother to check ranges after append.
3426 EXPECT_FALSE(demuxer_->EvictCodedFrames(
3427 kSourceId, base::TimeDelta::FromMilliseconds(0), 0));
3428 CheckExpectedRanges(kSourceId, "{ [0,230) }");
3429
3430 // Increase media_time a bit, this will allow some data to be collected, but
3431 // we are still over memory usage limit.
3432 base::TimeDelta seek_time1 = base::TimeDelta::FromMilliseconds(23*2);
3433 Seek(seek_time1);
3434 EXPECT_FALSE(demuxer_->EvictCodedFrames(kSourceId, seek_time1, 0));
3435 CheckExpectedRanges(kSourceId, "{ [46,230) }");
3436
3437 base::TimeDelta seek_time2 = base::TimeDelta::FromMilliseconds(23*4);
3438 Seek(seek_time2);
3439 EXPECT_FALSE(demuxer_->EvictCodedFrames(kSourceId, seek_time2, 0));
3440 CheckExpectedRanges(kSourceId, "{ [92,230) }");
3441
3442 // media_time has progressed to a point where we can collect enough data to
3443 // be under memory limit, so Evict should return true.
3444 base::TimeDelta seek_time3 = base::TimeDelta::FromMilliseconds(23*6);
3445 Seek(seek_time3);
3446 EXPECT_TRUE(demuxer_->EvictCodedFrames(kSourceId, seek_time3, 0));
3447 // Strictly speaking the current playback time is 23*6==138ms, so we could
3448 // release data up to 138ms, but we only release as much data as necessary
3449 // to bring memory usage under the limit, so we release only up to 115ms.
3450 CheckExpectedRanges(kSourceId, "{ [115,230) }");
3403 } 3451 }
3404 3452
3405 TEST_F(ChunkDemuxerTest, AppendWindow_Video) { 3453 TEST_F(ChunkDemuxerTest, AppendWindow_Video) {
3406 ASSERT_TRUE(InitDemuxer(HAS_VIDEO)); 3454 ASSERT_TRUE(InitDemuxer(HAS_VIDEO));
3407 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO); 3455 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
3408 3456
3409 // Set the append window to [50,280). 3457 // Set the append window to [50,280).
3410 append_window_start_for_next_append_ = base::TimeDelta::FromMilliseconds(50); 3458 append_window_start_for_next_append_ = base::TimeDelta::FromMilliseconds(50);
3411 append_window_end_for_next_append_ = base::TimeDelta::FromMilliseconds(280); 3459 append_window_end_for_next_append_ = base::TimeDelta::FromMilliseconds(280);
3412 3460
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after
3747 3795
3748 TEST_F(ChunkDemuxerTest, CuesBetweenClusters) { 3796 TEST_F(ChunkDemuxerTest, CuesBetweenClusters) {
3749 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 3797 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
3750 3798
3751 AppendCluster(GenerateCluster(0, 0, 4)); 3799 AppendCluster(GenerateCluster(0, 0, 4));
3752 AppendData(kCuesHeader, sizeof(kCuesHeader)); 3800 AppendData(kCuesHeader, sizeof(kCuesHeader));
3753 AppendCluster(GenerateCluster(46, 66, 5)); 3801 AppendCluster(GenerateCluster(46, 66, 5));
3754 CheckExpectedRanges(kSourceId, "{ [0,115) }"); 3802 CheckExpectedRanges(kSourceId, "{ [0,115) }");
3755 } 3803 }
3756 3804
3805 TEST_F(ChunkDemuxerTest, EvictCodedFramesTest) {
3806 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
3807 demuxer_->SetMemoryLimits(DemuxerStream::AUDIO, 10 * kBlockSize);
3808 demuxer_->SetMemoryLimits(DemuxerStream::VIDEO, 15 * kBlockSize);
3809 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO);
3810 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO);
3811
3812 const char* kAudioStreamInfo = "0K 40K 80K 120K 160K 200K 240K 280K";
3813 const char* kVideoStreamInfo = "0K 10 20K 30 40K 50 60K 70 80K 90 100K "
3814 "110 120K 130 140K";
3815 // Append 8 blocks (80 bytes) of data to audio stream and 15 blocks (150
3816 // bytes) to video stream.
3817 AppendMuxedCluster(
3818 MuxedStreamInfo(kAudioTrackNum, kAudioStreamInfo),
3819 MuxedStreamInfo(kVideoTrackNum, kVideoStreamInfo));
3820 CheckExpectedBuffers(audio_stream, kAudioStreamInfo);
3821 CheckExpectedBuffers(video_stream, kVideoStreamInfo);
3822
3823 // If we want to append 80 more blocks of muxed a+v data and the current
3824 // position is 0, that will fail, because EvictCodedFrames won't remove the
3825 // data after the current playback position.
3826 ASSERT_FALSE(demuxer_->EvictCodedFrames(kSourceId,
3827 base::TimeDelta::FromMilliseconds(0),
3828 80));
3829 // EvictCodedFrames has failed, so data should be unchanged.
3830 Seek(base::TimeDelta::FromMilliseconds(0));
3831 CheckExpectedBuffers(audio_stream, kAudioStreamInfo);
3832 CheckExpectedBuffers(video_stream, kVideoStreamInfo);
3833
3834 // But if we pretend that playback position has moved to 120ms, that allows
3835 // EvictCodedFrames to garbage-collect enough data to succeed.
3836 ASSERT_TRUE(demuxer_->EvictCodedFrames(kSourceId,
3837 base::TimeDelta::FromMilliseconds(120),
3838 80));
3839
3840 Seek(base::TimeDelta::FromMilliseconds(0));
3841 // Audio stream had 8 buffers, video stream had 15. We told EvictCodedFrames
3842 // that the new data size is 8 blocks muxed, i.e. 80 bytes. Given the current
3843 // ratio of video to the total data size (15 : (8+15) ~= 0.65) the estimated
3844 // sizes of video and audio data in the new 80 byte chunk are 52 bytes for
3845 // video (80*0.65 = 52) and 28 bytes for audio (80 - 52).
3846 // Given these numbers MSE GC will remove just one audio block (since current
3847 // audio size is 80 bytes, new data is 28 bytes, we need to remove just one 10
3848 // byte block to stay under 100 bytes memory limit after append
3849 // 80 - 10 + 28 = 98).
3850 // For video stream 150 + 52 = 202. Video limit is 150 bytes. We need to
3851 // remove at least 6 blocks to stay under limit.
3852 CheckExpectedBuffers(audio_stream, "40K 80K 120K 160K 200K 240K 280K");
3853 CheckExpectedBuffers(video_stream, "60K 70 80K 90 100K 110 120K 130 140K");
3854 }
3855
3757 } // namespace media 3856 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698