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 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
169 base::Bind(&ChunkDemuxerTest::InitSegmentReceived, | 169 base::Bind(&ChunkDemuxerTest::InitSegmentReceived, |
170 base::Unretained(this)); | 170 base::Unretained(this)); |
171 CreateNewDemuxer(); | 171 CreateNewDemuxer(); |
172 } | 172 } |
173 | 173 |
174 void CreateNewDemuxer() { | 174 void CreateNewDemuxer() { |
175 base::Closure open_cb = | 175 base::Closure open_cb = |
176 base::Bind(&ChunkDemuxerTest::DemuxerOpened, base::Unretained(this)); | 176 base::Bind(&ChunkDemuxerTest::DemuxerOpened, base::Unretained(this)); |
177 Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb = base::Bind( | 177 Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb = base::Bind( |
178 &ChunkDemuxerTest::OnEncryptedMediaInitData, base::Unretained(this)); | 178 &ChunkDemuxerTest::OnEncryptedMediaInitData, base::Unretained(this)); |
179 current_playback_position_ = kNoTimestamp(); | |
179 demuxer_.reset(new ChunkDemuxer( | 180 demuxer_.reset(new ChunkDemuxer( |
180 open_cb, encrypted_media_init_data_cb, base::Bind(&AddLogEntryForTest), | 181 open_cb, encrypted_media_init_data_cb, base::Bind(&AddLogEntryForTest), |
182 base::Bind(&ChunkDemuxerTest::GetCurrentPlaybackPosition, | |
183 base::Unretained(this)), | |
181 scoped_refptr<MediaLog>(new MediaLog()), true)); | 184 scoped_refptr<MediaLog>(new MediaLog()), true)); |
182 } | 185 } |
183 | 186 |
184 virtual ~ChunkDemuxerTest() { | 187 virtual ~ChunkDemuxerTest() { |
185 ShutdownDemuxer(); | 188 ShutdownDemuxer(); |
186 } | 189 } |
187 | 190 |
188 void CreateInitSegment(int stream_flags, | 191 void CreateInitSegment(int stream_flags, |
189 bool is_audio_encrypted, | 192 bool is_audio_encrypted, |
190 bool is_video_encrypted, | 193 bool is_video_encrypted, |
(...skipping 985 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1176 | 1179 |
1177 bool SetTimestampOffset(const std::string& id, | 1180 bool SetTimestampOffset(const std::string& id, |
1178 base::TimeDelta timestamp_offset) { | 1181 base::TimeDelta timestamp_offset) { |
1179 if (demuxer_->IsParsingMediaSegment(id)) | 1182 if (demuxer_->IsParsingMediaSegment(id)) |
1180 return false; | 1183 return false; |
1181 | 1184 |
1182 timestamp_offset_map_[id] = timestamp_offset; | 1185 timestamp_offset_map_[id] = timestamp_offset; |
1183 return true; | 1186 return true; |
1184 } | 1187 } |
1185 | 1188 |
1189 void SetCurrentPlaybackPosition(base::TimeDelta media_time) { | |
1190 current_playback_position_ = media_time; | |
1191 } | |
1192 | |
1193 base::TimeDelta GetCurrentPlaybackPosition() { | |
1194 return current_playback_position_; | |
1195 } | |
1196 | |
1186 base::MessageLoop message_loop_; | 1197 base::MessageLoop message_loop_; |
1187 MockDemuxerHost host_; | 1198 MockDemuxerHost host_; |
1188 | 1199 |
1189 scoped_ptr<ChunkDemuxer> demuxer_; | 1200 scoped_ptr<ChunkDemuxer> demuxer_; |
1190 ChunkDemuxer::InitSegmentReceivedCB init_segment_received_cb_; | 1201 ChunkDemuxer::InitSegmentReceivedCB init_segment_received_cb_; |
1191 | 1202 |
1203 // Used to provide current playback position for ChunkDemuxer garbage | |
1204 // collection algorithm. | |
1205 base::TimeDelta current_playback_position_; | |
1206 | |
1192 base::TimeDelta append_window_start_for_next_append_; | 1207 base::TimeDelta append_window_start_for_next_append_; |
1193 base::TimeDelta append_window_end_for_next_append_; | 1208 base::TimeDelta append_window_end_for_next_append_; |
1194 | 1209 |
1195 // Map of source id to timestamp offset to use for the next AppendData() | 1210 // Map of source id to timestamp offset to use for the next AppendData() |
1196 // operation for that source id. | 1211 // operation for that source id. |
1197 std::map<std::string, base::TimeDelta> timestamp_offset_map_; | 1212 std::map<std::string, base::TimeDelta> timestamp_offset_map_; |
1198 | 1213 |
1199 private: | 1214 private: |
1200 DISALLOW_COPY_AND_ASSIGN(ChunkDemuxerTest); | 1215 DISALLOW_COPY_AND_ASSIGN(ChunkDemuxerTest); |
1201 }; | 1216 }; |
(...skipping 2125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3327 | 3342 |
3328 // Append data to satisfy the seek. | 3343 // Append data to satisfy the seek. |
3329 AppendCluster(seek_time.InMilliseconds(), 10); | 3344 AppendCluster(seek_time.InMilliseconds(), 10); |
3330 } | 3345 } |
3331 | 3346 |
3332 TEST_F(ChunkDemuxerTest, SetMemoryLimitType) { | 3347 TEST_F(ChunkDemuxerTest, SetMemoryLimitType) { |
3333 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); | 3348 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); |
3334 | 3349 |
3335 // Set different memory limits for audio and video. | 3350 // Set different memory limits for audio and video. |
3336 demuxer_->SetMemoryLimits(DemuxerStream::AUDIO, 10 * kBlockSize); | 3351 demuxer_->SetMemoryLimits(DemuxerStream::AUDIO, 10 * kBlockSize); |
3337 demuxer_->SetMemoryLimits(DemuxerStream::VIDEO, 5 * kBlockSize); | 3352 demuxer_->SetMemoryLimits(DemuxerStream::VIDEO, 5 * kBlockSize + 1); |
3338 | 3353 |
3339 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(1000); | 3354 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(1000); |
3340 | 3355 |
3341 // Append data at the start that can be garbage collected: | 3356 // Append data at the start that can be garbage collected: |
3342 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 0, 10); | 3357 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 0, 10); |
3343 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, 0, 5); | 3358 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, 0, 5); |
3344 | 3359 |
3360 // We should be right at buffer limit, should pass | |
3361 EXPECT_TRUE(demuxer_->EvictFrames()); | |
3362 | |
3345 CheckExpectedRanges(DemuxerStream::AUDIO, "{ [0,230) }"); | 3363 CheckExpectedRanges(DemuxerStream::AUDIO, "{ [0,230) }"); |
3346 CheckExpectedRanges(DemuxerStream::VIDEO, "{ [0,165) }"); | 3364 CheckExpectedRanges(DemuxerStream::VIDEO, "{ [0,165) }"); |
3347 | 3365 |
3348 // Seek so we can garbage collect the data appended above. | 3366 // Seek so we can garbage collect the data appended above. |
3349 Seek(seek_time); | 3367 Seek(seek_time); |
3350 | 3368 |
3351 // Append data at seek_time. | 3369 // Append data at seek_time. |
3352 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, | 3370 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, |
3353 seek_time.InMilliseconds(), 10); | 3371 seek_time.InMilliseconds(), 10); |
3354 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, | 3372 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, |
3355 seek_time.InMilliseconds(), 5); | 3373 seek_time.InMilliseconds(), 5); |
3356 | 3374 |
3375 // We should delete first append, and be exactly at buffer limit | |
3376 EXPECT_TRUE(demuxer_->EvictFrames()); | |
3377 | |
3357 // Verify that the old data, and nothing more, has been garbage collected. | 3378 // Verify that the old data, and nothing more, has been garbage collected. |
3358 CheckExpectedRanges(DemuxerStream::AUDIO, "{ [1000,1230) }"); | 3379 CheckExpectedRanges(DemuxerStream::AUDIO, "{ [1000,1230) }"); |
3359 CheckExpectedRanges(DemuxerStream::VIDEO, "{ [1000,1165) }"); | 3380 CheckExpectedRanges(DemuxerStream::VIDEO, "{ [1000,1165) }"); |
3360 } | 3381 } |
3361 | 3382 |
3362 TEST_F(ChunkDemuxerTest, GCDuringSeek) { | 3383 TEST_F(ChunkDemuxerTest, GCDuringSeek) { |
3363 ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); | 3384 ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); |
3364 | 3385 |
3365 demuxer_->SetMemoryLimits(DemuxerStream::AUDIO, 5 * kBlockSize); | 3386 demuxer_->SetMemoryLimits(DemuxerStream::AUDIO, 5 * kBlockSize); |
3366 | 3387 |
3367 base::TimeDelta seek_time1 = base::TimeDelta::FromMilliseconds(1000); | 3388 base::TimeDelta seek_time1 = base::TimeDelta::FromMilliseconds(1000); |
3368 base::TimeDelta seek_time2 = base::TimeDelta::FromMilliseconds(500); | 3389 base::TimeDelta seek_time2 = base::TimeDelta::FromMilliseconds(500); |
3369 | 3390 |
3370 // Initiate a seek to |seek_time1|. | 3391 // Initiate a seek to |seek_time1|. |
3371 Seek(seek_time1); | 3392 Seek(seek_time1); |
3372 | 3393 |
3373 // Append data to satisfy the first seek request. | 3394 // Append data to satisfy the first seek request. |
3374 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, | 3395 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, |
3375 seek_time1.InMilliseconds(), 5); | 3396 seek_time1.InMilliseconds(), 5); |
3376 CheckExpectedRanges(kSourceId, "{ [1000,1115) }"); | 3397 CheckExpectedRanges(kSourceId, "{ [1000,1115) }"); |
3377 | 3398 |
3378 // Signal that the second seek is starting. | 3399 // Signal that the second seek is starting. |
3379 demuxer_->StartWaitingForSeek(seek_time2); | 3400 demuxer_->StartWaitingForSeek(seek_time2); |
3380 | 3401 |
3381 // Append data to satisfy the second seek. This append triggers | 3402 // 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, | 3403 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, |
3385 seek_time2.InMilliseconds(), 5); | 3404 seek_time2.InMilliseconds(), 5); |
3386 | 3405 |
3406 // Should remove first append | |
3407 EXPECT_TRUE(demuxer_->EvictFrames()); | |
3408 | |
3387 // Verify that the buffers that cover |seek_time2| do not get | 3409 // Verify that the buffers that cover |seek_time2| do not get |
3388 // garbage collected. | 3410 // garbage collected. |
3389 CheckExpectedRanges(kSourceId, "{ [500,615) }"); | 3411 CheckExpectedRanges(kSourceId, "{ [500,615) }"); |
3390 | 3412 |
3391 // Complete the seek. | 3413 // Complete the seek. |
3392 demuxer_->Seek(seek_time2, NewExpectedStatusCB(PIPELINE_OK)); | 3414 demuxer_->Seek(seek_time2, NewExpectedStatusCB(PIPELINE_OK)); |
3393 | 3415 |
3394 | |
3395 // Append more data and make sure that the blocks for |seek_time2| | 3416 // Append more data and make sure that the blocks for |seek_time2| |
3396 // don't get removed. | 3417 // don't get removed. |
3397 // | |
3398 // NOTE: The current GC algorithm tries to preserve the GOP at the | |
3399 // current position as well as the last appended GOP. This is | |
3400 // why there are 2 ranges in the expectations. | |
3401 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 700, 5); | 3418 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 700, 5); |
3402 CheckExpectedRanges(kSourceId, "{ [500,592) [792,815) }"); | 3419 |
3420 // We should not delete things between head and last append, so buffer | |
3421 // remains overfull. | |
3422 EXPECT_FALSE(demuxer_->EvictFrames()); | |
3423 | |
3424 CheckExpectedRanges(kSourceId, "{ [500,615) [700,815) }"); | |
3425 } | |
3426 | |
3427 TEST_F(ChunkDemuxerTest, GCKeepPlayhead) { | |
3428 ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); | |
3429 | |
3430 // Set different memory limits for audio and video. | |
3431 demuxer_->SetMemoryLimits(DemuxerStream::AUDIO, 5 * kBlockSize); | |
3432 | |
3433 // Set media time to report playback head at 0ms | |
3434 SetCurrentPlaybackPosition(base::TimeDelta::FromMilliseconds(0)); | |
3435 | |
3436 // Append data at the start that can be garbage collected: | |
3437 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 0, 10); | |
3438 | |
3439 // We expect garbage collection to fail, as we don't want to spontaneously | |
3440 // create gaps in source buffer stream. This could break playback for many | |
wolenetz
2015/06/04 20:06:50
nit: s/This/Gaps/
servolk
2015/06/04 20:22:46
Done.
| |
3441 // clients, who don't bother to check ranges after append. | |
3442 EXPECT_FALSE(demuxer_->EvictFrames()); | |
3443 CheckExpectedRanges(kSourceId, "{ [0,230) }"); | |
3444 | |
3445 // Seek, confirm that media time holds us at zero | |
3446 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(207); | |
3447 Seek(seek_time); | |
3448 | |
3449 EXPECT_FALSE(demuxer_->EvictFrames()); | |
3450 CheckExpectedRanges(kSourceId, "{ [0,230) }"); | |
3451 | |
3452 // Progress media time, show that we can collect up to that point | |
3453 SetCurrentPlaybackPosition(base::TimeDelta::FromMilliseconds(69)); | |
3454 EXPECT_FALSE(demuxer_->EvictFrames()); | |
3455 CheckExpectedRanges(kSourceId, "{ [69,230) }"); | |
3403 } | 3456 } |
3404 | 3457 |
3405 TEST_F(ChunkDemuxerTest, AppendWindow_Video) { | 3458 TEST_F(ChunkDemuxerTest, AppendWindow_Video) { |
3406 ASSERT_TRUE(InitDemuxer(HAS_VIDEO)); | 3459 ASSERT_TRUE(InitDemuxer(HAS_VIDEO)); |
3407 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO); | 3460 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO); |
3408 | 3461 |
3409 // Set the append window to [50,280). | 3462 // Set the append window to [50,280). |
3410 append_window_start_for_next_append_ = base::TimeDelta::FromMilliseconds(50); | 3463 append_window_start_for_next_append_ = base::TimeDelta::FromMilliseconds(50); |
3411 append_window_end_for_next_append_ = base::TimeDelta::FromMilliseconds(280); | 3464 append_window_end_for_next_append_ = base::TimeDelta::FromMilliseconds(280); |
3412 | 3465 |
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3748 TEST_F(ChunkDemuxerTest, CuesBetweenClusters) { | 3801 TEST_F(ChunkDemuxerTest, CuesBetweenClusters) { |
3749 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); | 3802 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); |
3750 | 3803 |
3751 AppendCluster(GenerateCluster(0, 0, 4)); | 3804 AppendCluster(GenerateCluster(0, 0, 4)); |
3752 AppendData(kCuesHeader, sizeof(kCuesHeader)); | 3805 AppendData(kCuesHeader, sizeof(kCuesHeader)); |
3753 AppendCluster(GenerateCluster(46, 66, 5)); | 3806 AppendCluster(GenerateCluster(46, 66, 5)); |
3754 CheckExpectedRanges(kSourceId, "{ [0,115) }"); | 3807 CheckExpectedRanges(kSourceId, "{ [0,115) }"); |
3755 } | 3808 } |
3756 | 3809 |
3757 } // namespace media | 3810 } // namespace media |
OLD | NEW |