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

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 new test case: GarbageCollection_SaveDataAtPlaybackPosition Created 5 years, 6 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 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698