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 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 static void WriteInt64(uint8* buffer, int64 number) { | 97 static void WriteInt64(uint8* buffer, int64 number) { |
98 DCHECK(number >= 0 && number < 0x00FFFFFFFFFFFFFFLL); | 98 DCHECK(number >= 0 && number < 0x00FFFFFFFFFFFFFFLL); |
99 buffer[0] = 0x01; | 99 buffer[0] = 0x01; |
100 int64 tmp = number; | 100 int64 tmp = number; |
101 for (int i = 7; i > 0; i--) { | 101 for (int i = 7; i > 0; i--) { |
102 buffer[i] = tmp & 0xff; | 102 buffer[i] = tmp & 0xff; |
103 tmp >>= 8; | 103 tmp >>= 8; |
104 } | 104 } |
105 } | 105 } |
106 | 106 |
| 107 base::TimeDelta DummyGetMediaTime(base::TimeDelta time) { |
| 108 return time; |
| 109 } |
| 110 |
107 MATCHER_P(HasTimestamp, timestamp_in_ms, "") { | 111 MATCHER_P(HasTimestamp, timestamp_in_ms, "") { |
108 return arg.get() && !arg->end_of_stream() && | 112 return arg.get() && !arg->end_of_stream() && |
109 arg->timestamp().InMilliseconds() == timestamp_in_ms; | 113 arg->timestamp().InMilliseconds() == timestamp_in_ms; |
110 } | 114 } |
111 | 115 |
112 MATCHER(IsEndOfStream, "") { return arg.get() && arg->end_of_stream(); } | 116 MATCHER(IsEndOfStream, "") { return arg.get() && arg->end_of_stream(); } |
113 | 117 |
114 static void OnReadDone(const base::TimeDelta& expected_time, | 118 static void OnReadDone(const base::TimeDelta& expected_time, |
115 bool* called, | 119 bool* called, |
116 DemuxerStream::Status status, | 120 DemuxerStream::Status status, |
(...skipping 3211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3328 | 3332 |
3329 // Append data to satisfy the seek. | 3333 // Append data to satisfy the seek. |
3330 AppendCluster(seek_time.InMilliseconds(), 10); | 3334 AppendCluster(seek_time.InMilliseconds(), 10); |
3331 } | 3335 } |
3332 | 3336 |
3333 TEST_F(ChunkDemuxerTest, SetMemoryLimitType) { | 3337 TEST_F(ChunkDemuxerTest, SetMemoryLimitType) { |
3334 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); | 3338 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); |
3335 | 3339 |
3336 // Set different memory limits for audio and video. | 3340 // Set different memory limits for audio and video. |
3337 demuxer_->SetMemoryLimits(DemuxerStream::AUDIO, 10 * kBlockSize); | 3341 demuxer_->SetMemoryLimits(DemuxerStream::AUDIO, 10 * kBlockSize); |
3338 demuxer_->SetMemoryLimits(DemuxerStream::VIDEO, 5 * kBlockSize); | 3342 demuxer_->SetMemoryLimits(DemuxerStream::VIDEO, 5 * kBlockSize + 1); |
3339 | 3343 |
3340 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(1000); | 3344 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(1000); |
3341 | 3345 |
3342 // Append data at the start that can be garbage collected: | 3346 // Append data at the start that can be garbage collected: |
3343 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 0, 10); | 3347 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 0, 10); |
3344 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, 0, 5); | 3348 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, 0, 5); |
3345 | 3349 |
| 3350 // We should be right at buffer limit, should pass |
| 3351 EXPECT_TRUE(demuxer_->EvictFrames()); |
| 3352 |
3346 CheckExpectedRanges(DemuxerStream::AUDIO, "{ [0,230) }"); | 3353 CheckExpectedRanges(DemuxerStream::AUDIO, "{ [0,230) }"); |
3347 CheckExpectedRanges(DemuxerStream::VIDEO, "{ [0,165) }"); | 3354 CheckExpectedRanges(DemuxerStream::VIDEO, "{ [0,165) }"); |
3348 | 3355 |
3349 // Seek so we can garbage collect the data appended above. | 3356 // Seek so we can garbage collect the data appended above. |
3350 Seek(seek_time); | 3357 Seek(seek_time); |
3351 | 3358 |
3352 // Append data at seek_time. | 3359 // Append data at seek_time. |
3353 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, | 3360 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, |
3354 seek_time.InMilliseconds(), 10); | 3361 seek_time.InMilliseconds(), 10); |
3355 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, | 3362 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, |
3356 seek_time.InMilliseconds(), 5); | 3363 seek_time.InMilliseconds(), 5); |
3357 | 3364 |
| 3365 // We should delete first append, and be exactly at buffer limit |
| 3366 EXPECT_TRUE(demuxer_->EvictFrames()); |
| 3367 |
3358 // Verify that the old data, and nothing more, has been garbage collected. | 3368 // Verify that the old data, and nothing more, has been garbage collected. |
3359 CheckExpectedRanges(DemuxerStream::AUDIO, "{ [1000,1230) }"); | 3369 CheckExpectedRanges(DemuxerStream::AUDIO, "{ [1000,1230) }"); |
3360 CheckExpectedRanges(DemuxerStream::VIDEO, "{ [1000,1165) }"); | 3370 CheckExpectedRanges(DemuxerStream::VIDEO, "{ [1000,1165) }"); |
3361 } | 3371 } |
3362 | 3372 |
3363 TEST_F(ChunkDemuxerTest, GCDuringSeek) { | 3373 TEST_F(ChunkDemuxerTest, GCDuringSeek) { |
3364 ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); | 3374 ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); |
3365 | 3375 |
3366 demuxer_->SetMemoryLimits(DemuxerStream::AUDIO, 5 * kBlockSize); | 3376 demuxer_->SetMemoryLimits(DemuxerStream::AUDIO, 5 * kBlockSize); |
3367 | 3377 |
3368 base::TimeDelta seek_time1 = base::TimeDelta::FromMilliseconds(1000); | 3378 base::TimeDelta seek_time1 = base::TimeDelta::FromMilliseconds(1000); |
3369 base::TimeDelta seek_time2 = base::TimeDelta::FromMilliseconds(500); | 3379 base::TimeDelta seek_time2 = base::TimeDelta::FromMilliseconds(500); |
3370 | 3380 |
3371 // Initiate a seek to |seek_time1|. | 3381 // Initiate a seek to |seek_time1|. |
3372 Seek(seek_time1); | 3382 Seek(seek_time1); |
3373 | 3383 |
3374 // Append data to satisfy the first seek request. | 3384 // Append data to satisfy the first seek request. |
3375 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, | 3385 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, |
3376 seek_time1.InMilliseconds(), 5); | 3386 seek_time1.InMilliseconds(), 5); |
3377 CheckExpectedRanges(kSourceId, "{ [1000,1115) }"); | 3387 CheckExpectedRanges(kSourceId, "{ [1000,1115) }"); |
3378 | 3388 |
3379 // Signal that the second seek is starting. | 3389 // Signal that the second seek is starting. |
3380 demuxer_->StartWaitingForSeek(seek_time2); | 3390 demuxer_->StartWaitingForSeek(seek_time2); |
3381 | 3391 |
3382 // Append data to satisfy the second seek. This append triggers | 3392 // Append data to satisfy the second seek. |
3383 // the garbage collection logic since we set the memory limit to | |
3384 // 5 blocks. | |
3385 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, | 3393 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, |
3386 seek_time2.InMilliseconds(), 5); | 3394 seek_time2.InMilliseconds(), 5); |
3387 | 3395 |
| 3396 // Should remove first append |
| 3397 EXPECT_TRUE(demuxer_->EvictFrames()); |
| 3398 |
3388 // Verify that the buffers that cover |seek_time2| do not get | 3399 // Verify that the buffers that cover |seek_time2| do not get |
3389 // garbage collected. | 3400 // garbage collected. |
3390 CheckExpectedRanges(kSourceId, "{ [500,615) }"); | 3401 CheckExpectedRanges(kSourceId, "{ [500,615) }"); |
3391 | 3402 |
3392 // Complete the seek. | 3403 // Complete the seek. |
3393 demuxer_->Seek(seek_time2, NewExpectedStatusCB(PIPELINE_OK)); | 3404 demuxer_->Seek(seek_time2, NewExpectedStatusCB(PIPELINE_OK)); |
3394 | 3405 |
3395 | |
3396 // Append more data and make sure that the blocks for |seek_time2| | 3406 // Append more data and make sure that the blocks for |seek_time2| |
3397 // don't get removed. | 3407 // don't get removed. |
3398 // | |
3399 // NOTE: The current GC algorithm tries to preserve the GOP at the | |
3400 // current position as well as the last appended GOP. This is | |
3401 // why there are 2 ranges in the expectations. | |
3402 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 700, 5); | 3408 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 700, 5); |
3403 CheckExpectedRanges(kSourceId, "{ [500,592) [792,815) }"); | 3409 |
| 3410 // We should not delete things between head and last append, so buffer |
| 3411 // remains overfull. |
| 3412 EXPECT_FALSE(demuxer_->EvictFrames()); |
| 3413 |
| 3414 CheckExpectedRanges(kSourceId, "{ [500,615) [700,815) }"); |
| 3415 } |
| 3416 |
| 3417 TEST_F(ChunkDemuxerTest, GCKeepPlayhead) { |
| 3418 ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); |
| 3419 |
| 3420 // Set different memory limits for audio and video. |
| 3421 demuxer_->SetMemoryLimits(DemuxerStream::AUDIO, 5 * kBlockSize); |
| 3422 |
| 3423 // Set media time provider to report playback head at 0ms |
| 3424 demuxer_->SetMediaTimeProvider( |
| 3425 base::Bind(DummyGetMediaTime, base::TimeDelta())); |
| 3426 |
| 3427 // Append data at the start that can be garbage collected: |
| 3428 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 0, 10); |
| 3429 |
| 3430 // We expect garbage collection to fail, as we don't want to spontaneously |
| 3431 // create gaps in source buffer stream. This could screw up playback for many |
| 3432 // clients, who don't bother to check ranges after append. |
| 3433 EXPECT_FALSE(demuxer_->EvictFrames()); |
| 3434 CheckExpectedRanges(kSourceId, "{ [0,230) }"); |
| 3435 |
| 3436 // Seek, confirm that media time holds us at zero |
| 3437 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(207); |
| 3438 Seek(seek_time); |
| 3439 |
| 3440 EXPECT_FALSE(demuxer_->EvictFrames()); |
| 3441 CheckExpectedRanges(kSourceId, "{ [0,230) }"); |
| 3442 |
| 3443 // Progress media time, show that we can collect up to that point |
| 3444 demuxer_->SetMediaTimeProvider( |
| 3445 base::Bind(DummyGetMediaTime, base::TimeDelta::FromMilliseconds(69))); |
| 3446 EXPECT_FALSE(demuxer_->EvictFrames()); |
| 3447 CheckExpectedRanges(kSourceId, "{ [69,230) }"); |
3404 } | 3448 } |
3405 | 3449 |
3406 TEST_F(ChunkDemuxerTest, AppendWindow_Video) { | 3450 TEST_F(ChunkDemuxerTest, AppendWindow_Video) { |
3407 ASSERT_TRUE(InitDemuxer(HAS_VIDEO)); | 3451 ASSERT_TRUE(InitDemuxer(HAS_VIDEO)); |
3408 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO); | 3452 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO); |
3409 | 3453 |
3410 // Set the append window to [50,280). | 3454 // Set the append window to [50,280). |
3411 append_window_start_for_next_append_ = base::TimeDelta::FromMilliseconds(50); | 3455 append_window_start_for_next_append_ = base::TimeDelta::FromMilliseconds(50); |
3412 append_window_end_for_next_append_ = base::TimeDelta::FromMilliseconds(280); | 3456 append_window_end_for_next_append_ = base::TimeDelta::FromMilliseconds(280); |
3413 | 3457 |
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3749 TEST_F(ChunkDemuxerTest, CuesBetweenClusters) { | 3793 TEST_F(ChunkDemuxerTest, CuesBetweenClusters) { |
3750 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); | 3794 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); |
3751 | 3795 |
3752 AppendCluster(GenerateCluster(0, 0, 4)); | 3796 AppendCluster(GenerateCluster(0, 0, 4)); |
3753 AppendData(kCuesHeader, sizeof(kCuesHeader)); | 3797 AppendData(kCuesHeader, sizeof(kCuesHeader)); |
3754 AppendCluster(GenerateCluster(46, 66, 5)); | 3798 AppendCluster(GenerateCluster(46, 66, 5)); |
3755 CheckExpectedRanges(kSourceId, "{ [0,115) }"); | 3799 CheckExpectedRanges(kSourceId, "{ [0,115) }"); |
3756 } | 3800 } |
3757 | 3801 |
3758 } // namespace media | 3802 } // namespace media |
OLD | NEW |