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