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