Chromium Code Reviews| 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) { | |
|
wolenetz
2015/08/21 18:15:57
Please update this test to expose the problem with
| |
| 3806 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); | |
| 3807 demuxer_->SetMemoryLimits(DemuxerStream::AUDIO, 10 * kBlockSize); | |
| 3808 demuxer_->SetMemoryLimits(DemuxerStream::VIDEO, 10 * kBlockSize); | |
| 3809 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO); | |
| 3810 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO); | |
| 3811 | |
| 3812 // Append 8 blocks (80 bytes) of data to each stream | |
| 3813 AppendMuxedCluster( | |
| 3814 MuxedStreamInfo(kAudioTrackNum, "0K 20K 40K 60K 80K 100K 120K 140K"), | |
| 3815 MuxedStreamInfo(kVideoTrackNum, "0K 30 60 90 120K 150 180 210K")); | |
| 3816 CheckExpectedBuffers(audio_stream, "0K 20K 40K 60K 80K 100K 120K 140K"); | |
| 3817 CheckExpectedBuffers(video_stream, "0K 30 60 90 120K 150 180 210K"); | |
| 3818 | |
| 3819 // If we want to append 80 more blocks of muxed a+v data and the current | |
| 3820 // position is 0, that will fail, because EvictCodedFrames won't remove the | |
| 3821 // data after the current playback position. | |
| 3822 ASSERT_FALSE(demuxer_->EvictCodedFrames(kSourceId, | |
| 3823 base::TimeDelta::FromMilliseconds(0), | |
| 3824 80)); | |
| 3825 // EvictCodedFrames has failed, so data should be unchanged. | |
| 3826 Seek(base::TimeDelta::FromMilliseconds(0)); | |
| 3827 CheckExpectedBuffers(audio_stream, "0K 20K 40K 60K 80K 100K 120K 140K"); | |
| 3828 CheckExpectedBuffers(video_stream, "0K 30 60 90 120K 150 180 210K"); | |
| 3829 | |
| 3830 // But if we pretend that playback position has moved to 100ms, that allows | |
| 3831 // EvictCodedFrames to garbage-collect enough data to succeed. | |
| 3832 ASSERT_TRUE(demuxer_->EvictCodedFrames(kSourceId, | |
| 3833 base::TimeDelta::FromMilliseconds(120), | |
| 3834 80)); | |
| 3835 // EvictCodedFrames will remove some data from the front of both buffers. | |
| 3836 Seek(base::TimeDelta::FromMilliseconds(0)); | |
| 3837 // Audio stream had 8 buffers, memory limit is 10, we told EvictCodedFrames | |
| 3838 // that the new data size is 8 blocks muxed. Since we have equal amounts of | |
| 3839 // audio and video data size, EvictCodedFrames assumes the new data is 4 audio | |
| 3840 // blocks and 4 video blocks. It will remove 2 audio blocks, since that's | |
| 3841 // enough to accomodate 4 newly appended audio blocks and still stay under the | |
| 3842 // 10 block memory limit. | |
| 3843 CheckExpectedBuffers(audio_stream, "40K 60K 80K 100K 120K 140K"); | |
| 3844 // For video stream EvictCodedFrames removes GOP at a time, so the whole first | |
| 3845 // GOP will be removed. | |
| 3846 CheckExpectedBuffers(video_stream, "120K 150 180 210K"); | |
| 3847 } | |
| 3848 | |
| 3757 } // namespace media | 3849 } // namespace media |
| OLD | NEW |