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 3 // found in the LICENSE file. 4 5 #include <algorithm> 6 7 #include "base/bind.h" 8 #include "base/message_loop/message_loop.h" 9 #include "base/strings/string_number_conversions.h" 10 #include "base/strings/string_split.h" 11 #include "base/strings/string_util.h" 12 #include "media/base/audio_decoder_config.h" 13 #include "media/base/decoder_buffer.h" 14 #include "media/base/decrypt_config.h" 15 #include "media/base/mock_demuxer_host.h" 16 #include "media/base/test_data_util.h" 17 #include "media/base/test_helpers.h" 18 #include "media/filters/chunk_demuxer.h" 19 #include "media/webm/cluster_builder.h" 20 #include "media/webm/webm_constants.h" 21 #include "media/webm/webm_crypto_helpers.h" 22 #include "testing/gtest/include/gtest/gtest.h" 23 24 using ::testing::AnyNumber; 25 using ::testing::Exactly; 26 using ::testing::InSequence; 27 using ::testing::NotNull; 28 using ::testing::Return; 29 using ::testing::SaveArg; 30 using ::testing::SetArgumentPointee; 31 using ::testing::_; 32 33 namespace media { 34 35 static const uint8 kTracksHeader[] = { 36 0x16, 0x54, 0xAE, 0x6B, // Tracks ID 37 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // tracks(size = 0) 38 }; 39 40 // WebM Block bytes that represent a VP8 keyframe. 41 static const uint8 kVP8Keyframe[] = { 42 0x010, 0x00, 0x00, 0x9d, 0x01, 0x2a, 0x00, 0x10, 0x00, 0x10, 0x00 43 }; 44 45 // WebM Block bytes that represent a VP8 interframe. 46 static const uint8 kVP8Interframe[] = { 0x11, 0x00, 0x00 }; 47 48 static const int kTracksHeaderSize = sizeof(kTracksHeader); 49 static const int kTracksSizeOffset = 4; 50 51 // The size of TrackEntry element in test file "webm_vorbis_track_entry" starts 52 // at index 1 and spans 8 bytes. 53 static const int kAudioTrackSizeOffset = 1; 54 static const int kAudioTrackSizeWidth = 8; 55 static const int kAudioTrackEntryHeaderSize = kAudioTrackSizeOffset + 56 kAudioTrackSizeWidth; 57 58 // The size of TrackEntry element in test file "webm_vp8_track_entry" starts at 59 // index 1 and spans 8 bytes. 60 static const int kVideoTrackSizeOffset = 1; 61 static const int kVideoTrackSizeWidth = 8; 62 static const int kVideoTrackEntryHeaderSize = kVideoTrackSizeOffset + 63 kVideoTrackSizeWidth; 64 65 static const int kVideoTrackNum = 1; 66 static const int kAudioTrackNum = 2; 67 68 static const int kAudioBlockDuration = 23; 69 static const int kVideoBlockDuration = 33; 70 static const int kBlockSize = 10; 71 72 static const char kSourceId[] = "SourceId"; 73 static const char kDefaultFirstClusterRange[] = "{ [0,46) }"; 74 static const int kDefaultFirstClusterEndTimestamp = 66; 75 static const int kDefaultSecondClusterEndTimestamp = 132; 76 77 base::TimeDelta kDefaultDuration() { 78 return base::TimeDelta::FromMilliseconds(201224); 79 } 80 81 // Write an integer into buffer in the form of vint that spans 8 bytes. 82 // The data pointed by |buffer| should be at least 8 bytes long. 83 // |number| should be in the range 0 <= number < 0x00FFFFFFFFFFFFFF. 84 static void WriteInt64(uint8* buffer, int64 number) { 85 DCHECK(number >= 0 && number < GG_LONGLONG(0x00FFFFFFFFFFFFFF)); 86 buffer[0] = 0x01; 87 int64 tmp = number; 88 for (int i = 7; i > 0; i--) { 89 buffer[i] = tmp & 0xff; 90 tmp >>= 8; 91 } 92 } 93 94 MATCHER_P(HasTimestamp, timestamp_in_ms, "") { 95 return arg.get() && !arg->end_of_stream() && 96 arg->timestamp().InMilliseconds() == timestamp_in_ms; 97 } 98 99 MATCHER(IsEndOfStream, "") { return arg.get() && arg->end_of_stream(); } 100 101 static void OnReadDone(const base::TimeDelta& expected_time, 102 bool* called, 103 DemuxerStream::Status status, 104 const scoped_refptr<DecoderBuffer>& buffer) { 105 EXPECT_EQ(status, DemuxerStream::kOk); 106 EXPECT_EQ(expected_time, buffer->timestamp()); 107 *called = true; 108 } 109 110 static void OnReadDone_AbortExpected( 111 bool* called, DemuxerStream::Status status, 112 const scoped_refptr<DecoderBuffer>& buffer) { 113 EXPECT_EQ(status, DemuxerStream::kAborted); 114 EXPECT_EQ(NULL, buffer.get()); 115 *called = true; 116 } 117 118 static void OnReadDone_EOSExpected(bool* called, 119 DemuxerStream::Status status, 120 const scoped_refptr<DecoderBuffer>& buffer) { 121 EXPECT_EQ(status, DemuxerStream::kOk); 122 EXPECT_TRUE(buffer->end_of_stream()); 123 *called = true; 124 } 125 126 static void OnSeekDone_OKExpected(bool* called, PipelineStatus status) { 127 EXPECT_EQ(status, PIPELINE_OK); 128 *called = true; 129 } 130 131 class ChunkDemuxerTest : public testing::Test { 132 protected: 133 enum CodecsIndex { 134 AUDIO, 135 VIDEO, 136 MAX_CODECS_INDEX 137 }; 138 139 // Default cluster to append first for simple tests. 140 scoped_ptr<Cluster> kDefaultFirstCluster() { 141 return GenerateCluster(0, 4); 142 } 143 144 // Default cluster to append after kDefaultFirstCluster() 145 // has been appended. This cluster starts with blocks that 146 // have timestamps consistent with the end times of the blocks 147 // in kDefaultFirstCluster() so that these two clusters represent 148 // a continuous region. 149 scoped_ptr<Cluster> kDefaultSecondCluster() { 150 return GenerateCluster(46, 66, 5); 151 } 152 153 ChunkDemuxerTest() { 154 CreateNewDemuxer(); 155 } 156 157 void CreateNewDemuxer() { 158 base::Closure open_cb = 159 base::Bind(&ChunkDemuxerTest::DemuxerOpened, base::Unretained(this)); 160 Demuxer::NeedKeyCB need_key_cb = 161 base::Bind(&ChunkDemuxerTest::DemuxerNeedKey, base::Unretained(this)); 162 demuxer_.reset(new ChunkDemuxer(open_cb, need_key_cb, LogCB())); 163 } 164 165 virtual ~ChunkDemuxerTest() { 166 ShutdownDemuxer(); 167 } 168 169 void CreateInitSegment(bool has_audio, bool has_video, bool has_text, 170 bool is_audio_encrypted, bool is_video_encrypted, 171 scoped_ptr<uint8[]>* buffer, 172 int* size) { 173 scoped_refptr<DecoderBuffer> ebml_header; 174 scoped_refptr<DecoderBuffer> info; 175 scoped_refptr<DecoderBuffer> audio_track_entry; 176 scoped_refptr<DecoderBuffer> video_track_entry; 177 scoped_refptr<DecoderBuffer> audio_content_encodings; 178 scoped_refptr<DecoderBuffer> video_content_encodings; 179 scoped_refptr<DecoderBuffer> text_track_entry; 180 181 ebml_header = ReadTestDataFile("webm_ebml_element"); 182 183 info = ReadTestDataFile("webm_info_element"); 184 185 int tracks_element_size = 0; 186 187 if (has_audio) { 188 audio_track_entry = ReadTestDataFile("webm_vorbis_track_entry"); 189 tracks_element_size += audio_track_entry->data_size(); 190 if (is_audio_encrypted) { 191 audio_content_encodings = ReadTestDataFile("webm_content_encodings"); 192 tracks_element_size += audio_content_encodings->data_size(); 193 } 194 } 195 196 if (has_video) { 197 video_track_entry = ReadTestDataFile("webm_vp8_track_entry"); 198 tracks_element_size += video_track_entry->data_size(); 199 if (is_video_encrypted) { 200 video_content_encodings = ReadTestDataFile("webm_content_encodings"); 201 tracks_element_size += video_content_encodings->data_size(); 202 } 203 } 204 205 if (has_text) { 206 // TODO(matthewjheaney): create an abstraction to do 207 // this (http://crbug/321454). 208 // We need it to also handle the creation of multiple text tracks. 209 // 210 // This is the track entry for a text track, 211 // TrackEntry [AE], size=30 212 // TrackNum [D7], size=1, val=3 213 // TrackUID [73] [C5], size=1, value=3 214 // TrackType [83], size=1, val=0x11 215 // CodecId [86], size=18, val="D_WEBVTT/SUBTITLES" 216 const char str[] = "\xAE\x9E\xD7\x81\x03\x73\xC5\x81\x03" 217 "\x83\x81\x11\x86\x92" 218 "D_WEBVTT/SUBTITLES"; 219 const int len = strlen(str); 220 DCHECK_EQ(len, 32); 221 const uint8* const buf = reinterpret_cast<const uint8*>(str); 222 text_track_entry = DecoderBuffer::CopyFrom(buf, len); 223 tracks_element_size += text_track_entry->data_size(); 224 } 225 226 *size = ebml_header->data_size() + info->data_size() + 227 kTracksHeaderSize + tracks_element_size; 228 229 buffer->reset(new uint8[*size]); 230 231 uint8* buf = buffer->get(); 232 memcpy(buf, ebml_header->data(), ebml_header->data_size()); 233 buf += ebml_header->data_size(); 234 235 memcpy(buf, info->data(), info->data_size()); 236 buf += info->data_size(); 237 238 memcpy(buf, kTracksHeader, kTracksHeaderSize); 239 WriteInt64(buf + kTracksSizeOffset, tracks_element_size); 240 buf += kTracksHeaderSize; 241 242 // TODO(xhwang): Simplify this! Probably have test data files that contain 243 // ContentEncodings directly instead of trying to create one at run-time. 244 if (has_audio) { 245 memcpy(buf, audio_track_entry->data(), 246 audio_track_entry->data_size()); 247 if (is_audio_encrypted) { 248 memcpy(buf + audio_track_entry->data_size(), 249 audio_content_encodings->data(), 250 audio_content_encodings->data_size()); 251 WriteInt64(buf + kAudioTrackSizeOffset, 252 audio_track_entry->data_size() + 253 audio_content_encodings->data_size() - 254 kAudioTrackEntryHeaderSize); 255 buf += audio_content_encodings->data_size(); 256 } 257 buf += audio_track_entry->data_size(); 258 } 259 260 if (has_video) { 261 memcpy(buf, video_track_entry->data(), 262 video_track_entry->data_size()); 263 if (is_video_encrypted) { 264 memcpy(buf + video_track_entry->data_size(), 265 video_content_encodings->data(), 266 video_content_encodings->data_size()); 267 WriteInt64(buf + kVideoTrackSizeOffset, 268 video_track_entry->data_size() + 269 video_content_encodings->data_size() - 270 kVideoTrackEntryHeaderSize); 271 buf += video_content_encodings->data_size(); 272 } 273 buf += video_track_entry->data_size(); 274 } 275 276 if (has_text) { 277 memcpy(buf, text_track_entry->data(), 278 text_track_entry->data_size()); 279 buf += text_track_entry->data_size(); 280 } 281 } 282 283 ChunkDemuxer::Status AddId() { 284 return AddId(kSourceId, true, true); 285 } 286 287 ChunkDemuxer::Status AddId(const std::string& source_id, 288 bool has_audio, bool has_video) { 289 std::vector<std::string> codecs; 290 std::string type; 291 292 if (has_audio) { 293 codecs.push_back("vorbis"); 294 type = "audio/webm"; 295 } 296 297 if (has_video) { 298 codecs.push_back("vp8"); 299 type = "video/webm"; 300 } 301 302 if (!has_audio && !has_video) { 303 return AddId(kSourceId, true, true); 304 } 305 306 return demuxer_->AddId(source_id, type, codecs); 307 } 308 309 void AppendData(const uint8* data, size_t length) { 310 AppendData(kSourceId, data, length); 311 } 312 313 void AppendCluster(const std::string& source_id, 314 scoped_ptr<Cluster> cluster) { 315 AppendData(source_id, cluster->data(), cluster->size()); 316 } 317 318 void AppendCluster(scoped_ptr<Cluster> cluster) { 319 AppendCluster(kSourceId, cluster.Pass()); 320 } 321 322 void AppendCluster(int timecode, int block_count) { 323 AppendCluster(GenerateCluster(timecode, block_count)); 324 } 325 326 void AppendSingleStreamCluster(const std::string& source_id, int track_number, 327 int timecode, int block_count) { 328 int block_duration = 0; 329 switch(track_number) { 330 case kVideoTrackNum: 331 block_duration = kVideoBlockDuration; 332 break; 333 case kAudioTrackNum: 334 block_duration = kAudioBlockDuration; 335 break; 336 } 337 ASSERT_NE(block_duration, 0); 338 int end_timecode = timecode + block_count * block_duration; 339 AppendCluster(source_id, 340 GenerateSingleStreamCluster( 341 timecode, end_timecode, track_number, block_duration)); 342 } 343 344 void AppendSingleStreamCluster(const std::string& source_id, int track_number, 345 const std::string& cluster_description) { 346 std::vector<std::string> timestamps; 347 base::SplitString(cluster_description, ' ', ×tamps); 348 349 ClusterBuilder cb; 350 std::vector<uint8> data(10); 351 for (size_t i = 0; i < timestamps.size(); ++i) { 352 std::string timestamp_str = timestamps[i]; 353 int block_flags = 0; 354 if (EndsWith(timestamp_str, "K", true)) { 355 block_flags = kWebMFlagKeyframe; 356 // Remove the "K" off of the token. 357 timestamp_str = timestamp_str.substr(0, timestamps[i].length() - 1); 358 } 359 int timestamp_in_ms; 360 CHECK(base::StringToInt(timestamp_str, ×tamp_in_ms)); 361 362 if (i == 0) 363 cb.SetClusterTimecode(timestamp_in_ms); 364 365 cb.AddSimpleBlock(track_number, timestamp_in_ms, block_flags, 366 &data[0], data.size()); 367 } 368 AppendCluster(source_id, cb.Finish()); 369 } 370 371 void AppendData(const std::string& source_id, 372 const uint8* data, size_t length) { 373 EXPECT_CALL(host_, AddBufferedTimeRange(_, _)).Times(AnyNumber()); 374 demuxer_->AppendData(source_id, data, length); 375 } 376 377 void AppendDataInPieces(const uint8* data, size_t length) { 378 AppendDataInPieces(data, length, 7); 379 } 380 381 void AppendDataInPieces(const uint8* data, size_t length, size_t piece_size) { 382 const uint8* start = data; 383 const uint8* end = data + length; 384 while (start < end) { 385 size_t append_size = std::min(piece_size, 386 static_cast<size_t>(end - start)); 387 AppendData(start, append_size); 388 start += append_size; 389 } 390 } 391 392 void AppendInitSegment(bool has_audio, bool has_video) { 393 AppendInitSegmentWithSourceId(kSourceId, has_audio, has_video, false); 394 } 395 396 void AppendInitSegmentText(bool has_audio, bool has_video) { 397 AppendInitSegmentWithSourceId(kSourceId, has_audio, has_video, true); 398 } 399 400 void AppendInitSegmentWithSourceId(const std::string& source_id, 401 bool has_audio, bool has_video, 402 bool has_text) { 403 AppendInitSegmentWithEncryptedInfo( 404 source_id, has_audio, has_video, has_text, false, false); 405 } 406 407 void AppendInitSegmentWithEncryptedInfo(const std::string& source_id, 408 bool has_audio, bool has_video, 409 bool has_text, 410 bool is_audio_encrypted, 411 bool is_video_encrypted) { 412 scoped_ptr<uint8[]> info_tracks; 413 int info_tracks_size = 0; 414 CreateInitSegment(has_audio, has_video, has_text, 415 is_audio_encrypted, is_video_encrypted, 416 &info_tracks, &info_tracks_size); 417 AppendData(source_id, info_tracks.get(), info_tracks_size); 418 } 419 420 void AppendGarbage() { 421 // Fill up an array with gibberish. 422 int garbage_cluster_size = 10; 423 scoped_ptr<uint8[]> garbage_cluster(new uint8[garbage_cluster_size]); 424 for (int i = 0; i < garbage_cluster_size; ++i) 425 garbage_cluster[i] = i; 426 AppendData(garbage_cluster.get(), garbage_cluster_size); 427 } 428 429 void InitDoneCalled(PipelineStatus expected_status, 430 PipelineStatus status) { 431 EXPECT_EQ(status, expected_status); 432 } 433 434 void AppendEmptyCluster(int timecode) { 435 AppendCluster(GenerateEmptyCluster(timecode)); 436 } 437 438 PipelineStatusCB CreateInitDoneCB(const base::TimeDelta& expected_duration, 439 PipelineStatus expected_status) { 440 if (expected_duration != kNoTimestamp()) 441 EXPECT_CALL(host_, SetDuration(expected_duration)); 442 return CreateInitDoneCB(expected_status); 443 } 444 445 PipelineStatusCB CreateInitDoneCB(PipelineStatus expected_status) { 446 return base::Bind(&ChunkDemuxerTest::InitDoneCalled, 447 base::Unretained(this), 448 expected_status); 449 } 450 451 bool InitDemuxer(bool has_audio, bool has_video) { 452 return InitDemuxerWithEncryptionInfo(has_audio, has_video, false, 453 false, false); 454 } 455 456 bool InitDemuxerText(bool has_audio, bool has_video) { 457 return InitDemuxerWithEncryptionInfo(has_audio, has_video, true, 458 false, false); 459 } 460 461 bool InitDemuxerWithEncryptionInfo( 462 bool has_audio, bool has_video, bool has_text, 463 bool is_audio_encrypted, bool is_video_encrypted) { 464 PipelineStatus expected_status = 465 (has_audio || has_video) ? PIPELINE_OK : DEMUXER_ERROR_COULD_NOT_OPEN; 466 467 base::TimeDelta expected_duration = kNoTimestamp(); 468 if (expected_status == PIPELINE_OK) 469 expected_duration = kDefaultDuration(); 470 471 EXPECT_CALL(*this, DemuxerOpened()); 472 demuxer_->Initialize( 473 &host_, CreateInitDoneCB(expected_duration, expected_status), true); 474 475 if (AddId(kSourceId, has_audio, has_video) != ChunkDemuxer::kOk) 476 return false; 477 478 AppendInitSegmentWithEncryptedInfo( 479 kSourceId, has_audio, has_video, has_text, 480 is_audio_encrypted, is_video_encrypted); 481 return true; 482 } 483 484 bool InitDemuxerAudioAndVideoSourcesText(const std::string& audio_id, 485 const std::string& video_id, 486 bool has_text) { 487 EXPECT_CALL(*this, DemuxerOpened()); 488 demuxer_->Initialize( 489 &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true); 490 491 if (AddId(audio_id, true, false) != ChunkDemuxer::kOk) 492 return false; 493 if (AddId(video_id, false, true) != ChunkDemuxer::kOk) 494 return false; 495 496 AppendInitSegmentWithSourceId(audio_id, true, false, has_text); 497 AppendInitSegmentWithSourceId(video_id, false, true, has_text); 498 return true; 499 } 500 501 bool InitDemuxerAudioAndVideoSources(const std::string& audio_id, 502 const std::string& video_id) { 503 return InitDemuxerAudioAndVideoSourcesText(audio_id, video_id, false); 504 } 505 506 // Initializes the demuxer with data from 2 files with different 507 // decoder configurations. This is used to test the decoder config change 508 // logic. 509 // 510 // bear-320x240.webm VideoDecoderConfig returns 320x240 for its natural_size() 511 // bear-640x360.webm VideoDecoderConfig returns 640x360 for its natural_size() 512 // The resulting video stream returns data from each file for the following 513 // time ranges. 514 // bear-320x240.webm : [0-501) [801-2737) 515 // bear-640x360.webm : [527-793) 516 // 517 // bear-320x240.webm AudioDecoderConfig returns 3863 for its extra_data_size() 518 // bear-640x360.webm AudioDecoderConfig returns 3935 for its extra_data_size() 519 // The resulting audio stream returns data from each file for the following 520 // time ranges. 521 // bear-320x240.webm : [0-524) [779-2737) 522 // bear-640x360.webm : [527-759) 523 bool InitDemuxerWithConfigChangeData() { 524 scoped_refptr<DecoderBuffer> bear1 = ReadTestDataFile("bear-320x240.webm"); 525 scoped_refptr<DecoderBuffer> bear2 = ReadTestDataFile("bear-640x360.webm"); 526 527 EXPECT_CALL(*this, DemuxerOpened()); 528 demuxer_->Initialize( 529 &host_, CreateInitDoneCB(base::TimeDelta::FromMilliseconds(2744), 530 PIPELINE_OK), true); 531 532 if (AddId(kSourceId, true, true) != ChunkDemuxer::kOk) 533 return false; 534 535 // Append the whole bear1 file. 536 AppendData(bear1->data(), bear1->data_size()); 537 CheckExpectedRanges(kSourceId, "{ [0,2737) }"); 538 539 // Append initialization segment for bear2. 540 // Note: Offsets here and below are derived from 541 // media/test/data/bear-640x360-manifest.js and 542 // media/test/data/bear-320x240-manifest.js which were 543 // generated from media/test/data/bear-640x360.webm and 544 // media/test/data/bear-320x240.webm respectively. 545 AppendData(bear2->data(), 4340); 546 547 // Append a media segment that goes from [0.527000, 1.014000). 548 AppendData(bear2->data() + 55290, 18785); 549 CheckExpectedRanges(kSourceId, "{ [0,1028) [1201,2737) }"); 550 551 // Append initialization segment for bear1 & fill gap with [779-1197) 552 // segment. 553 AppendData(bear1->data(), 4370); 554 AppendData(bear1->data() + 72737, 28183); 555 CheckExpectedRanges(kSourceId, "{ [0,2737) }"); 556 557 MarkEndOfStream(PIPELINE_OK); 558 return true; 559 } 560 561 void ShutdownDemuxer() { 562 if (demuxer_) { 563 demuxer_->Shutdown(); 564 message_loop_.RunUntilIdle(); 565 } 566 } 567 568 void AddSimpleBlock(ClusterBuilder* cb, int track_num, int64 timecode) { 569 uint8 data[] = { 0x00 }; 570 cb->AddSimpleBlock(track_num, timecode, 0, data, sizeof(data)); 571 } 572 573 scoped_ptr<Cluster> GenerateCluster(int timecode, int block_count) { 574 return GenerateCluster(timecode, timecode, block_count); 575 } 576 577 void AddVideoBlockGroup(ClusterBuilder* cb, int track_num, int64 timecode, 578 int duration, int flags) { 579 const uint8* data = 580 (flags & kWebMFlagKeyframe) != 0 ? kVP8Keyframe : kVP8Interframe; 581 int size = (flags & kWebMFlagKeyframe) != 0 ? sizeof(kVP8Keyframe) : 582 sizeof(kVP8Interframe); 583 cb->AddBlockGroup(track_num, timecode, duration, flags, data, size); 584 } 585 586 scoped_ptr<Cluster> GenerateCluster(int first_audio_timecode, 587 int first_video_timecode, 588 int block_count) { 589 CHECK_GT(block_count, 0); 590 591 int size = 10; 592 scoped_ptr<uint8[]> data(new uint8[size]); 593 594 ClusterBuilder cb; 595 cb.SetClusterTimecode(std::min(first_audio_timecode, first_video_timecode)); 596 597 if (block_count == 1) { 598 cb.AddBlockGroup(kAudioTrackNum, first_audio_timecode, 599 kAudioBlockDuration, kWebMFlagKeyframe, 600 data.get(), size); 601 return cb.Finish(); 602 } 603 604 int audio_timecode = first_audio_timecode; 605 int video_timecode = first_video_timecode; 606 607 // Create simple blocks for everything except the last 2 blocks. 608 // The first video frame must be a keyframe. 609 uint8 video_flag = kWebMFlagKeyframe; 610 for (int i = 0; i < block_count - 2; i++) { 611 if (audio_timecode <= video_timecode) { 612 cb.AddSimpleBlock(kAudioTrackNum, audio_timecode, kWebMFlagKeyframe, 613 data.get(), size); 614 audio_timecode += kAudioBlockDuration; 615 continue; 616 } 617 618 cb.AddSimpleBlock(kVideoTrackNum, video_timecode, video_flag, data.get(), 619 size); 620 video_timecode += kVideoBlockDuration; 621 video_flag = 0; 622 } 623 624 // Make the last 2 blocks BlockGroups so that they don't get delayed by the 625 // block duration calculation logic. 626 if (audio_timecode <= video_timecode) { 627 cb.AddBlockGroup(kAudioTrackNum, audio_timecode, kAudioBlockDuration, 628 kWebMFlagKeyframe, data.get(), size); 629 AddVideoBlockGroup(&cb, kVideoTrackNum, video_timecode, 630 kVideoBlockDuration, video_flag); 631 } else { 632 AddVideoBlockGroup(&cb, kVideoTrackNum, video_timecode, 633 kVideoBlockDuration, video_flag); 634 cb.AddBlockGroup(kAudioTrackNum, audio_timecode, kAudioBlockDuration, 635 kWebMFlagKeyframe, data.get(), size); 636 } 637 638 return cb.Finish(); 639 } 640 641 scoped_ptr<Cluster> GenerateSingleStreamCluster(int timecode, 642 int end_timecode, 643 int track_number, 644 int block_duration) { 645 CHECK_GT(end_timecode, timecode); 646 647 std::vector<uint8> data(kBlockSize); 648 649 ClusterBuilder cb; 650 cb.SetClusterTimecode(timecode); 651 652 // Create simple blocks for everything except the last block. 653 for (int i = 0; timecode < (end_timecode - block_duration); i++) { 654 cb.AddSimpleBlock(track_number, timecode, kWebMFlagKeyframe, 655 &data[0], data.size()); 656 timecode += block_duration; 657 } 658 659 // Make the last block a BlockGroup so that it doesn't get delayed by the 660 // block duration calculation logic. 661 if (track_number == kVideoTrackNum) { 662 AddVideoBlockGroup(&cb, track_number, timecode, block_duration, 663 kWebMFlagKeyframe); 664 } else { 665 cb.AddBlockGroup(track_number, timecode, block_duration, 666 kWebMFlagKeyframe, &data[0], data.size()); 667 } 668 return cb.Finish(); 669 } 670 671 void Read(DemuxerStream::Type type, const DemuxerStream::ReadCB& read_cb) { 672 demuxer_->GetStream(type)->Read(read_cb); 673 message_loop_.RunUntilIdle(); 674 } 675 676 void ReadAudio(const DemuxerStream::ReadCB& read_cb) { 677 Read(DemuxerStream::AUDIO, read_cb); 678 } 679 680 void ReadVideo(const DemuxerStream::ReadCB& read_cb) { 681 Read(DemuxerStream::VIDEO, read_cb); 682 } 683 684 void GenerateExpectedReads(int timecode, int block_count) { 685 GenerateExpectedReads(timecode, timecode, block_count); 686 } 687 688 void GenerateExpectedReads(int start_audio_timecode, 689 int start_video_timecode, 690 int block_count) { 691 CHECK_GT(block_count, 0); 692 693 if (block_count == 1) { 694 ExpectRead(DemuxerStream::AUDIO, start_audio_timecode); 695 return; 696 } 697 698 int audio_timecode = start_audio_timecode; 699 int video_timecode = start_video_timecode; 700 701 for (int i = 0; i < block_count; i++) { 702 if (audio_timecode <= video_timecode) { 703 ExpectRead(DemuxerStream::AUDIO, audio_timecode); 704 audio_timecode += kAudioBlockDuration; 705 continue; 706 } 707 708 ExpectRead(DemuxerStream::VIDEO, video_timecode); 709 video_timecode += kVideoBlockDuration; 710 } 711 } 712 713 void GenerateSingleStreamExpectedReads(int timecode, 714 int block_count, 715 DemuxerStream::Type type, 716 int block_duration) { 717 CHECK_GT(block_count, 0); 718 int stream_timecode = timecode; 719 720 for (int i = 0; i < block_count; i++) { 721 ExpectRead(type, stream_timecode); 722 stream_timecode += block_duration; 723 } 724 } 725 726 void GenerateAudioStreamExpectedReads(int timecode, int block_count) { 727 GenerateSingleStreamExpectedReads( 728 timecode, block_count, DemuxerStream::AUDIO, kAudioBlockDuration); 729 } 730 731 void GenerateVideoStreamExpectedReads(int timecode, int block_count) { 732 GenerateSingleStreamExpectedReads( 733 timecode, block_count, DemuxerStream::VIDEO, kVideoBlockDuration); 734 } 735 736 scoped_ptr<Cluster> GenerateEmptyCluster(int timecode) { 737 ClusterBuilder cb; 738 cb.SetClusterTimecode(timecode); 739 return cb.Finish(); 740 } 741 742 void CheckExpectedRanges(const std::string& expected) { 743 CheckExpectedRanges(kSourceId, expected); 744 } 745 746 void CheckExpectedRanges(const std::string& id, 747 const std::string& expected) { 748 Ranges<base::TimeDelta> r = demuxer_->GetBufferedRanges(id); 749 750 std::stringstream ss; 751 ss << "{ "; 752 for (size_t i = 0; i < r.size(); ++i) { 753 ss << "[" << r.start(i).InMilliseconds() << "," 754 << r.end(i).InMilliseconds() << ") "; 755 } 756 ss << "}"; 757 EXPECT_EQ(ss.str(), expected); 758 } 759 760 MOCK_METHOD2(ReadDone, void(DemuxerStream::Status status, 761 const scoped_refptr<DecoderBuffer>&)); 762 763 void StoreStatusAndBuffer(DemuxerStream::Status* status_out, 764 scoped_refptr<DecoderBuffer>* buffer_out, 765 DemuxerStream::Status status, 766 const scoped_refptr<DecoderBuffer>& buffer) { 767 *status_out = status; 768 *buffer_out = buffer; 769 } 770 771 void ReadUntilNotOkOrEndOfStream(DemuxerStream::Type type, 772 DemuxerStream::Status* status, 773 base::TimeDelta* last_timestamp) { 774 DemuxerStream* stream = demuxer_->GetStream(type); 775 scoped_refptr<DecoderBuffer> buffer; 776 777 *last_timestamp = kNoTimestamp(); 778 do { 779 stream->Read(base::Bind(&ChunkDemuxerTest::StoreStatusAndBuffer, 780 base::Unretained(this), status, &buffer)); 781 base::MessageLoop::current()->RunUntilIdle(); 782 if (*status == DemuxerStream::kOk && !buffer->end_of_stream()) 783 *last_timestamp = buffer->timestamp(); 784 } while (*status == DemuxerStream::kOk && !buffer->end_of_stream()); 785 } 786 787 void ExpectEndOfStream(DemuxerStream::Type type) { 788 EXPECT_CALL(*this, ReadDone(DemuxerStream::kOk, IsEndOfStream())); 789 demuxer_->GetStream(type)->Read(base::Bind( 790 &ChunkDemuxerTest::ReadDone, base::Unretained(this))); 791 message_loop_.RunUntilIdle(); 792 } 793 794 void ExpectRead(DemuxerStream::Type type, int64 timestamp_in_ms) { 795 EXPECT_CALL(*this, ReadDone(DemuxerStream::kOk, 796 HasTimestamp(timestamp_in_ms))); 797 demuxer_->GetStream(type)->Read(base::Bind( 798 &ChunkDemuxerTest::ReadDone, base::Unretained(this))); 799 message_loop_.RunUntilIdle(); 800 } 801 802 void ExpectConfigChanged(DemuxerStream::Type type) { 803 EXPECT_CALL(*this, ReadDone(DemuxerStream::kConfigChanged, _)); 804 demuxer_->GetStream(type)->Read(base::Bind( 805 &ChunkDemuxerTest::ReadDone, base::Unretained(this))); 806 message_loop_.RunUntilIdle(); 807 } 808 809 void CheckExpectedBuffers(DemuxerStream* stream, 810 const std::string& expected) { 811 std::vector<std::string> timestamps; 812 base::SplitString(expected, ' ', ×tamps); 813 std::stringstream ss; 814 for (size_t i = 0; i < timestamps.size(); ++i) { 815 DemuxerStream::Status status; 816 scoped_refptr<DecoderBuffer> buffer; 817 stream->Read(base::Bind(&ChunkDemuxerTest::StoreStatusAndBuffer, 818 base::Unretained(this), &status, &buffer)); 819 base::MessageLoop::current()->RunUntilIdle(); 820 if (status != DemuxerStream::kOk || buffer->end_of_stream()) 821 break; 822 823 if (i > 0) 824 ss << " "; 825 ss << buffer->timestamp().InMilliseconds(); 826 } 827 EXPECT_EQ(expected, ss.str()); 828 } 829 830 MOCK_METHOD1(Checkpoint, void(int id)); 831 832 struct BufferTimestamps { 833 int video_time_ms; 834 int audio_time_ms; 835 }; 836 static const int kSkip = -1; 837 838 // Test parsing a WebM file. 839 // |filename| - The name of the file in media/test/data to parse. 840 // |timestamps| - The expected timestamps on the parsed buffers. 841 // a timestamp of kSkip indicates that a Read() call for that stream 842 // shouldn't be made on that iteration of the loop. If both streams have 843 // a kSkip then the loop will terminate. 844 bool ParseWebMFile(const std::string& filename, 845 const BufferTimestamps* timestamps, 846 const base::TimeDelta& duration) { 847 return ParseWebMFile(filename, timestamps, duration, true, true); 848 } 849 850 bool ParseWebMFile(const std::string& filename, 851 const BufferTimestamps* timestamps, 852 const base::TimeDelta& duration, 853 bool has_audio, bool has_video) { 854 EXPECT_CALL(*this, DemuxerOpened()); 855 demuxer_->Initialize( 856 &host_, CreateInitDoneCB(duration, PIPELINE_OK), true); 857 858 if (AddId(kSourceId, has_audio, has_video) != ChunkDemuxer::kOk) 859 return false; 860 861 // Read a WebM file into memory and send the data to the demuxer. 862 scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(filename); 863 AppendDataInPieces(buffer->data(), buffer->data_size(), 512); 864 865 // Verify that the timestamps on the first few packets match what we 866 // expect. 867 for (size_t i = 0; 868 (timestamps[i].audio_time_ms != kSkip || 869 timestamps[i].video_time_ms != kSkip); 870 i++) { 871 bool audio_read_done = false; 872 bool video_read_done = false; 873 874 if (timestamps[i].audio_time_ms != kSkip) { 875 ReadAudio(base::Bind(&OnReadDone, 876 base::TimeDelta::FromMilliseconds( 877 timestamps[i].audio_time_ms), 878 &audio_read_done)); 879 EXPECT_TRUE(audio_read_done); 880 } 881 882 if (timestamps[i].video_time_ms != kSkip) { 883 ReadVideo(base::Bind(&OnReadDone, 884 base::TimeDelta::FromMilliseconds( 885 timestamps[i].video_time_ms), 886 &video_read_done)); 887 EXPECT_TRUE(video_read_done); 888 } 889 } 890 891 return true; 892 } 893 894 MOCK_METHOD0(DemuxerOpened, void()); 895 // TODO(xhwang): This is a workaround of the issue that move-only parameters 896 // are not supported in mocked methods. Remove this when the issue is fixed 897 // (http://code.google.com/p/googletest/issues/detail?id=395) or when we use 898 // std::string instead of scoped_ptr<uint8[]> (http://crbug.com/130689). 899 MOCK_METHOD3(NeedKeyMock, void(const std::string& type, 900 const uint8* init_data, int init_data_size)); 901 void DemuxerNeedKey(const std::string& type, 902 const std::vector<uint8>& init_data) { 903 const uint8* init_data_ptr = init_data.empty() ? NULL : &init_data[0]; 904 NeedKeyMock(type, init_data_ptr, init_data.size()); 905 } 906 907 void Seek(base::TimeDelta seek_time) { 908 demuxer_->StartWaitingForSeek(seek_time); 909 demuxer_->Seek(seek_time, NewExpectedStatusCB(PIPELINE_OK)); 910 message_loop_.RunUntilIdle(); 911 } 912 913 void MarkEndOfStream(PipelineStatus status) { 914 demuxer_->MarkEndOfStream(status); 915 message_loop_.RunUntilIdle(); 916 } 917 918 base::MessageLoop message_loop_; 919 MockDemuxerHost host_; 920 921 scoped_ptr<ChunkDemuxer> demuxer_; 922 923 private: 924 DISALLOW_COPY_AND_ASSIGN(ChunkDemuxerTest); 925 }; 926 927 TEST_F(ChunkDemuxerTest, Init) { 928 // Test no streams, audio-only, video-only, and audio & video scenarios. 929 // Audio and video streams can be encrypted or not encrypted. 930 for (int i = 0; i < 16; i++) { 931 bool has_audio = (i & 0x1) != 0; 932 bool has_video = (i & 0x2) != 0; 933 bool is_audio_encrypted = (i & 0x4) != 0; 934 bool is_video_encrypted = (i & 0x8) != 0; 935 936 // No test on invalid combination. 937 if ((!has_audio && is_audio_encrypted) || 938 (!has_video && is_video_encrypted)) { 939 continue; 940 } 941 942 CreateNewDemuxer(); 943 944 if (is_audio_encrypted || is_video_encrypted) { 945 int need_key_count = (is_audio_encrypted ? 1 : 0) + 946 (is_video_encrypted ? 1 : 0); 947 EXPECT_CALL(*this, NeedKeyMock(kWebMEncryptInitDataType, NotNull(), 948 DecryptConfig::kDecryptionKeySize)) 949 .Times(Exactly(need_key_count)); 950 } 951 952 ASSERT_TRUE(InitDemuxerWithEncryptionInfo( 953 has_audio, has_video, false, is_audio_encrypted, is_video_encrypted)); 954 955 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO); 956 if (has_audio) { 957 ASSERT_TRUE(audio_stream); 958 959 const AudioDecoderConfig& config = audio_stream->audio_decoder_config(); 960 EXPECT_EQ(kCodecVorbis, config.codec()); 961 EXPECT_EQ(32, config.bits_per_channel()); 962 EXPECT_EQ(CHANNEL_LAYOUT_STEREO, config.channel_layout()); 963 EXPECT_EQ(44100, config.samples_per_second()); 964 EXPECT_TRUE(config.extra_data()); 965 EXPECT_GT(config.extra_data_size(), 0u); 966 EXPECT_EQ(kSampleFormatPlanarF32, config.sample_format()); 967 EXPECT_EQ(is_audio_encrypted, 968 audio_stream->audio_decoder_config().is_encrypted()); 969 } else { 970 EXPECT_FALSE(audio_stream); 971 } 972 973 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO); 974 if (has_video) { 975 EXPECT_TRUE(video_stream); 976 EXPECT_EQ(is_video_encrypted, 977 video_stream->video_decoder_config().is_encrypted()); 978 } else { 979 EXPECT_FALSE(video_stream); 980 } 981 982 ShutdownDemuxer(); 983 demuxer_.reset(); 984 } 985 } 986 987 TEST_F(ChunkDemuxerTest, InitText) { 988 // Test with 1 video stream and 1 text streams, and 0 or 1 audio streams. 989 // No encryption cases handled here. 990 bool has_video = true; 991 bool is_audio_encrypted = false; 992 bool is_video_encrypted = false; 993 for (int i = 0; i < 2; i++) { 994 bool has_audio = (i & 0x1) != 0; 995 996 CreateNewDemuxer(); 997 998 DemuxerStream* text_stream = NULL; 999 TextTrackConfig text_config; 1000 EXPECT_CALL(host_, AddTextStream(_,_)) 1001 .WillOnce(DoAll(SaveArg<0>(&text_stream), 1002 SaveArg<1>(&text_config))); 1003 1004 ASSERT_TRUE(InitDemuxerWithEncryptionInfo( 1005 has_audio, has_video, true, is_audio_encrypted, is_video_encrypted)); 1006 ASSERT_TRUE(text_stream); 1007 EXPECT_EQ(DemuxerStream::TEXT, text_stream->type()); 1008 EXPECT_EQ(kTextSubtitles, text_config.kind()); 1009 1010 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO); 1011 if (has_audio) { 1012 ASSERT_TRUE(audio_stream); 1013 1014 const AudioDecoderConfig& config = audio_stream->audio_decoder_config(); 1015 EXPECT_EQ(kCodecVorbis, config.codec()); 1016 EXPECT_EQ(32, config.bits_per_channel()); 1017 EXPECT_EQ(CHANNEL_LAYOUT_STEREO, config.channel_layout()); 1018 EXPECT_EQ(44100, config.samples_per_second()); 1019 EXPECT_TRUE(config.extra_data()); 1020 EXPECT_GT(config.extra_data_size(), 0u); 1021 EXPECT_EQ(kSampleFormatPlanarF32, config.sample_format()); 1022 EXPECT_EQ(is_audio_encrypted, 1023 audio_stream->audio_decoder_config().is_encrypted()); 1024 } else { 1025 EXPECT_FALSE(audio_stream); 1026 } 1027 1028 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO); 1029 if (has_video) { 1030 EXPECT_TRUE(video_stream); 1031 EXPECT_EQ(is_video_encrypted, 1032 video_stream->video_decoder_config().is_encrypted()); 1033 } else { 1034 EXPECT_FALSE(video_stream); 1035 } 1036 1037 ShutdownDemuxer(); 1038 demuxer_.reset(); 1039 } 1040 } 1041 1042 // Make sure that the demuxer reports an error if Shutdown() 1043 // is called before all the initialization segments are appended. 1044 TEST_F(ChunkDemuxerTest, ShutdownBeforeAllInitSegmentsAppended) { 1045 EXPECT_CALL(*this, DemuxerOpened()); 1046 demuxer_->Initialize( 1047 &host_, CreateInitDoneCB( 1048 kDefaultDuration(), DEMUXER_ERROR_COULD_NOT_OPEN), true); 1049 1050 EXPECT_EQ(AddId("audio", true, false), ChunkDemuxer::kOk); 1051 EXPECT_EQ(AddId("video", false, true), ChunkDemuxer::kOk); 1052 1053 AppendInitSegmentWithSourceId("audio", true, false, false); 1054 } 1055 1056 TEST_F(ChunkDemuxerTest, ShutdownBeforeAllInitSegmentsAppendedText) { 1057 EXPECT_CALL(*this, DemuxerOpened()); 1058 demuxer_->Initialize( 1059 &host_, CreateInitDoneCB( 1060 kDefaultDuration(), DEMUXER_ERROR_COULD_NOT_OPEN), true); 1061 1062 EXPECT_EQ(AddId("audio", true, false), ChunkDemuxer::kOk); 1063 EXPECT_EQ(AddId("video", false, true), ChunkDemuxer::kOk); 1064 1065 EXPECT_CALL(host_, AddTextStream(_,_)) 1066 .Times(Exactly(1)); 1067 1068 AppendInitSegmentWithSourceId("video", false, true, true); 1069 } 1070 1071 // Test that Seek() completes successfully when the first cluster 1072 // arrives. 1073 TEST_F(ChunkDemuxerTest, AppendDataAfterSeek) { 1074 ASSERT_TRUE(InitDemuxer(true, true)); 1075 AppendCluster(kDefaultFirstCluster()); 1076 1077 InSequence s; 1078 1079 EXPECT_CALL(*this, Checkpoint(1)); 1080 1081 Seek(base::TimeDelta::FromMilliseconds(46)); 1082 1083 EXPECT_CALL(*this, Checkpoint(2)); 1084 1085 Checkpoint(1); 1086 1087 AppendCluster(kDefaultSecondCluster()); 1088 1089 message_loop_.RunUntilIdle(); 1090 1091 Checkpoint(2); 1092 } 1093 1094 // Test that parsing errors are handled for clusters appended after init. 1095 TEST_F(ChunkDemuxerTest, ErrorWhileParsingClusterAfterInit) { 1096 ASSERT_TRUE(InitDemuxer(true, true)); 1097 AppendCluster(kDefaultFirstCluster()); 1098 1099 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE)); 1100 AppendGarbage(); 1101 } 1102 1103 // Test the case where a Seek() is requested while the parser 1104 // is in the middle of cluster. This is to verify that the parser 1105 // does not reset itself on a seek. 1106 TEST_F(ChunkDemuxerTest, SeekWhileParsingCluster) { 1107 ASSERT_TRUE(InitDemuxer(true, true)); 1108 1109 InSequence s; 1110 1111 scoped_ptr<Cluster> cluster_a(GenerateCluster(0, 6)); 1112 1113 // Split the cluster into two appends at an arbitrary point near the end. 1114 int first_append_size = cluster_a->size() - 11; 1115 int second_append_size = cluster_a->size() - first_append_size; 1116 1117 // Append the first part of the cluster. 1118 AppendData(cluster_a->data(), first_append_size); 1119 1120 ExpectRead(DemuxerStream::AUDIO, 0); 1121 ExpectRead(DemuxerStream::VIDEO, 0); 1122 ExpectRead(DemuxerStream::AUDIO, kAudioBlockDuration); 1123 // Note: We skip trying to read a video buffer here because computing 1124 // the duration for this block relies on successfully parsing the last block 1125 // in the cluster the cluster. 1126 ExpectRead(DemuxerStream::AUDIO, 2 * kAudioBlockDuration); 1127 1128 Seek(base::TimeDelta::FromSeconds(5)); 1129 1130 // Append the rest of the cluster. 1131 AppendData(cluster_a->data() + first_append_size, second_append_size); 1132 1133 // Append the new cluster and verify that only the blocks 1134 // in the new cluster are returned. 1135 AppendCluster(GenerateCluster(5000, 6)); 1136 GenerateExpectedReads(5000, 6); 1137 } 1138 1139 // Test the case where AppendData() is called before Init(). 1140 TEST_F(ChunkDemuxerTest, AppendDataBeforeInit) { 1141 scoped_ptr<uint8[]> info_tracks; 1142 int info_tracks_size = 0; 1143 CreateInitSegment(true, true, false, 1144 false, false, &info_tracks, &info_tracks_size); 1145 1146 demuxer_->AppendData(kSourceId, info_tracks.get(), info_tracks_size); 1147 } 1148 1149 // Make sure Read() callbacks are dispatched with the proper data. 1150 TEST_F(ChunkDemuxerTest, Read) { 1151 ASSERT_TRUE(InitDemuxer(true, true)); 1152 1153 AppendCluster(kDefaultFirstCluster()); 1154 1155 bool audio_read_done = false; 1156 bool video_read_done = false; 1157 ReadAudio(base::Bind(&OnReadDone, 1158 base::TimeDelta::FromMilliseconds(0), 1159 &audio_read_done)); 1160 ReadVideo(base::Bind(&OnReadDone, 1161 base::TimeDelta::FromMilliseconds(0), 1162 &video_read_done)); 1163 1164 EXPECT_TRUE(audio_read_done); 1165 EXPECT_TRUE(video_read_done); 1166 } 1167 1168 TEST_F(ChunkDemuxerTest, OutOfOrderClusters) { 1169 ASSERT_TRUE(InitDemuxer(true, true)); 1170 AppendCluster(kDefaultFirstCluster()); 1171 AppendCluster(GenerateCluster(10, 4)); 1172 1173 // Make sure that AppendCluster() does not fail with a cluster that has 1174 // overlaps with the previously appended cluster. 1175 AppendCluster(GenerateCluster(5, 4)); 1176 1177 // Verify that AppendData() can still accept more data. 1178 scoped_ptr<Cluster> cluster_c(GenerateCluster(45, 2)); 1179 demuxer_->AppendData(kSourceId, cluster_c->data(), cluster_c->size()); 1180 } 1181 1182 TEST_F(ChunkDemuxerTest, NonMonotonicButAboveClusterTimecode) { 1183 ASSERT_TRUE(InitDemuxer(true, true)); 1184 AppendCluster(kDefaultFirstCluster()); 1185 1186 ClusterBuilder cb; 1187 1188 // Test the case where block timecodes are not monotonically 1189 // increasing but stay above the cluster timecode. 1190 cb.SetClusterTimecode(5); 1191 AddSimpleBlock(&cb, kAudioTrackNum, 5); 1192 AddSimpleBlock(&cb, kVideoTrackNum, 10); 1193 AddSimpleBlock(&cb, kAudioTrackNum, 7); 1194 AddSimpleBlock(&cb, kVideoTrackNum, 15); 1195 1196 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE)); 1197 AppendCluster(cb.Finish()); 1198 1199 // Verify that AppendData() ignores data after the error. 1200 scoped_ptr<Cluster> cluster_b(GenerateCluster(20, 2)); 1201 demuxer_->AppendData(kSourceId, cluster_b->data(), cluster_b->size()); 1202 } 1203 1204 TEST_F(ChunkDemuxerTest, BackwardsAndBeforeClusterTimecode) { 1205 ASSERT_TRUE(InitDemuxer(true, true)); 1206 AppendCluster(kDefaultFirstCluster()); 1207 1208 ClusterBuilder cb; 1209 1210 // Test timecodes going backwards and including values less than the cluster 1211 // timecode. 1212 cb.SetClusterTimecode(5); 1213 AddSimpleBlock(&cb, kAudioTrackNum, 5); 1214 AddSimpleBlock(&cb, kVideoTrackNum, 5); 1215 AddSimpleBlock(&cb, kAudioTrackNum, 3); 1216 AddSimpleBlock(&cb, kVideoTrackNum, 3); 1217 1218 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE)); 1219 AppendCluster(cb.Finish()); 1220 1221 // Verify that AppendData() ignores data after the error. 1222 scoped_ptr<Cluster> cluster_b(GenerateCluster(6, 2)); 1223 demuxer_->AppendData(kSourceId, cluster_b->data(), cluster_b->size()); 1224 } 1225 1226 1227 TEST_F(ChunkDemuxerTest, PerStreamMonotonicallyIncreasingTimestamps) { 1228 ASSERT_TRUE(InitDemuxer(true, true)); 1229 AppendCluster(kDefaultFirstCluster()); 1230 1231 ClusterBuilder cb; 1232 1233 // Test monotonic increasing timestamps on a per stream 1234 // basis. 1235 cb.SetClusterTimecode(5); 1236 AddSimpleBlock(&cb, kAudioTrackNum, 5); 1237 AddSimpleBlock(&cb, kVideoTrackNum, 5); 1238 AddSimpleBlock(&cb, kAudioTrackNum, 4); 1239 AddSimpleBlock(&cb, kVideoTrackNum, 7); 1240 1241 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE)); 1242 AppendCluster(cb.Finish()); 1243 } 1244 1245 // Test the case where a cluster is passed to AppendCluster() before 1246 // INFO & TRACKS data. 1247 TEST_F(ChunkDemuxerTest, ClusterBeforeInitSegment) { 1248 EXPECT_CALL(*this, DemuxerOpened()); 1249 demuxer_->Initialize( 1250 &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN), true); 1251 1252 ASSERT_EQ(AddId(), ChunkDemuxer::kOk); 1253 1254 AppendCluster(GenerateCluster(0, 1)); 1255 } 1256 1257 // Test cases where we get an MarkEndOfStream() call during initialization. 1258 TEST_F(ChunkDemuxerTest, EOSDuringInit) { 1259 EXPECT_CALL(*this, DemuxerOpened()); 1260 demuxer_->Initialize( 1261 &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN), true); 1262 MarkEndOfStream(PIPELINE_OK); 1263 } 1264 1265 TEST_F(ChunkDemuxerTest, EndOfStreamWithNoAppend) { 1266 EXPECT_CALL(*this, DemuxerOpened()); 1267 demuxer_->Initialize( 1268 &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN), true); 1269 1270 ASSERT_EQ(AddId(), ChunkDemuxer::kOk); 1271 1272 CheckExpectedRanges("{ }"); 1273 MarkEndOfStream(PIPELINE_OK); 1274 ShutdownDemuxer(); 1275 CheckExpectedRanges("{ }"); 1276 demuxer_->RemoveId(kSourceId); 1277 demuxer_.reset(); 1278 } 1279 1280 TEST_F(ChunkDemuxerTest, EndOfStreamWithNoMediaAppend) { 1281 ASSERT_TRUE(InitDemuxer(true, true)); 1282 1283 CheckExpectedRanges("{ }"); 1284 MarkEndOfStream(PIPELINE_OK); 1285 CheckExpectedRanges("{ }"); 1286 } 1287 1288 TEST_F(ChunkDemuxerTest, DecodeErrorEndOfStream) { 1289 ASSERT_TRUE(InitDemuxer(true, true)); 1290 1291 AppendCluster(kDefaultFirstCluster()); 1292 CheckExpectedRanges(kDefaultFirstClusterRange); 1293 1294 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE)); 1295 MarkEndOfStream(PIPELINE_ERROR_DECODE); 1296 CheckExpectedRanges(kDefaultFirstClusterRange); 1297 } 1298 1299 TEST_F(ChunkDemuxerTest, NetworkErrorEndOfStream) { 1300 ASSERT_TRUE(InitDemuxer(true, true)); 1301 1302 AppendCluster(kDefaultFirstCluster()); 1303 CheckExpectedRanges(kDefaultFirstClusterRange); 1304 1305 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_NETWORK)); 1306 MarkEndOfStream(PIPELINE_ERROR_NETWORK); 1307 } 1308 1309 // Helper class to reduce duplicate code when testing end of stream 1310 // Read() behavior. 1311 class EndOfStreamHelper { 1312 public: 1313 explicit EndOfStreamHelper(Demuxer* demuxer) 1314 : demuxer_(demuxer), 1315 audio_read_done_(false), 1316 video_read_done_(false) { 1317 } 1318 1319 // Request a read on the audio and video streams. 1320 void RequestReads() { 1321 EXPECT_FALSE(audio_read_done_); 1322 EXPECT_FALSE(video_read_done_); 1323 1324 DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO); 1325 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO); 1326 1327 audio->Read(base::Bind(&OnEndOfStreamReadDone, &audio_read_done_)); 1328 video->Read(base::Bind(&OnEndOfStreamReadDone, &video_read_done_)); 1329 base::MessageLoop::current()->RunUntilIdle(); 1330 } 1331 1332 // Check to see if |audio_read_done_| and |video_read_done_| variables 1333 // match |expected|. 1334 void CheckIfReadDonesWereCalled(bool expected) { 1335 base::MessageLoop::current()->RunUntilIdle(); 1336 EXPECT_EQ(expected, audio_read_done_); 1337 EXPECT_EQ(expected, video_read_done_); 1338 } 1339 1340 private: 1341 static void OnEndOfStreamReadDone( 1342 bool* called, 1343 DemuxerStream::Status status, 1344 const scoped_refptr<DecoderBuffer>& buffer) { 1345 EXPECT_EQ(status, DemuxerStream::kOk); 1346 EXPECT_TRUE(buffer->end_of_stream()); 1347 *called = true; 1348 } 1349 1350 Demuxer* demuxer_; 1351 bool audio_read_done_; 1352 bool video_read_done_; 1353 1354 DISALLOW_COPY_AND_ASSIGN(EndOfStreamHelper); 1355 }; 1356 1357 // Make sure that all pending reads that we don't have media data for get an 1358 // "end of stream" buffer when MarkEndOfStream() is called. 1359 TEST_F(ChunkDemuxerTest, EndOfStreamWithPendingReads) { 1360 ASSERT_TRUE(InitDemuxer(true, true)); 1361 1362 AppendCluster(GenerateCluster(0, 2)); 1363 1364 bool audio_read_done_1 = false; 1365 bool video_read_done_1 = false; 1366 EndOfStreamHelper end_of_stream_helper_1(demuxer_.get()); 1367 EndOfStreamHelper end_of_stream_helper_2(demuxer_.get()); 1368 1369 ReadAudio(base::Bind(&OnReadDone, 1370 base::TimeDelta::FromMilliseconds(0), 1371 &audio_read_done_1)); 1372 ReadVideo(base::Bind(&OnReadDone, 1373 base::TimeDelta::FromMilliseconds(0), 1374 &video_read_done_1)); 1375 message_loop_.RunUntilIdle(); 1376 1377 EXPECT_TRUE(audio_read_done_1); 1378 EXPECT_TRUE(video_read_done_1); 1379 1380 end_of_stream_helper_1.RequestReads(); 1381 1382 EXPECT_CALL(host_, SetDuration( 1383 base::TimeDelta::FromMilliseconds(kVideoBlockDuration))); 1384 MarkEndOfStream(PIPELINE_OK); 1385 1386 end_of_stream_helper_1.CheckIfReadDonesWereCalled(true); 1387 1388 end_of_stream_helper_2.RequestReads(); 1389 end_of_stream_helper_2.CheckIfReadDonesWereCalled(true); 1390 } 1391 1392 // Make sure that all Read() calls after we get an MarkEndOfStream() 1393 // call return an "end of stream" buffer. 1394 TEST_F(ChunkDemuxerTest, ReadsAfterEndOfStream) { 1395 ASSERT_TRUE(InitDemuxer(true, true)); 1396 1397 AppendCluster(GenerateCluster(0, 2)); 1398 1399 bool audio_read_done_1 = false; 1400 bool video_read_done_1 = false; 1401 EndOfStreamHelper end_of_stream_helper_1(demuxer_.get()); 1402 EndOfStreamHelper end_of_stream_helper_2(demuxer_.get()); 1403 EndOfStreamHelper end_of_stream_helper_3(demuxer_.get()); 1404 1405 ReadAudio(base::Bind(&OnReadDone, 1406 base::TimeDelta::FromMilliseconds(0), 1407 &audio_read_done_1)); 1408 ReadVideo(base::Bind(&OnReadDone, 1409 base::TimeDelta::FromMilliseconds(0), 1410 &video_read_done_1)); 1411 1412 end_of_stream_helper_1.RequestReads(); 1413 1414 EXPECT_TRUE(audio_read_done_1); 1415 EXPECT_TRUE(video_read_done_1); 1416 end_of_stream_helper_1.CheckIfReadDonesWereCalled(false); 1417 1418 EXPECT_CALL(host_, SetDuration( 1419 base::TimeDelta::FromMilliseconds(kVideoBlockDuration))); 1420 MarkEndOfStream(PIPELINE_OK); 1421 1422 end_of_stream_helper_1.CheckIfReadDonesWereCalled(true); 1423 1424 // Request a few more reads and make sure we immediately get 1425 // end of stream buffers. 1426 end_of_stream_helper_2.RequestReads(); 1427 end_of_stream_helper_2.CheckIfReadDonesWereCalled(true); 1428 1429 end_of_stream_helper_3.RequestReads(); 1430 end_of_stream_helper_3.CheckIfReadDonesWereCalled(true); 1431 } 1432 1433 TEST_F(ChunkDemuxerTest, EndOfStreamDuringCanceledSeek) { 1434 ASSERT_TRUE(InitDemuxer(true, true)); 1435 1436 AppendCluster(0, 10); 1437 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(138))); 1438 MarkEndOfStream(PIPELINE_OK); 1439 1440 // Start the first seek. 1441 Seek(base::TimeDelta::FromMilliseconds(20)); 1442 1443 // Simulate another seek being requested before the first 1444 // seek has finished prerolling. 1445 base::TimeDelta seek_time2 = base::TimeDelta::FromMilliseconds(30); 1446 demuxer_->CancelPendingSeek(seek_time2); 1447 1448 // Finish second seek. 1449 Seek(seek_time2); 1450 1451 DemuxerStream::Status status; 1452 base::TimeDelta last_timestamp; 1453 1454 // Make sure audio can reach end of stream. 1455 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp); 1456 ASSERT_EQ(status, DemuxerStream::kOk); 1457 1458 // Make sure video can reach end of stream. 1459 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp); 1460 ASSERT_EQ(status, DemuxerStream::kOk); 1461 } 1462 1463 // Make sure AppendData() will accept elements that span multiple calls. 1464 TEST_F(ChunkDemuxerTest, AppendingInPieces) { 1465 EXPECT_CALL(*this, DemuxerOpened()); 1466 demuxer_->Initialize( 1467 &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true); 1468 1469 ASSERT_EQ(AddId(), ChunkDemuxer::kOk); 1470 1471 scoped_ptr<uint8[]> info_tracks; 1472 int info_tracks_size = 0; 1473 CreateInitSegment(true, true, false, 1474 false, false, &info_tracks, &info_tracks_size); 1475 1476 scoped_ptr<Cluster> cluster_a(kDefaultFirstCluster()); 1477 scoped_ptr<Cluster> cluster_b(kDefaultSecondCluster()); 1478 1479 size_t buffer_size = info_tracks_size + cluster_a->size() + cluster_b->size(); 1480 scoped_ptr<uint8[]> buffer(new uint8[buffer_size]); 1481 uint8* dst = buffer.get(); 1482 memcpy(dst, info_tracks.get(), info_tracks_size); 1483 dst += info_tracks_size; 1484 1485 memcpy(dst, cluster_a->data(), cluster_a->size()); 1486 dst += cluster_a->size(); 1487 1488 memcpy(dst, cluster_b->data(), cluster_b->size()); 1489 dst += cluster_b->size(); 1490 1491 AppendDataInPieces(buffer.get(), buffer_size); 1492 1493 GenerateExpectedReads(0, 9); 1494 } 1495 1496 TEST_F(ChunkDemuxerTest, WebMFile_AudioAndVideo) { 1497 struct BufferTimestamps buffer_timestamps[] = { 1498 {0, 0}, 1499 {33, 3}, 1500 {67, 6}, 1501 {100, 9}, 1502 {133, 12}, 1503 {kSkip, kSkip}, 1504 }; 1505 1506 ASSERT_TRUE(ParseWebMFile("bear-320x240.webm", buffer_timestamps, 1507 base::TimeDelta::FromMilliseconds(2744))); 1508 } 1509 1510 TEST_F(ChunkDemuxerTest, WebMFile_LiveAudioAndVideo) { 1511 struct BufferTimestamps buffer_timestamps[] = { 1512 {0, 0}, 1513 {33, 3}, 1514 {67, 6}, 1515 {100, 9}, 1516 {133, 12}, 1517 {kSkip, kSkip}, 1518 }; 1519 1520 ASSERT_TRUE(ParseWebMFile("bear-320x240-live.webm", buffer_timestamps, 1521 kInfiniteDuration())); 1522 } 1523 1524 TEST_F(ChunkDemuxerTest, WebMFile_AudioOnly) { 1525 struct BufferTimestamps buffer_timestamps[] = { 1526 {kSkip, 0}, 1527 {kSkip, 3}, 1528 {kSkip, 6}, 1529 {kSkip, 9}, 1530 {kSkip, 12}, 1531 {kSkip, kSkip}, 1532 }; 1533 1534 ASSERT_TRUE(ParseWebMFile("bear-320x240-audio-only.webm", buffer_timestamps, 1535 base::TimeDelta::FromMilliseconds(2744), 1536 true, false)); 1537 } 1538 1539 TEST_F(ChunkDemuxerTest, WebMFile_VideoOnly) { 1540 struct BufferTimestamps buffer_timestamps[] = { 1541 {0, kSkip}, 1542 {33, kSkip}, 1543 {67, kSkip}, 1544 {100, kSkip}, 1545 {133, kSkip}, 1546 {kSkip, kSkip}, 1547 }; 1548 1549 ASSERT_TRUE(ParseWebMFile("bear-320x240-video-only.webm", buffer_timestamps, 1550 base::TimeDelta::FromMilliseconds(2703), 1551 false, true)); 1552 } 1553 1554 TEST_F(ChunkDemuxerTest, WebMFile_AltRefFrames) { 1555 struct BufferTimestamps buffer_timestamps[] = { 1556 {0, 0}, 1557 {33, 3}, 1558 {33, 6}, 1559 {67, 9}, 1560 {100, 12}, 1561 {kSkip, kSkip}, 1562 }; 1563 1564 ASSERT_TRUE(ParseWebMFile("bear-320x240-altref.webm", buffer_timestamps, 1565 base::TimeDelta::FromMilliseconds(2767))); 1566 } 1567 1568 // Verify that we output buffers before the entire cluster has been parsed. 1569 TEST_F(ChunkDemuxerTest, IncrementalClusterParsing) { 1570 ASSERT_TRUE(InitDemuxer(true, true)); 1571 AppendEmptyCluster(0); 1572 1573 scoped_ptr<Cluster> cluster(GenerateCluster(0, 6)); 1574 1575 bool audio_read_done = false; 1576 bool video_read_done = false; 1577 ReadAudio(base::Bind(&OnReadDone, 1578 base::TimeDelta::FromMilliseconds(0), 1579 &audio_read_done)); 1580 ReadVideo(base::Bind(&OnReadDone, 1581 base::TimeDelta::FromMilliseconds(0), 1582 &video_read_done)); 1583 1584 // Make sure the reads haven't completed yet. 1585 EXPECT_FALSE(audio_read_done); 1586 EXPECT_FALSE(video_read_done); 1587 1588 // Append data one byte at a time until the audio read completes. 1589 int i = 0; 1590 for (; i < cluster->size() && !audio_read_done; ++i) { 1591 AppendData(cluster->data() + i, 1); 1592 message_loop_.RunUntilIdle(); 1593 } 1594 1595 EXPECT_TRUE(audio_read_done); 1596 EXPECT_FALSE(video_read_done); 1597 EXPECT_GT(i, 0); 1598 EXPECT_LT(i, cluster->size()); 1599 1600 // Append data one byte at a time until the video read completes. 1601 for (; i < cluster->size() && !video_read_done; ++i) { 1602 AppendData(cluster->data() + i, 1); 1603 message_loop_.RunUntilIdle(); 1604 } 1605 1606 EXPECT_TRUE(video_read_done); 1607 EXPECT_LT(i, cluster->size()); 1608 1609 audio_read_done = false; 1610 video_read_done = false; 1611 ReadAudio(base::Bind(&OnReadDone, 1612 base::TimeDelta::FromMilliseconds(23), 1613 &audio_read_done)); 1614 ReadVideo(base::Bind(&OnReadDone, 1615 base::TimeDelta::FromMilliseconds(33), 1616 &video_read_done)); 1617 1618 // Make sure the reads haven't completed yet. 1619 EXPECT_FALSE(audio_read_done); 1620 EXPECT_FALSE(video_read_done); 1621 1622 // Append the remaining data. 1623 ASSERT_LT(i, cluster->size()); 1624 AppendData(cluster->data() + i, cluster->size() - i); 1625 1626 message_loop_.RunUntilIdle(); 1627 1628 EXPECT_TRUE(audio_read_done); 1629 EXPECT_TRUE(video_read_done); 1630 } 1631 1632 TEST_F(ChunkDemuxerTest, ParseErrorDuringInit) { 1633 EXPECT_CALL(*this, DemuxerOpened()); 1634 demuxer_->Initialize( 1635 &host_, CreateInitDoneCB( 1636 kNoTimestamp(), DEMUXER_ERROR_COULD_NOT_OPEN), true); 1637 1638 ASSERT_EQ(AddId(), ChunkDemuxer::kOk); 1639 1640 uint8 tmp = 0; 1641 demuxer_->AppendData(kSourceId, &tmp, 1); 1642 } 1643 1644 TEST_F(ChunkDemuxerTest, AVHeadersWithAudioOnlyType) { 1645 EXPECT_CALL(*this, DemuxerOpened()); 1646 demuxer_->Initialize( 1647 &host_, CreateInitDoneCB(kNoTimestamp(), 1648 DEMUXER_ERROR_COULD_NOT_OPEN), true); 1649 1650 std::vector<std::string> codecs(1); 1651 codecs[0] = "vorbis"; 1652 ASSERT_EQ(demuxer_->AddId(kSourceId, "audio/webm", codecs), 1653 ChunkDemuxer::kOk); 1654 1655 AppendInitSegment(true, true); 1656 } 1657 1658 TEST_F(ChunkDemuxerTest, AVHeadersWithVideoOnlyType) { 1659 EXPECT_CALL(*this, DemuxerOpened()); 1660 demuxer_->Initialize( 1661 &host_, CreateInitDoneCB(kNoTimestamp(), 1662 DEMUXER_ERROR_COULD_NOT_OPEN), true); 1663 1664 std::vector<std::string> codecs(1); 1665 codecs[0] = "vp8"; 1666 ASSERT_EQ(demuxer_->AddId(kSourceId, "video/webm", codecs), 1667 ChunkDemuxer::kOk); 1668 1669 AppendInitSegment(true, true); 1670 } 1671 1672 TEST_F(ChunkDemuxerTest, MultipleHeaders) { 1673 ASSERT_TRUE(InitDemuxer(true, true)); 1674 1675 AppendCluster(kDefaultFirstCluster()); 1676 1677 // Append another identical initialization segment. 1678 AppendInitSegment(true, true); 1679 1680 AppendCluster(kDefaultSecondCluster()); 1681 1682 GenerateExpectedReads(0, 9); 1683 } 1684 1685 TEST_F(ChunkDemuxerTest, AddSeparateSourcesForAudioAndVideo) { 1686 std::string audio_id = "audio1"; 1687 std::string video_id = "video1"; 1688 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id)); 1689 1690 // Append audio and video data into separate source ids. 1691 AppendCluster(audio_id, 1692 GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration)); 1693 GenerateAudioStreamExpectedReads(0, 4); 1694 AppendCluster(video_id, 1695 GenerateSingleStreamCluster(0, 132, kVideoTrackNum, kVideoBlockDuration)); 1696 GenerateVideoStreamExpectedReads(0, 4); 1697 } 1698 1699 TEST_F(ChunkDemuxerTest, AddSeparateSourcesForAudioAndVideoText) { 1700 // TODO(matthewjheaney): Here and elsewhere, we need more tests 1701 // for inband text tracks (http://crbug/321455). 1702 1703 std::string audio_id = "audio1"; 1704 std::string video_id = "video1"; 1705 1706 EXPECT_CALL(host_, AddTextStream(_,_)) 1707 .Times(Exactly(2)); 1708 ASSERT_TRUE(InitDemuxerAudioAndVideoSourcesText(audio_id, video_id, true)); 1709 1710 // Append audio and video data into separate source ids. 1711 AppendCluster(audio_id, 1712 GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration)); 1713 GenerateAudioStreamExpectedReads(0, 4); 1714 AppendCluster(video_id, 1715 GenerateSingleStreamCluster(0, 132, kVideoTrackNum, kVideoBlockDuration)); 1716 GenerateVideoStreamExpectedReads(0, 4); 1717 } 1718 1719 TEST_F(ChunkDemuxerTest, AddIdFailures) { 1720 EXPECT_CALL(*this, DemuxerOpened()); 1721 demuxer_->Initialize( 1722 &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true); 1723 1724 std::string audio_id = "audio1"; 1725 std::string video_id = "video1"; 1726 1727 ASSERT_EQ(AddId(audio_id, true, false), ChunkDemuxer::kOk); 1728 1729 // Adding an id with audio/video should fail because we already added audio. 1730 ASSERT_EQ(AddId(), ChunkDemuxer::kReachedIdLimit); 1731 1732 AppendInitSegmentWithSourceId(audio_id, true, false, false); 1733 1734 // Adding an id after append should fail. 1735 ASSERT_EQ(AddId(video_id, false, true), ChunkDemuxer::kReachedIdLimit); 1736 } 1737 1738 // Test that Read() calls after a RemoveId() return "end of stream" buffers. 1739 TEST_F(ChunkDemuxerTest, RemoveId) { 1740 std::string audio_id = "audio1"; 1741 std::string video_id = "video1"; 1742 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id)); 1743 1744 // Append audio and video data into separate source ids. 1745 AppendCluster(audio_id, 1746 GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration)); 1747 AppendCluster(video_id, 1748 GenerateSingleStreamCluster(0, 132, kVideoTrackNum, kVideoBlockDuration)); 1749 1750 // Read() from audio should return normal buffers. 1751 GenerateAudioStreamExpectedReads(0, 4); 1752 1753 // Remove the audio id. 1754 demuxer_->RemoveId(audio_id); 1755 1756 // Read() from audio should return "end of stream" buffers. 1757 bool audio_read_done = false; 1758 ReadAudio(base::Bind(&OnReadDone_EOSExpected, &audio_read_done)); 1759 message_loop_.RunUntilIdle(); 1760 EXPECT_TRUE(audio_read_done); 1761 1762 // Read() from video should still return normal buffers. 1763 GenerateVideoStreamExpectedReads(0, 4); 1764 } 1765 1766 // Test that removing an ID immediately after adding it does not interfere with 1767 // quota for new IDs in the future. 1768 TEST_F(ChunkDemuxerTest, RemoveAndAddId) { 1769 std::string audio_id_1 = "audio1"; 1770 ASSERT_TRUE(AddId(audio_id_1, true, false) == ChunkDemuxer::kOk); 1771 demuxer_->RemoveId(audio_id_1); 1772 1773 std::string audio_id_2 = "audio2"; 1774 ASSERT_TRUE(AddId(audio_id_2, true, false) == ChunkDemuxer::kOk); 1775 } 1776 1777 TEST_F(ChunkDemuxerTest, SeekCanceled) { 1778 ASSERT_TRUE(InitDemuxer(true, true)); 1779 1780 // Append cluster at the beginning of the stream. 1781 AppendCluster(GenerateCluster(0, 4)); 1782 1783 // Seek to an unbuffered region. 1784 Seek(base::TimeDelta::FromSeconds(50)); 1785 1786 // Attempt to read in unbuffered area; should not fulfill the read. 1787 bool audio_read_done = false; 1788 bool video_read_done = false; 1789 ReadAudio(base::Bind(&OnReadDone_AbortExpected, &audio_read_done)); 1790 ReadVideo(base::Bind(&OnReadDone_AbortExpected, &video_read_done)); 1791 EXPECT_FALSE(audio_read_done); 1792 EXPECT_FALSE(video_read_done); 1793 1794 // Now cancel the pending seek, which should flush the reads with empty 1795 // buffers. 1796 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(0); 1797 demuxer_->CancelPendingSeek(seek_time); 1798 message_loop_.RunUntilIdle(); 1799 EXPECT_TRUE(audio_read_done); 1800 EXPECT_TRUE(video_read_done); 1801 1802 // A seek back to the buffered region should succeed. 1803 Seek(seek_time); 1804 GenerateExpectedReads(0, 4); 1805 } 1806 1807 TEST_F(ChunkDemuxerTest, SeekCanceledWhileWaitingForSeek) { 1808 ASSERT_TRUE(InitDemuxer(true, true)); 1809 1810 // Append cluster at the beginning of the stream. 1811 AppendCluster(GenerateCluster(0, 4)); 1812 1813 // Start waiting for a seek. 1814 base::TimeDelta seek_time1 = base::TimeDelta::FromSeconds(50); 1815 base::TimeDelta seek_time2 = base::TimeDelta::FromSeconds(0); 1816 demuxer_->StartWaitingForSeek(seek_time1); 1817 1818 // Now cancel the upcoming seek to an unbuffered region. 1819 demuxer_->CancelPendingSeek(seek_time2); 1820 demuxer_->Seek(seek_time1, NewExpectedStatusCB(PIPELINE_OK)); 1821 1822 // Read requests should be fulfilled with empty buffers. 1823 bool audio_read_done = false; 1824 bool video_read_done = false; 1825 ReadAudio(base::Bind(&OnReadDone_AbortExpected, &audio_read_done)); 1826 ReadVideo(base::Bind(&OnReadDone_AbortExpected, &video_read_done)); 1827 EXPECT_TRUE(audio_read_done); 1828 EXPECT_TRUE(video_read_done); 1829 1830 // A seek back to the buffered region should succeed. 1831 Seek(seek_time2); 1832 GenerateExpectedReads(0, 4); 1833 } 1834 1835 // Test that Seek() successfully seeks to all source IDs. 1836 TEST_F(ChunkDemuxerTest, SeekAudioAndVideoSources) { 1837 std::string audio_id = "audio1"; 1838 std::string video_id = "video1"; 1839 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id)); 1840 1841 AppendCluster( 1842 audio_id, 1843 GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration)); 1844 AppendCluster( 1845 video_id, 1846 GenerateSingleStreamCluster(0, 132, kVideoTrackNum, kVideoBlockDuration)); 1847 1848 // Read() should return buffers at 0. 1849 bool audio_read_done = false; 1850 bool video_read_done = false; 1851 ReadAudio(base::Bind(&OnReadDone, 1852 base::TimeDelta::FromMilliseconds(0), 1853 &audio_read_done)); 1854 ReadVideo(base::Bind(&OnReadDone, 1855 base::TimeDelta::FromMilliseconds(0), 1856 &video_read_done)); 1857 EXPECT_TRUE(audio_read_done); 1858 EXPECT_TRUE(video_read_done); 1859 1860 // Seek to 3 (an unbuffered region). 1861 Seek(base::TimeDelta::FromSeconds(3)); 1862 1863 audio_read_done = false; 1864 video_read_done = false; 1865 ReadAudio(base::Bind(&OnReadDone, 1866 base::TimeDelta::FromSeconds(3), 1867 &audio_read_done)); 1868 ReadVideo(base::Bind(&OnReadDone, 1869 base::TimeDelta::FromSeconds(3), 1870 &video_read_done)); 1871 // Read()s should not return until after data is appended at the Seek point. 1872 EXPECT_FALSE(audio_read_done); 1873 EXPECT_FALSE(video_read_done); 1874 1875 AppendCluster(audio_id, 1876 GenerateSingleStreamCluster( 1877 3000, 3092, kAudioTrackNum, kAudioBlockDuration)); 1878 AppendCluster(video_id, 1879 GenerateSingleStreamCluster( 1880 3000, 3132, kVideoTrackNum, kVideoBlockDuration)); 1881 1882 message_loop_.RunUntilIdle(); 1883 1884 // Read() should return buffers at 3. 1885 EXPECT_TRUE(audio_read_done); 1886 EXPECT_TRUE(video_read_done); 1887 } 1888 1889 // Test that Seek() completes successfully when EndOfStream 1890 // is called before data is available for that seek point. 1891 // This scenario might be useful if seeking past the end of stream 1892 // of either audio or video (or both). 1893 TEST_F(ChunkDemuxerTest, EndOfStreamAfterPastEosSeek) { 1894 ASSERT_TRUE(InitDemuxer(true, true)); 1895 1896 AppendCluster(GenerateSingleStreamCluster(0, 120, kAudioTrackNum, 10)); 1897 AppendCluster(GenerateSingleStreamCluster(0, 100, kVideoTrackNum, 5)); 1898 1899 // Seeking past the end of video. 1900 // Note: audio data is available for that seek point. 1901 bool seek_cb_was_called = false; 1902 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(110); 1903 demuxer_->StartWaitingForSeek(seek_time); 1904 demuxer_->Seek(seek_time, 1905 base::Bind(OnSeekDone_OKExpected, &seek_cb_was_called)); 1906 message_loop_.RunUntilIdle(); 1907 1908 EXPECT_FALSE(seek_cb_was_called); 1909 1910 EXPECT_CALL(host_, SetDuration( 1911 base::TimeDelta::FromMilliseconds(120))); 1912 MarkEndOfStream(PIPELINE_OK); 1913 message_loop_.RunUntilIdle(); 1914 1915 EXPECT_TRUE(seek_cb_was_called); 1916 1917 ShutdownDemuxer(); 1918 } 1919 1920 // Test that EndOfStream is ignored if coming during a pending seek 1921 // whose seek time is before some existing ranges. 1922 TEST_F(ChunkDemuxerTest, EndOfStreamDuringPendingSeek) { 1923 ASSERT_TRUE(InitDemuxer(true, true)); 1924 1925 AppendCluster(GenerateSingleStreamCluster(0, 120, kAudioTrackNum, 10)); 1926 AppendCluster(GenerateSingleStreamCluster(0, 100, kVideoTrackNum, 5)); 1927 AppendCluster(GenerateSingleStreamCluster(200, 300, kAudioTrackNum, 10)); 1928 AppendCluster(GenerateSingleStreamCluster(200, 300, kVideoTrackNum, 5)); 1929 1930 bool seek_cb_was_called = false; 1931 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(160); 1932 demuxer_->StartWaitingForSeek(seek_time); 1933 demuxer_->Seek(seek_time, 1934 base::Bind(OnSeekDone_OKExpected, &seek_cb_was_called)); 1935 message_loop_.RunUntilIdle(); 1936 1937 EXPECT_FALSE(seek_cb_was_called); 1938 1939 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(300))); 1940 MarkEndOfStream(PIPELINE_OK); 1941 message_loop_.RunUntilIdle(); 1942 1943 EXPECT_FALSE(seek_cb_was_called); 1944 1945 demuxer_->UnmarkEndOfStream(); 1946 1947 AppendCluster(GenerateSingleStreamCluster(140, 180, kAudioTrackNum, 10)); 1948 AppendCluster(GenerateSingleStreamCluster(140, 180, kVideoTrackNum, 5)); 1949 1950 message_loop_.RunUntilIdle(); 1951 1952 EXPECT_TRUE(seek_cb_was_called); 1953 1954 ShutdownDemuxer(); 1955 } 1956 1957 // Test ranges in an audio-only stream. 1958 TEST_F(ChunkDemuxerTest, GetBufferedRanges_AudioIdOnly) { 1959 EXPECT_CALL(*this, DemuxerOpened()); 1960 demuxer_->Initialize( 1961 &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true); 1962 1963 ASSERT_EQ(AddId(kSourceId, true, false), ChunkDemuxer::kOk); 1964 AppendInitSegment(true, false); 1965 1966 // Test a simple cluster. 1967 AppendCluster( 1968 GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration)); 1969 1970 CheckExpectedRanges("{ [0,92) }"); 1971 1972 // Append a disjoint cluster to check for two separate ranges. 1973 AppendCluster(GenerateSingleStreamCluster( 1974 150, 219, kAudioTrackNum, kAudioBlockDuration)); 1975 1976 CheckExpectedRanges("{ [0,92) [150,219) }"); 1977 } 1978 1979 // Test ranges in a video-only stream. 1980 TEST_F(ChunkDemuxerTest, GetBufferedRanges_VideoIdOnly) { 1981 EXPECT_CALL(*this, DemuxerOpened()); 1982 demuxer_->Initialize( 1983 &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true); 1984 1985 ASSERT_EQ(AddId(kSourceId, false, true), ChunkDemuxer::kOk); 1986 AppendInitSegment(false, true); 1987 1988 // Test a simple cluster. 1989 AppendCluster( 1990 GenerateSingleStreamCluster(0, 132, kVideoTrackNum, kVideoBlockDuration)); 1991 1992 CheckExpectedRanges("{ [0,132) }"); 1993 1994 // Append a disjoint cluster to check for two separate ranges. 1995 AppendCluster(GenerateSingleStreamCluster( 1996 200, 299, kVideoTrackNum, kVideoBlockDuration)); 1997 1998 CheckExpectedRanges("{ [0,132) [200,299) }"); 1999 } 2000 2001 TEST_F(ChunkDemuxerTest, GetBufferedRanges_AudioVideo) { 2002 ASSERT_TRUE(InitDemuxer(true, true)); 2003 2004 // Audio: 0 -> 23 2005 // Video: 0 -> 33 2006 // Buffered Range: 0 -> 23 2007 // Audio block duration is smaller than video block duration, 2008 // so the buffered ranges should correspond to the audio blocks. 2009 AppendCluster(GenerateSingleStreamCluster( 2010 0, kAudioBlockDuration, kAudioTrackNum, kAudioBlockDuration)); 2011 AppendCluster(GenerateSingleStreamCluster( 2012 0, kVideoBlockDuration, kVideoTrackNum, kVideoBlockDuration)); 2013 2014 CheckExpectedRanges("{ [0,23) }"); 2015 2016 // Audio: 300 -> 400 2017 // Video: 320 -> 420 2018 // Buffered Range: 320 -> 400 (end overlap) 2019 AppendCluster(GenerateSingleStreamCluster(300, 400, kAudioTrackNum, 50)); 2020 AppendCluster(GenerateSingleStreamCluster(320, 420, kVideoTrackNum, 50)); 2021 2022 CheckExpectedRanges("{ [0,23) [320,400) }"); 2023 2024 // Audio: 520 -> 590 2025 // Video: 500 -> 570 2026 // Buffered Range: 520 -> 570 (front overlap) 2027 AppendCluster(GenerateSingleStreamCluster(520, 590, kAudioTrackNum, 70)); 2028 AppendCluster(GenerateSingleStreamCluster(500, 570, kVideoTrackNum, 70)); 2029 2030 CheckExpectedRanges("{ [0,23) [320,400) [520,570) }"); 2031 2032 // Audio: 720 -> 750 2033 // Video: 700 -> 770 2034 // Buffered Range: 720 -> 750 (complete overlap, audio) 2035 AppendCluster(GenerateSingleStreamCluster(720, 750, kAudioTrackNum, 30)); 2036 AppendCluster(GenerateSingleStreamCluster(700, 770, kVideoTrackNum, 70)); 2037 2038 CheckExpectedRanges("{ [0,23) [320,400) [520,570) [720,750) }"); 2039 2040 // Audio: 900 -> 970 2041 // Video: 920 -> 950 2042 // Buffered Range: 920 -> 950 (complete overlap, video) 2043 AppendCluster(GenerateSingleStreamCluster(900, 970, kAudioTrackNum, 70)); 2044 AppendCluster(GenerateSingleStreamCluster(920, 950, kVideoTrackNum, 30)); 2045 2046 CheckExpectedRanges("{ [0,23) [320,400) [520,570) [720,750) [920,950) }"); 2047 2048 // Appending within buffered range should not affect buffered ranges. 2049 AppendCluster(GenerateSingleStreamCluster(930, 950, kAudioTrackNum, 20)); 2050 CheckExpectedRanges("{ [0,23) [320,400) [520,570) [720,750) [920,950) }"); 2051 2052 // Appending to single stream outside buffered ranges should not affect 2053 // buffered ranges. 2054 AppendCluster(GenerateSingleStreamCluster(1230, 1240, kVideoTrackNum, 10)); 2055 CheckExpectedRanges("{ [0,23) [320,400) [520,570) [720,750) [920,950) }"); 2056 } 2057 2058 // Once MarkEndOfStream() is called, GetBufferedRanges should not cut off any 2059 // over-hanging tails at the end of the ranges as this is likely due to block 2060 // duration differences. 2061 TEST_F(ChunkDemuxerTest, GetBufferedRanges_EndOfStream) { 2062 ASSERT_TRUE(InitDemuxer(true, true)); 2063 2064 AppendCluster(GenerateSingleStreamCluster(0, 90, kAudioTrackNum, 90)); 2065 AppendCluster(GenerateSingleStreamCluster(0, 100, kVideoTrackNum, 100)); 2066 2067 CheckExpectedRanges("{ [0,90) }"); 2068 2069 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(100))); 2070 MarkEndOfStream(PIPELINE_OK); 2071 2072 CheckExpectedRanges("{ [0,100) }"); 2073 } 2074 2075 TEST_F(ChunkDemuxerTest, DifferentStreamTimecodes) { 2076 ASSERT_TRUE(InitDemuxer(true, true)); 2077 2078 // Create a cluster where the video timecode begins 25ms after the audio. 2079 AppendCluster(GenerateCluster(0, 25, 8)); 2080 2081 Seek(base::TimeDelta::FromSeconds(0)); 2082 GenerateExpectedReads(0, 25, 8); 2083 2084 // Seek to 5 seconds. 2085 Seek(base::TimeDelta::FromSeconds(5)); 2086 2087 // Generate a cluster to fulfill this seek, where audio timecode begins 25ms 2088 // after the video. 2089 AppendCluster(GenerateCluster(5025, 5000, 8)); 2090 GenerateExpectedReads(5025, 5000, 8); 2091 } 2092 2093 TEST_F(ChunkDemuxerTest, DifferentStreamTimecodesSeparateSources) { 2094 std::string audio_id = "audio1"; 2095 std::string video_id = "video1"; 2096 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id)); 2097 2098 // Generate two streams where the video stream starts 5ms after the audio 2099 // stream and append them. 2100 AppendCluster(audio_id, GenerateSingleStreamCluster( 2101 25, 4 * kAudioBlockDuration + 25, kAudioTrackNum, kAudioBlockDuration)); 2102 AppendCluster(video_id, GenerateSingleStreamCluster( 2103 30, 4 * kVideoBlockDuration + 30, kVideoTrackNum, kVideoBlockDuration)); 2104 2105 // Both streams should be able to fulfill a seek to 25. 2106 Seek(base::TimeDelta::FromMilliseconds(25)); 2107 GenerateAudioStreamExpectedReads(25, 4); 2108 GenerateVideoStreamExpectedReads(30, 4); 2109 } 2110 2111 TEST_F(ChunkDemuxerTest, DifferentStreamTimecodesOutOfRange) { 2112 std::string audio_id = "audio1"; 2113 std::string video_id = "video1"; 2114 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id)); 2115 2116 // Generate two streams where the video stream starts 10s after the audio 2117 // stream and append them. 2118 AppendCluster(audio_id, GenerateSingleStreamCluster(0, 2119 4 * kAudioBlockDuration + 0, kAudioTrackNum, kAudioBlockDuration)); 2120 AppendCluster(video_id, GenerateSingleStreamCluster(10000, 2121 4 * kVideoBlockDuration + 10000, kVideoTrackNum, kVideoBlockDuration)); 2122 2123 // Should not be able to fulfill a seek to 0. 2124 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(0); 2125 demuxer_->StartWaitingForSeek(seek_time); 2126 demuxer_->Seek(seek_time, 2127 NewExpectedStatusCB(PIPELINE_ERROR_ABORT)); 2128 ExpectRead(DemuxerStream::AUDIO, 0); 2129 ExpectEndOfStream(DemuxerStream::VIDEO); 2130 } 2131 2132 TEST_F(ChunkDemuxerTest, ClusterWithNoBuffers) { 2133 ASSERT_TRUE(InitDemuxer(true, true)); 2134 2135 // Generate and append an empty cluster beginning at 0. 2136 AppendEmptyCluster(0); 2137 2138 // Sanity check that data can be appended after this cluster correctly. 2139 AppendCluster(GenerateCluster(0, 2)); 2140 ExpectRead(DemuxerStream::AUDIO, 0); 2141 ExpectRead(DemuxerStream::VIDEO, 0); 2142 } 2143 2144 TEST_F(ChunkDemuxerTest, CodecPrefixMatching) { 2145 ChunkDemuxer::Status expected = ChunkDemuxer::kNotSupported; 2146 2147 #if defined(USE_PROPRIETARY_CODECS) 2148 expected = ChunkDemuxer::kOk; 2149 #endif 2150 2151 std::vector<std::string> codecs; 2152 codecs.push_back("avc1.4D4041"); 2153 2154 EXPECT_EQ(demuxer_->AddId("source_id", "video/mp4", codecs), expected); 2155 } 2156 2157 // Test codec ID's that are not compliant with RFC6381, but have been 2158 // seen in the wild. 2159 TEST_F(ChunkDemuxerTest, CodecIDsThatAreNotRFC6381Compliant) { 2160 ChunkDemuxer::Status expected = ChunkDemuxer::kNotSupported; 2161 2162 #if defined(USE_PROPRIETARY_CODECS) 2163 expected = ChunkDemuxer::kOk; 2164 #endif 2165 const char* codec_ids[] = { 2166 // GPAC places leading zeros on the audio object type. 2167 "mp4a.40.02", 2168 "mp4a.40.05" 2169 }; 2170 2171 for (size_t i = 0; i < arraysize(codec_ids); ++i) { 2172 std::vector<std::string> codecs; 2173 codecs.push_back(codec_ids[i]); 2174 2175 ChunkDemuxer::Status result = 2176 demuxer_->AddId("source_id", "audio/mp4", codecs); 2177 2178 EXPECT_EQ(result, expected) 2179 << "Fail to add codec_id '" << codec_ids[i] << "'"; 2180 2181 if (result == ChunkDemuxer::kOk) 2182 demuxer_->RemoveId("source_id"); 2183 } 2184 } 2185 2186 TEST_F(ChunkDemuxerTest, EndOfStreamStillSetAfterSeek) { 2187 ASSERT_TRUE(InitDemuxer(true, true)); 2188 2189 EXPECT_CALL(host_, SetDuration(_)) 2190 .Times(AnyNumber()); 2191 2192 base::TimeDelta kLastAudioTimestamp = base::TimeDelta::FromMilliseconds(92); 2193 base::TimeDelta kLastVideoTimestamp = base::TimeDelta::FromMilliseconds(99); 2194 2195 AppendCluster(kDefaultFirstCluster()); 2196 AppendCluster(kDefaultSecondCluster()); 2197 MarkEndOfStream(PIPELINE_OK); 2198 2199 DemuxerStream::Status status; 2200 base::TimeDelta last_timestamp; 2201 2202 // Verify that we can read audio & video to the end w/o problems. 2203 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp); 2204 EXPECT_EQ(DemuxerStream::kOk, status); 2205 EXPECT_EQ(kLastAudioTimestamp, last_timestamp); 2206 2207 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp); 2208 EXPECT_EQ(DemuxerStream::kOk, status); 2209 EXPECT_EQ(kLastVideoTimestamp, last_timestamp); 2210 2211 // Seek back to 0 and verify that we can read to the end again.. 2212 Seek(base::TimeDelta::FromMilliseconds(0)); 2213 2214 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp); 2215 EXPECT_EQ(DemuxerStream::kOk, status); 2216 EXPECT_EQ(kLastAudioTimestamp, last_timestamp); 2217 2218 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp); 2219 EXPECT_EQ(DemuxerStream::kOk, status); 2220 EXPECT_EQ(kLastVideoTimestamp, last_timestamp); 2221 } 2222 2223 TEST_F(ChunkDemuxerTest, GetBufferedRangesBeforeInitSegment) { 2224 EXPECT_CALL(*this, DemuxerOpened()); 2225 demuxer_->Initialize(&host_, CreateInitDoneCB(PIPELINE_OK), true); 2226 ASSERT_EQ(AddId("audio", true, false), ChunkDemuxer::kOk); 2227 ASSERT_EQ(AddId("video", false, true), ChunkDemuxer::kOk); 2228 2229 CheckExpectedRanges("audio", "{ }"); 2230 CheckExpectedRanges("video", "{ }"); 2231 } 2232 2233 // Test that Seek() completes successfully when the first cluster 2234 // arrives. 2235 TEST_F(ChunkDemuxerTest, EndOfStreamDuringSeek) { 2236 InSequence s; 2237 2238 ASSERT_TRUE(InitDemuxer(true, true)); 2239 2240 AppendCluster(kDefaultFirstCluster()); 2241 2242 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(0); 2243 demuxer_->StartWaitingForSeek(seek_time); 2244 2245 AppendCluster(kDefaultSecondCluster()); 2246 EXPECT_CALL(host_, SetDuration( 2247 base::TimeDelta::FromMilliseconds(kDefaultSecondClusterEndTimestamp))); 2248 MarkEndOfStream(PIPELINE_OK); 2249 2250 demuxer_->Seek(seek_time, NewExpectedStatusCB(PIPELINE_OK)); 2251 2252 GenerateExpectedReads(0, 4); 2253 GenerateExpectedReads(46, 66, 5); 2254 2255 EndOfStreamHelper end_of_stream_helper(demuxer_.get()); 2256 end_of_stream_helper.RequestReads(); 2257 end_of_stream_helper.CheckIfReadDonesWereCalled(true); 2258 } 2259 2260 TEST_F(ChunkDemuxerTest, ConfigChange_Video) { 2261 InSequence s; 2262 2263 ASSERT_TRUE(InitDemuxerWithConfigChangeData()); 2264 2265 DemuxerStream::Status status; 2266 base::TimeDelta last_timestamp; 2267 2268 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO); 2269 2270 // Fetch initial video config and verify it matches what we expect. 2271 const VideoDecoderConfig& video_config_1 = video->video_decoder_config(); 2272 ASSERT_TRUE(video_config_1.IsValidConfig()); 2273 EXPECT_EQ(video_config_1.natural_size().width(), 320); 2274 EXPECT_EQ(video_config_1.natural_size().height(), 240); 2275 2276 ExpectRead(DemuxerStream::VIDEO, 0); 2277 2278 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp); 2279 2280 ASSERT_EQ(status, DemuxerStream::kConfigChanged); 2281 EXPECT_EQ(last_timestamp.InMilliseconds(), 501); 2282 2283 // Fetch the new decoder config. 2284 const VideoDecoderConfig& video_config_2 = video->video_decoder_config(); 2285 ASSERT_TRUE(video_config_2.IsValidConfig()); 2286 EXPECT_EQ(video_config_2.natural_size().width(), 640); 2287 EXPECT_EQ(video_config_2.natural_size().height(), 360); 2288 2289 ExpectRead(DemuxerStream::VIDEO, 527); 2290 2291 // Read until the next config change. 2292 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp); 2293 ASSERT_EQ(status, DemuxerStream::kConfigChanged); 2294 EXPECT_EQ(last_timestamp.InMilliseconds(), 793); 2295 2296 // Get the new config and verify that it matches the first one. 2297 ASSERT_TRUE(video_config_1.Matches(video->video_decoder_config())); 2298 2299 ExpectRead(DemuxerStream::VIDEO, 801); 2300 2301 // Read until the end of the stream just to make sure there aren't any other 2302 // config changes. 2303 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp); 2304 ASSERT_EQ(status, DemuxerStream::kOk); 2305 } 2306 2307 TEST_F(ChunkDemuxerTest, ConfigChange_Audio) { 2308 InSequence s; 2309 2310 ASSERT_TRUE(InitDemuxerWithConfigChangeData()); 2311 2312 DemuxerStream::Status status; 2313 base::TimeDelta last_timestamp; 2314 2315 DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO); 2316 2317 // Fetch initial audio config and verify it matches what we expect. 2318 const AudioDecoderConfig& audio_config_1 = audio->audio_decoder_config(); 2319 ASSERT_TRUE(audio_config_1.IsValidConfig()); 2320 EXPECT_EQ(audio_config_1.samples_per_second(), 44100); 2321 EXPECT_EQ(audio_config_1.extra_data_size(), 3863u); 2322 2323 ExpectRead(DemuxerStream::AUDIO, 0); 2324 2325 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp); 2326 2327 ASSERT_EQ(status, DemuxerStream::kConfigChanged); 2328 EXPECT_EQ(last_timestamp.InMilliseconds(), 524); 2329 2330 // Fetch the new decoder config. 2331 const AudioDecoderConfig& audio_config_2 = audio->audio_decoder_config(); 2332 ASSERT_TRUE(audio_config_2.IsValidConfig()); 2333 EXPECT_EQ(audio_config_2.samples_per_second(), 44100); 2334 EXPECT_EQ(audio_config_2.extra_data_size(), 3935u); 2335 2336 ExpectRead(DemuxerStream::AUDIO, 527); 2337 2338 // Read until the next config change. 2339 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp); 2340 ASSERT_EQ(status, DemuxerStream::kConfigChanged); 2341 EXPECT_EQ(last_timestamp.InMilliseconds(), 759); 2342 2343 // Get the new config and verify that it matches the first one. 2344 ASSERT_TRUE(audio_config_1.Matches(audio->audio_decoder_config())); 2345 2346 ExpectRead(DemuxerStream::AUDIO, 779); 2347 2348 // Read until the end of the stream just to make sure there aren't any other 2349 // config changes. 2350 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp); 2351 ASSERT_EQ(status, DemuxerStream::kOk); 2352 } 2353 2354 TEST_F(ChunkDemuxerTest, ConfigChange_Seek) { 2355 InSequence s; 2356 2357 ASSERT_TRUE(InitDemuxerWithConfigChangeData()); 2358 2359 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO); 2360 2361 // Fetch initial video config and verify it matches what we expect. 2362 const VideoDecoderConfig& video_config_1 = video->video_decoder_config(); 2363 ASSERT_TRUE(video_config_1.IsValidConfig()); 2364 EXPECT_EQ(video_config_1.natural_size().width(), 320); 2365 EXPECT_EQ(video_config_1.natural_size().height(), 240); 2366 2367 ExpectRead(DemuxerStream::VIDEO, 0); 2368 2369 // Seek to a location with a different config. 2370 Seek(base::TimeDelta::FromMilliseconds(527)); 2371 2372 // Verify that the config change is signalled. 2373 ExpectConfigChanged(DemuxerStream::VIDEO); 2374 2375 // Fetch the new decoder config and verify it is what we expect. 2376 const VideoDecoderConfig& video_config_2 = video->video_decoder_config(); 2377 ASSERT_TRUE(video_config_2.IsValidConfig()); 2378 EXPECT_EQ(video_config_2.natural_size().width(), 640); 2379 EXPECT_EQ(video_config_2.natural_size().height(), 360); 2380 2381 // Verify that Read() will return a buffer now. 2382 ExpectRead(DemuxerStream::VIDEO, 527); 2383 2384 // Seek back to the beginning and verify we get another config change. 2385 Seek(base::TimeDelta::FromMilliseconds(0)); 2386 ExpectConfigChanged(DemuxerStream::VIDEO); 2387 ASSERT_TRUE(video_config_1.Matches(video->video_decoder_config())); 2388 ExpectRead(DemuxerStream::VIDEO, 0); 2389 2390 // Seek to a location that requires a config change and then 2391 // seek to a new location that has the same configuration as 2392 // the start of the file without a Read() in the middle. 2393 Seek(base::TimeDelta::FromMilliseconds(527)); 2394 Seek(base::TimeDelta::FromMilliseconds(801)); 2395 2396 // Verify that no config change is signalled. 2397 ExpectRead(DemuxerStream::VIDEO, 801); 2398 ASSERT_TRUE(video_config_1.Matches(video->video_decoder_config())); 2399 } 2400 2401 TEST_F(ChunkDemuxerTest, TimestampPositiveOffset) { 2402 ASSERT_TRUE(InitDemuxer(true, true)); 2403 2404 ASSERT_TRUE(demuxer_->SetTimestampOffset( 2405 kSourceId, base::TimeDelta::FromSeconds(30))); 2406 AppendCluster(GenerateCluster(0, 2)); 2407 2408 Seek(base::TimeDelta::FromMilliseconds(30000)); 2409 2410 GenerateExpectedReads(30000, 2); 2411 } 2412 2413 TEST_F(ChunkDemuxerTest, TimestampNegativeOffset) { 2414 ASSERT_TRUE(InitDemuxer(true, true)); 2415 2416 ASSERT_TRUE(demuxer_->SetTimestampOffset( 2417 kSourceId, base::TimeDelta::FromSeconds(-1))); 2418 AppendCluster(GenerateCluster(1000, 2)); 2419 2420 GenerateExpectedReads(0, 2); 2421 } 2422 2423 TEST_F(ChunkDemuxerTest, TimestampOffsetSeparateStreams) { 2424 std::string audio_id = "audio1"; 2425 std::string video_id = "video1"; 2426 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id)); 2427 2428 ASSERT_TRUE(demuxer_->SetTimestampOffset( 2429 audio_id, base::TimeDelta::FromMilliseconds(-2500))); 2430 ASSERT_TRUE(demuxer_->SetTimestampOffset( 2431 video_id, base::TimeDelta::FromMilliseconds(-2500))); 2432 AppendCluster(audio_id, GenerateSingleStreamCluster(2500, 2433 2500 + kAudioBlockDuration * 4, kAudioTrackNum, kAudioBlockDuration)); 2434 AppendCluster(video_id, GenerateSingleStreamCluster(2500, 2435 2500 + kVideoBlockDuration * 4, kVideoTrackNum, kVideoBlockDuration)); 2436 GenerateAudioStreamExpectedReads(0, 4); 2437 GenerateVideoStreamExpectedReads(0, 4); 2438 2439 Seek(base::TimeDelta::FromMilliseconds(27300)); 2440 2441 ASSERT_TRUE(demuxer_->SetTimestampOffset( 2442 audio_id, base::TimeDelta::FromMilliseconds(27300))); 2443 ASSERT_TRUE(demuxer_->SetTimestampOffset( 2444 video_id, base::TimeDelta::FromMilliseconds(27300))); 2445 AppendCluster(audio_id, GenerateSingleStreamCluster( 2446 0, kAudioBlockDuration * 4, kAudioTrackNum, kAudioBlockDuration)); 2447 AppendCluster(video_id, GenerateSingleStreamCluster( 2448 0, kVideoBlockDuration * 4, kVideoTrackNum, kVideoBlockDuration)); 2449 GenerateVideoStreamExpectedReads(27300, 4); 2450 GenerateAudioStreamExpectedReads(27300, 4); 2451 } 2452 2453 TEST_F(ChunkDemuxerTest, TimestampOffsetMidParse) { 2454 ASSERT_TRUE(InitDemuxer(true, true)); 2455 2456 scoped_ptr<Cluster> cluster = GenerateCluster(0, 2); 2457 // Append only part of the cluster data. 2458 AppendData(cluster->data(), cluster->size() - 13); 2459 2460 // Setting a timestamp should fail because we're in the middle of a cluster. 2461 ASSERT_FALSE(demuxer_->SetTimestampOffset( 2462 kSourceId, base::TimeDelta::FromSeconds(25))); 2463 2464 demuxer_->Abort(kSourceId); 2465 // After Abort(), setting a timestamp should succeed since we're no longer 2466 // in the middle of a cluster 2467 ASSERT_TRUE(demuxer_->SetTimestampOffset( 2468 kSourceId, base::TimeDelta::FromSeconds(25))); 2469 } 2470 2471 TEST_F(ChunkDemuxerTest, DurationChange) { 2472 ASSERT_TRUE(InitDemuxer(true, true)); 2473 static const int kStreamDuration = kDefaultDuration().InMilliseconds(); 2474 2475 // Add data leading up to the currently set duration. 2476 AppendCluster(GenerateCluster(kStreamDuration - kAudioBlockDuration, 2477 kStreamDuration - kVideoBlockDuration, 2478 2)); 2479 2480 CheckExpectedRanges(kSourceId, "{ [201191,201224) }"); 2481 2482 // Add data at the currently set duration. The duration should not increase. 2483 AppendCluster(GenerateCluster(kDefaultDuration().InMilliseconds(), 2)); 2484 2485 // Range should not be affected. 2486 CheckExpectedRanges(kSourceId, "{ [201191,201224) }"); 2487 2488 // Now add data past the duration and expect a new duration to be signalled. 2489 static const int kNewStreamDuration = 2490 kStreamDuration + kAudioBlockDuration * 2; 2491 EXPECT_CALL(host_, SetDuration( 2492 base::TimeDelta::FromMilliseconds(kNewStreamDuration))); 2493 AppendCluster(GenerateCluster(kStreamDuration + kAudioBlockDuration, 2494 kStreamDuration + kVideoBlockDuration, 2495 2)); 2496 2497 // See that the range has increased appropriately. 2498 CheckExpectedRanges(kSourceId, "{ [201191,201270) }"); 2499 } 2500 2501 TEST_F(ChunkDemuxerTest, DurationChangeTimestampOffset) { 2502 ASSERT_TRUE(InitDemuxer(true, true)); 2503 2504 ASSERT_TRUE(demuxer_->SetTimestampOffset(kSourceId, kDefaultDuration())); 2505 2506 EXPECT_CALL(host_, SetDuration( 2507 kDefaultDuration() + base::TimeDelta::FromMilliseconds( 2508 kAudioBlockDuration * 2))); 2509 AppendCluster(GenerateCluster(0, 4)); 2510 } 2511 2512 TEST_F(ChunkDemuxerTest, EndOfStreamTruncateDuration) { 2513 ASSERT_TRUE(InitDemuxer(true, true)); 2514 2515 AppendCluster(kDefaultFirstCluster()); 2516 2517 EXPECT_CALL(host_, SetDuration( 2518 base::TimeDelta::FromMilliseconds(kDefaultFirstClusterEndTimestamp))); 2519 MarkEndOfStream(PIPELINE_OK); 2520 } 2521 2522 2523 TEST_F(ChunkDemuxerTest, ZeroLengthAppend) { 2524 ASSERT_TRUE(InitDemuxer(true, true)); 2525 AppendData(NULL, 0); 2526 } 2527 2528 TEST_F(ChunkDemuxerTest, AppendAfterEndOfStream) { 2529 ASSERT_TRUE(InitDemuxer(true, true)); 2530 2531 EXPECT_CALL(host_, SetDuration(_)) 2532 .Times(AnyNumber()); 2533 2534 AppendCluster(kDefaultFirstCluster()); 2535 MarkEndOfStream(PIPELINE_OK); 2536 2537 demuxer_->UnmarkEndOfStream(); 2538 2539 AppendCluster(kDefaultSecondCluster()); 2540 MarkEndOfStream(PIPELINE_OK); 2541 } 2542 2543 // Test receiving a Shutdown() call before we get an Initialize() 2544 // call. This can happen if video element gets destroyed before 2545 // the pipeline has a chance to initialize the demuxer. 2546 TEST_F(ChunkDemuxerTest, ShutdownBeforeInitialize) { 2547 demuxer_->Shutdown(); 2548 demuxer_->Initialize( 2549 &host_, CreateInitDoneCB(DEMUXER_ERROR_COULD_NOT_OPEN), true); 2550 message_loop_.RunUntilIdle(); 2551 } 2552 2553 TEST_F(ChunkDemuxerTest, ReadAfterAudioDisabled) { 2554 ASSERT_TRUE(InitDemuxer(true, true)); 2555 AppendCluster(kDefaultFirstCluster()); 2556 2557 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::AUDIO); 2558 ASSERT_TRUE(stream); 2559 2560 // The stream should no longer be present. 2561 demuxer_->OnAudioRendererDisabled(); 2562 ASSERT_FALSE(demuxer_->GetStream(DemuxerStream::AUDIO)); 2563 2564 // Normally this would return an audio buffer at timestamp zero, but 2565 // all reads should return EOS buffers when disabled. 2566 bool audio_read_done = false; 2567 stream->Read(base::Bind(&OnReadDone_EOSExpected, &audio_read_done)); 2568 message_loop_.RunUntilIdle(); 2569 2570 EXPECT_TRUE(audio_read_done); 2571 } 2572 2573 // Verifies that signalling end of stream while stalled at a gap 2574 // boundary does not trigger end of stream buffers to be returned. 2575 TEST_F(ChunkDemuxerTest, EndOfStreamWhileWaitingForGapToBeFilled) { 2576 ASSERT_TRUE(InitDemuxer(true, true)); 2577 2578 AppendCluster(0, 10); 2579 AppendCluster(300, 10); 2580 CheckExpectedRanges(kSourceId, "{ [0,132) [300,432) }"); 2581 2582 2583 GenerateExpectedReads(0, 10); 2584 2585 bool audio_read_done = false; 2586 bool video_read_done = false; 2587 ReadAudio(base::Bind(&OnReadDone, 2588 base::TimeDelta::FromMilliseconds(138), 2589 &audio_read_done)); 2590 ReadVideo(base::Bind(&OnReadDone, 2591 base::TimeDelta::FromMilliseconds(138), 2592 &video_read_done)); 2593 2594 // Verify that the reads didn't complete 2595 EXPECT_FALSE(audio_read_done); 2596 EXPECT_FALSE(video_read_done); 2597 2598 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(438))); 2599 MarkEndOfStream(PIPELINE_OK); 2600 2601 // Verify that the reads still haven't completed. 2602 EXPECT_FALSE(audio_read_done); 2603 EXPECT_FALSE(video_read_done); 2604 2605 demuxer_->UnmarkEndOfStream(); 2606 2607 AppendCluster(138, 24); 2608 2609 message_loop_.RunUntilIdle(); 2610 2611 CheckExpectedRanges(kSourceId, "{ [0,438) }"); 2612 2613 // Verify that the reads have completed. 2614 EXPECT_TRUE(audio_read_done); 2615 EXPECT_TRUE(video_read_done); 2616 2617 // Read the rest of the buffers. 2618 GenerateExpectedReads(161, 171, 22); 2619 2620 // Verify that reads block because the append cleared the end of stream state. 2621 audio_read_done = false; 2622 video_read_done = false; 2623 ReadAudio(base::Bind(&OnReadDone_EOSExpected, 2624 &audio_read_done)); 2625 ReadVideo(base::Bind(&OnReadDone_EOSExpected, 2626 &video_read_done)); 2627 2628 // Verify that the reads don't complete. 2629 EXPECT_FALSE(audio_read_done); 2630 EXPECT_FALSE(video_read_done); 2631 2632 MarkEndOfStream(PIPELINE_OK); 2633 2634 EXPECT_TRUE(audio_read_done); 2635 EXPECT_TRUE(video_read_done); 2636 } 2637 2638 TEST_F(ChunkDemuxerTest, CanceledSeekDuringInitialPreroll) { 2639 ASSERT_TRUE(InitDemuxer(true, true)); 2640 2641 // Cancel preroll. 2642 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(200); 2643 demuxer_->CancelPendingSeek(seek_time); 2644 2645 // Initiate the seek to the new location. 2646 Seek(seek_time); 2647 2648 // Append data to satisfy the seek. 2649 AppendCluster(seek_time.InMilliseconds(), 10); 2650 } 2651 2652 TEST_F(ChunkDemuxerTest, GCDuringSeek) { 2653 ASSERT_TRUE(InitDemuxer(true, false)); 2654 2655 demuxer_->SetMemoryLimitsForTesting(5 * kBlockSize); 2656 2657 base::TimeDelta seek_time1 = base::TimeDelta::FromMilliseconds(1000); 2658 base::TimeDelta seek_time2 = base::TimeDelta::FromMilliseconds(500); 2659 2660 // Initiate a seek to |seek_time1|. 2661 Seek(seek_time1); 2662 2663 // Append data to satisfy the first seek request. 2664 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 2665 seek_time1.InMilliseconds(), 5); 2666 CheckExpectedRanges(kSourceId, "{ [1000,1115) }"); 2667 2668 // Signal that the second seek is starting. 2669 demuxer_->StartWaitingForSeek(seek_time2); 2670 2671 // Append data to satisfy the second seek. This append triggers 2672 // the garbage collection logic since we set the memory limit to 2673 // 5 blocks. 2674 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 2675 seek_time2.InMilliseconds(), 5); 2676 2677 // Verify that the buffers that cover |seek_time2| do not get 2678 // garbage collected. 2679 CheckExpectedRanges(kSourceId, "{ [500,615) }"); 2680 2681 // Complete the seek. 2682 demuxer_->Seek(seek_time2, NewExpectedStatusCB(PIPELINE_OK)); 2683 2684 2685 // Append more data and make sure that the blocks for |seek_time2| 2686 // don't get removed. 2687 // 2688 // NOTE: The current GC algorithm tries to preserve the GOP at the 2689 // current position as well as the last appended GOP. This is 2690 // why there are 2 ranges in the expectations. 2691 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 700, 5); 2692 CheckExpectedRanges(kSourceId, "{ [500,592) [792,815) }"); 2693 } 2694 2695 TEST_F(ChunkDemuxerTest, RemoveBeforeInitSegment) { 2696 EXPECT_CALL(*this, DemuxerOpened()); 2697 demuxer_->Initialize( 2698 &host_, CreateInitDoneCB(kNoTimestamp(), PIPELINE_OK), true); 2699 2700 EXPECT_EQ(ChunkDemuxer::kOk, AddId(kSourceId, true, true)); 2701 2702 demuxer_->Remove(kSourceId, base::TimeDelta::FromMilliseconds(0), 2703 base::TimeDelta::FromMilliseconds(1)); 2704 } 2705 2706 TEST_F(ChunkDemuxerTest, AppendWindow) { 2707 ASSERT_TRUE(InitDemuxer(false, true)); 2708 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO); 2709 2710 // Set the append window to [20,280). 2711 demuxer_->SetAppendWindowStart(kSourceId, 2712 base::TimeDelta::FromMilliseconds(20)); 2713 demuxer_->SetAppendWindowEnd(kSourceId, 2714 base::TimeDelta::FromMilliseconds(280)); 2715 2716 // Append a cluster that starts before and ends after the append window. 2717 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, 2718 "0K 30 60 90 120K 150 180 210 240K 270 300 330K"); 2719 2720 // Verify that GOPs that start outside the window are not included 2721 // in the buffer. Also verify that buffers that extend beyond the 2722 // window are not included. 2723 CheckExpectedRanges(kSourceId, "{ [120,300) }"); 2724 CheckExpectedBuffers(stream, "120 150 180 210 240 270"); 2725 2726 // Extend the append window to [20,650). 2727 demuxer_->SetAppendWindowEnd(kSourceId, 2728 base::TimeDelta::FromMilliseconds(650)); 2729 2730 // Append more data and verify that adding buffers start at the next 2731 // keyframe. 2732 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, 2733 "360 390 420K 450 480 510 540K 570 600 630K"); 2734 CheckExpectedRanges(kSourceId, "{ [120,300) [420,660) }"); 2735 } 2736 2737 TEST_F(ChunkDemuxerTest, StartWaitingForSeekAfterParseError) { 2738 ASSERT_TRUE(InitDemuxer(true, true)); 2739 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE)); 2740 AppendGarbage(); 2741 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(50); 2742 demuxer_->StartWaitingForSeek(seek_time); 2743 } 2744 2745 } // namespace media 2746