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 <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 Loading... |
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 Loading... |
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 |
OLD | NEW |