1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <algorithm> 6 7 #include "base/bind.h" 8 #include "base/message_loop/message_loop.h" 9 #include "base/strings/string_number_conversions.h" 10 #include "base/strings/string_split.h" 11 #include "base/strings/string_util.h" 12 #include "media/base/audio_decoder_config.h" 13 #include "media/base/decoder_buffer.h" 14 #include "media/base/decrypt_config.h" 15 #include "media/base/mock_demuxer_host.h" 16 #include "media/base/test_data_util.h" 17 #include "media/base/test_helpers.h" 18 #include "media/filters/chunk_demuxer.h" 19 #include "media/formats/webm/cluster_builder.h" 20 #include "media/formats/webm/webm_constants.h" 21 #include "media/formats/webm/webm_crypto_helpers.h" 22 #include "testing/gtest/include/gtest/gtest.h" 23 24 using ::testing::AnyNumber; 25 using ::testing::Exactly; 26 using ::testing::InSequence; 27 using ::testing::NotNull; 28 using ::testing::Return; 29 using ::testing::SaveArg; 30 using ::testing::SetArgumentPointee; 31 using ::testing::_; 32 33 namespace media { 34 35 const uint8 kTracksHeader[] = { 36 0x16, 0x54, 0xAE, 0x6B, // Tracks ID 37 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // tracks(size = 0) 38 }; 39 40 // WebM Block bytes that represent a VP8 keyframe. 41 const uint8 kVP8Keyframe[] = { 42 0x010, 0x00, 0x00, 0x9d, 0x01, 0x2a, 0x00, 0x10, 0x00, 0x10, 0x00 43 }; 44 45 // WebM Block bytes that represent a VP8 interframe. 46 const uint8 kVP8Interframe[] = { 0x11, 0x00, 0x00 }; 47 48 static const uint8 kCuesHeader[] = { 49 0x1C, 0x53, 0xBB, 0x6B, // Cues ID 50 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // cues(size = 0) 51 }; 52 53 const int kTracksHeaderSize = sizeof(kTracksHeader); 54 const int kTracksSizeOffset = 4; 55 56 // The size of TrackEntry element in test file "webm_vorbis_track_entry" starts 57 // at index 1 and spans 8 bytes. 58 const int kAudioTrackSizeOffset = 1; 59 const int kAudioTrackSizeWidth = 8; 60 const int kAudioTrackEntryHeaderSize = 61 kAudioTrackSizeOffset + kAudioTrackSizeWidth; 62 63 // The size of TrackEntry element in test file "webm_vp8_track_entry" starts at 64 // index 1 and spans 8 bytes. 65 const int kVideoTrackSizeOffset = 1; 66 const int kVideoTrackSizeWidth = 8; 67 const int kVideoTrackEntryHeaderSize = 68 kVideoTrackSizeOffset + kVideoTrackSizeWidth; 69 70 const int kVideoTrackNum = 1; 71 const int kAudioTrackNum = 2; 72 const int kTextTrackNum = 3; 73 const int kAlternateTextTrackNum = 4; 74 75 const int kAudioBlockDuration = 23; 76 const int kVideoBlockDuration = 33; 77 const int kTextBlockDuration = 100; 78 const int kBlockSize = 10; 79 80 const char kSourceId[] = "SourceId"; 81 const char kDefaultFirstClusterRange[] = "{ [0,46) }"; 82 const int kDefaultFirstClusterEndTimestamp = 66; 83 const int kDefaultSecondClusterEndTimestamp = 132; 84 85 base::TimeDelta kDefaultDuration() { 86 return base::TimeDelta::FromMilliseconds(201224); 87 } 88 89 // Write an integer into buffer in the form of vint that spans 8 bytes. 90 // The data pointed by |buffer| should be at least 8 bytes long. 91 // |number| should be in the range 0 <= number < 0x00FFFFFFFFFFFFFF. 92 static void WriteInt64(uint8* buffer, int64 number) { 93 DCHECK(number >= 0 && number < 0x00FFFFFFFFFFFFFFLL); 94 buffer[0] = 0x01; 95 int64 tmp = number; 96 for (int i = 7; i > 0; i--) { 97 buffer[i] = tmp & 0xff; 98 tmp >>= 8; 99 } 100 } 101 102 MATCHER_P(HasTimestamp, timestamp_in_ms, "") { 103 return arg.get() && !arg->end_of_stream() && 104 arg->timestamp().InMilliseconds() == timestamp_in_ms; 105 } 106 107 MATCHER(IsEndOfStream, "") { return arg.get() && arg->end_of_stream(); } 108 109 static void OnReadDone(const base::TimeDelta& expected_time, 110 bool* called, 111 DemuxerStream::Status status, 112 const scoped_refptr<DecoderBuffer>& buffer) { 113 EXPECT_EQ(status, DemuxerStream::kOk); 114 EXPECT_EQ(expected_time, buffer->timestamp()); 115 *called = true; 116 } 117 118 static void OnReadDone_AbortExpected( 119 bool* called, DemuxerStream::Status status, 120 const scoped_refptr<DecoderBuffer>& buffer) { 121 EXPECT_EQ(status, DemuxerStream::kAborted); 122 EXPECT_EQ(NULL, buffer.get()); 123 *called = true; 124 } 125 126 static void OnReadDone_EOSExpected(bool* called, 127 DemuxerStream::Status status, 128 const scoped_refptr<DecoderBuffer>& buffer) { 129 EXPECT_EQ(status, DemuxerStream::kOk); 130 EXPECT_TRUE(buffer->end_of_stream()); 131 *called = true; 132 } 133 134 static void OnSeekDone_OKExpected(bool* called, PipelineStatus status) { 135 EXPECT_EQ(status, PIPELINE_OK); 136 *called = true; 137 } 138 139 static void LogFunc(const std::string& str) { DVLOG(1) << str; } 140 141 class ChunkDemuxerTest : public ::testing::Test { 142 protected: 143 enum CodecsIndex { 144 AUDIO, 145 VIDEO, 146 MAX_CODECS_INDEX 147 }; 148 149 // Default cluster to append first for simple tests. 150 scoped_ptr<Cluster> kDefaultFirstCluster() { 151 return GenerateCluster(0, 4); 152 } 153 154 // Default cluster to append after kDefaultFirstCluster() 155 // has been appended. This cluster starts with blocks that 156 // have timestamps consistent with the end times of the blocks 157 // in kDefaultFirstCluster() so that these two clusters represent 158 // a continuous region. 159 scoped_ptr<Cluster> kDefaultSecondCluster() { 160 return GenerateCluster(46, 66, 5); 161 } 162 163 ChunkDemuxerTest() 164 : append_window_end_for_next_append_(kInfiniteDuration()) { 165 CreateNewDemuxer(); 166 } 167 168 void CreateNewDemuxer() { 169 base::Closure open_cb = 170 base::Bind(&ChunkDemuxerTest::DemuxerOpened, base::Unretained(this)); 171 Demuxer::NeedKeyCB need_key_cb = 172 base::Bind(&ChunkDemuxerTest::DemuxerNeedKey, base::Unretained(this)); 173 demuxer_.reset( 174 new ChunkDemuxer(open_cb, need_key_cb, base::Bind(&LogFunc), true)); 175 } 176 177 virtual ~ChunkDemuxerTest() { 178 ShutdownDemuxer(); 179 } 180 181 void CreateInitSegment(int stream_flags, 182 bool is_audio_encrypted, 183 bool is_video_encrypted, 184 scoped_ptr<uint8[]>* buffer, 185 int* size) { 186 CreateInitSegmentInternal( 187 stream_flags, is_audio_encrypted, is_video_encrypted, buffer, false, 188 size); 189 } 190 191 void CreateInitSegmentWithAlternateTextTrackNum(int stream_flags, 192 bool is_audio_encrypted, 193 bool is_video_encrypted, 194 scoped_ptr<uint8[]>* buffer, 195 int* size) { 196 DCHECK(stream_flags & HAS_TEXT); 197 CreateInitSegmentInternal( 198 stream_flags, is_audio_encrypted, is_video_encrypted, buffer, true, 199 size); 200 } 201 202 void CreateInitSegmentInternal(int stream_flags, 203 bool is_audio_encrypted, 204 bool is_video_encrypted, 205 scoped_ptr<uint8[]>* buffer, 206 bool use_alternate_text_track_id, 207 int* size) { 208 bool has_audio = (stream_flags & HAS_AUDIO) != 0; 209 bool has_video = (stream_flags & HAS_VIDEO) != 0; 210 bool has_text = (stream_flags & HAS_TEXT) != 0; 211 scoped_refptr<DecoderBuffer> ebml_header; 212 scoped_refptr<DecoderBuffer> info; 213 scoped_refptr<DecoderBuffer> audio_track_entry; 214 scoped_refptr<DecoderBuffer> video_track_entry; 215 scoped_refptr<DecoderBuffer> audio_content_encodings; 216 scoped_refptr<DecoderBuffer> video_content_encodings; 217 scoped_refptr<DecoderBuffer> text_track_entry; 218 219 ebml_header = ReadTestDataFile("webm_ebml_element"); 220 221 info = ReadTestDataFile("webm_info_element"); 222 223 int tracks_element_size = 0; 224 225 if (has_audio) { 226 audio_track_entry = ReadTestDataFile("webm_vorbis_track_entry"); 227 tracks_element_size += audio_track_entry->data_size(); 228 if (is_audio_encrypted) { 229 audio_content_encodings = ReadTestDataFile("webm_content_encodings"); 230 tracks_element_size += audio_content_encodings->data_size(); 231 } 232 } 233 234 if (has_video) { 235 video_track_entry = ReadTestDataFile("webm_vp8_track_entry"); 236 tracks_element_size += video_track_entry->data_size(); 237 if (is_video_encrypted) { 238 video_content_encodings = ReadTestDataFile("webm_content_encodings"); 239 tracks_element_size += video_content_encodings->data_size(); 240 } 241 } 242 243 if (has_text) { 244 // TODO(matthewjheaney): create an abstraction to do 245 // this (http://crbug/321454). 246 // We need it to also handle the creation of multiple text tracks. 247 // 248 // This is the track entry for a text track, 249 // TrackEntry [AE], size=30 250 // TrackNum [D7], size=1, val=3 (or 4 if use_alternate_text_track_id) 251 // TrackUID [73] [C5], size=1, value=3 (must remain constant for same 252 // track, even if TrackNum changes) 253 // TrackType [83], size=1, val=0x11 254 // CodecId [86], size=18, val="D_WEBVTT/SUBTITLES" 255 char str[] = "\xAE\x9E\xD7\x81\x03\x73\xC5\x81\x03" 256 "\x83\x81\x11\x86\x92" 257 "D_WEBVTT/SUBTITLES"; 258 DCHECK_EQ(str[4], kTextTrackNum); 259 if (use_alternate_text_track_id) 260 str[4] = kAlternateTextTrackNum; 261 262 const int len = strlen(str); 263 DCHECK_EQ(len, 32); 264 const uint8* const buf = reinterpret_cast<const uint8*>(str); 265 text_track_entry = DecoderBuffer::CopyFrom(buf, len); 266 tracks_element_size += text_track_entry->data_size(); 267 } 268 269 *size = ebml_header->data_size() + info->data_size() + 270 kTracksHeaderSize + tracks_element_size; 271 272 buffer->reset(new uint8[*size]); 273 274 uint8* buf = buffer->get(); 275 memcpy(buf, ebml_header->data(), ebml_header->data_size()); 276 buf += ebml_header->data_size(); 277 278 memcpy(buf, info->data(), info->data_size()); 279 buf += info->data_size(); 280 281 memcpy(buf, kTracksHeader, kTracksHeaderSize); 282 WriteInt64(buf + kTracksSizeOffset, tracks_element_size); 283 buf += kTracksHeaderSize; 284 285 // TODO(xhwang): Simplify this! Probably have test data files that contain 286 // ContentEncodings directly instead of trying to create one at run-time. 287 if (has_audio) { 288 memcpy(buf, audio_track_entry->data(), 289 audio_track_entry->data_size()); 290 if (is_audio_encrypted) { 291 memcpy(buf + audio_track_entry->data_size(), 292 audio_content_encodings->data(), 293 audio_content_encodings->data_size()); 294 WriteInt64(buf + kAudioTrackSizeOffset, 295 audio_track_entry->data_size() + 296 audio_content_encodings->data_size() - 297 kAudioTrackEntryHeaderSize); 298 buf += audio_content_encodings->data_size(); 299 } 300 buf += audio_track_entry->data_size(); 301 } 302 303 if (has_video) { 304 memcpy(buf, video_track_entry->data(), 305 video_track_entry->data_size()); 306 if (is_video_encrypted) { 307 memcpy(buf + video_track_entry->data_size(), 308 video_content_encodings->data(), 309 video_content_encodings->data_size()); 310 WriteInt64(buf + kVideoTrackSizeOffset, 311 video_track_entry->data_size() + 312 video_content_encodings->data_size() - 313 kVideoTrackEntryHeaderSize); 314 buf += video_content_encodings->data_size(); 315 } 316 buf += video_track_entry->data_size(); 317 } 318 319 if (has_text) { 320 memcpy(buf, text_track_entry->data(), 321 text_track_entry->data_size()); 322 buf += text_track_entry->data_size(); 323 } 324 } 325 326 ChunkDemuxer::Status AddId() { 327 return AddId(kSourceId, HAS_AUDIO | HAS_VIDEO); 328 } 329 330 ChunkDemuxer::Status AddId(const std::string& source_id, int stream_flags) { 331 bool has_audio = (stream_flags & HAS_AUDIO) != 0; 332 bool has_video = (stream_flags & HAS_VIDEO) != 0; 333 std::vector<std::string> codecs; 334 std::string type; 335 336 if (has_audio) { 337 codecs.push_back("vorbis"); 338 type = "audio/webm"; 339 } 340 341 if (has_video) { 342 codecs.push_back("vp8"); 343 type = "video/webm"; 344 } 345 346 if (!has_audio && !has_video) { 347 return AddId(kSourceId, HAS_AUDIO | HAS_VIDEO); 348 } 349 350 return demuxer_->AddId(source_id, type, codecs); 351 } 352 353 ChunkDemuxer::Status AddIdForMp2tSource(const std::string& source_id) { 354 std::vector<std::string> codecs; 355 std::string type = "video/mp2t"; 356 codecs.push_back("mp4a.40.2"); 357 codecs.push_back("avc1.640028"); 358 return demuxer_->AddId(source_id, type, codecs); 359 } 360 361 void AppendData(const uint8* data, size_t length) { 362 AppendData(kSourceId, data, length); 363 } 364 365 void AppendCluster(const std::string& source_id, 366 scoped_ptr<Cluster> cluster) { 367 AppendData(source_id, cluster->data(), cluster->size()); 368 } 369 370 void AppendCluster(scoped_ptr<Cluster> cluster) { 371 AppendCluster(kSourceId, cluster.Pass()); 372 } 373 374 void AppendCluster(int timecode, int block_count) { 375 AppendCluster(GenerateCluster(timecode, block_count)); 376 } 377 378 void AppendSingleStreamCluster(const std::string& source_id, int track_number, 379 int timecode, int block_count) { 380 int block_duration = 0; 381 switch (track_number) { 382 case kVideoTrackNum: 383 block_duration = kVideoBlockDuration; 384 break; 385 case kAudioTrackNum: 386 block_duration = kAudioBlockDuration; 387 break; 388 case kTextTrackNum: // Fall-through. 389 case kAlternateTextTrackNum: 390 block_duration = kTextBlockDuration; 391 break; 392 } 393 ASSERT_NE(block_duration, 0); 394 int end_timecode = timecode + block_count * block_duration; 395 AppendCluster(source_id, 396 GenerateSingleStreamCluster( 397 timecode, end_timecode, track_number, block_duration)); 398 } 399 400 // |cluster_description| - A space delimited string of buffer info that 401 // is used to construct a cluster. Each buffer info is a timestamp in 402 // milliseconds and optionally followed by a 'K' to indicate that a buffer 403 // should be marked as a keyframe. For example "0K 30 60" should constuct 404 // a cluster with 3 blocks: a keyframe with timestamp 0 and 2 non-keyframes 405 // at 30ms and 60ms. 406 void AppendSingleStreamCluster(const std::string& source_id, int track_number, 407 const std::string& cluster_description) { 408 std::vector<std::string> timestamps; 409 base::SplitString(cluster_description, ' ', ×tamps); 410 411 ClusterBuilder cb; 412 std::vector<uint8> data(10); 413 for (size_t i = 0; i < timestamps.size(); ++i) { 414 std::string timestamp_str = timestamps[i]; 415 int block_flags = 0; 416 if (EndsWith(timestamp_str, "K", true)) { 417 block_flags = kWebMFlagKeyframe; 418 // Remove the "K" off of the token. 419 timestamp_str = timestamp_str.substr(0, timestamps[i].length() - 1); 420 } 421 int timestamp_in_ms; 422 CHECK(base::StringToInt(timestamp_str, ×tamp_in_ms)); 423 424 if (i == 0) 425 cb.SetClusterTimecode(timestamp_in_ms); 426 427 if (track_number == kTextTrackNum || 428 track_number == kAlternateTextTrackNum) { 429 cb.AddBlockGroup(track_number, timestamp_in_ms, kTextBlockDuration, 430 block_flags, &data[0], data.size()); 431 } else { 432 cb.AddSimpleBlock(track_number, timestamp_in_ms, block_flags, 433 &data[0], data.size()); 434 } 435 } 436 AppendCluster(source_id, cb.Finish()); 437 } 438 439 void AppendData(const std::string& source_id, 440 const uint8* data, size_t length) { 441 EXPECT_CALL(host_, AddBufferedTimeRange(_, _)).Times(AnyNumber()); 442 443 demuxer_->AppendData(source_id, data, length, 444 append_window_start_for_next_append_, 445 append_window_end_for_next_append_, 446 ×tamp_offset_map_[source_id]); 447 } 448 449 void AppendDataInPieces(const uint8* data, size_t length) { 450 AppendDataInPieces(data, length, 7); 451 } 452 453 void AppendDataInPieces(const uint8* data, size_t length, size_t piece_size) { 454 const uint8* start = data; 455 const uint8* end = data + length; 456 while (start < end) { 457 size_t append_size = std::min(piece_size, 458 static_cast<size_t>(end - start)); 459 AppendData(start, append_size); 460 start += append_size; 461 } 462 } 463 464 void AppendInitSegment(int stream_flags) { 465 AppendInitSegmentWithSourceId(kSourceId, stream_flags); 466 } 467 468 void AppendInitSegmentWithSourceId(const std::string& source_id, 469 int stream_flags) { 470 AppendInitSegmentWithEncryptedInfo(source_id, stream_flags, false, false); 471 } 472 473 void AppendInitSegmentWithEncryptedInfo(const std::string& source_id, 474 int stream_flags, 475 bool is_audio_encrypted, 476 bool is_video_encrypted) { 477 scoped_ptr<uint8[]> info_tracks; 478 int info_tracks_size = 0; 479 CreateInitSegment(stream_flags, 480 is_audio_encrypted, is_video_encrypted, 481 &info_tracks, &info_tracks_size); 482 AppendData(source_id, info_tracks.get(), info_tracks_size); 483 } 484 485 void AppendGarbage() { 486 // Fill up an array with gibberish. 487 int garbage_cluster_size = 10; 488 scoped_ptr<uint8[]> garbage_cluster(new uint8[garbage_cluster_size]); 489 for (int i = 0; i < garbage_cluster_size; ++i) 490 garbage_cluster[i] = i; 491 AppendData(garbage_cluster.get(), garbage_cluster_size); 492 } 493 494 void InitDoneCalled(PipelineStatus expected_status, 495 PipelineStatus status) { 496 EXPECT_EQ(status, expected_status); 497 } 498 499 void AppendEmptyCluster(int timecode) { 500 AppendCluster(GenerateEmptyCluster(timecode)); 501 } 502 503 PipelineStatusCB CreateInitDoneCB(const base::TimeDelta& expected_duration, 504 PipelineStatus expected_status) { 505 if (expected_duration != kNoTimestamp()) 506 EXPECT_CALL(host_, SetDuration(expected_duration)); 507 return CreateInitDoneCB(expected_status); 508 } 509 510 PipelineStatusCB CreateInitDoneCB(PipelineStatus expected_status) { 511 return base::Bind(&ChunkDemuxerTest::InitDoneCalled, 512 base::Unretained(this), 513 expected_status); 514 } 515 516 enum StreamFlags { 517 HAS_AUDIO = 1 << 0, 518 HAS_VIDEO = 1 << 1, 519 HAS_TEXT = 1 << 2 520 }; 521 522 bool InitDemuxer(int stream_flags) { 523 return InitDemuxerWithEncryptionInfo(stream_flags, false, false); 524 } 525 526 bool InitDemuxerWithEncryptionInfo( 527 int stream_flags, bool is_audio_encrypted, bool is_video_encrypted) { 528 529 PipelineStatus expected_status = 530 (stream_flags != 0) ? PIPELINE_OK : DEMUXER_ERROR_COULD_NOT_OPEN; 531 532 base::TimeDelta expected_duration = kNoTimestamp(); 533 if (expected_status == PIPELINE_OK) 534 expected_duration = kDefaultDuration(); 535 536 EXPECT_CALL(*this, DemuxerOpened()); 537 demuxer_->Initialize( 538 &host_, CreateInitDoneCB(expected_duration, expected_status), true); 539 540 if (AddId(kSourceId, stream_flags) != ChunkDemuxer::kOk) 541 return false; 542 543 AppendInitSegmentWithEncryptedInfo( 544 kSourceId, stream_flags, 545 is_audio_encrypted, is_video_encrypted); 546 return true; 547 } 548 549 bool InitDemuxerAudioAndVideoSourcesText(const std::string& audio_id, 550 const std::string& video_id, 551 bool has_text) { 552 EXPECT_CALL(*this, DemuxerOpened()); 553 demuxer_->Initialize( 554 &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true); 555 556 if (AddId(audio_id, HAS_AUDIO) != ChunkDemuxer::kOk) 557 return false; 558 if (AddId(video_id, HAS_VIDEO) != ChunkDemuxer::kOk) 559 return false; 560 561 int audio_flags = HAS_AUDIO; 562 int video_flags = HAS_VIDEO; 563 564 if (has_text) { 565 audio_flags |= HAS_TEXT; 566 video_flags |= HAS_TEXT; 567 } 568 569 AppendInitSegmentWithSourceId(audio_id, audio_flags); 570 AppendInitSegmentWithSourceId(video_id, video_flags); 571 return true; 572 } 573 574 bool InitDemuxerAudioAndVideoSources(const std::string& audio_id, 575 const std::string& video_id) { 576 return InitDemuxerAudioAndVideoSourcesText(audio_id, video_id, false); 577 } 578 579 // Initializes the demuxer with data from 2 files with different 580 // decoder configurations. This is used to test the decoder config change 581 // logic. 582 // 583 // bear-320x240.webm VideoDecoderConfig returns 320x240 for its natural_size() 584 // bear-640x360.webm VideoDecoderConfig returns 640x360 for its natural_size() 585 // The resulting video stream returns data from each file for the following 586 // time ranges. 587 // bear-320x240.webm : [0-501) [801-2736) 588 // bear-640x360.webm : [527-793) 589 // 590 // bear-320x240.webm AudioDecoderConfig returns 3863 for its extra_data_size() 591 // bear-640x360.webm AudioDecoderConfig returns 3935 for its extra_data_size() 592 // The resulting audio stream returns data from each file for the following 593 // time ranges. 594 // bear-320x240.webm : [0-524) [779-2736) 595 // bear-640x360.webm : [527-759) 596 bool InitDemuxerWithConfigChangeData() { 597 scoped_refptr<DecoderBuffer> bear1 = ReadTestDataFile("bear-320x240.webm"); 598 scoped_refptr<DecoderBuffer> bear2 = ReadTestDataFile("bear-640x360.webm"); 599 600 EXPECT_CALL(*this, DemuxerOpened()); 601 602 demuxer_->Initialize( 603 &host_, CreateInitDoneCB(base::TimeDelta::FromMilliseconds(2744), 604 PIPELINE_OK), true); 605 606 if (AddId(kSourceId, HAS_AUDIO | HAS_VIDEO) != ChunkDemuxer::kOk) 607 return false; 608 609 // Append the whole bear1 file. 610 // TODO(wolenetz/acolwell): Remove this extra SetDuration expectation once 611 // the files are fixed to have the correct duration in their init segments, 612 // and the CreateInitDoneCB() call, above, is fixed to used that duration. 613 // See http://crbug.com/354284. 614 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2746))); 615 AppendData(bear1->data(), bear1->data_size()); 616 // Last audio frame has timestamp 2721 and duration 24 (estimated from max 617 // seen so far for audio track). 618 // Last video frame has timestamp 2703 and duration 33 (from TrackEntry 619 // DefaultDuration for video track). 620 CheckExpectedRanges(kSourceId, "{ [0,2736) }"); 621 622 // Append initialization segment for bear2. 623 // Note: Offsets here and below are derived from 624 // media/test/data/bear-640x360-manifest.js and 625 // media/test/data/bear-320x240-manifest.js which were 626 // generated from media/test/data/bear-640x360.webm and 627 // media/test/data/bear-320x240.webm respectively. 628 AppendData(bear2->data(), 4340); 629 630 // Append a media segment that goes from [0.527000, 1.014000). 631 AppendData(bear2->data() + 55290, 18785); 632 CheckExpectedRanges(kSourceId, "{ [0,1027) [1201,2736) }"); 633 634 // Append initialization segment for bear1 & fill gap with [779-1197) 635 // segment. 636 AppendData(bear1->data(), 4370); 637 AppendData(bear1->data() + 72737, 28183); 638 CheckExpectedRanges(kSourceId, "{ [0,2736) }"); 639 640 MarkEndOfStream(PIPELINE_OK); 641 return true; 642 } 643 644 void ShutdownDemuxer() { 645 if (demuxer_) { 646 demuxer_->Shutdown(); 647 message_loop_.RunUntilIdle(); 648 } 649 } 650 651 void AddSimpleBlock(ClusterBuilder* cb, int track_num, int64 timecode) { 652 uint8 data[] = { 0x00 }; 653 cb->AddSimpleBlock(track_num, timecode, 0, data, sizeof(data)); 654 } 655 656 scoped_ptr<Cluster> GenerateCluster(int timecode, int block_count) { 657 return GenerateCluster(timecode, timecode, block_count); 658 } 659 660 void AddVideoBlockGroup(ClusterBuilder* cb, int track_num, int64 timecode, 661 int duration, int flags) { 662 const uint8* data = 663 (flags & kWebMFlagKeyframe) != 0 ? kVP8Keyframe : kVP8Interframe; 664 int size = (flags & kWebMFlagKeyframe) != 0 ? sizeof(kVP8Keyframe) : 665 sizeof(kVP8Interframe); 666 cb->AddBlockGroup(track_num, timecode, duration, flags, data, size); 667 } 668 669 scoped_ptr<Cluster> GenerateCluster(int first_audio_timecode, 670 int first_video_timecode, 671 int block_count) { 672 return GenerateCluster(first_audio_timecode, first_video_timecode, 673 block_count, false); 674 } 675 scoped_ptr<Cluster> GenerateCluster(int first_audio_timecode, 676 int first_video_timecode, 677 int block_count, 678 bool unknown_size) { 679 CHECK_GT(block_count, 0); 680 681 int size = 10; 682 scoped_ptr<uint8[]> data(new uint8[size]); 683 684 ClusterBuilder cb; 685 cb.SetClusterTimecode(std::min(first_audio_timecode, first_video_timecode)); 686 687 if (block_count == 1) { 688 cb.AddBlockGroup(kAudioTrackNum, first_audio_timecode, 689 kAudioBlockDuration, kWebMFlagKeyframe, 690 data.get(), size); 691 return cb.Finish(); 692 } 693 694 int audio_timecode = first_audio_timecode; 695 int video_timecode = first_video_timecode; 696 697 // Create simple blocks for everything except the last 2 blocks. 698 // The first video frame must be a keyframe. 699 uint8 video_flag = kWebMFlagKeyframe; 700 for (int i = 0; i < block_count - 2; i++) { 701 if (audio_timecode <= video_timecode) { 702 cb.AddSimpleBlock(kAudioTrackNum, audio_timecode, kWebMFlagKeyframe, 703 data.get(), size); 704 audio_timecode += kAudioBlockDuration; 705 continue; 706 } 707 708 cb.AddSimpleBlock(kVideoTrackNum, video_timecode, video_flag, data.get(), 709 size); 710 video_timecode += kVideoBlockDuration; 711 video_flag = 0; 712 } 713 714 // Make the last 2 blocks BlockGroups so that they don't get delayed by the 715 // block duration calculation logic. 716 if (audio_timecode <= video_timecode) { 717 cb.AddBlockGroup(kAudioTrackNum, audio_timecode, kAudioBlockDuration, 718 kWebMFlagKeyframe, data.get(), size); 719 AddVideoBlockGroup(&cb, kVideoTrackNum, video_timecode, 720 kVideoBlockDuration, video_flag); 721 } else { 722 AddVideoBlockGroup(&cb, kVideoTrackNum, video_timecode, 723 kVideoBlockDuration, video_flag); 724 cb.AddBlockGroup(kAudioTrackNum, audio_timecode, kAudioBlockDuration, 725 kWebMFlagKeyframe, data.get(), size); 726 } 727 728 return unknown_size ? cb.FinishWithUnknownSize() : cb.Finish(); 729 } 730 731 scoped_ptr<Cluster> GenerateSingleStreamCluster(int timecode, 732 int end_timecode, 733 int track_number, 734 int block_duration) { 735 CHECK_GT(end_timecode, timecode); 736 737 std::vector<uint8> data(kBlockSize); 738 739 ClusterBuilder cb; 740 cb.SetClusterTimecode(timecode); 741 742 // Create simple blocks for everything except the last block. 743 while (timecode < (end_timecode - block_duration)) { 744 cb.AddSimpleBlock(track_number, timecode, kWebMFlagKeyframe, 745 &data[0], data.size()); 746 timecode += block_duration; 747 } 748 749 if (track_number == kVideoTrackNum) { 750 AddVideoBlockGroup(&cb, track_number, timecode, block_duration, 751 kWebMFlagKeyframe); 752 } else { 753 cb.AddBlockGroup(track_number, timecode, block_duration, 754 kWebMFlagKeyframe, &data[0], data.size()); 755 } 756 757 return cb.Finish(); 758 } 759 760 void Read(DemuxerStream::Type type, const DemuxerStream::ReadCB& read_cb) { 761 demuxer_->GetStream(type)->Read(read_cb); 762 message_loop_.RunUntilIdle(); 763 } 764 765 void ReadAudio(const DemuxerStream::ReadCB& read_cb) { 766 Read(DemuxerStream::AUDIO, read_cb); 767 } 768 769 void ReadVideo(const DemuxerStream::ReadCB& read_cb) { 770 Read(DemuxerStream::VIDEO, read_cb); 771 } 772 773 void GenerateExpectedReads(int timecode, int block_count) { 774 GenerateExpectedReads(timecode, timecode, block_count); 775 } 776 777 void GenerateExpectedReads(int start_audio_timecode, 778 int start_video_timecode, 779 int block_count) { 780 CHECK_GT(block_count, 0); 781 782 if (block_count == 1) { 783 ExpectRead(DemuxerStream::AUDIO, start_audio_timecode); 784 return; 785 } 786 787 int audio_timecode = start_audio_timecode; 788 int video_timecode = start_video_timecode; 789 790 for (int i = 0; i < block_count; i++) { 791 if (audio_timecode <= video_timecode) { 792 ExpectRead(DemuxerStream::AUDIO, audio_timecode); 793 audio_timecode += kAudioBlockDuration; 794 continue; 795 } 796 797 ExpectRead(DemuxerStream::VIDEO, video_timecode); 798 video_timecode += kVideoBlockDuration; 799 } 800 } 801 802 void GenerateSingleStreamExpectedReads(int timecode, 803 int block_count, 804 DemuxerStream::Type type, 805 int block_duration) { 806 CHECK_GT(block_count, 0); 807 int stream_timecode = timecode; 808 809 for (int i = 0; i < block_count; i++) { 810 ExpectRead(type, stream_timecode); 811 stream_timecode += block_duration; 812 } 813 } 814 815 void GenerateAudioStreamExpectedReads(int timecode, int block_count) { 816 GenerateSingleStreamExpectedReads( 817 timecode, block_count, DemuxerStream::AUDIO, kAudioBlockDuration); 818 } 819 820 void GenerateVideoStreamExpectedReads(int timecode, int block_count) { 821 GenerateSingleStreamExpectedReads( 822 timecode, block_count, DemuxerStream::VIDEO, kVideoBlockDuration); 823 } 824 825 scoped_ptr<Cluster> GenerateEmptyCluster(int timecode) { 826 ClusterBuilder cb; 827 cb.SetClusterTimecode(timecode); 828 return cb.Finish(); 829 } 830 831 void CheckExpectedRanges(const std::string& expected) { 832 CheckExpectedRanges(kSourceId, expected); 833 } 834 835 void CheckExpectedRanges(const std::string& id, 836 const std::string& expected) { 837 Ranges<base::TimeDelta> r = demuxer_->GetBufferedRanges(id); 838 839 std::stringstream ss; 840 ss << "{ "; 841 for (size_t i = 0; i < r.size(); ++i) { 842 ss << "[" << r.start(i).InMilliseconds() << "," 843 << r.end(i).InMilliseconds() << ") "; 844 } 845 ss << "}"; 846 EXPECT_EQ(expected, ss.str()); 847 } 848 849 MOCK_METHOD2(ReadDone, void(DemuxerStream::Status status, 850 const scoped_refptr<DecoderBuffer>&)); 851 852 void StoreStatusAndBuffer(DemuxerStream::Status* status_out, 853 scoped_refptr<DecoderBuffer>* buffer_out, 854 DemuxerStream::Status status, 855 const scoped_refptr<DecoderBuffer>& buffer) { 856 *status_out = status; 857 *buffer_out = buffer; 858 } 859 860 void ReadUntilNotOkOrEndOfStream(DemuxerStream::Type type, 861 DemuxerStream::Status* status, 862 base::TimeDelta* last_timestamp) { 863 DemuxerStream* stream = demuxer_->GetStream(type); 864 scoped_refptr<DecoderBuffer> buffer; 865 866 *last_timestamp = kNoTimestamp(); 867 do { 868 stream->Read(base::Bind(&ChunkDemuxerTest::StoreStatusAndBuffer, 869 base::Unretained(this), status, &buffer)); 870 base::MessageLoop::current()->RunUntilIdle(); 871 if (*status == DemuxerStream::kOk && !buffer->end_of_stream()) 872 *last_timestamp = buffer->timestamp(); 873 } while (*status == DemuxerStream::kOk && !buffer->end_of_stream()); 874 } 875 876 void ExpectEndOfStream(DemuxerStream::Type type) { 877 EXPECT_CALL(*this, ReadDone(DemuxerStream::kOk, IsEndOfStream())); 878 demuxer_->GetStream(type)->Read(base::Bind( 879 &ChunkDemuxerTest::ReadDone, base::Unretained(this))); 880 message_loop_.RunUntilIdle(); 881 } 882 883 void ExpectRead(DemuxerStream::Type type, int64 timestamp_in_ms) { 884 EXPECT_CALL(*this, ReadDone(DemuxerStream::kOk, 885 HasTimestamp(timestamp_in_ms))); 886 demuxer_->GetStream(type)->Read(base::Bind( 887 &ChunkDemuxerTest::ReadDone, base::Unretained(this))); 888 message_loop_.RunUntilIdle(); 889 } 890 891 void ExpectConfigChanged(DemuxerStream::Type type) { 892 EXPECT_CALL(*this, ReadDone(DemuxerStream::kConfigChanged, _)); 893 demuxer_->GetStream(type)->Read(base::Bind( 894 &ChunkDemuxerTest::ReadDone, base::Unretained(this))); 895 message_loop_.RunUntilIdle(); 896 } 897 898 void CheckExpectedBuffers(DemuxerStream* stream, 899 const std::string& expected) { 900 std::vector<std::string> timestamps; 901 base::SplitString(expected, ' ', ×tamps); 902 std::stringstream ss; 903 for (size_t i = 0; i < timestamps.size(); ++i) { 904 // Initialize status to kAborted since it's possible for Read() to return 905 // without calling StoreStatusAndBuffer() if it doesn't have any buffers 906 // left to return. 907 DemuxerStream::Status status = DemuxerStream::kAborted; 908 scoped_refptr<DecoderBuffer> buffer; 909 stream->Read(base::Bind(&ChunkDemuxerTest::StoreStatusAndBuffer, 910 base::Unretained(this), &status, &buffer)); 911 base::MessageLoop::current()->RunUntilIdle(); 912 if (status != DemuxerStream::kOk || buffer->end_of_stream()) 913 break; 914 915 if (i > 0) 916 ss << " "; 917 ss << buffer->timestamp().InMilliseconds(); 918 919 // Handle preroll buffers. 920 if (EndsWith(timestamps[i], "P", true)) { 921 ASSERT_EQ(kInfiniteDuration(), buffer->discard_padding().first); 922 ASSERT_EQ(base::TimeDelta(), buffer->discard_padding().second); 923 ss << "P"; 924 } 925 } 926 EXPECT_EQ(expected, ss.str()); 927 } 928 929 MOCK_METHOD1(Checkpoint, void(int id)); 930 931 struct BufferTimestamps { 932 int video_time_ms; 933 int audio_time_ms; 934 }; 935 static const int kSkip = -1; 936 937 // Test parsing a WebM file. 938 // |filename| - The name of the file in media/test/data to parse. 939 // |timestamps| - The expected timestamps on the parsed buffers. 940 // a timestamp of kSkip indicates that a Read() call for that stream 941 // shouldn't be made on that iteration of the loop. If both streams have 942 // a kSkip then the loop will terminate. 943 bool ParseWebMFile(const std::string& filename, 944 const BufferTimestamps* timestamps, 945 const base::TimeDelta& duration) { 946 return ParseWebMFile(filename, timestamps, duration, HAS_AUDIO | HAS_VIDEO); 947 } 948 949 bool ParseWebMFile(const std::string& filename, 950 const BufferTimestamps* timestamps, 951 const base::TimeDelta& duration, 952 int stream_flags) { 953 EXPECT_CALL(*this, DemuxerOpened()); 954 demuxer_->Initialize( 955 &host_, CreateInitDoneCB(duration, PIPELINE_OK), true); 956 957 if (AddId(kSourceId, stream_flags) != ChunkDemuxer::kOk) 958 return false; 959 960 // Read a WebM file into memory and send the data to the demuxer. 961 scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(filename); 962 AppendDataInPieces(buffer->data(), buffer->data_size(), 512); 963 964 // Verify that the timestamps on the first few packets match what we 965 // expect. 966 for (size_t i = 0; 967 (timestamps[i].audio_time_ms != kSkip || 968 timestamps[i].video_time_ms != kSkip); 969 i++) { 970 bool audio_read_done = false; 971 bool video_read_done = false; 972 973 if (timestamps[i].audio_time_ms != kSkip) { 974 ReadAudio(base::Bind(&OnReadDone, 975 base::TimeDelta::FromMilliseconds( 976 timestamps[i].audio_time_ms), 977 &audio_read_done)); 978 EXPECT_TRUE(audio_read_done); 979 } 980 981 if (timestamps[i].video_time_ms != kSkip) { 982 ReadVideo(base::Bind(&OnReadDone, 983 base::TimeDelta::FromMilliseconds( 984 timestamps[i].video_time_ms), 985 &video_read_done)); 986 EXPECT_TRUE(video_read_done); 987 } 988 } 989 990 return true; 991 } 992 993 MOCK_METHOD0(DemuxerOpened, void()); 994 // TODO(xhwang): This is a workaround of the issue that move-only parameters 995 // are not supported in mocked methods. Remove this when the issue is fixed 996 // (http://code.google.com/p/googletest/issues/detail?id=395) or when we use 997 // std::string instead of scoped_ptr<uint8[]> (http://crbug.com/130689). 998 MOCK_METHOD3(NeedKeyMock, void(const std::string& type, 999 const uint8* init_data, int init_data_size)); 1000 void DemuxerNeedKey(const std::string& type, 1001 const std::vector<uint8>& init_data) { 1002 const uint8* init_data_ptr = init_data.empty() ? NULL : &init_data[0]; 1003 NeedKeyMock(type, init_data_ptr, init_data.size()); 1004 } 1005 1006 void Seek(base::TimeDelta seek_time) { 1007 demuxer_->StartWaitingForSeek(seek_time); 1008 demuxer_->Seek(seek_time, NewExpectedStatusCB(PIPELINE_OK)); 1009 message_loop_.RunUntilIdle(); 1010 } 1011 1012 void MarkEndOfStream(PipelineStatus status) { 1013 demuxer_->MarkEndOfStream(status); 1014 message_loop_.RunUntilIdle(); 1015 } 1016 1017 bool SetTimestampOffset(const std::string& id, 1018 base::TimeDelta timestamp_offset) { 1019 if (demuxer_->IsParsingMediaSegment(id)) 1020 return false; 1021 1022 timestamp_offset_map_[id] = timestamp_offset; 1023 return true; 1024 } 1025 1026 base::MessageLoop message_loop_; 1027 MockDemuxerHost host_; 1028 1029 scoped_ptr<ChunkDemuxer> demuxer_; 1030 1031 base::TimeDelta append_window_start_for_next_append_; 1032 base::TimeDelta append_window_end_for_next_append_; 1033 1034 // Map of source id to timestamp offset to use for the next AppendData() 1035 // operation for that source id. 1036 std::map<std::string, base::TimeDelta> timestamp_offset_map_; 1037 1038 private: 1039 DISALLOW_COPY_AND_ASSIGN(ChunkDemuxerTest); 1040 }; 1041 1042 TEST_F(ChunkDemuxerTest, Init) { 1043 // Test no streams, audio-only, video-only, and audio & video scenarios. 1044 // Audio and video streams can be encrypted or not encrypted. 1045 for (int i = 0; i < 16; i++) { 1046 bool has_audio = (i & 0x1) != 0; 1047 bool has_video = (i & 0x2) != 0; 1048 bool is_audio_encrypted = (i & 0x4) != 0; 1049 bool is_video_encrypted = (i & 0x8) != 0; 1050 1051 // No test on invalid combination. 1052 if ((!has_audio && is_audio_encrypted) || 1053 (!has_video && is_video_encrypted)) { 1054 continue; 1055 } 1056 1057 CreateNewDemuxer(); 1058 1059 if (is_audio_encrypted || is_video_encrypted) { 1060 int need_key_count = (is_audio_encrypted ? 1 : 0) + 1061 (is_video_encrypted ? 1 : 0); 1062 EXPECT_CALL(*this, NeedKeyMock(kWebMEncryptInitDataType, NotNull(), 1063 DecryptConfig::kDecryptionKeySize)) 1064 .Times(Exactly(need_key_count)); 1065 } 1066 1067 int stream_flags = 0; 1068 if (has_audio) 1069 stream_flags |= HAS_AUDIO; 1070 1071 if (has_video) 1072 stream_flags |= HAS_VIDEO; 1073 1074 ASSERT_TRUE(InitDemuxerWithEncryptionInfo( 1075 stream_flags, is_audio_encrypted, is_video_encrypted)); 1076 1077 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO); 1078 if (has_audio) { 1079 ASSERT_TRUE(audio_stream); 1080 1081 const AudioDecoderConfig& config = audio_stream->audio_decoder_config(); 1082 EXPECT_EQ(kCodecVorbis, config.codec()); 1083 EXPECT_EQ(32, config.bits_per_channel()); 1084 EXPECT_EQ(CHANNEL_LAYOUT_STEREO, config.channel_layout()); 1085 EXPECT_EQ(44100, config.samples_per_second()); 1086 EXPECT_TRUE(config.extra_data()); 1087 EXPECT_GT(config.extra_data_size(), 0u); 1088 EXPECT_EQ(kSampleFormatPlanarF32, config.sample_format()); 1089 EXPECT_EQ(is_audio_encrypted, 1090 audio_stream->audio_decoder_config().is_encrypted()); 1091 EXPECT_TRUE(static_cast<ChunkDemuxerStream*>(audio_stream) 1092 ->supports_partial_append_window_trimming()); 1093 } else { 1094 EXPECT_FALSE(audio_stream); 1095 } 1096 1097 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO); 1098 if (has_video) { 1099 EXPECT_TRUE(video_stream); 1100 EXPECT_EQ(is_video_encrypted, 1101 video_stream->video_decoder_config().is_encrypted()); 1102 EXPECT_FALSE(static_cast<ChunkDemuxerStream*>(video_stream) 1103 ->supports_partial_append_window_trimming()); 1104 } else { 1105 EXPECT_FALSE(video_stream); 1106 } 1107 1108 ShutdownDemuxer(); 1109 demuxer_.reset(); 1110 } 1111 } 1112 1113 // TODO(acolwell): Fold this test into Init tests since the tests are 1114 // almost identical. 1115 TEST_F(ChunkDemuxerTest, InitText) { 1116 // Test with 1 video stream and 1 text streams, and 0 or 1 audio streams. 1117 // No encryption cases handled here. 1118 bool has_video = true; 1119 bool is_audio_encrypted = false; 1120 bool is_video_encrypted = false; 1121 for (int i = 0; i < 2; i++) { 1122 bool has_audio = (i & 0x1) != 0; 1123 1124 CreateNewDemuxer(); 1125 1126 DemuxerStream* text_stream = NULL; 1127 TextTrackConfig text_config; 1128 EXPECT_CALL(host_, AddTextStream(_, _)) 1129 .WillOnce(DoAll(SaveArg<0>(&text_stream), 1130 SaveArg<1>(&text_config))); 1131 1132 int stream_flags = HAS_TEXT; 1133 if (has_audio) 1134 stream_flags |= HAS_AUDIO; 1135 1136 if (has_video) 1137 stream_flags |= HAS_VIDEO; 1138 1139 ASSERT_TRUE(InitDemuxerWithEncryptionInfo( 1140 stream_flags, is_audio_encrypted, is_video_encrypted)); 1141 ASSERT_TRUE(text_stream); 1142 EXPECT_EQ(DemuxerStream::TEXT, text_stream->type()); 1143 EXPECT_EQ(kTextSubtitles, text_config.kind()); 1144 EXPECT_FALSE(static_cast<ChunkDemuxerStream*>(text_stream) 1145 ->supports_partial_append_window_trimming()); 1146 1147 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO); 1148 if (has_audio) { 1149 ASSERT_TRUE(audio_stream); 1150 1151 const AudioDecoderConfig& config = audio_stream->audio_decoder_config(); 1152 EXPECT_EQ(kCodecVorbis, config.codec()); 1153 EXPECT_EQ(32, config.bits_per_channel()); 1154 EXPECT_EQ(CHANNEL_LAYOUT_STEREO, config.channel_layout()); 1155 EXPECT_EQ(44100, config.samples_per_second()); 1156 EXPECT_TRUE(config.extra_data()); 1157 EXPECT_GT(config.extra_data_size(), 0u); 1158 EXPECT_EQ(kSampleFormatPlanarF32, config.sample_format()); 1159 EXPECT_EQ(is_audio_encrypted, 1160 audio_stream->audio_decoder_config().is_encrypted()); 1161 EXPECT_TRUE(static_cast<ChunkDemuxerStream*>(audio_stream) 1162 ->supports_partial_append_window_trimming()); 1163 } else { 1164 EXPECT_FALSE(audio_stream); 1165 } 1166 1167 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO); 1168 if (has_video) { 1169 EXPECT_TRUE(video_stream); 1170 EXPECT_EQ(is_video_encrypted, 1171 video_stream->video_decoder_config().is_encrypted()); 1172 EXPECT_FALSE(static_cast<ChunkDemuxerStream*>(video_stream) 1173 ->supports_partial_append_window_trimming()); 1174 } else { 1175 EXPECT_FALSE(video_stream); 1176 } 1177 1178 ShutdownDemuxer(); 1179 demuxer_.reset(); 1180 } 1181 } 1182 1183 TEST_F(ChunkDemuxerTest, SingleTextTrackIdChange) { 1184 // Test with 1 video stream, 1 audio, and 1 text stream. Send a second init 1185 // segment in which the text track ID changes. Verify appended buffers before 1186 // and after the second init segment map to the same underlying track buffers. 1187 CreateNewDemuxer(); 1188 DemuxerStream* text_stream = NULL; 1189 TextTrackConfig text_config; 1190 EXPECT_CALL(host_, AddTextStream(_, _)) 1191 .WillOnce(DoAll(SaveArg<0>(&text_stream), 1192 SaveArg<1>(&text_config))); 1193 ASSERT_TRUE(InitDemuxerWithEncryptionInfo( 1194 HAS_TEXT | HAS_AUDIO | HAS_VIDEO, false, false)); 1195 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO); 1196 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO); 1197 ASSERT_TRUE(audio_stream); 1198 ASSERT_TRUE(video_stream); 1199 ASSERT_TRUE(text_stream); 1200 1201 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, "0K 23K"); 1202 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "0K 30"); 1203 AppendSingleStreamCluster(kSourceId, kTextTrackNum, "10K"); 1204 CheckExpectedRanges(kSourceId, "{ [0,46) }"); 1205 1206 scoped_ptr<uint8[]> info_tracks; 1207 int info_tracks_size = 0; 1208 CreateInitSegmentWithAlternateTextTrackNum(HAS_TEXT | HAS_AUDIO | HAS_VIDEO, 1209 false, false, 1210 &info_tracks, &info_tracks_size); 1211 demuxer_->AppendData(kSourceId, info_tracks.get(), info_tracks_size, 1212 append_window_start_for_next_append_, 1213 append_window_end_for_next_append_, 1214 ×tamp_offset_map_[kSourceId]); 1215 1216 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, "46K 69K"); 1217 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "60K"); 1218 AppendSingleStreamCluster(kSourceId, kAlternateTextTrackNum, "45K"); 1219 1220 CheckExpectedRanges(kSourceId, "{ [0,92) }"); 1221 CheckExpectedBuffers(audio_stream, "0 23 46 69"); 1222 CheckExpectedBuffers(video_stream, "0 30 60"); 1223 CheckExpectedBuffers(text_stream, "10 45"); 1224 1225 ShutdownDemuxer(); 1226 } 1227 1228 TEST_F(ChunkDemuxerTest, InitSegmentSetsNeedRandomAccessPointFlag) { 1229 // Tests that non-keyframes following an init segment are allowed 1230 // and dropped, as expected if the initialization segment received 1231 // algorithm correctly sets the needs random access point flag to true for all 1232 // track buffers. Note that the first initialization segment is insufficient 1233 // to fully test this since needs random access point flag initializes to 1234 // true. 1235 CreateNewDemuxer(); 1236 DemuxerStream* text_stream = NULL; 1237 EXPECT_CALL(host_, AddTextStream(_, _)) 1238 .WillOnce(SaveArg<0>(&text_stream)); 1239 ASSERT_TRUE(InitDemuxerWithEncryptionInfo( 1240 HAS_TEXT | HAS_AUDIO | HAS_VIDEO, false, false)); 1241 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO); 1242 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO); 1243 ASSERT_TRUE(audio_stream && video_stream && text_stream); 1244 1245 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, "0 23K"); 1246 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "0 30K"); 1247 AppendSingleStreamCluster(kSourceId, kTextTrackNum, "0 40K"); 1248 CheckExpectedRanges(kSourceId, "{ [30,46) }"); 1249 1250 AppendInitSegment(HAS_TEXT | HAS_AUDIO | HAS_VIDEO); 1251 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, "46 69K"); 1252 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "60 90K"); 1253 AppendSingleStreamCluster(kSourceId, kTextTrackNum, "80 90K"); 1254 CheckExpectedRanges(kSourceId, "{ [30,92) }"); 1255 1256 CheckExpectedBuffers(audio_stream, "23 69"); 1257 CheckExpectedBuffers(video_stream, "30 90"); 1258 1259 // WebM parser marks all text buffers as keyframes. 1260 CheckExpectedBuffers(text_stream, "0 40 80 90"); 1261 } 1262 1263 // Make sure that the demuxer reports an error if Shutdown() 1264 // is called before all the initialization segments are appended. 1265 TEST_F(ChunkDemuxerTest, Shutdown_BeforeAllInitSegmentsAppended) { 1266 EXPECT_CALL(*this, DemuxerOpened()); 1267 demuxer_->Initialize( 1268 &host_, CreateInitDoneCB( 1269 kDefaultDuration(), DEMUXER_ERROR_COULD_NOT_OPEN), true); 1270 1271 EXPECT_EQ(AddId("audio", HAS_AUDIO), ChunkDemuxer::kOk); 1272 EXPECT_EQ(AddId("video", HAS_VIDEO), ChunkDemuxer::kOk); 1273 1274 AppendInitSegmentWithSourceId("audio", HAS_AUDIO); 1275 1276 ShutdownDemuxer(); 1277 } 1278 1279 TEST_F(ChunkDemuxerTest, Shutdown_BeforeAllInitSegmentsAppendedText) { 1280 EXPECT_CALL(*this, DemuxerOpened()); 1281 demuxer_->Initialize( 1282 &host_, CreateInitDoneCB( 1283 kDefaultDuration(), DEMUXER_ERROR_COULD_NOT_OPEN), true); 1284 1285 EXPECT_EQ(AddId("audio", HAS_AUDIO), ChunkDemuxer::kOk); 1286 EXPECT_EQ(AddId("video_and_text", HAS_VIDEO), ChunkDemuxer::kOk); 1287 1288 EXPECT_CALL(host_, AddTextStream(_, _)) 1289 .Times(Exactly(1)); 1290 1291 AppendInitSegmentWithSourceId("video_and_text", HAS_VIDEO | HAS_TEXT); 1292 1293 ShutdownDemuxer(); 1294 } 1295 1296 // Verifies that all streams waiting for data receive an end of stream 1297 // buffer when Shutdown() is called. 1298 TEST_F(ChunkDemuxerTest, Shutdown_EndOfStreamWhileWaitingForData) { 1299 DemuxerStream* text_stream = NULL; 1300 EXPECT_CALL(host_, AddTextStream(_, _)) 1301 .WillOnce(SaveArg<0>(&text_stream)); 1302 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO | HAS_TEXT)); 1303 1304 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO); 1305 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO); 1306 1307 bool audio_read_done = false; 1308 bool video_read_done = false; 1309 bool text_read_done = false; 1310 audio_stream->Read(base::Bind(&OnReadDone_EOSExpected, &audio_read_done)); 1311 video_stream->Read(base::Bind(&OnReadDone_EOSExpected, &video_read_done)); 1312 text_stream->Read(base::Bind(&OnReadDone_EOSExpected, &text_read_done)); 1313 message_loop_.RunUntilIdle(); 1314 1315 EXPECT_FALSE(audio_read_done); 1316 EXPECT_FALSE(video_read_done); 1317 EXPECT_FALSE(text_read_done); 1318 1319 ShutdownDemuxer(); 1320 1321 EXPECT_TRUE(audio_read_done); 1322 EXPECT_TRUE(video_read_done); 1323 EXPECT_TRUE(text_read_done); 1324 } 1325 1326 // Test that Seek() completes successfully when the first cluster 1327 // arrives. 1328 TEST_F(ChunkDemuxerTest, AppendDataAfterSeek) { 1329 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 1330 AppendCluster(kDefaultFirstCluster()); 1331 1332 InSequence s; 1333 1334 EXPECT_CALL(*this, Checkpoint(1)); 1335 1336 Seek(base::TimeDelta::FromMilliseconds(46)); 1337 1338 EXPECT_CALL(*this, Checkpoint(2)); 1339 1340 Checkpoint(1); 1341 1342 AppendCluster(kDefaultSecondCluster()); 1343 1344 message_loop_.RunUntilIdle(); 1345 1346 Checkpoint(2); 1347 } 1348 1349 // Test that parsing errors are handled for clusters appended after init. 1350 TEST_F(ChunkDemuxerTest, ErrorWhileParsingClusterAfterInit) { 1351 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 1352 AppendCluster(kDefaultFirstCluster()); 1353 1354 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE)); 1355 AppendGarbage(); 1356 } 1357 1358 // Test the case where a Seek() is requested while the parser 1359 // is in the middle of cluster. This is to verify that the parser 1360 // does not reset itself on a seek. 1361 TEST_F(ChunkDemuxerTest, SeekWhileParsingCluster) { 1362 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 1363 1364 InSequence s; 1365 1366 scoped_ptr<Cluster> cluster_a(GenerateCluster(0, 6)); 1367 1368 // Split the cluster into two appends at an arbitrary point near the end. 1369 int first_append_size = cluster_a->size() - 11; 1370 int second_append_size = cluster_a->size() - first_append_size; 1371 1372 // Append the first part of the cluster. 1373 AppendData(cluster_a->data(), first_append_size); 1374 1375 ExpectRead(DemuxerStream::AUDIO, 0); 1376 ExpectRead(DemuxerStream::VIDEO, 0); 1377 ExpectRead(DemuxerStream::AUDIO, kAudioBlockDuration); 1378 1379 Seek(base::TimeDelta::FromSeconds(5)); 1380 1381 // Append the rest of the cluster. 1382 AppendData(cluster_a->data() + first_append_size, second_append_size); 1383 1384 // Append the new cluster and verify that only the blocks 1385 // in the new cluster are returned. 1386 AppendCluster(GenerateCluster(5000, 6)); 1387 GenerateExpectedReads(5000, 6); 1388 } 1389 1390 // Test the case where AppendData() is called before Init(). 1391 TEST_F(ChunkDemuxerTest, AppendDataBeforeInit) { 1392 scoped_ptr<uint8[]> info_tracks; 1393 int info_tracks_size = 0; 1394 CreateInitSegment(HAS_AUDIO | HAS_VIDEO, 1395 false, false, &info_tracks, &info_tracks_size); 1396 demuxer_->AppendData(kSourceId, info_tracks.get(), info_tracks_size, 1397 append_window_start_for_next_append_, 1398 append_window_end_for_next_append_, 1399 ×tamp_offset_map_[kSourceId]); 1400 } 1401 1402 // Make sure Read() callbacks are dispatched with the proper data. 1403 TEST_F(ChunkDemuxerTest, Read) { 1404 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 1405 1406 AppendCluster(kDefaultFirstCluster()); 1407 1408 bool audio_read_done = false; 1409 bool video_read_done = false; 1410 ReadAudio(base::Bind(&OnReadDone, 1411 base::TimeDelta::FromMilliseconds(0), 1412 &audio_read_done)); 1413 ReadVideo(base::Bind(&OnReadDone, 1414 base::TimeDelta::FromMilliseconds(0), 1415 &video_read_done)); 1416 1417 EXPECT_TRUE(audio_read_done); 1418 EXPECT_TRUE(video_read_done); 1419 } 1420 1421 TEST_F(ChunkDemuxerTest, OutOfOrderClusters) { 1422 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 1423 AppendCluster(kDefaultFirstCluster()); 1424 AppendCluster(GenerateCluster(10, 4)); 1425 1426 // Make sure that AppendCluster() does not fail with a cluster that has 1427 // overlaps with the previously appended cluster. 1428 AppendCluster(GenerateCluster(5, 4)); 1429 1430 // Verify that AppendData() can still accept more data. 1431 scoped_ptr<Cluster> cluster_c(GenerateCluster(45, 2)); 1432 demuxer_->AppendData(kSourceId, cluster_c->data(), cluster_c->size(), 1433 append_window_start_for_next_append_, 1434 append_window_end_for_next_append_, 1435 ×tamp_offset_map_[kSourceId]); 1436 } 1437 1438 TEST_F(ChunkDemuxerTest, NonMonotonicButAboveClusterTimecode) { 1439 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 1440 AppendCluster(kDefaultFirstCluster()); 1441 1442 ClusterBuilder cb; 1443 1444 // Test the case where block timecodes are not monotonically 1445 // increasing but stay above the cluster timecode. 1446 cb.SetClusterTimecode(5); 1447 AddSimpleBlock(&cb, kAudioTrackNum, 5); 1448 AddSimpleBlock(&cb, kVideoTrackNum, 10); 1449 AddSimpleBlock(&cb, kAudioTrackNum, 7); 1450 AddSimpleBlock(&cb, kVideoTrackNum, 15); 1451 1452 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE)); 1453 AppendCluster(cb.Finish()); 1454 1455 // Verify that AppendData() ignores data after the error. 1456 scoped_ptr<Cluster> cluster_b(GenerateCluster(20, 2)); 1457 demuxer_->AppendData(kSourceId, cluster_b->data(), cluster_b->size(), 1458 append_window_start_for_next_append_, 1459 append_window_end_for_next_append_, 1460 ×tamp_offset_map_[kSourceId]); 1461 } 1462 1463 TEST_F(ChunkDemuxerTest, BackwardsAndBeforeClusterTimecode) { 1464 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 1465 AppendCluster(kDefaultFirstCluster()); 1466 1467 ClusterBuilder cb; 1468 1469 // Test timecodes going backwards and including values less than the cluster 1470 // timecode. 1471 cb.SetClusterTimecode(5); 1472 AddSimpleBlock(&cb, kAudioTrackNum, 5); 1473 AddSimpleBlock(&cb, kVideoTrackNum, 5); 1474 AddSimpleBlock(&cb, kAudioTrackNum, 3); 1475 AddSimpleBlock(&cb, kVideoTrackNum, 3); 1476 1477 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE)); 1478 AppendCluster(cb.Finish()); 1479 1480 // Verify that AppendData() ignores data after the error. 1481 scoped_ptr<Cluster> cluster_b(GenerateCluster(6, 2)); 1482 demuxer_->AppendData(kSourceId, cluster_b->data(), cluster_b->size(), 1483 append_window_start_for_next_append_, 1484 append_window_end_for_next_append_, 1485 ×tamp_offset_map_[kSourceId]); 1486 } 1487 1488 1489 TEST_F(ChunkDemuxerTest, PerStreamMonotonicallyIncreasingTimestamps) { 1490 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 1491 AppendCluster(kDefaultFirstCluster()); 1492 1493 ClusterBuilder cb; 1494 1495 // Test monotonic increasing timestamps on a per stream 1496 // basis. 1497 cb.SetClusterTimecode(5); 1498 AddSimpleBlock(&cb, kAudioTrackNum, 5); 1499 AddSimpleBlock(&cb, kVideoTrackNum, 5); 1500 AddSimpleBlock(&cb, kAudioTrackNum, 4); 1501 AddSimpleBlock(&cb, kVideoTrackNum, 7); 1502 1503 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE)); 1504 AppendCluster(cb.Finish()); 1505 } 1506 1507 // Test the case where a cluster is passed to AppendCluster() before 1508 // INFO & TRACKS data. 1509 TEST_F(ChunkDemuxerTest, ClusterBeforeInitSegment) { 1510 EXPECT_CALL(*this, DemuxerOpened()); 1511 demuxer_->Initialize( 1512 &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN), true); 1513 1514 ASSERT_EQ(AddId(), ChunkDemuxer::kOk); 1515 1516 AppendCluster(GenerateCluster(0, 1)); 1517 } 1518 1519 // Test cases where we get an MarkEndOfStream() call during initialization. 1520 TEST_F(ChunkDemuxerTest, EOSDuringInit) { 1521 EXPECT_CALL(*this, DemuxerOpened()); 1522 demuxer_->Initialize( 1523 &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN), true); 1524 MarkEndOfStream(PIPELINE_OK); 1525 } 1526 1527 TEST_F(ChunkDemuxerTest, EndOfStreamWithNoAppend) { 1528 EXPECT_CALL(*this, DemuxerOpened()); 1529 demuxer_->Initialize( 1530 &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN), true); 1531 1532 ASSERT_EQ(AddId(), ChunkDemuxer::kOk); 1533 1534 CheckExpectedRanges("{ }"); 1535 MarkEndOfStream(PIPELINE_OK); 1536 ShutdownDemuxer(); 1537 CheckExpectedRanges("{ }"); 1538 demuxer_->RemoveId(kSourceId); 1539 demuxer_.reset(); 1540 } 1541 1542 TEST_F(ChunkDemuxerTest, EndOfStreamWithNoMediaAppend) { 1543 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 1544 1545 CheckExpectedRanges("{ }"); 1546 MarkEndOfStream(PIPELINE_OK); 1547 CheckExpectedRanges("{ }"); 1548 } 1549 1550 TEST_F(ChunkDemuxerTest, DecodeErrorEndOfStream) { 1551 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 1552 1553 AppendCluster(kDefaultFirstCluster()); 1554 CheckExpectedRanges(kDefaultFirstClusterRange); 1555 1556 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE)); 1557 MarkEndOfStream(PIPELINE_ERROR_DECODE); 1558 CheckExpectedRanges(kDefaultFirstClusterRange); 1559 } 1560 1561 TEST_F(ChunkDemuxerTest, NetworkErrorEndOfStream) { 1562 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 1563 1564 AppendCluster(kDefaultFirstCluster()); 1565 CheckExpectedRanges(kDefaultFirstClusterRange); 1566 1567 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_NETWORK)); 1568 MarkEndOfStream(PIPELINE_ERROR_NETWORK); 1569 } 1570 1571 // Helper class to reduce duplicate code when testing end of stream 1572 // Read() behavior. 1573 class EndOfStreamHelper { 1574 public: 1575 explicit EndOfStreamHelper(Demuxer* demuxer) 1576 : demuxer_(demuxer), 1577 audio_read_done_(false), 1578 video_read_done_(false) { 1579 } 1580 1581 // Request a read on the audio and video streams. 1582 void RequestReads() { 1583 EXPECT_FALSE(audio_read_done_); 1584 EXPECT_FALSE(video_read_done_); 1585 1586 DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO); 1587 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO); 1588 1589 audio->Read(base::Bind(&OnEndOfStreamReadDone, &audio_read_done_)); 1590 video->Read(base::Bind(&OnEndOfStreamReadDone, &video_read_done_)); 1591 base::MessageLoop::current()->RunUntilIdle(); 1592 } 1593 1594 // Check to see if |audio_read_done_| and |video_read_done_| variables 1595 // match |expected|. 1596 void CheckIfReadDonesWereCalled(bool expected) { 1597 base::MessageLoop::current()->RunUntilIdle(); 1598 EXPECT_EQ(expected, audio_read_done_); 1599 EXPECT_EQ(expected, video_read_done_); 1600 } 1601 1602 private: 1603 static void OnEndOfStreamReadDone( 1604 bool* called, 1605 DemuxerStream::Status status, 1606 const scoped_refptr<DecoderBuffer>& buffer) { 1607 EXPECT_EQ(status, DemuxerStream::kOk); 1608 EXPECT_TRUE(buffer->end_of_stream()); 1609 *called = true; 1610 } 1611 1612 Demuxer* demuxer_; 1613 bool audio_read_done_; 1614 bool video_read_done_; 1615 1616 DISALLOW_COPY_AND_ASSIGN(EndOfStreamHelper); 1617 }; 1618 1619 // Make sure that all pending reads that we don't have media data for get an 1620 // "end of stream" buffer when MarkEndOfStream() is called. 1621 TEST_F(ChunkDemuxerTest, EndOfStreamWithPendingReads) { 1622 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 1623 1624 AppendCluster(GenerateCluster(0, 2)); 1625 1626 bool audio_read_done_1 = false; 1627 bool video_read_done_1 = false; 1628 EndOfStreamHelper end_of_stream_helper_1(demuxer_.get()); 1629 EndOfStreamHelper end_of_stream_helper_2(demuxer_.get()); 1630 1631 ReadAudio(base::Bind(&OnReadDone, 1632 base::TimeDelta::FromMilliseconds(0), 1633 &audio_read_done_1)); 1634 ReadVideo(base::Bind(&OnReadDone, 1635 base::TimeDelta::FromMilliseconds(0), 1636 &video_read_done_1)); 1637 message_loop_.RunUntilIdle(); 1638 1639 EXPECT_TRUE(audio_read_done_1); 1640 EXPECT_TRUE(video_read_done_1); 1641 1642 end_of_stream_helper_1.RequestReads(); 1643 1644 EXPECT_CALL(host_, SetDuration( 1645 base::TimeDelta::FromMilliseconds(kVideoBlockDuration))); 1646 MarkEndOfStream(PIPELINE_OK); 1647 1648 end_of_stream_helper_1.CheckIfReadDonesWereCalled(true); 1649 1650 end_of_stream_helper_2.RequestReads(); 1651 end_of_stream_helper_2.CheckIfReadDonesWereCalled(true); 1652 } 1653 1654 // Make sure that all Read() calls after we get an MarkEndOfStream() 1655 // call return an "end of stream" buffer. 1656 TEST_F(ChunkDemuxerTest, ReadsAfterEndOfStream) { 1657 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 1658 1659 AppendCluster(GenerateCluster(0, 2)); 1660 1661 bool audio_read_done_1 = false; 1662 bool video_read_done_1 = false; 1663 EndOfStreamHelper end_of_stream_helper_1(demuxer_.get()); 1664 EndOfStreamHelper end_of_stream_helper_2(demuxer_.get()); 1665 EndOfStreamHelper end_of_stream_helper_3(demuxer_.get()); 1666 1667 ReadAudio(base::Bind(&OnReadDone, 1668 base::TimeDelta::FromMilliseconds(0), 1669 &audio_read_done_1)); 1670 ReadVideo(base::Bind(&OnReadDone, 1671 base::TimeDelta::FromMilliseconds(0), 1672 &video_read_done_1)); 1673 1674 end_of_stream_helper_1.RequestReads(); 1675 1676 EXPECT_TRUE(audio_read_done_1); 1677 EXPECT_TRUE(video_read_done_1); 1678 end_of_stream_helper_1.CheckIfReadDonesWereCalled(false); 1679 1680 EXPECT_CALL(host_, SetDuration( 1681 base::TimeDelta::FromMilliseconds(kVideoBlockDuration))); 1682 MarkEndOfStream(PIPELINE_OK); 1683 1684 end_of_stream_helper_1.CheckIfReadDonesWereCalled(true); 1685 1686 // Request a few more reads and make sure we immediately get 1687 // end of stream buffers. 1688 end_of_stream_helper_2.RequestReads(); 1689 end_of_stream_helper_2.CheckIfReadDonesWereCalled(true); 1690 1691 end_of_stream_helper_3.RequestReads(); 1692 end_of_stream_helper_3.CheckIfReadDonesWereCalled(true); 1693 } 1694 1695 TEST_F(ChunkDemuxerTest, EndOfStreamDuringCanceledSeek) { 1696 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 1697 1698 AppendCluster(0, 10); 1699 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(138))); 1700 MarkEndOfStream(PIPELINE_OK); 1701 1702 // Start the first seek. 1703 Seek(base::TimeDelta::FromMilliseconds(20)); 1704 1705 // Simulate another seek being requested before the first 1706 // seek has finished prerolling. 1707 base::TimeDelta seek_time2 = base::TimeDelta::FromMilliseconds(30); 1708 demuxer_->CancelPendingSeek(seek_time2); 1709 1710 // Finish second seek. 1711 Seek(seek_time2); 1712 1713 DemuxerStream::Status status; 1714 base::TimeDelta last_timestamp; 1715 1716 // Make sure audio can reach end of stream. 1717 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp); 1718 ASSERT_EQ(status, DemuxerStream::kOk); 1719 1720 // Make sure video can reach end of stream. 1721 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp); 1722 ASSERT_EQ(status, DemuxerStream::kOk); 1723 } 1724 1725 // Verify buffered range change behavior for audio/video/text tracks. 1726 TEST_F(ChunkDemuxerTest, EndOfStreamRangeChanges) { 1727 DemuxerStream* text_stream = NULL; 1728 1729 EXPECT_CALL(host_, AddTextStream(_, _)) 1730 .WillOnce(SaveArg<0>(&text_stream)); 1731 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO | HAS_TEXT)); 1732 1733 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "0K 33"); 1734 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, "0K 23K"); 1735 1736 // Check expected ranges and verify that an empty text track does not 1737 // affect the expected ranges. 1738 CheckExpectedRanges(kSourceId, "{ [0,46) }"); 1739 1740 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(66))); 1741 MarkEndOfStream(PIPELINE_OK); 1742 1743 // Check expected ranges and verify that an empty text track does not 1744 // affect the expected ranges. 1745 CheckExpectedRanges(kSourceId, "{ [0,66) }"); 1746 1747 // Unmark end of stream state and verify that the ranges return to 1748 // their pre-"end of stream" values. 1749 demuxer_->UnmarkEndOfStream(); 1750 CheckExpectedRanges(kSourceId, "{ [0,46) }"); 1751 1752 // Add text track data and verify that the buffered ranges don't change 1753 // since the intersection of all the tracks doesn't change. 1754 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(200))); 1755 AppendSingleStreamCluster(kSourceId, kTextTrackNum, "0K 100K"); 1756 CheckExpectedRanges(kSourceId, "{ [0,46) }"); 1757 1758 // Mark end of stream and verify that text track data is reflected in 1759 // the new range. 1760 MarkEndOfStream(PIPELINE_OK); 1761 CheckExpectedRanges(kSourceId, "{ [0,200) }"); 1762 } 1763 1764 // Make sure AppendData() will accept elements that span multiple calls. 1765 TEST_F(ChunkDemuxerTest, AppendingInPieces) { 1766 EXPECT_CALL(*this, DemuxerOpened()); 1767 demuxer_->Initialize( 1768 &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true); 1769 1770 ASSERT_EQ(AddId(), ChunkDemuxer::kOk); 1771 1772 scoped_ptr<uint8[]> info_tracks; 1773 int info_tracks_size = 0; 1774 CreateInitSegment(HAS_AUDIO | HAS_VIDEO, 1775 false, false, &info_tracks, &info_tracks_size); 1776 1777 scoped_ptr<Cluster> cluster_a(kDefaultFirstCluster()); 1778 scoped_ptr<Cluster> cluster_b(kDefaultSecondCluster()); 1779 1780 size_t buffer_size = info_tracks_size + cluster_a->size() + cluster_b->size(); 1781 scoped_ptr<uint8[]> buffer(new uint8[buffer_size]); 1782 uint8* dst = buffer.get(); 1783 memcpy(dst, info_tracks.get(), info_tracks_size); 1784 dst += info_tracks_size; 1785 1786 memcpy(dst, cluster_a->data(), cluster_a->size()); 1787 dst += cluster_a->size(); 1788 1789 memcpy(dst, cluster_b->data(), cluster_b->size()); 1790 dst += cluster_b->size(); 1791 1792 AppendDataInPieces(buffer.get(), buffer_size); 1793 1794 GenerateExpectedReads(0, 9); 1795 } 1796 1797 TEST_F(ChunkDemuxerTest, WebMFile_AudioAndVideo) { 1798 struct BufferTimestamps buffer_timestamps[] = { 1799 {0, 0}, 1800 {33, 3}, 1801 {67, 6}, 1802 {100, 9}, 1803 {133, 12}, 1804 {kSkip, kSkip}, 1805 }; 1806 1807 // TODO(wolenetz/acolwell): Remove this SetDuration expectation and update the 1808 // ParseWebMFile() call's expected duration, below, once the file is fixed to 1809 // have the correct duration in the init segment. See http://crbug.com/354284. 1810 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2746))); 1811 1812 ASSERT_TRUE(ParseWebMFile("bear-320x240.webm", buffer_timestamps, 1813 base::TimeDelta::FromMilliseconds(2744))); 1814 } 1815 1816 TEST_F(ChunkDemuxerTest, WebMFile_LiveAudioAndVideo) { 1817 struct BufferTimestamps buffer_timestamps[] = { 1818 {0, 0}, 1819 {33, 3}, 1820 {67, 6}, 1821 {100, 9}, 1822 {133, 12}, 1823 {kSkip, kSkip}, 1824 }; 1825 1826 ASSERT_TRUE(ParseWebMFile("bear-320x240-live.webm", buffer_timestamps, 1827 kInfiniteDuration())); 1828 } 1829 1830 TEST_F(ChunkDemuxerTest, WebMFile_AudioOnly) { 1831 struct BufferTimestamps buffer_timestamps[] = { 1832 {kSkip, 0}, 1833 {kSkip, 3}, 1834 {kSkip, 6}, 1835 {kSkip, 9}, 1836 {kSkip, 12}, 1837 {kSkip, kSkip}, 1838 }; 1839 1840 // TODO(wolenetz/acolwell): Remove this SetDuration expectation and update the 1841 // ParseWebMFile() call's expected duration, below, once the file is fixed to 1842 // have the correct duration in the init segment. See http://crbug.com/354284. 1843 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2746))); 1844 1845 ASSERT_TRUE(ParseWebMFile("bear-320x240-audio-only.webm", buffer_timestamps, 1846 base::TimeDelta::FromMilliseconds(2744), 1847 HAS_AUDIO)); 1848 } 1849 1850 TEST_F(ChunkDemuxerTest, WebMFile_VideoOnly) { 1851 struct BufferTimestamps buffer_timestamps[] = { 1852 {0, kSkip}, 1853 {33, kSkip}, 1854 {67, kSkip}, 1855 {100, kSkip}, 1856 {133, kSkip}, 1857 {kSkip, kSkip}, 1858 }; 1859 1860 // TODO(wolenetz/acolwell): Remove this SetDuration expectation and update the 1861 // ParseWebMFile() call's expected duration, below, once the file is fixed to 1862 // have the correct duration in the init segment. See http://crbug.com/354284. 1863 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2736))); 1864 1865 ASSERT_TRUE(ParseWebMFile("bear-320x240-video-only.webm", buffer_timestamps, 1866 base::TimeDelta::FromMilliseconds(2703), 1867 HAS_VIDEO)); 1868 } 1869 1870 TEST_F(ChunkDemuxerTest, WebMFile_AltRefFrames) { 1871 struct BufferTimestamps buffer_timestamps[] = { 1872 {0, 0}, 1873 {33, 3}, 1874 {33, 6}, 1875 {67, 9}, 1876 {100, 12}, 1877 {kSkip, kSkip}, 1878 }; 1879 1880 ASSERT_TRUE(ParseWebMFile("bear-320x240-altref.webm", buffer_timestamps, 1881 base::TimeDelta::FromMilliseconds(2767))); 1882 } 1883 1884 // Verify that we output buffers before the entire cluster has been parsed. 1885 TEST_F(ChunkDemuxerTest, IncrementalClusterParsing) { 1886 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 1887 AppendEmptyCluster(0); 1888 1889 scoped_ptr<Cluster> cluster(GenerateCluster(0, 6)); 1890 1891 bool audio_read_done = false; 1892 bool video_read_done = false; 1893 ReadAudio(base::Bind(&OnReadDone, 1894 base::TimeDelta::FromMilliseconds(0), 1895 &audio_read_done)); 1896 ReadVideo(base::Bind(&OnReadDone, 1897 base::TimeDelta::FromMilliseconds(0), 1898 &video_read_done)); 1899 1900 // Make sure the reads haven't completed yet. 1901 EXPECT_FALSE(audio_read_done); 1902 EXPECT_FALSE(video_read_done); 1903 1904 // Append data one byte at a time until one or both reads complete. 1905 int i = 0; 1906 for (; i < cluster->size() && !(audio_read_done || video_read_done); ++i) { 1907 AppendData(cluster->data() + i, 1); 1908 message_loop_.RunUntilIdle(); 1909 } 1910 1911 EXPECT_TRUE(audio_read_done || video_read_done); 1912 EXPECT_GT(i, 0); 1913 EXPECT_LT(i, cluster->size()); 1914 1915 audio_read_done = false; 1916 video_read_done = false; 1917 ReadAudio(base::Bind(&OnReadDone, 1918 base::TimeDelta::FromMilliseconds(23), 1919 &audio_read_done)); 1920 ReadVideo(base::Bind(&OnReadDone, 1921 base::TimeDelta::FromMilliseconds(33), 1922 &video_read_done)); 1923 1924 // Make sure the reads haven't completed yet. 1925 EXPECT_FALSE(audio_read_done); 1926 EXPECT_FALSE(video_read_done); 1927 1928 // Append the remaining data. 1929 ASSERT_LT(i, cluster->size()); 1930 AppendData(cluster->data() + i, cluster->size() - i); 1931 1932 message_loop_.RunUntilIdle(); 1933 1934 EXPECT_TRUE(audio_read_done); 1935 EXPECT_TRUE(video_read_done); 1936 } 1937 1938 TEST_F(ChunkDemuxerTest, ParseErrorDuringInit) { 1939 EXPECT_CALL(*this, DemuxerOpened()); 1940 demuxer_->Initialize( 1941 &host_, CreateInitDoneCB( 1942 kNoTimestamp(), DEMUXER_ERROR_COULD_NOT_OPEN), true); 1943 1944 ASSERT_EQ(AddId(), ChunkDemuxer::kOk); 1945 1946 uint8 tmp = 0; 1947 demuxer_->AppendData(kSourceId, &tmp, 1, 1948 append_window_start_for_next_append_, 1949 append_window_end_for_next_append_, 1950 ×tamp_offset_map_[kSourceId]); 1951 } 1952 1953 TEST_F(ChunkDemuxerTest, AVHeadersWithAudioOnlyType) { 1954 EXPECT_CALL(*this, DemuxerOpened()); 1955 demuxer_->Initialize( 1956 &host_, CreateInitDoneCB(kNoTimestamp(), 1957 DEMUXER_ERROR_COULD_NOT_OPEN), true); 1958 1959 std::vector<std::string> codecs(1); 1960 codecs[0] = "vorbis"; 1961 ASSERT_EQ(demuxer_->AddId(kSourceId, "audio/webm", codecs), 1962 ChunkDemuxer::kOk); 1963 1964 AppendInitSegment(HAS_AUDIO | HAS_VIDEO); 1965 } 1966 1967 TEST_F(ChunkDemuxerTest, AVHeadersWithVideoOnlyType) { 1968 EXPECT_CALL(*this, DemuxerOpened()); 1969 demuxer_->Initialize( 1970 &host_, CreateInitDoneCB(kNoTimestamp(), 1971 DEMUXER_ERROR_COULD_NOT_OPEN), true); 1972 1973 std::vector<std::string> codecs(1); 1974 codecs[0] = "vp8"; 1975 ASSERT_EQ(demuxer_->AddId(kSourceId, "video/webm", codecs), 1976 ChunkDemuxer::kOk); 1977 1978 AppendInitSegment(HAS_AUDIO | HAS_VIDEO); 1979 } 1980 1981 TEST_F(ChunkDemuxerTest, MultipleHeaders) { 1982 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 1983 1984 AppendCluster(kDefaultFirstCluster()); 1985 1986 // Append another identical initialization segment. 1987 AppendInitSegment(HAS_AUDIO | HAS_VIDEO); 1988 1989 AppendCluster(kDefaultSecondCluster()); 1990 1991 GenerateExpectedReads(0, 9); 1992 } 1993 1994 TEST_F(ChunkDemuxerTest, AddSeparateSourcesForAudioAndVideo) { 1995 std::string audio_id = "audio1"; 1996 std::string video_id = "video1"; 1997 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id)); 1998 1999 // Append audio and video data into separate source ids. 2000 AppendCluster(audio_id, 2001 GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration)); 2002 GenerateAudioStreamExpectedReads(0, 4); 2003 AppendCluster(video_id, 2004 GenerateSingleStreamCluster(0, 132, kVideoTrackNum, kVideoBlockDuration)); 2005 GenerateVideoStreamExpectedReads(0, 4); 2006 } 2007 2008 TEST_F(ChunkDemuxerTest, AddSeparateSourcesForAudioAndVideoText) { 2009 // TODO(matthewjheaney): Here and elsewhere, we need more tests 2010 // for inband text tracks (http://crbug/321455). 2011 2012 std::string audio_id = "audio1"; 2013 std::string video_id = "video1"; 2014 2015 EXPECT_CALL(host_, AddTextStream(_, _)) 2016 .Times(Exactly(2)); 2017 ASSERT_TRUE(InitDemuxerAudioAndVideoSourcesText(audio_id, video_id, true)); 2018 2019 // Append audio and video data into separate source ids. 2020 AppendCluster(audio_id, 2021 GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration)); 2022 GenerateAudioStreamExpectedReads(0, 4); 2023 AppendCluster(video_id, 2024 GenerateSingleStreamCluster(0, 132, kVideoTrackNum, kVideoBlockDuration)); 2025 GenerateVideoStreamExpectedReads(0, 4); 2026 } 2027 2028 TEST_F(ChunkDemuxerTest, AddIdFailures) { 2029 EXPECT_CALL(*this, DemuxerOpened()); 2030 demuxer_->Initialize( 2031 &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true); 2032 2033 std::string audio_id = "audio1"; 2034 std::string video_id = "video1"; 2035 2036 ASSERT_EQ(AddId(audio_id, HAS_AUDIO), ChunkDemuxer::kOk); 2037 2038 // Adding an id with audio/video should fail because we already added audio. 2039 ASSERT_EQ(AddId(), ChunkDemuxer::kReachedIdLimit); 2040 2041 AppendInitSegmentWithSourceId(audio_id, HAS_AUDIO); 2042 2043 // Adding an id after append should fail. 2044 ASSERT_EQ(AddId(video_id, HAS_VIDEO), ChunkDemuxer::kReachedIdLimit); 2045 } 2046 2047 // Test that Read() calls after a RemoveId() return "end of stream" buffers. 2048 TEST_F(ChunkDemuxerTest, RemoveId) { 2049 std::string audio_id = "audio1"; 2050 std::string video_id = "video1"; 2051 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id)); 2052 2053 // Append audio and video data into separate source ids. 2054 AppendCluster(audio_id, 2055 GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration)); 2056 AppendCluster(video_id, 2057 GenerateSingleStreamCluster(0, 132, kVideoTrackNum, kVideoBlockDuration)); 2058 2059 // Read() from audio should return normal buffers. 2060 GenerateAudioStreamExpectedReads(0, 4); 2061 2062 // Remove the audio id. 2063 demuxer_->RemoveId(audio_id); 2064 2065 // Read() from audio should return "end of stream" buffers. 2066 bool audio_read_done = false; 2067 ReadAudio(base::Bind(&OnReadDone_EOSExpected, &audio_read_done)); 2068 message_loop_.RunUntilIdle(); 2069 EXPECT_TRUE(audio_read_done); 2070 2071 // Read() from video should still return normal buffers. 2072 GenerateVideoStreamExpectedReads(0, 4); 2073 } 2074 2075 // Test that removing an ID immediately after adding it does not interfere with 2076 // quota for new IDs in the future. 2077 TEST_F(ChunkDemuxerTest, RemoveAndAddId) { 2078 std::string audio_id_1 = "audio1"; 2079 ASSERT_TRUE(AddId(audio_id_1, HAS_AUDIO) == ChunkDemuxer::kOk); 2080 demuxer_->RemoveId(audio_id_1); 2081 2082 std::string audio_id_2 = "audio2"; 2083 ASSERT_TRUE(AddId(audio_id_2, HAS_AUDIO) == ChunkDemuxer::kOk); 2084 } 2085 2086 TEST_F(ChunkDemuxerTest, SeekCanceled) { 2087 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 2088 2089 // Append cluster at the beginning of the stream. 2090 AppendCluster(GenerateCluster(0, 4)); 2091 2092 // Seek to an unbuffered region. 2093 Seek(base::TimeDelta::FromSeconds(50)); 2094 2095 // Attempt to read in unbuffered area; should not fulfill the read. 2096 bool audio_read_done = false; 2097 bool video_read_done = false; 2098 ReadAudio(base::Bind(&OnReadDone_AbortExpected, &audio_read_done)); 2099 ReadVideo(base::Bind(&OnReadDone_AbortExpected, &video_read_done)); 2100 EXPECT_FALSE(audio_read_done); 2101 EXPECT_FALSE(video_read_done); 2102 2103 // Now cancel the pending seek, which should flush the reads with empty 2104 // buffers. 2105 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(0); 2106 demuxer_->CancelPendingSeek(seek_time); 2107 message_loop_.RunUntilIdle(); 2108 EXPECT_TRUE(audio_read_done); 2109 EXPECT_TRUE(video_read_done); 2110 2111 // A seek back to the buffered region should succeed. 2112 Seek(seek_time); 2113 GenerateExpectedReads(0, 4); 2114 } 2115 2116 TEST_F(ChunkDemuxerTest, SeekCanceledWhileWaitingForSeek) { 2117 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 2118 2119 // Append cluster at the beginning of the stream. 2120 AppendCluster(GenerateCluster(0, 4)); 2121 2122 // Start waiting for a seek. 2123 base::TimeDelta seek_time1 = base::TimeDelta::FromSeconds(50); 2124 base::TimeDelta seek_time2 = base::TimeDelta::FromSeconds(0); 2125 demuxer_->StartWaitingForSeek(seek_time1); 2126 2127 // Now cancel the upcoming seek to an unbuffered region. 2128 demuxer_->CancelPendingSeek(seek_time2); 2129 demuxer_->Seek(seek_time1, NewExpectedStatusCB(PIPELINE_OK)); 2130 2131 // Read requests should be fulfilled with empty buffers. 2132 bool audio_read_done = false; 2133 bool video_read_done = false; 2134 ReadAudio(base::Bind(&OnReadDone_AbortExpected, &audio_read_done)); 2135 ReadVideo(base::Bind(&OnReadDone_AbortExpected, &video_read_done)); 2136 EXPECT_TRUE(audio_read_done); 2137 EXPECT_TRUE(video_read_done); 2138 2139 // A seek back to the buffered region should succeed. 2140 Seek(seek_time2); 2141 GenerateExpectedReads(0, 4); 2142 } 2143 2144 // Test that Seek() successfully seeks to all source IDs. 2145 TEST_F(ChunkDemuxerTest, SeekAudioAndVideoSources) { 2146 std::string audio_id = "audio1"; 2147 std::string video_id = "video1"; 2148 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id)); 2149 2150 AppendCluster( 2151 audio_id, 2152 GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration)); 2153 AppendCluster( 2154 video_id, 2155 GenerateSingleStreamCluster(0, 132, kVideoTrackNum, kVideoBlockDuration)); 2156 2157 // Read() should return buffers at 0. 2158 bool audio_read_done = false; 2159 bool video_read_done = false; 2160 ReadAudio(base::Bind(&OnReadDone, 2161 base::TimeDelta::FromMilliseconds(0), 2162 &audio_read_done)); 2163 ReadVideo(base::Bind(&OnReadDone, 2164 base::TimeDelta::FromMilliseconds(0), 2165 &video_read_done)); 2166 EXPECT_TRUE(audio_read_done); 2167 EXPECT_TRUE(video_read_done); 2168 2169 // Seek to 3 (an unbuffered region). 2170 Seek(base::TimeDelta::FromSeconds(3)); 2171 2172 audio_read_done = false; 2173 video_read_done = false; 2174 ReadAudio(base::Bind(&OnReadDone, 2175 base::TimeDelta::FromSeconds(3), 2176 &audio_read_done)); 2177 ReadVideo(base::Bind(&OnReadDone, 2178 base::TimeDelta::FromSeconds(3), 2179 &video_read_done)); 2180 // Read()s should not return until after data is appended at the Seek point. 2181 EXPECT_FALSE(audio_read_done); 2182 EXPECT_FALSE(video_read_done); 2183 2184 AppendCluster(audio_id, 2185 GenerateSingleStreamCluster( 2186 3000, 3092, kAudioTrackNum, kAudioBlockDuration)); 2187 AppendCluster(video_id, 2188 GenerateSingleStreamCluster( 2189 3000, 3132, kVideoTrackNum, kVideoBlockDuration)); 2190 2191 message_loop_.RunUntilIdle(); 2192 2193 // Read() should return buffers at 3. 2194 EXPECT_TRUE(audio_read_done); 2195 EXPECT_TRUE(video_read_done); 2196 } 2197 2198 // Test that Seek() completes successfully when EndOfStream 2199 // is called before data is available for that seek point. 2200 // This scenario might be useful if seeking past the end of stream 2201 // of either audio or video (or both). 2202 TEST_F(ChunkDemuxerTest, EndOfStreamAfterPastEosSeek) { 2203 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 2204 2205 AppendCluster(GenerateSingleStreamCluster(0, 120, kAudioTrackNum, 10)); 2206 AppendCluster(GenerateSingleStreamCluster(0, 100, kVideoTrackNum, 5)); 2207 2208 // Seeking past the end of video. 2209 // Note: audio data is available for that seek point. 2210 bool seek_cb_was_called = false; 2211 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(110); 2212 demuxer_->StartWaitingForSeek(seek_time); 2213 demuxer_->Seek(seek_time, 2214 base::Bind(OnSeekDone_OKExpected, &seek_cb_was_called)); 2215 message_loop_.RunUntilIdle(); 2216 2217 EXPECT_FALSE(seek_cb_was_called); 2218 2219 EXPECT_CALL(host_, SetDuration( 2220 base::TimeDelta::FromMilliseconds(120))); 2221 MarkEndOfStream(PIPELINE_OK); 2222 message_loop_.RunUntilIdle(); 2223 2224 EXPECT_TRUE(seek_cb_was_called); 2225 2226 ShutdownDemuxer(); 2227 } 2228 2229 // Test that EndOfStream is ignored if coming during a pending seek 2230 // whose seek time is before some existing ranges. 2231 TEST_F(ChunkDemuxerTest, EndOfStreamDuringPendingSeek) { 2232 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 2233 2234 AppendCluster(GenerateSingleStreamCluster(0, 120, kAudioTrackNum, 10)); 2235 AppendCluster(GenerateSingleStreamCluster(0, 100, kVideoTrackNum, 5)); 2236 AppendCluster(GenerateSingleStreamCluster(200, 300, kAudioTrackNum, 10)); 2237 AppendCluster(GenerateSingleStreamCluster(200, 300, kVideoTrackNum, 5)); 2238 2239 bool seek_cb_was_called = false; 2240 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(160); 2241 demuxer_->StartWaitingForSeek(seek_time); 2242 demuxer_->Seek(seek_time, 2243 base::Bind(OnSeekDone_OKExpected, &seek_cb_was_called)); 2244 message_loop_.RunUntilIdle(); 2245 2246 EXPECT_FALSE(seek_cb_was_called); 2247 2248 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(300))); 2249 MarkEndOfStream(PIPELINE_OK); 2250 message_loop_.RunUntilIdle(); 2251 2252 EXPECT_FALSE(seek_cb_was_called); 2253 2254 demuxer_->UnmarkEndOfStream(); 2255 2256 AppendCluster(GenerateSingleStreamCluster(140, 180, kAudioTrackNum, 10)); 2257 AppendCluster(GenerateSingleStreamCluster(140, 180, kVideoTrackNum, 5)); 2258 2259 message_loop_.RunUntilIdle(); 2260 2261 EXPECT_TRUE(seek_cb_was_called); 2262 2263 ShutdownDemuxer(); 2264 } 2265 2266 // Test ranges in an audio-only stream. 2267 TEST_F(ChunkDemuxerTest, GetBufferedRanges_AudioIdOnly) { 2268 EXPECT_CALL(*this, DemuxerOpened()); 2269 demuxer_->Initialize( 2270 &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true); 2271 2272 ASSERT_EQ(AddId(kSourceId, HAS_AUDIO), ChunkDemuxer::kOk); 2273 AppendInitSegment(HAS_AUDIO); 2274 2275 // Test a simple cluster. 2276 AppendCluster( 2277 GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration)); 2278 2279 CheckExpectedRanges("{ [0,92) }"); 2280 2281 // Append a disjoint cluster to check for two separate ranges. 2282 AppendCluster(GenerateSingleStreamCluster( 2283 150, 219, kAudioTrackNum, kAudioBlockDuration)); 2284 2285 CheckExpectedRanges("{ [0,92) [150,219) }"); 2286 } 2287 2288 // Test ranges in a video-only stream. 2289 TEST_F(ChunkDemuxerTest, GetBufferedRanges_VideoIdOnly) { 2290 EXPECT_CALL(*this, DemuxerOpened()); 2291 demuxer_->Initialize( 2292 &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true); 2293 2294 ASSERT_EQ(AddId(kSourceId, HAS_VIDEO), ChunkDemuxer::kOk); 2295 AppendInitSegment(HAS_VIDEO); 2296 2297 // Test a simple cluster. 2298 AppendCluster( 2299 GenerateSingleStreamCluster(0, 132, kVideoTrackNum, kVideoBlockDuration)); 2300 2301 CheckExpectedRanges("{ [0,132) }"); 2302 2303 // Append a disjoint cluster to check for two separate ranges. 2304 AppendCluster(GenerateSingleStreamCluster( 2305 200, 299, kVideoTrackNum, kVideoBlockDuration)); 2306 2307 CheckExpectedRanges("{ [0,132) [200,299) }"); 2308 } 2309 2310 TEST_F(ChunkDemuxerTest, GetBufferedRanges_AudioVideo) { 2311 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 2312 2313 // Audio: 0 -> 23 2314 // Video: 0 -> 33 2315 // Buffered Range: 0 -> 23 2316 // Audio block duration is smaller than video block duration, 2317 // so the buffered ranges should correspond to the audio blocks. 2318 AppendCluster(GenerateSingleStreamCluster( 2319 0, kAudioBlockDuration, kAudioTrackNum, kAudioBlockDuration)); 2320 AppendCluster(GenerateSingleStreamCluster( 2321 0, kVideoBlockDuration, kVideoTrackNum, kVideoBlockDuration)); 2322 2323 CheckExpectedRanges("{ [0,23) }"); 2324 2325 // Audio: 300 -> 400 2326 // Video: 320 -> 420 2327 // Buffered Range: 320 -> 400 (end overlap) 2328 AppendCluster(GenerateSingleStreamCluster(300, 400, kAudioTrackNum, 50)); 2329 AppendCluster(GenerateSingleStreamCluster(320, 420, kVideoTrackNum, 50)); 2330 2331 CheckExpectedRanges("{ [0,23) [320,400) }"); 2332 2333 // Audio: 520 -> 590 2334 // Video: 500 -> 570 2335 // Buffered Range: 520 -> 570 (front overlap) 2336 AppendCluster(GenerateSingleStreamCluster(520, 590, kAudioTrackNum, 70)); 2337 AppendCluster(GenerateSingleStreamCluster(500, 570, kVideoTrackNum, 70)); 2338 2339 CheckExpectedRanges("{ [0,23) [320,400) [520,570) }"); 2340 2341 // Audio: 720 -> 750 2342 // Video: 700 -> 770 2343 // Buffered Range: 720 -> 750 (complete overlap, audio) 2344 AppendCluster(GenerateSingleStreamCluster(720, 750, kAudioTrackNum, 30)); 2345 AppendCluster(GenerateSingleStreamCluster(700, 770, kVideoTrackNum, 70)); 2346 2347 CheckExpectedRanges("{ [0,23) [320,400) [520,570) [720,750) }"); 2348 2349 // Audio: 900 -> 970 2350 // Video: 920 -> 950 2351 // Buffered Range: 920 -> 950 (complete overlap, video) 2352 AppendCluster(GenerateSingleStreamCluster(900, 970, kAudioTrackNum, 70)); 2353 AppendCluster(GenerateSingleStreamCluster(920, 950, kVideoTrackNum, 30)); 2354 2355 CheckExpectedRanges("{ [0,23) [320,400) [520,570) [720,750) [920,950) }"); 2356 2357 // Appending within buffered range should not affect buffered ranges. 2358 AppendCluster(GenerateSingleStreamCluster(930, 950, kAudioTrackNum, 20)); 2359 CheckExpectedRanges("{ [0,23) [320,400) [520,570) [720,750) [920,950) }"); 2360 2361 // Appending to single stream outside buffered ranges should not affect 2362 // buffered ranges. 2363 AppendCluster(GenerateSingleStreamCluster(1230, 1240, kVideoTrackNum, 10)); 2364 CheckExpectedRanges("{ [0,23) [320,400) [520,570) [720,750) [920,950) }"); 2365 } 2366 2367 TEST_F(ChunkDemuxerTest, GetBufferedRanges_AudioVideoText) { 2368 EXPECT_CALL(host_, AddTextStream(_, _)); 2369 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO | HAS_TEXT)); 2370 2371 // Append audio & video data 2372 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, "0K 23"); 2373 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "0K 33"); 2374 2375 // Verify that a text track with no cues does not result in an empty buffered 2376 // range. 2377 CheckExpectedRanges("{ [0,46) }"); 2378 2379 // Add some text cues. 2380 AppendSingleStreamCluster(kSourceId, kTextTrackNum, "0K 100K"); 2381 2382 // Verify that the new cues did not affect the buffered ranges. 2383 CheckExpectedRanges("{ [0,46) }"); 2384 2385 // Remove the buffered range. 2386 demuxer_->Remove(kSourceId, base::TimeDelta(), 2387 base::TimeDelta::FromMilliseconds(46)); 2388 CheckExpectedRanges("{ }"); 2389 } 2390 2391 // Once MarkEndOfStream() is called, GetBufferedRanges should not cut off any 2392 // over-hanging tails at the end of the ranges as this is likely due to block 2393 // duration differences. 2394 TEST_F(ChunkDemuxerTest, GetBufferedRanges_EndOfStream) { 2395 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 2396 2397 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, "0K 23K"); 2398 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "0K 33"); 2399 2400 CheckExpectedRanges("{ [0,46) }"); 2401 2402 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(66))); 2403 MarkEndOfStream(PIPELINE_OK); 2404 2405 // Verify that the range extends to the end of the video data. 2406 CheckExpectedRanges("{ [0,66) }"); 2407 2408 // Verify that the range reverts to the intersection when end of stream 2409 // has been cancelled. 2410 demuxer_->UnmarkEndOfStream(); 2411 CheckExpectedRanges("{ [0,46) }"); 2412 2413 // Append and remove data so that the 2 streams' end ranges do not overlap. 2414 2415 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(246))); 2416 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(398))); 2417 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, "200K 223K"); 2418 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, 2419 "200K 233 266 299 332K 365"); 2420 2421 // At this point, the per-stream ranges are as follows: 2422 // Audio: [0,46) [200,246) 2423 // Video: [0,66) [200,398) 2424 CheckExpectedRanges("{ [0,46) [200,246) }"); 2425 2426 demuxer_->Remove(kSourceId, base::TimeDelta::FromMilliseconds(200), 2427 base::TimeDelta::FromMilliseconds(300)); 2428 2429 // At this point, the per-stream ranges are as follows: 2430 // Audio: [0,46) 2431 // Video: [0,66) [332,398) 2432 CheckExpectedRanges("{ [0,46) }"); 2433 2434 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, "200K 223K"); 2435 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "200K 233"); 2436 2437 // At this point, the per-stream ranges are as follows: 2438 // Audio: [0,46) [200,246) 2439 // Video: [0,66) [200,266) [332,398) 2440 // NOTE: The last range on each stream do not overlap in time. 2441 CheckExpectedRanges("{ [0,46) [200,246) }"); 2442 2443 MarkEndOfStream(PIPELINE_OK); 2444 2445 // NOTE: The last range on each stream gets extended to the highest 2446 // end timestamp according to the spec. The last audio range gets extended 2447 // from [200,246) to [200,398) which is why the intersection results in the 2448 // middle range getting larger AND the new range appearing. 2449 CheckExpectedRanges("{ [0,46) [200,266) [332,398) }"); 2450 } 2451 2452 TEST_F(ChunkDemuxerTest, DifferentStreamTimecodes) { 2453 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 2454 2455 // Create a cluster where the video timecode begins 25ms after the audio. 2456 AppendCluster(GenerateCluster(0, 25, 8)); 2457 2458 Seek(base::TimeDelta::FromSeconds(0)); 2459 GenerateExpectedReads(0, 25, 8); 2460 2461 // Seek to 5 seconds. 2462 Seek(base::TimeDelta::FromSeconds(5)); 2463 2464 // Generate a cluster to fulfill this seek, where audio timecode begins 25ms 2465 // after the video. 2466 AppendCluster(GenerateCluster(5025, 5000, 8)); 2467 GenerateExpectedReads(5025, 5000, 8); 2468 } 2469 2470 TEST_F(ChunkDemuxerTest, DifferentStreamTimecodesSeparateSources) { 2471 std::string audio_id = "audio1"; 2472 std::string video_id = "video1"; 2473 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id)); 2474 2475 // Generate two streams where the video stream starts 5ms after the audio 2476 // stream and append them. 2477 AppendCluster(audio_id, GenerateSingleStreamCluster( 2478 25, 4 * kAudioBlockDuration + 25, kAudioTrackNum, kAudioBlockDuration)); 2479 AppendCluster(video_id, GenerateSingleStreamCluster( 2480 30, 4 * kVideoBlockDuration + 30, kVideoTrackNum, kVideoBlockDuration)); 2481 2482 // Both streams should be able to fulfill a seek to 25. 2483 Seek(base::TimeDelta::FromMilliseconds(25)); 2484 GenerateAudioStreamExpectedReads(25, 4); 2485 GenerateVideoStreamExpectedReads(30, 4); 2486 } 2487 2488 TEST_F(ChunkDemuxerTest, DifferentStreamTimecodesOutOfRange) { 2489 std::string audio_id = "audio1"; 2490 std::string video_id = "video1"; 2491 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id)); 2492 2493 // Generate two streams where the video stream starts 10s after the audio 2494 // stream and append them. 2495 AppendCluster(audio_id, GenerateSingleStreamCluster(0, 2496 4 * kAudioBlockDuration + 0, kAudioTrackNum, kAudioBlockDuration)); 2497 AppendCluster(video_id, GenerateSingleStreamCluster(10000, 2498 4 * kVideoBlockDuration + 10000, kVideoTrackNum, kVideoBlockDuration)); 2499 2500 // Should not be able to fulfill a seek to 0. 2501 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(0); 2502 demuxer_->StartWaitingForSeek(seek_time); 2503 demuxer_->Seek(seek_time, 2504 NewExpectedStatusCB(PIPELINE_ERROR_ABORT)); 2505 ExpectRead(DemuxerStream::AUDIO, 0); 2506 ExpectEndOfStream(DemuxerStream::VIDEO); 2507 } 2508 2509 TEST_F(ChunkDemuxerTest, ClusterWithNoBuffers) { 2510 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 2511 2512 // Generate and append an empty cluster beginning at 0. 2513 AppendEmptyCluster(0); 2514 2515 // Sanity check that data can be appended after this cluster correctly. 2516 AppendCluster(GenerateCluster(0, 2)); 2517 ExpectRead(DemuxerStream::AUDIO, 0); 2518 ExpectRead(DemuxerStream::VIDEO, 0); 2519 } 2520 2521 TEST_F(ChunkDemuxerTest, CodecPrefixMatching) { 2522 ChunkDemuxer::Status expected = ChunkDemuxer::kNotSupported; 2523 2524 #if defined(USE_PROPRIETARY_CODECS) 2525 expected = ChunkDemuxer::kOk; 2526 #endif 2527 2528 std::vector<std::string> codecs; 2529 codecs.push_back("avc1.4D4041"); 2530 2531 EXPECT_EQ(demuxer_->AddId("source_id", "video/mp4", codecs), expected); 2532 } 2533 2534 // Test codec ID's that are not compliant with RFC6381, but have been 2535 // seen in the wild. 2536 TEST_F(ChunkDemuxerTest, CodecIDsThatAreNotRFC6381Compliant) { 2537 ChunkDemuxer::Status expected = ChunkDemuxer::kNotSupported; 2538 2539 #if defined(USE_PROPRIETARY_CODECS) 2540 expected = ChunkDemuxer::kOk; 2541 #endif 2542 const char* codec_ids[] = { 2543 // GPAC places leading zeros on the audio object type. 2544 "mp4a.40.02", 2545 "mp4a.40.05" 2546 }; 2547 2548 for (size_t i = 0; i < arraysize(codec_ids); ++i) { 2549 std::vector<std::string> codecs; 2550 codecs.push_back(codec_ids[i]); 2551 2552 ChunkDemuxer::Status result = 2553 demuxer_->AddId("source_id", "audio/mp4", codecs); 2554 2555 EXPECT_EQ(result, expected) 2556 << "Fail to add codec_id '" << codec_ids[i] << "'"; 2557 2558 if (result == ChunkDemuxer::kOk) 2559 demuxer_->RemoveId("source_id"); 2560 } 2561 } 2562 2563 TEST_F(ChunkDemuxerTest, EndOfStreamStillSetAfterSeek) { 2564 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 2565 2566 EXPECT_CALL(host_, SetDuration(_)) 2567 .Times(AnyNumber()); 2568 2569 base::TimeDelta kLastAudioTimestamp = base::TimeDelta::FromMilliseconds(92); 2570 base::TimeDelta kLastVideoTimestamp = base::TimeDelta::FromMilliseconds(99); 2571 2572 AppendCluster(kDefaultFirstCluster()); 2573 AppendCluster(kDefaultSecondCluster()); 2574 MarkEndOfStream(PIPELINE_OK); 2575 2576 DemuxerStream::Status status; 2577 base::TimeDelta last_timestamp; 2578 2579 // Verify that we can read audio & video to the end w/o problems. 2580 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp); 2581 EXPECT_EQ(DemuxerStream::kOk, status); 2582 EXPECT_EQ(kLastAudioTimestamp, last_timestamp); 2583 2584 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp); 2585 EXPECT_EQ(DemuxerStream::kOk, status); 2586 EXPECT_EQ(kLastVideoTimestamp, last_timestamp); 2587 2588 // Seek back to 0 and verify that we can read to the end again.. 2589 Seek(base::TimeDelta::FromMilliseconds(0)); 2590 2591 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp); 2592 EXPECT_EQ(DemuxerStream::kOk, status); 2593 EXPECT_EQ(kLastAudioTimestamp, last_timestamp); 2594 2595 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp); 2596 EXPECT_EQ(DemuxerStream::kOk, status); 2597 EXPECT_EQ(kLastVideoTimestamp, last_timestamp); 2598 } 2599 2600 TEST_F(ChunkDemuxerTest, GetBufferedRangesBeforeInitSegment) { 2601 EXPECT_CALL(*this, DemuxerOpened()); 2602 demuxer_->Initialize(&host_, CreateInitDoneCB(PIPELINE_OK), true); 2603 ASSERT_EQ(AddId("audio", HAS_AUDIO), ChunkDemuxer::kOk); 2604 ASSERT_EQ(AddId("video", HAS_VIDEO), ChunkDemuxer::kOk); 2605 2606 CheckExpectedRanges("audio", "{ }"); 2607 CheckExpectedRanges("video", "{ }"); 2608 } 2609 2610 // Test that Seek() completes successfully when the first cluster 2611 // arrives. 2612 TEST_F(ChunkDemuxerTest, EndOfStreamDuringSeek) { 2613 InSequence s; 2614 2615 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 2616 2617 AppendCluster(kDefaultFirstCluster()); 2618 2619 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(0); 2620 demuxer_->StartWaitingForSeek(seek_time); 2621 2622 AppendCluster(kDefaultSecondCluster()); 2623 EXPECT_CALL(host_, SetDuration( 2624 base::TimeDelta::FromMilliseconds(kDefaultSecondClusterEndTimestamp))); 2625 MarkEndOfStream(PIPELINE_OK); 2626 2627 demuxer_->Seek(seek_time, NewExpectedStatusCB(PIPELINE_OK)); 2628 2629 GenerateExpectedReads(0, 4); 2630 GenerateExpectedReads(46, 66, 5); 2631 2632 EndOfStreamHelper end_of_stream_helper(demuxer_.get()); 2633 end_of_stream_helper.RequestReads(); 2634 end_of_stream_helper.CheckIfReadDonesWereCalled(true); 2635 } 2636 2637 TEST_F(ChunkDemuxerTest, ConfigChange_Video) { 2638 InSequence s; 2639 2640 ASSERT_TRUE(InitDemuxerWithConfigChangeData()); 2641 2642 DemuxerStream::Status status; 2643 base::TimeDelta last_timestamp; 2644 2645 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO); 2646 2647 // Fetch initial video config and verify it matches what we expect. 2648 const VideoDecoderConfig& video_config_1 = video->video_decoder_config(); 2649 ASSERT_TRUE(video_config_1.IsValidConfig()); 2650 EXPECT_EQ(video_config_1.natural_size().width(), 320); 2651 EXPECT_EQ(video_config_1.natural_size().height(), 240); 2652 2653 ExpectRead(DemuxerStream::VIDEO, 0); 2654 2655 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp); 2656 2657 ASSERT_EQ(status, DemuxerStream::kConfigChanged); 2658 EXPECT_EQ(last_timestamp.InMilliseconds(), 501); 2659 2660 // Fetch the new decoder config. 2661 const VideoDecoderConfig& video_config_2 = video->video_decoder_config(); 2662 ASSERT_TRUE(video_config_2.IsValidConfig()); 2663 EXPECT_EQ(video_config_2.natural_size().width(), 640); 2664 EXPECT_EQ(video_config_2.natural_size().height(), 360); 2665 2666 ExpectRead(DemuxerStream::VIDEO, 527); 2667 2668 // Read until the next config change. 2669 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp); 2670 ASSERT_EQ(status, DemuxerStream::kConfigChanged); 2671 EXPECT_EQ(last_timestamp.InMilliseconds(), 793); 2672 2673 // Get the new config and verify that it matches the first one. 2674 ASSERT_TRUE(video_config_1.Matches(video->video_decoder_config())); 2675 2676 ExpectRead(DemuxerStream::VIDEO, 801); 2677 2678 // Read until the end of the stream just to make sure there aren't any other 2679 // config changes. 2680 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp); 2681 ASSERT_EQ(status, DemuxerStream::kOk); 2682 } 2683 2684 TEST_F(ChunkDemuxerTest, ConfigChange_Audio) { 2685 InSequence s; 2686 2687 ASSERT_TRUE(InitDemuxerWithConfigChangeData()); 2688 2689 DemuxerStream::Status status; 2690 base::TimeDelta last_timestamp; 2691 2692 DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO); 2693 2694 // Fetch initial audio config and verify it matches what we expect. 2695 const AudioDecoderConfig& audio_config_1 = audio->audio_decoder_config(); 2696 ASSERT_TRUE(audio_config_1.IsValidConfig()); 2697 EXPECT_EQ(audio_config_1.samples_per_second(), 44100); 2698 EXPECT_EQ(audio_config_1.extra_data_size(), 3863u); 2699 2700 ExpectRead(DemuxerStream::AUDIO, 0); 2701 2702 // The first config change seen is from a splice frame representing an overlap 2703 // of buffer from config 1 by buffers from config 2. 2704 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp); 2705 ASSERT_EQ(status, DemuxerStream::kConfigChanged); 2706 EXPECT_EQ(last_timestamp.InMilliseconds(), 524); 2707 2708 // Fetch the new decoder config. 2709 const AudioDecoderConfig& audio_config_2 = audio->audio_decoder_config(); 2710 ASSERT_TRUE(audio_config_2.IsValidConfig()); 2711 EXPECT_EQ(audio_config_2.samples_per_second(), 44100); 2712 EXPECT_EQ(audio_config_2.extra_data_size(), 3935u); 2713 2714 // The next config change is from a splice frame representing an overlap of 2715 // buffers from config 2 by buffers from config 1. 2716 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp); 2717 ASSERT_EQ(status, DemuxerStream::kConfigChanged); 2718 EXPECT_EQ(last_timestamp.InMilliseconds(), 782); 2719 ASSERT_TRUE(audio_config_1.Matches(audio->audio_decoder_config())); 2720 2721 // Read until the end of the stream just to make sure there aren't any other 2722 // config changes. 2723 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp); 2724 ASSERT_EQ(status, DemuxerStream::kOk); 2725 EXPECT_EQ(last_timestamp.InMilliseconds(), 2744); 2726 } 2727 2728 TEST_F(ChunkDemuxerTest, ConfigChange_Seek) { 2729 InSequence s; 2730 2731 ASSERT_TRUE(InitDemuxerWithConfigChangeData()); 2732 2733 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO); 2734 2735 // Fetch initial video config and verify it matches what we expect. 2736 const VideoDecoderConfig& video_config_1 = video->video_decoder_config(); 2737 ASSERT_TRUE(video_config_1.IsValidConfig()); 2738 EXPECT_EQ(video_config_1.natural_size().width(), 320); 2739 EXPECT_EQ(video_config_1.natural_size().height(), 240); 2740 2741 ExpectRead(DemuxerStream::VIDEO, 0); 2742 2743 // Seek to a location with a different config. 2744 Seek(base::TimeDelta::FromMilliseconds(527)); 2745 2746 // Verify that the config change is signalled. 2747 ExpectConfigChanged(DemuxerStream::VIDEO); 2748 2749 // Fetch the new decoder config and verify it is what we expect. 2750 const VideoDecoderConfig& video_config_2 = video->video_decoder_config(); 2751 ASSERT_TRUE(video_config_2.IsValidConfig()); 2752 EXPECT_EQ(video_config_2.natural_size().width(), 640); 2753 EXPECT_EQ(video_config_2.natural_size().height(), 360); 2754 2755 // Verify that Read() will return a buffer now. 2756 ExpectRead(DemuxerStream::VIDEO, 527); 2757 2758 // Seek back to the beginning and verify we get another config change. 2759 Seek(base::TimeDelta::FromMilliseconds(0)); 2760 ExpectConfigChanged(DemuxerStream::VIDEO); 2761 ASSERT_TRUE(video_config_1.Matches(video->video_decoder_config())); 2762 ExpectRead(DemuxerStream::VIDEO, 0); 2763 2764 // Seek to a location that requires a config change and then 2765 // seek to a new location that has the same configuration as 2766 // the start of the file without a Read() in the middle. 2767 Seek(base::TimeDelta::FromMilliseconds(527)); 2768 Seek(base::TimeDelta::FromMilliseconds(801)); 2769 2770 // Verify that no config change is signalled. 2771 ExpectRead(DemuxerStream::VIDEO, 801); 2772 ASSERT_TRUE(video_config_1.Matches(video->video_decoder_config())); 2773 } 2774 2775 TEST_F(ChunkDemuxerTest, TimestampPositiveOffset) { 2776 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 2777 2778 ASSERT_TRUE(SetTimestampOffset(kSourceId, base::TimeDelta::FromSeconds(30))); 2779 AppendCluster(GenerateCluster(0, 2)); 2780 2781 Seek(base::TimeDelta::FromMilliseconds(30000)); 2782 2783 GenerateExpectedReads(30000, 2); 2784 } 2785 2786 TEST_F(ChunkDemuxerTest, TimestampNegativeOffset) { 2787 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 2788 2789 ASSERT_TRUE(SetTimestampOffset(kSourceId, base::TimeDelta::FromSeconds(-1))); 2790 AppendCluster(GenerateCluster(1000, 2)); 2791 2792 GenerateExpectedReads(0, 2); 2793 } 2794 2795 TEST_F(ChunkDemuxerTest, TimestampOffsetSeparateStreams) { 2796 std::string audio_id = "audio1"; 2797 std::string video_id = "video1"; 2798 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id)); 2799 2800 ASSERT_TRUE(SetTimestampOffset( 2801 audio_id, base::TimeDelta::FromMilliseconds(-2500))); 2802 ASSERT_TRUE(SetTimestampOffset( 2803 video_id, base::TimeDelta::FromMilliseconds(-2500))); 2804 AppendCluster(audio_id, GenerateSingleStreamCluster(2500, 2805 2500 + kAudioBlockDuration * 4, kAudioTrackNum, kAudioBlockDuration)); 2806 AppendCluster(video_id, GenerateSingleStreamCluster(2500, 2807 2500 + kVideoBlockDuration * 4, kVideoTrackNum, kVideoBlockDuration)); 2808 GenerateAudioStreamExpectedReads(0, 4); 2809 GenerateVideoStreamExpectedReads(0, 4); 2810 2811 Seek(base::TimeDelta::FromMilliseconds(27300)); 2812 2813 ASSERT_TRUE(SetTimestampOffset( 2814 audio_id, base::TimeDelta::FromMilliseconds(27300))); 2815 ASSERT_TRUE(SetTimestampOffset( 2816 video_id, base::TimeDelta::FromMilliseconds(27300))); 2817 AppendCluster(audio_id, GenerateSingleStreamCluster( 2818 0, kAudioBlockDuration * 4, kAudioTrackNum, kAudioBlockDuration)); 2819 AppendCluster(video_id, GenerateSingleStreamCluster( 2820 0, kVideoBlockDuration * 4, kVideoTrackNum, kVideoBlockDuration)); 2821 GenerateVideoStreamExpectedReads(27300, 4); 2822 GenerateAudioStreamExpectedReads(27300, 4); 2823 } 2824 2825 TEST_F(ChunkDemuxerTest, IsParsingMediaSegmentMidMediaSegment) { 2826 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 2827 2828 scoped_ptr<Cluster> cluster = GenerateCluster(0, 2); 2829 // Append only part of the cluster data. 2830 AppendData(cluster->data(), cluster->size() - 13); 2831 2832 // Confirm we're in the middle of parsing a media segment. 2833 ASSERT_TRUE(demuxer_->IsParsingMediaSegment(kSourceId)); 2834 2835 demuxer_->Abort(kSourceId, 2836 append_window_start_for_next_append_, 2837 append_window_end_for_next_append_, 2838 ×tamp_offset_map_[kSourceId]); 2839 2840 // After Abort(), parsing should no longer be in the middle of a media 2841 // segment. 2842 ASSERT_FALSE(demuxer_->IsParsingMediaSegment(kSourceId)); 2843 } 2844 2845 #if defined(USE_PROPRIETARY_CODECS) 2846 #if defined(ENABLE_MPEG2TS_STREAM_PARSER) 2847 TEST_F(ChunkDemuxerTest, EmitBuffersDuringAbort) { 2848 EXPECT_CALL(*this, DemuxerOpened()); 2849 demuxer_->Initialize( 2850 &host_, CreateInitDoneCB(kInfiniteDuration(), PIPELINE_OK), true); 2851 EXPECT_EQ(ChunkDemuxer::kOk, AddIdForMp2tSource(kSourceId)); 2852 2853 // For info: 2854 // DTS/PTS derived using dvbsnoop -s ts -if bear-1280x720.ts -tssubdecode 2855 // Video: first PES: 2856 // PTS: 126912 (0x0001efc0) [= 90 kHz-Timestamp: 0:00:01.4101] 2857 // DTS: 123909 (0x0001e405) [= 90 kHz-Timestamp: 0:00:01.3767] 2858 // Audio: first PES: 2859 // PTS: 126000 (0x0001ec30) [= 90 kHz-Timestamp: 0:00:01.4000] 2860 // DTS: 123910 (0x0001e406) [= 90 kHz-Timestamp: 0:00:01.3767] 2861 // Video: last PES: 2862 // PTS: 370155 (0x0005a5eb) [= 90 kHz-Timestamp: 0:00:04.1128] 2863 // DTS: 367152 (0x00059a30) [= 90 kHz-Timestamp: 0:00:04.0794] 2864 // Audio: last PES: 2865 // PTS: 353788 (0x000565fc) [= 90 kHz-Timestamp: 0:00:03.9309] 2866 2867 scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile("bear-1280x720.ts"); 2868 AppendData(kSourceId, buffer->data(), buffer->data_size()); 2869 2870 // Confirm we're in the middle of parsing a media segment. 2871 ASSERT_TRUE(demuxer_->IsParsingMediaSegment(kSourceId)); 2872 2873 // Abort on the Mpeg2 TS parser triggers the emission of the last video 2874 // buffer which is pending in the stream parser. 2875 Ranges<base::TimeDelta> range_before_abort = 2876 demuxer_->GetBufferedRanges(kSourceId); 2877 demuxer_->Abort(kSourceId, 2878 append_window_start_for_next_append_, 2879 append_window_end_for_next_append_, 2880 ×tamp_offset_map_[kSourceId]); 2881 Ranges<base::TimeDelta> range_after_abort = 2882 demuxer_->GetBufferedRanges(kSourceId); 2883 2884 ASSERT_EQ(range_before_abort.size(), 1u); 2885 ASSERT_EQ(range_after_abort.size(), 1u); 2886 EXPECT_EQ(range_after_abort.start(0), range_before_abort.start(0)); 2887 EXPECT_GT(range_after_abort.end(0), range_before_abort.end(0)); 2888 } 2889 #endif 2890 #endif 2891 2892 TEST_F(ChunkDemuxerTest, WebMIsParsingMediaSegmentDetection) { 2893 const uint8 kBuffer[] = { 2894 0x1F, 0x43, 0xB6, 0x75, 0x83, // CLUSTER (size = 3) 2895 0xE7, 0x81, 0x01, // Cluster TIMECODE (value = 1) 2896 2897 0x1F, 0x43, 0xB6, 0x75, 0xFF, // CLUSTER (size = unknown; really 3 due to:) 2898 0xE7, 0x81, 0x02, // Cluster TIMECODE (value = 2) 2899 /* e.g. put some blocks here... */ 2900 0x1A, 0x45, 0xDF, 0xA3, 0x8A, // EBMLHEADER (size = 10, not fully appended) 2901 }; 2902 2903 // This array indicates expected return value of IsParsingMediaSegment() 2904 // following each incrementally appended byte in |kBuffer|. 2905 const bool kExpectedReturnValues[] = { 2906 false, false, false, false, true, 2907 true, true, false, 2908 2909 false, false, false, false, true, 2910 true, true, true, 2911 2912 true, true, true, true, false, 2913 }; 2914 2915 COMPILE_ASSERT(arraysize(kBuffer) == arraysize(kExpectedReturnValues), 2916 test_arrays_out_of_sync); 2917 COMPILE_ASSERT(arraysize(kBuffer) == sizeof(kBuffer), not_one_byte_per_index); 2918 2919 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 2920 2921 for (size_t i = 0; i < sizeof(kBuffer); i++) { 2922 DVLOG(3) << "Appending and testing index " << i; 2923 AppendData(kBuffer + i, 1); 2924 bool expected_return_value = kExpectedReturnValues[i]; 2925 EXPECT_EQ(expected_return_value, 2926 demuxer_->IsParsingMediaSegment(kSourceId)); 2927 } 2928 } 2929 2930 TEST_F(ChunkDemuxerTest, DurationChange) { 2931 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 2932 const int kStreamDuration = kDefaultDuration().InMilliseconds(); 2933 2934 // Add data leading up to the currently set duration. 2935 AppendCluster(GenerateCluster(kStreamDuration - kAudioBlockDuration, 2936 kStreamDuration - kVideoBlockDuration, 2937 2)); 2938 2939 CheckExpectedRanges(kSourceId, "{ [201191,201224) }"); 2940 2941 // Add data beginning at the currently set duration and expect a new duration 2942 // to be signaled. Note that the last video block will have a higher end 2943 // timestamp than the last audio block. 2944 const int kNewStreamDurationVideo = kStreamDuration + kVideoBlockDuration; 2945 EXPECT_CALL(host_, SetDuration( 2946 base::TimeDelta::FromMilliseconds(kNewStreamDurationVideo))); 2947 AppendCluster(GenerateCluster(kDefaultDuration().InMilliseconds(), 2)); 2948 2949 CheckExpectedRanges(kSourceId, "{ [201191,201247) }"); 2950 2951 // Add more data to the end of each media type. Note that the last audio block 2952 // will have a higher end timestamp than the last video block. 2953 const int kFinalStreamDuration = kStreamDuration + kAudioBlockDuration * 3; 2954 EXPECT_CALL(host_, SetDuration( 2955 base::TimeDelta::FromMilliseconds(kFinalStreamDuration))); 2956 AppendCluster(GenerateCluster(kStreamDuration + kAudioBlockDuration, 2957 kStreamDuration + kVideoBlockDuration, 2958 3)); 2959 2960 // See that the range has increased appropriately (but not to the full 2961 // duration of 201293, since there is not enough video appended for that). 2962 CheckExpectedRanges(kSourceId, "{ [201191,201290) }"); 2963 } 2964 2965 TEST_F(ChunkDemuxerTest, DurationChangeTimestampOffset) { 2966 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 2967 ASSERT_TRUE(SetTimestampOffset(kSourceId, kDefaultDuration())); 2968 EXPECT_CALL(host_, SetDuration( 2969 kDefaultDuration() + base::TimeDelta::FromMilliseconds( 2970 kVideoBlockDuration * 2))); 2971 AppendCluster(GenerateCluster(0, 4)); 2972 } 2973 2974 TEST_F(ChunkDemuxerTest, EndOfStreamTruncateDuration) { 2975 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 2976 2977 AppendCluster(kDefaultFirstCluster()); 2978 2979 EXPECT_CALL(host_, SetDuration( 2980 base::TimeDelta::FromMilliseconds(kDefaultFirstClusterEndTimestamp))); 2981 MarkEndOfStream(PIPELINE_OK); 2982 } 2983 2984 2985 TEST_F(ChunkDemuxerTest, ZeroLengthAppend) { 2986 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 2987 AppendData(NULL, 0); 2988 } 2989 2990 TEST_F(ChunkDemuxerTest, AppendAfterEndOfStream) { 2991 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 2992 2993 EXPECT_CALL(host_, SetDuration(_)) 2994 .Times(AnyNumber()); 2995 2996 AppendCluster(kDefaultFirstCluster()); 2997 MarkEndOfStream(PIPELINE_OK); 2998 2999 demuxer_->UnmarkEndOfStream(); 3000 3001 AppendCluster(kDefaultSecondCluster()); 3002 MarkEndOfStream(PIPELINE_OK); 3003 } 3004 3005 // Test receiving a Shutdown() call before we get an Initialize() 3006 // call. This can happen if video element gets destroyed before 3007 // the pipeline has a chance to initialize the demuxer. 3008 TEST_F(ChunkDemuxerTest, Shutdown_BeforeInitialize) { 3009 demuxer_->Shutdown(); 3010 demuxer_->Initialize( 3011 &host_, CreateInitDoneCB(DEMUXER_ERROR_COULD_NOT_OPEN), true); 3012 message_loop_.RunUntilIdle(); 3013 } 3014 3015 // Verifies that signaling end of stream while stalled at a gap 3016 // boundary does not trigger end of stream buffers to be returned. 3017 TEST_F(ChunkDemuxerTest, EndOfStreamWhileWaitingForGapToBeFilled) { 3018 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 3019 3020 AppendCluster(0, 10); 3021 AppendCluster(300, 10); 3022 CheckExpectedRanges(kSourceId, "{ [0,132) [300,432) }"); 3023 3024 GenerateExpectedReads(0, 10); 3025 3026 bool audio_read_done = false; 3027 bool video_read_done = false; 3028 ReadAudio(base::Bind(&OnReadDone, 3029 base::TimeDelta::FromMilliseconds(138), 3030 &audio_read_done)); 3031 ReadVideo(base::Bind(&OnReadDone, 3032 base::TimeDelta::FromMilliseconds(138), 3033 &video_read_done)); 3034 3035 // Verify that the reads didn't complete 3036 EXPECT_FALSE(audio_read_done); 3037 EXPECT_FALSE(video_read_done); 3038 3039 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(438))); 3040 MarkEndOfStream(PIPELINE_OK); 3041 3042 // Verify that the reads still haven't completed. 3043 EXPECT_FALSE(audio_read_done); 3044 EXPECT_FALSE(video_read_done); 3045 3046 demuxer_->UnmarkEndOfStream(); 3047 3048 AppendCluster(138, 22); 3049 3050 message_loop_.RunUntilIdle(); 3051 3052 CheckExpectedRanges(kSourceId, "{ [0,435) }"); 3053 3054 // Verify that the reads have completed. 3055 EXPECT_TRUE(audio_read_done); 3056 EXPECT_TRUE(video_read_done); 3057 3058 // Read the rest of the buffers. 3059 GenerateExpectedReads(161, 171, 20); 3060 3061 // Verify that reads block because the append cleared the end of stream state. 3062 audio_read_done = false; 3063 video_read_done = false; 3064 ReadAudio(base::Bind(&OnReadDone_EOSExpected, 3065 &audio_read_done)); 3066 ReadVideo(base::Bind(&OnReadDone_EOSExpected, 3067 &video_read_done)); 3068 3069 // Verify that the reads don't complete. 3070 EXPECT_FALSE(audio_read_done); 3071 EXPECT_FALSE(video_read_done); 3072 3073 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(437))); 3074 MarkEndOfStream(PIPELINE_OK); 3075 3076 EXPECT_TRUE(audio_read_done); 3077 EXPECT_TRUE(video_read_done); 3078 } 3079 3080 TEST_F(ChunkDemuxerTest, CanceledSeekDuringInitialPreroll) { 3081 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 3082 3083 // Cancel preroll. 3084 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(200); 3085 demuxer_->CancelPendingSeek(seek_time); 3086 3087 // Initiate the seek to the new location. 3088 Seek(seek_time); 3089 3090 // Append data to satisfy the seek. 3091 AppendCluster(seek_time.InMilliseconds(), 10); 3092 } 3093 3094 TEST_F(ChunkDemuxerTest, GCDuringSeek) { 3095 ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); 3096 3097 demuxer_->SetMemoryLimitsForTesting(5 * kBlockSize); 3098 3099 base::TimeDelta seek_time1 = base::TimeDelta::FromMilliseconds(1000); 3100 base::TimeDelta seek_time2 = base::TimeDelta::FromMilliseconds(500); 3101 3102 // Initiate a seek to |seek_time1|. 3103 Seek(seek_time1); 3104 3105 // Append data to satisfy the first seek request. 3106 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 3107 seek_time1.InMilliseconds(), 5); 3108 CheckExpectedRanges(kSourceId, "{ [1000,1115) }"); 3109 3110 // Signal that the second seek is starting. 3111 demuxer_->StartWaitingForSeek(seek_time2); 3112 3113 // Append data to satisfy the second seek. This append triggers 3114 // the garbage collection logic since we set the memory limit to 3115 // 5 blocks. 3116 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 3117 seek_time2.InMilliseconds(), 5); 3118 3119 // Verify that the buffers that cover |seek_time2| do not get 3120 // garbage collected. 3121 CheckExpectedRanges(kSourceId, "{ [500,615) }"); 3122 3123 // Complete the seek. 3124 demuxer_->Seek(seek_time2, NewExpectedStatusCB(PIPELINE_OK)); 3125 3126 3127 // Append more data and make sure that the blocks for |seek_time2| 3128 // don't get removed. 3129 // 3130 // NOTE: The current GC algorithm tries to preserve the GOP at the 3131 // current position as well as the last appended GOP. This is 3132 // why there are 2 ranges in the expectations. 3133 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 700, 5); 3134 CheckExpectedRanges(kSourceId, "{ [500,592) [792,815) }"); 3135 } 3136 3137 TEST_F(ChunkDemuxerTest, AppendWindow_Video) { 3138 ASSERT_TRUE(InitDemuxer(HAS_VIDEO)); 3139 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO); 3140 3141 // Set the append window to [50,280). 3142 append_window_start_for_next_append_ = base::TimeDelta::FromMilliseconds(50); 3143 append_window_end_for_next_append_ = base::TimeDelta::FromMilliseconds(280); 3144 3145 // Append a cluster that starts before and ends after the append window. 3146 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, 3147 "0K 30 60 90 120K 150 180 210 240K 270 300 330K"); 3148 3149 // Verify that GOPs that start outside the window are not included 3150 // in the buffer. Also verify that buffers that start inside the 3151 // window and extend beyond the end of the window are not included. 3152 CheckExpectedRanges(kSourceId, "{ [120,270) }"); 3153 CheckExpectedBuffers(stream, "120 150 180 210 240"); 3154 3155 // Extend the append window to [50,650). 3156 append_window_end_for_next_append_ = base::TimeDelta::FromMilliseconds(650); 3157 3158 // Append more data and verify that adding buffers start at the next 3159 // keyframe. 3160 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, 3161 "360 390 420K 450 480 510 540K 570 600 630K"); 3162 CheckExpectedRanges(kSourceId, "{ [120,270) [420,630) }"); 3163 } 3164 3165 TEST_F(ChunkDemuxerTest, AppendWindow_Audio) { 3166 ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); 3167 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::AUDIO); 3168 3169 // Set the append window to [50,280). 3170 append_window_start_for_next_append_ = base::TimeDelta::FromMilliseconds(50); 3171 append_window_end_for_next_append_ = base::TimeDelta::FromMilliseconds(280); 3172 3173 // Append a cluster that starts before and ends after the append window. 3174 AppendSingleStreamCluster( 3175 kSourceId, kAudioTrackNum, 3176 "0K 30K 60K 90K 120K 150K 180K 210K 240K 270K 300K 330K"); 3177 3178 // Verify that frames that end outside the window are not included 3179 // in the buffer. Also verify that buffers that start inside the 3180 // window and extend beyond the end of the window are not included. 3181 // 3182 // The first 50ms of the range should be truncated since it overlaps 3183 // the start of the append window. 3184 CheckExpectedRanges(kSourceId, "{ [50,270) }"); 3185 3186 // The "50P" buffer is the "0" buffer marked for complete discard. The next 3187 // "50" buffer is the "30" buffer marked with 20ms of start discard. 3188 CheckExpectedBuffers(stream, "50P 50 60 90 120 150 180 210 240"); 3189 3190 // Extend the append window to [50,650). 3191 append_window_end_for_next_append_ = base::TimeDelta::FromMilliseconds(650); 3192 3193 // Append more data and verify that a new range is created. 3194 AppendSingleStreamCluster( 3195 kSourceId, kAudioTrackNum, 3196 "360K 390K 420K 450K 480K 510K 540K 570K 600K 630K"); 3197 CheckExpectedRanges(kSourceId, "{ [50,270) [360,630) }"); 3198 } 3199 3200 TEST_F(ChunkDemuxerTest, AppendWindow_AudioOverlapStartAndEnd) { 3201 ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); 3202 3203 // Set the append window to [10,20). 3204 append_window_start_for_next_append_ = base::TimeDelta::FromMilliseconds(10); 3205 append_window_end_for_next_append_ = base::TimeDelta::FromMilliseconds(20); 3206 3207 // Append a cluster that starts before and ends after the append window. 3208 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, "0K"); 3209 3210 // Verify that everything is dropped in this case. No partial append should 3211 // be generated. 3212 CheckExpectedRanges(kSourceId, "{ }"); 3213 } 3214 3215 TEST_F(ChunkDemuxerTest, AppendWindow_WebMFile_AudioOnly) { 3216 EXPECT_CALL(*this, DemuxerOpened()); 3217 demuxer_->Initialize( 3218 &host_, 3219 CreateInitDoneCB(base::TimeDelta::FromMilliseconds(2744), PIPELINE_OK), 3220 true); 3221 ASSERT_EQ(ChunkDemuxer::kOk, AddId(kSourceId, HAS_AUDIO)); 3222 3223 // Set the append window to [50,150). 3224 append_window_start_for_next_append_ = base::TimeDelta::FromMilliseconds(50); 3225 append_window_end_for_next_append_ = base::TimeDelta::FromMilliseconds(150); 3226 3227 // Read a WebM file into memory and send the data to the demuxer. The chunk 3228 // size has been chosen carefully to ensure the preroll buffer used by the 3229 // partial append window trim must come from a previous Append() call. 3230 scoped_refptr<DecoderBuffer> buffer = 3231 ReadTestDataFile("bear-320x240-audio-only.webm"); 3232 AppendDataInPieces(buffer->data(), buffer->data_size(), 128); 3233 3234 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::AUDIO); 3235 CheckExpectedBuffers(stream, "50P 50 62 86 109 122 125 128"); 3236 } 3237 3238 TEST_F(ChunkDemuxerTest, AppendWindow_AudioConfigUpdateRemovesPreroll) { 3239 EXPECT_CALL(*this, DemuxerOpened()); 3240 demuxer_->Initialize( 3241 &host_, 3242 CreateInitDoneCB(base::TimeDelta::FromMilliseconds(2744), PIPELINE_OK), 3243 true); 3244 ASSERT_EQ(ChunkDemuxer::kOk, AddId(kSourceId, HAS_AUDIO)); 3245 3246 // Set the append window such that the first file is completely before the 3247 // append window. 3248 // TODO(wolenetz/acolwell): Update this duration once the files are fixed to 3249 // have the correct duration in their init segments, and the 3250 // CreateInitDoneCB() call, above, is fixed to used that duration. See 3251 // http://crbug.com/354284. 3252 const base::TimeDelta duration_1 = base::TimeDelta::FromMilliseconds(2746); 3253 append_window_start_for_next_append_ = duration_1; 3254 3255 // Read a WebM file into memory and append the data. 3256 scoped_refptr<DecoderBuffer> buffer = 3257 ReadTestDataFile("bear-320x240-audio-only.webm"); 3258 AppendDataInPieces(buffer->data(), buffer->data_size(), 512); 3259 CheckExpectedRanges(kSourceId, "{ }"); 3260 3261 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::AUDIO); 3262 AudioDecoderConfig config_1 = stream->audio_decoder_config(); 3263 3264 // Read a second WebM with a different config in and append the data. 3265 scoped_refptr<DecoderBuffer> buffer2 = 3266 ReadTestDataFile("bear-320x240-audio-only-48khz.webm"); 3267 EXPECT_CALL(host_, SetDuration(_)).Times(AnyNumber()); 3268 ASSERT_TRUE(SetTimestampOffset(kSourceId, duration_1)); 3269 AppendDataInPieces(buffer2->data(), buffer2->data_size(), 512); 3270 CheckExpectedRanges(kSourceId, "{ [2746,5519) }"); 3271 3272 Seek(duration_1); 3273 ExpectConfigChanged(DemuxerStream::AUDIO); 3274 ASSERT_FALSE(config_1.Matches(stream->audio_decoder_config())); 3275 CheckExpectedBuffers(stream, "2746 2767 2789 2810"); 3276 } 3277 3278 TEST_F(ChunkDemuxerTest, AppendWindow_Text) { 3279 DemuxerStream* text_stream = NULL; 3280 EXPECT_CALL(host_, AddTextStream(_, _)) 3281 .WillOnce(SaveArg<0>(&text_stream)); 3282 ASSERT_TRUE(InitDemuxer(HAS_VIDEO | HAS_TEXT)); 3283 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO); 3284 3285 // Set the append window to [20,280). 3286 append_window_start_for_next_append_ = base::TimeDelta::FromMilliseconds(20); 3287 append_window_end_for_next_append_ = base::TimeDelta::FromMilliseconds(280); 3288 3289 // Append a cluster that starts before and ends after the append 3290 // window. 3291 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, 3292 "0K 30 60 90 120K 150 180 210 240K 270 300 330K"); 3293 AppendSingleStreamCluster(kSourceId, kTextTrackNum, "0K 100K 200K 300K"); 3294 3295 // Verify that text cues that start outside the window are not included 3296 // in the buffer. Also verify that cues that extend beyond the 3297 // window are not included. 3298 CheckExpectedRanges(kSourceId, "{ [120,270) }"); 3299 CheckExpectedBuffers(video_stream, "120 150 180 210 240"); 3300 CheckExpectedBuffers(text_stream, "100"); 3301 3302 // Extend the append window to [20,650). 3303 append_window_end_for_next_append_ = base::TimeDelta::FromMilliseconds(650); 3304 3305 // Append more data and verify that a new range is created. 3306 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, 3307 "360 390 420K 450 480 510 540K 570 600 630K"); 3308 AppendSingleStreamCluster(kSourceId, kTextTrackNum, "400K 500K 600K 700K"); 3309 CheckExpectedRanges(kSourceId, "{ [120,270) [420,630) }"); 3310 3311 // Seek to the new range and verify that the expected buffers are returned. 3312 Seek(base::TimeDelta::FromMilliseconds(420)); 3313 CheckExpectedBuffers(video_stream, "420 450 480 510 540 570 600"); 3314 CheckExpectedBuffers(text_stream, "400 500"); 3315 } 3316 3317 TEST_F(ChunkDemuxerTest, StartWaitingForSeekAfterParseError) { 3318 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 3319 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE)); 3320 AppendGarbage(); 3321 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(50); 3322 demuxer_->StartWaitingForSeek(seek_time); 3323 } 3324 3325 TEST_F(ChunkDemuxerTest, Remove_AudioVideoText) { 3326 DemuxerStream* text_stream = NULL; 3327 EXPECT_CALL(host_, AddTextStream(_, _)) 3328 .WillOnce(SaveArg<0>(&text_stream)); 3329 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO | HAS_TEXT)); 3330 3331 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO); 3332 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO); 3333 3334 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 3335 "0K 20K 40K 60K 80K 100K 120K 140K"); 3336 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, 3337 "0K 30 60 90 120K 150 180"); 3338 AppendSingleStreamCluster(kSourceId, kTextTrackNum, "0K 100K 200K"); 3339 3340 CheckExpectedBuffers(audio_stream, "0 20 40 60 80 100 120 140"); 3341 CheckExpectedBuffers(video_stream, "0 30 60 90 120 150 180"); 3342 CheckExpectedBuffers(text_stream, "0 100 200"); 3343 3344 // Remove the buffers that were added. 3345 demuxer_->Remove(kSourceId, base::TimeDelta(), 3346 base::TimeDelta::FromMilliseconds(300)); 3347 3348 // Verify that all the appended data has been removed. 3349 CheckExpectedRanges(kSourceId, "{ }"); 3350 3351 // Append new buffers that are clearly different than the original 3352 // ones and verify that only the new buffers are returned. 3353 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 3354 "1K 21K 41K 61K 81K 101K 121K 141K"); 3355 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, 3356 "1K 31 61 91 121K 151 181"); 3357 AppendSingleStreamCluster(kSourceId, kTextTrackNum, "1K 101K 201K"); 3358 3359 Seek(base::TimeDelta()); 3360 CheckExpectedBuffers(audio_stream, "1 21 41 61 81 101 121 141"); 3361 CheckExpectedBuffers(video_stream, "1 31 61 91 121 151 181"); 3362 CheckExpectedBuffers(text_stream, "1 101 201"); 3363 } 3364 3365 TEST_F(ChunkDemuxerTest, Remove_StartAtDuration) { 3366 ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); 3367 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO); 3368 3369 // Set the duration to something small so that the append that 3370 // follows updates the duration to reflect the end of the appended data. 3371 EXPECT_CALL(host_, SetDuration( 3372 base::TimeDelta::FromMilliseconds(1))); 3373 demuxer_->SetDuration(0.001); 3374 3375 EXPECT_CALL(host_, SetDuration( 3376 base::TimeDelta::FromMilliseconds(160))); 3377 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 3378 "0K 20K 40K 60K 80K 100K 120K 140K"); 3379 3380 CheckExpectedRanges(kSourceId, "{ [0,160) }"); 3381 CheckExpectedBuffers(audio_stream, "0 20 40 60 80 100 120 140"); 3382 3383 demuxer_->Remove(kSourceId, 3384 base::TimeDelta::FromSecondsD(demuxer_->GetDuration()), 3385 kInfiniteDuration()); 3386 3387 Seek(base::TimeDelta()); 3388 CheckExpectedRanges(kSourceId, "{ [0,160) }"); 3389 CheckExpectedBuffers(audio_stream, "0 20 40 60 80 100 120 140"); 3390 } 3391 3392 // Verifies that a Seek() will complete without text cues for 3393 // the seek point and will return cues after the seek position 3394 // when they are eventually appended. 3395 TEST_F(ChunkDemuxerTest, SeekCompletesWithoutTextCues) { 3396 DemuxerStream* text_stream = NULL; 3397 EXPECT_CALL(host_, AddTextStream(_, _)) 3398 .WillOnce(SaveArg<0>(&text_stream)); 3399 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO | HAS_TEXT)); 3400 3401 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO); 3402 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO); 3403 3404 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(120); 3405 bool seek_cb_was_called = false; 3406 demuxer_->StartWaitingForSeek(seek_time); 3407 demuxer_->Seek(seek_time, 3408 base::Bind(OnSeekDone_OKExpected, &seek_cb_was_called)); 3409 message_loop_.RunUntilIdle(); 3410 3411 EXPECT_FALSE(seek_cb_was_called); 3412 3413 bool text_read_done = false; 3414 text_stream->Read(base::Bind(&OnReadDone, 3415 base::TimeDelta::FromMilliseconds(125), 3416 &text_read_done)); 3417 3418 // Append audio & video data so the seek completes. 3419 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 3420 "0K 20K 40K 60K 80K 100K 120K 140K 160K 180K"); 3421 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, 3422 "0K 30 60 90 120K 150 180 210"); 3423 3424 message_loop_.RunUntilIdle(); 3425 EXPECT_TRUE(seek_cb_was_called); 3426 EXPECT_FALSE(text_read_done); 3427 3428 // Read some audio & video buffers to further verify seek completion. 3429 CheckExpectedBuffers(audio_stream, "120 140"); 3430 CheckExpectedBuffers(video_stream, "120 150"); 3431 3432 EXPECT_FALSE(text_read_done); 3433 3434 // Append text cues that start after the seek point and verify that 3435 // they are returned by Read() calls. 3436 AppendSingleStreamCluster(kSourceId, kTextTrackNum, "125K 175K 225K"); 3437 3438 message_loop_.RunUntilIdle(); 3439 EXPECT_TRUE(text_read_done); 3440 3441 // NOTE: we start at 175 here because the buffer at 125 was returned 3442 // to the pending read initiated above. 3443 CheckExpectedBuffers(text_stream, "175 225"); 3444 3445 // Verify that audio & video streams continue to return expected values. 3446 CheckExpectedBuffers(audio_stream, "160 180"); 3447 CheckExpectedBuffers(video_stream, "180 210"); 3448 } 3449 3450 TEST_F(ChunkDemuxerTest, ClusterWithUnknownSize) { 3451 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 3452 3453 AppendCluster(GenerateCluster(0, 0, 4, true)); 3454 CheckExpectedRanges(kSourceId, "{ [0,46) }"); 3455 3456 // A new cluster indicates end of the previous cluster with unknown size. 3457 AppendCluster(GenerateCluster(46, 66, 5, true)); 3458 CheckExpectedRanges(kSourceId, "{ [0,115) }"); 3459 } 3460 3461 TEST_F(ChunkDemuxerTest, CuesBetweenClustersWithUnknownSize) { 3462 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 3463 3464 // Add two clusters separated by Cues in a single Append() call. 3465 scoped_ptr<Cluster> cluster = GenerateCluster(0, 0, 4, true); 3466 std::vector<uint8> data(cluster->data(), cluster->data() + cluster->size()); 3467 data.insert(data.end(), kCuesHeader, kCuesHeader + sizeof(kCuesHeader)); 3468 cluster = GenerateCluster(46, 66, 5, true); 3469 data.insert(data.end(), cluster->data(), cluster->data() + cluster->size()); 3470 AppendData(&*data.begin(), data.size()); 3471 3472 CheckExpectedRanges(kSourceId, "{ [0,115) }"); 3473 } 3474 3475 TEST_F(ChunkDemuxerTest, CuesBetweenClusters) { 3476 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); 3477 3478 AppendCluster(GenerateCluster(0, 0, 4)); 3479 AppendData(kCuesHeader, sizeof(kCuesHeader)); 3480 AppendCluster(GenerateCluster(46, 66, 5)); 3481 CheckExpectedRanges(kSourceId, "{ [0,115) }"); 3482 } 3483 3484 } // namespace media 3485