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