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

Side by Side Diff: media/filters/chunk_demuxer_unittest.cc

Issue 10545066: Implement support for 2 source ids (1 for audio and 1 for video). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 8 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 | Annotate | Revision Log
« no previous file with comments | « media/filters/chunk_demuxer.cc ('k') | media/filters/pipeline_integration_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "base/bind.h" 5 #include "base/bind.h"
6 #include "media/base/audio_decoder_config.h" 6 #include "media/base/audio_decoder_config.h"
7 #include "media/base/decoder_buffer.h" 7 #include "media/base/decoder_buffer.h"
8 #include "media/base/mock_callback.h" 8 #include "media/base/mock_callback.h"
9 #include "media/base/mock_demuxer_host.h" 9 #include "media/base/mock_demuxer_host.h"
10 #include "media/base/test_data_util.h" 10 #include "media/base/test_data_util.h"
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 arg->GetTimestamp().InMilliseconds() == timestamp_in_ms; 69 arg->GetTimestamp().InMilliseconds() == timestamp_in_ms;
70 } 70 }
71 71
72 static void OnReadDone(const base::TimeDelta& expected_time, 72 static void OnReadDone(const base::TimeDelta& expected_time,
73 bool* called, 73 bool* called,
74 const scoped_refptr<DecoderBuffer>& buffer) { 74 const scoped_refptr<DecoderBuffer>& buffer) {
75 EXPECT_EQ(expected_time, buffer->GetTimestamp()); 75 EXPECT_EQ(expected_time, buffer->GetTimestamp());
76 *called = true; 76 *called = true;
77 } 77 }
78 78
79 static void OnReadDone_EOSExpected(bool* called,
80 const scoped_refptr<DecoderBuffer>& buffer) {
81 EXPECT_TRUE(buffer->IsEndOfStream());
82 *called = true;
83 }
84
79 class MockChunkDemuxerClient : public ChunkDemuxerClient { 85 class MockChunkDemuxerClient : public ChunkDemuxerClient {
80 public: 86 public:
81 MockChunkDemuxerClient() {} 87 MockChunkDemuxerClient() {}
82 virtual ~MockChunkDemuxerClient() {} 88 virtual ~MockChunkDemuxerClient() {}
83 89
84 MOCK_METHOD1(DemuxerOpened, void(ChunkDemuxer* demuxer)); 90 MOCK_METHOD1(DemuxerOpened, void(ChunkDemuxer* demuxer));
85 MOCK_METHOD0(DemuxerClosed, void()); 91 MOCK_METHOD0(DemuxerClosed, void());
86 // TODO(xhwang): This is a workaround of the issue that move-only parameters 92 // TODO(xhwang): This is a workaround of the issue that move-only parameters
87 // are not supported in mocked methods. Remove this when the issue is fixed. 93 // are not supported in mocked methods. Remove this when the issue is fixed.
88 // See http://code.google.com/p/googletest/issues/detail?id=395 94 // See http://code.google.com/p/googletest/issues/detail?id=395
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 video_track_entry->GetDataSize() + 196 video_track_entry->GetDataSize() +
191 video_content_encodings->GetDataSize() - 197 video_content_encodings->GetDataSize() -
192 kVideoTrackEntryHeaderSize); 198 kVideoTrackEntryHeaderSize);
193 buf += video_content_encodings->GetDataSize(); 199 buf += video_content_encodings->GetDataSize();
194 } 200 }
195 buf += video_track_entry->GetDataSize(); 201 buf += video_track_entry->GetDataSize();
196 } 202 }
197 } 203 }
198 204
199 ChunkDemuxer::Status AddId() { 205 ChunkDemuxer::Status AddId() {
200 std::vector<std::string> codecs(2); 206 return AddId(kSourceId, true, true);
201 codecs[0] = "vp8"; 207 }
202 codecs[1] = "vorbis"; 208
203 return demuxer_->AddId(kSourceId, "video/webm", codecs); 209 ChunkDemuxer::Status AddId(const std::string& source_id,
210 bool has_audio, bool has_video) {
211 std::vector<std::string> codecs;
212 std::string type;
213
214 if (has_audio) {
215 codecs.push_back("vorbis");
216 type = "audio/webm";
217 }
218
219 if (has_video) {
220 codecs.push_back("vp8");
221 type = "video/webm";
222 }
223
224 if (!has_audio && !has_video) {
225 return AddId(kSourceId, true, true);
226 }
227
228 return demuxer_->AddId(source_id, type, codecs);
204 } 229 }
205 230
206 bool AppendData(const uint8* data, size_t length) { 231 bool AppendData(const uint8* data, size_t length) {
232 return AppendData(kSourceId, data, length);
233 }
234
235 bool AppendData(const std::string& source_id,
236 const uint8* data, size_t length) {
207 CHECK(length); 237 CHECK(length);
208 EXPECT_CALL(host_, AddBufferedByteRange(_, _)).Times(AnyNumber()) 238 EXPECT_CALL(host_, AddBufferedByteRange(_, _)).Times(AnyNumber())
209 .WillRepeatedly(SaveArg<1>(&buffered_bytes_)); 239 .WillRepeatedly(SaveArg<1>(&buffered_bytes_));
210 return demuxer_->AppendData(kSourceId, data, length); 240 return demuxer_->AppendData(source_id, data, length);
211 } 241 }
212 242
213 bool AppendDataInPieces(const uint8* data, size_t length) { 243 bool AppendDataInPieces(const uint8* data, size_t length) {
214 return AppendDataInPieces(data, length, 7); 244 return AppendDataInPieces(data, length, 7);
215 } 245 }
216 246
217 bool AppendDataInPieces(const uint8* data, size_t length, size_t piece_size) { 247 bool AppendDataInPieces(const uint8* data, size_t length, size_t piece_size) {
218 const uint8* start = data; 248 const uint8* start = data;
219 const uint8* end = data + length; 249 const uint8* end = data + length;
220 while (start < end) { 250 while (start < end) {
221 int64 old_buffered_bytes = buffered_bytes_; 251 int64 old_buffered_bytes = buffered_bytes_;
222 size_t append_size = std::min(piece_size, 252 size_t append_size = std::min(piece_size,
223 static_cast<size_t>(end - start)); 253 static_cast<size_t>(end - start));
224 if (!AppendData(start, append_size)) 254 if (!AppendData(start, append_size))
225 return false; 255 return false;
226 start += append_size; 256 start += append_size;
227 257
228 EXPECT_GT(buffered_bytes_, old_buffered_bytes); 258 EXPECT_GT(buffered_bytes_, old_buffered_bytes);
229 } 259 }
230 return true; 260 return true;
231 } 261 }
232 262
233 bool AppendInitSegment(bool has_audio, bool has_video, 263 bool AppendInitSegment(bool has_audio, bool has_video,
234 bool video_content_encoded) { 264 bool video_content_encoded) {
265 return AppendInitSegment(kSourceId, has_audio, has_video,
266 video_content_encoded);
267 }
268
269 bool AppendInitSegment(const std::string& source_id,
270 bool has_audio, bool has_video,
271 bool video_content_encoded) {
235 scoped_array<uint8> info_tracks; 272 scoped_array<uint8> info_tracks;
236 int info_tracks_size = 0; 273 int info_tracks_size = 0;
237 CreateInitSegment(has_audio, has_video, video_content_encoded, 274 CreateInitSegment(has_audio, has_video, video_content_encoded,
238 &info_tracks, &info_tracks_size); 275 &info_tracks, &info_tracks_size);
239 return AppendData(info_tracks.get(), info_tracks_size); 276 return AppendData(source_id, info_tracks.get(), info_tracks_size);
240 } 277 }
241 278
242 void InitDoneCalled(PipelineStatus expected_status, 279 void InitDoneCalled(PipelineStatus expected_status,
243 PipelineStatus status) { 280 PipelineStatus status) {
244 EXPECT_EQ(status, expected_status); 281 EXPECT_EQ(status, expected_status);
245 } 282 }
246 283
247 PipelineStatusCB CreateInitDoneCB(const base::TimeDelta& expected_duration, 284 PipelineStatusCB CreateInitDoneCB(const base::TimeDelta& expected_duration,
248 PipelineStatus expected_status) { 285 PipelineStatus expected_status) {
249 if (expected_status == PIPELINE_OK) 286 if (expected_status == PIPELINE_OK)
250 EXPECT_CALL(host_, SetDuration(expected_duration)); 287 EXPECT_CALL(host_, SetDuration(expected_duration));
251 288
252 return base::Bind(&ChunkDemuxerTest::InitDoneCalled, 289 return base::Bind(&ChunkDemuxerTest::InitDoneCalled,
253 base::Unretained(this), 290 base::Unretained(this),
254 expected_status); 291 expected_status);
255 } 292 }
256 293
257 bool InitDemuxer(bool has_audio, bool has_video, 294 bool InitDemuxer(bool has_audio, bool has_video,
258 bool video_content_encoded) { 295 bool video_content_encoded) {
259 PipelineStatus expected_status = 296 PipelineStatus expected_status =
260 (has_audio || has_video) ? PIPELINE_OK : DEMUXER_ERROR_COULD_NOT_OPEN; 297 (has_audio || has_video) ? PIPELINE_OK : DEMUXER_ERROR_COULD_NOT_OPEN;
261 298
262 EXPECT_CALL(*client_, DemuxerOpened(_)); 299 EXPECT_CALL(*client_, DemuxerOpened(_));
263 demuxer_->Initialize( 300 demuxer_->Initialize(
264 &host_, CreateInitDoneCB(kDefaultDuration(), expected_status)); 301 &host_, CreateInitDoneCB(kDefaultDuration(), expected_status));
265 302
266 if (AddId() != ChunkDemuxer::kOk) 303 if (AddId(kSourceId, has_audio, has_video) != ChunkDemuxer::kOk)
267 return false; 304 return false;
268 305
269 return AppendInitSegment(has_audio, has_video, video_content_encoded); 306 return AppendInitSegment(has_audio, has_video, video_content_encoded);
270 } 307 }
271 308
309 bool InitDemuxerAudioAndVideoSources(const std::string& audio_id,
310 const std::string& video_id) {
311 EXPECT_CALL(*client_, DemuxerOpened(_));
312 demuxer_->Initialize(
313 &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK));
314
315 if (AddId(audio_id, true, false) != ChunkDemuxer::kOk)
316 return false;
317 if (AddId(video_id, false, true) != ChunkDemuxer::kOk)
318 return false;
319
320 bool success = AppendInitSegment(audio_id, true, false, false);
321 success &= AppendInitSegment(video_id, false, true, false);
322 return success;
323 }
324
272 void ShutdownDemuxer() { 325 void ShutdownDemuxer() {
273 if (demuxer_) { 326 if (demuxer_) {
274 EXPECT_CALL(*client_, DemuxerClosed()); 327 EXPECT_CALL(*client_, DemuxerClosed());
275 demuxer_->Shutdown(); 328 demuxer_->Shutdown();
276 } 329 }
277 } 330 }
278 331
279 void AddSimpleBlock(ClusterBuilder* cb, int track_num, int64 timecode) { 332 void AddSimpleBlock(ClusterBuilder* cb, int track_num, int64 timecode) {
280 uint8 data[] = { 0x00 }; 333 uint8 data[] = { 0x00 };
281 cb->AddSimpleBlock(track_num, timecode, 0, data, sizeof(data)); 334 cb->AddSimpleBlock(track_num, timecode, 0, data, sizeof(data));
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
328 } else { 381 } else {
329 cb.AddBlockGroup(kVideoTrackNum, video_timecode, kVideoBlockDuration, 382 cb.AddBlockGroup(kVideoTrackNum, video_timecode, kVideoBlockDuration,
330 video_flag, data.get(), size); 383 video_flag, data.get(), size);
331 cb.AddBlockGroup(kAudioTrackNum, audio_timecode, kAudioBlockDuration, 384 cb.AddBlockGroup(kAudioTrackNum, audio_timecode, kAudioBlockDuration,
332 kWebMFlagKeyframe, data.get(), size); 385 kWebMFlagKeyframe, data.get(), size);
333 } 386 }
334 387
335 return cb.Finish(); 388 return cb.Finish();
336 } 389 }
337 390
391 scoped_ptr<Cluster> GenerateSingleStreamCluster(int timecode,
392 int block_count,
393 int track_number,
394 int block_duration) {
395 CHECK_GT(block_count, 0);
396
397 int size = 10;
398 scoped_array<uint8> data(new uint8[size]);
399
400 ClusterBuilder cb;
401 cb.SetClusterTimecode(timecode);
402
403 // Create simple blocks for everything except the last block.
404 for (int i = 0; i < block_count - 1; i++) {
405 cb.AddSimpleBlock(track_number, timecode, kWebMFlagKeyframe,
406 data.get(), size);
407 timecode += block_duration;
408 }
409
410 // Make the last block a BlockGroup so that it doesn't get delayed by the
411 // block duration calculation logic.
412 cb.AddBlockGroup(track_number, timecode, block_duration,
413 kWebMFlagKeyframe, data.get(), size);
414 return cb.Finish();
415 }
416
338 void GenerateExpectedReads(int timecode, int block_count, 417 void GenerateExpectedReads(int timecode, int block_count,
339 DemuxerStream* audio, 418 DemuxerStream* audio,
340 DemuxerStream* video) { 419 DemuxerStream* video) {
341 CHECK_GT(block_count, 0); 420 CHECK_GT(block_count, 0);
342 int audio_timecode = timecode; 421 int audio_timecode = timecode;
343 int video_timecode = timecode; 422 int video_timecode = timecode;
344 423
345 if (block_count == 1) { 424 if (block_count == 1) {
346 ExpectRead(audio, audio_timecode); 425 ExpectRead(audio, audio_timecode);
347 return; 426 return;
348 } 427 }
349 428
350 for (int i = 0; i < block_count; i++) { 429 for (int i = 0; i < block_count; i++) {
351 if (audio_timecode <= video_timecode) { 430 if (audio_timecode <= video_timecode) {
352 ExpectRead(audio, audio_timecode); 431 ExpectRead(audio, audio_timecode);
353 audio_timecode += kAudioBlockDuration; 432 audio_timecode += kAudioBlockDuration;
354 continue; 433 continue;
355 } 434 }
356 435
357 ExpectRead(video, video_timecode); 436 ExpectRead(video, video_timecode);
358 video_timecode += kVideoBlockDuration; 437 video_timecode += kVideoBlockDuration;
359 } 438 }
360 } 439 }
361 440
441 void GenerateExpectedReads(int timecode, int block_count,
442 DemuxerStream* stream, int block_duration) {
443 CHECK_GT(block_count, 0);
444 int stream_timecode = timecode;
445
446 for (int i = 0; i < block_count; i++) {
447 ExpectRead(stream, stream_timecode);
448 stream_timecode += block_duration;
449 }
450 }
451
362 MOCK_METHOD1(ReadDone, void(const scoped_refptr<DecoderBuffer>&)); 452 MOCK_METHOD1(ReadDone, void(const scoped_refptr<DecoderBuffer>&));
363 453
364 void ExpectRead(DemuxerStream* stream, int64 timestamp_in_ms) { 454 void ExpectRead(DemuxerStream* stream, int64 timestamp_in_ms) {
365 EXPECT_CALL(*this, ReadDone(HasTimestamp(timestamp_in_ms))); 455 EXPECT_CALL(*this, ReadDone(HasTimestamp(timestamp_in_ms)));
366 stream->Read(base::Bind(&ChunkDemuxerTest::ReadDone, 456 stream->Read(base::Bind(&ChunkDemuxerTest::ReadDone,
367 base::Unretained(this))); 457 base::Unretained(this)));
368 } 458 }
369 459
370 MOCK_METHOD1(Checkpoint, void(int id)); 460 MOCK_METHOD1(Checkpoint, void(int id));
371 461
372 struct BufferTimestamps { 462 struct BufferTimestamps {
373 int video_time_ms; 463 int video_time_ms;
374 int audio_time_ms; 464 int audio_time_ms;
375 }; 465 };
376 static const int kSkip = -1; 466 static const int kSkip = -1;
377 467
378 // Test parsing a WebM file. 468 // Test parsing a WebM file.
379 // |filename| - The name of the file in media/test/data to parse. 469 // |filename| - The name of the file in media/test/data to parse.
380 // |timestamps| - The expected timestamps on the parsed buffers. 470 // |timestamps| - The expected timestamps on the parsed buffers.
381 // a timestamp of kSkip indicates that a Read() call for that stream 471 // a timestamp of kSkip indicates that a Read() call for that stream
382 // shouldn't be made on that iteration of the loop. If both streams have 472 // shouldn't be made on that iteration of the loop. If both streams have
383 // a kSkip then the loop will terminate. 473 // a kSkip then the loop will terminate.
384 bool ParseWebMFile(const std::string& filename, 474 bool ParseWebMFile(const std::string& filename,
385 const BufferTimestamps* timestamps, 475 const BufferTimestamps* timestamps,
386 const base::TimeDelta& duration) { 476 const base::TimeDelta& duration) {
477 return ParseWebMFile(filename, timestamps, duration, true, true);
478 }
479
480 bool ParseWebMFile(const std::string& filename,
481 const BufferTimestamps* timestamps,
482 const base::TimeDelta& duration,
483 bool has_audio, bool has_video) {
387 EXPECT_CALL(*client_, DemuxerOpened(_)); 484 EXPECT_CALL(*client_, DemuxerOpened(_));
388 demuxer_->Initialize( 485 demuxer_->Initialize(
389 &host_, CreateInitDoneCB(duration, PIPELINE_OK)); 486 &host_, CreateInitDoneCB(duration, PIPELINE_OK));
390 487
391 if (AddId() != ChunkDemuxer::kOk) 488 if (AddId(kSourceId, has_audio, has_video) != ChunkDemuxer::kOk)
392 return false; 489 return false;
393 490
394 // Read a WebM file into memory and send the data to the demuxer. 491 // Read a WebM file into memory and send the data to the demuxer.
395 scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(filename); 492 scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(filename);
396 if (!AppendDataInPieces(buffer->GetData(), buffer->GetDataSize(), 512)) 493 if (!AppendDataInPieces(buffer->GetData(), buffer->GetDataSize(), 512))
397 return false; 494 return false;
398 495
399 scoped_refptr<DemuxerStream> audio = 496 scoped_refptr<DemuxerStream> audio =
400 demuxer_->GetStream(DemuxerStream::AUDIO); 497 demuxer_->GetStream(DemuxerStream::AUDIO);
401 scoped_refptr<DemuxerStream> video = 498 scoped_refptr<DemuxerStream> video =
(...skipping 567 matching lines...) Expand 10 before | Expand all | Expand 10 after
969 struct BufferTimestamps buffer_timestamps[] = { 1066 struct BufferTimestamps buffer_timestamps[] = {
970 {kSkip, 0}, 1067 {kSkip, 0},
971 {kSkip, 3}, 1068 {kSkip, 3},
972 {kSkip, 6}, 1069 {kSkip, 6},
973 {kSkip, 9}, 1070 {kSkip, 9},
974 {kSkip, 12}, 1071 {kSkip, 12},
975 {kSkip, kSkip}, 1072 {kSkip, kSkip},
976 }; 1073 };
977 1074
978 ASSERT_TRUE(ParseWebMFile("bear-320x240-audio-only.webm", buffer_timestamps, 1075 ASSERT_TRUE(ParseWebMFile("bear-320x240-audio-only.webm", buffer_timestamps,
979 base::TimeDelta::FromMilliseconds(2744))); 1076 base::TimeDelta::FromMilliseconds(2744),
1077 true, false));
980 } 1078 }
981 1079
982 TEST_F(ChunkDemuxerTest, TestWebMFile_VideoOnly) { 1080 TEST_F(ChunkDemuxerTest, TestWebMFile_VideoOnly) {
983 struct BufferTimestamps buffer_timestamps[] = { 1081 struct BufferTimestamps buffer_timestamps[] = {
984 {0, kSkip}, 1082 {0, kSkip},
985 {33, kSkip}, 1083 {33, kSkip},
986 {67, kSkip}, 1084 {67, kSkip},
987 {100, kSkip}, 1085 {100, kSkip},
988 {133, kSkip}, 1086 {133, kSkip},
989 {kSkip, kSkip}, 1087 {kSkip, kSkip},
990 }; 1088 };
991 1089
992 ASSERT_TRUE(ParseWebMFile("bear-320x240-video-only.webm", buffer_timestamps, 1090 ASSERT_TRUE(ParseWebMFile("bear-320x240-video-only.webm", buffer_timestamps,
993 base::TimeDelta::FromMilliseconds(2703))); 1091 base::TimeDelta::FromMilliseconds(2703),
1092 false, true));
994 } 1093 }
995 1094
996 TEST_F(ChunkDemuxerTest, TestWebMFile_AltRefFrames) { 1095 TEST_F(ChunkDemuxerTest, TestWebMFile_AltRefFrames) {
997 struct BufferTimestamps buffer_timestamps[] = { 1096 struct BufferTimestamps buffer_timestamps[] = {
998 {0, 0}, 1097 {0, 0},
999 {33, 3}, 1098 {33, 3},
1000 {33, 6}, 1099 {33, 6},
1001 {67, 9}, 1100 {67, 9},
1002 {100, 12}, 1101 {100, 12},
1003 {kSkip, kSkip}, 1102 {kSkip, kSkip},
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
1129 1228
1130 // Append another identical initialization segment. 1229 // Append another identical initialization segment.
1131 ASSERT_TRUE(AppendInitSegment(true, true, false)); 1230 ASSERT_TRUE(AppendInitSegment(true, true, false));
1132 1231
1133 scoped_ptr<Cluster> cluster_b(kDefaultSecondCluster()); 1232 scoped_ptr<Cluster> cluster_b(kDefaultSecondCluster());
1134 ASSERT_TRUE(AppendData(cluster_b->data(), cluster_b->size())); 1233 ASSERT_TRUE(AppendData(cluster_b->data(), cluster_b->size()));
1135 1234
1136 GenerateExpectedReads(0, 9, audio, video); 1235 GenerateExpectedReads(0, 9, audio, video);
1137 } 1236 }
1138 1237
1238 TEST_F(ChunkDemuxerTest, TestAddSeparateSourcesForAudioAndVideo) {
1239 std::string audio_id = "audio1";
1240 std::string video_id = "video1";
1241 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
1242
1243 scoped_refptr<DemuxerStream> audio =
1244 demuxer_->GetStream(DemuxerStream::AUDIO);
1245 scoped_refptr<DemuxerStream> video =
1246 demuxer_->GetStream(DemuxerStream::VIDEO);
1247
1248 scoped_ptr<Cluster> cluster_a(
1249 GenerateSingleStreamCluster(0, 4, kAudioTrackNum, kAudioBlockDuration));
1250
1251 scoped_ptr<Cluster> cluster_v(
1252 GenerateSingleStreamCluster(0, 4, kVideoTrackNum, kVideoBlockDuration));
1253
1254 // Append audio and video data into separate source ids.
1255 ASSERT_TRUE(AppendData(audio_id, cluster_a->data(), cluster_a->size()));
1256 GenerateExpectedReads(0, 4, audio, kAudioBlockDuration);
1257 ASSERT_TRUE(AppendData(video_id, cluster_v->data(), cluster_v->size()));
1258 GenerateExpectedReads(0, 4, video, kVideoBlockDuration);
1259 }
1260
1261 TEST_F(ChunkDemuxerTest, TestAddIdFailures) {
1262 EXPECT_CALL(*client_, DemuxerOpened(_));
1263 demuxer_->Initialize(
1264 &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK));
1265
1266 std::string audio_id = "audio1";
1267 std::string video_id = "video1";
1268
1269 ASSERT_EQ(AddId(audio_id, true, false), ChunkDemuxer::kOk);
1270
1271 // Adding an id with audio/video should fail because we already added audio.
1272 ASSERT_EQ(AddId(), ChunkDemuxer::kReachedIdLimit);
1273
1274 ASSERT_TRUE(AppendInitSegment(audio_id, true, false, false));
1275
1276 // Adding an id after append should fail.
1277 ASSERT_EQ(AddId(video_id, false, true), ChunkDemuxer::kReachedIdLimit);
1278 }
1279
1280 // Test that Read() calls after a RemoveId() return "end of stream" buffers.
1281 TEST_F(ChunkDemuxerTest, TestRemoveId) {
1282 std::string audio_id = "audio1";
1283 std::string video_id = "video1";
1284 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
1285
1286 scoped_ptr<Cluster> cluster_a(
1287 GenerateSingleStreamCluster(0, 4, kAudioTrackNum, kAudioBlockDuration));
1288
1289 scoped_ptr<Cluster> cluster_v(
1290 GenerateSingleStreamCluster(0, 4, kVideoTrackNum, kVideoBlockDuration));
1291
1292 // Append audio and video data into separate source ids.
1293 ASSERT_TRUE(AppendData(audio_id, cluster_a->data(), cluster_a->size()));
1294 ASSERT_TRUE(AppendData(video_id, cluster_v->data(), cluster_v->size()));
1295
1296 // Read() from audio should return normal buffers.
1297 scoped_refptr<DemuxerStream> audio =
1298 demuxer_->GetStream(DemuxerStream::AUDIO);
1299 GenerateExpectedReads(0, 4, audio, kAudioBlockDuration);
1300
1301 // Remove the audio id.
1302 demuxer_->RemoveId(audio_id);
1303
1304 // Read() from audio should return "end of stream" buffers.
1305 bool audio_read_done = false;
1306 audio->Read(base::Bind(&OnReadDone_EOSExpected,
1307 &audio_read_done));
1308 EXPECT_TRUE(audio_read_done);
1309
1310 // Read() from video should still return normal buffers.
1311 scoped_refptr<DemuxerStream> video =
1312 demuxer_->GetStream(DemuxerStream::VIDEO);
1313 GenerateExpectedReads(0, 4, video, kVideoBlockDuration);
1314 }
1315
1316 // Test that Seek() successfully seeks to all source IDs.
1317 TEST_F(ChunkDemuxerTest, TestSeekAudioAndVideoSources) {
1318 std::string audio_id = "audio1";
1319 std::string video_id = "video1";
1320 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
1321
1322 scoped_ptr<Cluster> cluster_a1(
1323 GenerateSingleStreamCluster(0, 4, kAudioTrackNum, kAudioBlockDuration));
1324
1325 scoped_ptr<Cluster> cluster_v1(
1326 GenerateSingleStreamCluster(0, 4, kVideoTrackNum, kVideoBlockDuration));
1327
1328 ASSERT_TRUE(AppendData(audio_id, cluster_a1->data(), cluster_a1->size()));
1329 ASSERT_TRUE(AppendData(video_id, cluster_v1->data(), cluster_v1->size()));
1330
1331 // Read() should return buffers at 0.
1332 bool audio_read_done = false;
1333 bool video_read_done = false;
1334 scoped_refptr<DemuxerStream> audio =
1335 demuxer_->GetStream(DemuxerStream::AUDIO);
1336 scoped_refptr<DemuxerStream> video =
1337 demuxer_->GetStream(DemuxerStream::VIDEO);
1338
1339 audio->Read(base::Bind(&OnReadDone,
1340 base::TimeDelta::FromMilliseconds(0),
1341 &audio_read_done));
1342 video->Read(base::Bind(&OnReadDone,
1343 base::TimeDelta::FromMilliseconds(0),
1344 &video_read_done));
1345 EXPECT_TRUE(audio_read_done);
1346 EXPECT_TRUE(video_read_done);
1347
1348 // Seek to 3 (an unbuffered region).
1349 demuxer_->StartWaitingForSeek();
1350 demuxer_->Seek(base::TimeDelta::FromSeconds(3),
1351 NewExpectedStatusCB(PIPELINE_OK));
1352
1353 audio_read_done = false;
1354 video_read_done = false;
1355 audio->Read(base::Bind(&OnReadDone,
1356 base::TimeDelta::FromSeconds(3),
1357 &audio_read_done));
1358 video->Read(base::Bind(&OnReadDone,
1359 base::TimeDelta::FromSeconds(3),
1360 &video_read_done));
1361
1362 // Read()s should not return until after data is appended at the Seek point.
1363 EXPECT_FALSE(audio_read_done);
1364 EXPECT_FALSE(video_read_done);
1365
1366 scoped_ptr<Cluster> cluster_a2(
1367 GenerateSingleStreamCluster(3000, 4, kAudioTrackNum,
1368 kAudioBlockDuration));
1369
1370 scoped_ptr<Cluster> cluster_v2(
1371 GenerateSingleStreamCluster(3000, 4, kVideoTrackNum,
1372 kVideoBlockDuration));
1373
1374 ASSERT_TRUE(AppendData(audio_id, cluster_a2->data(), cluster_a2->size()));
1375 ASSERT_TRUE(AppendData(video_id, cluster_v2->data(), cluster_v2->size()));
1376
1377 // Read() should return buffers at 3.
1378 EXPECT_TRUE(audio_read_done);
1379 EXPECT_TRUE(video_read_done);
1380 }
1381
1139 } // namespace media 1382 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/chunk_demuxer.cc ('k') | media/filters/pipeline_integration_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698