1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/filters/chunk_demuxer.h"
15 #include "base/bind.h"
16 #include "base/callback_helpers.h"
17 #include "base/command_line.h"
18 #include "base/memory/raw_ptr.h"
19 #include "base/run_loop.h"
20 #include "base/strings/string_number_conversions.h"
21 #include "base/strings/string_split.h"
22 #include "base/strings/string_util.h"
23 #include "base/synchronization/waitable_event.h"
24 #include "base/test/task_environment.h"
25 #include "base/time/time.h"
26 #include "build/build_config.h"
27 #include "media/base/audio_decoder_config.h"
28 #include "media/base/decoder_buffer.h"
29 #include "media/base/decrypt_config.h"
30 #include "media/base/media.h"
31 #include "media/base/media_switches.h"
32 #include "media/base/media_tracks.h"
33 #include "media/base/mock_demuxer_host.h"
34 #include "media/base/mock_media_log.h"
35 #include "media/base/test_data_util.h"
36 #include "media/base/test_helpers.h"
37 #include "media/base/timestamp_constants.h"
38 #include "media/formats/webm/cluster_builder.h"
39 #include "media/formats/webm/webm_cluster_parser.h"
40 #include "media/formats/webm/webm_constants.h"
41 #include "media/media_buildflags.h"
42 #include "testing/gtest/include/gtest/gtest.h"
44 using ::testing::AnyNumber;
45 using ::testing::AtLeast;
46 using ::testing::Exactly;
47 using ::testing::HasSubstr;
48 using ::testing::InSequence;
49 using ::testing::NotNull;
50 using ::testing::Return;
51 using ::testing::SaveArg;
52 using ::testing::SetArgPointee;
53 using ::testing::StrictMock;
54 using ::testing::WithParamInterface;
59 const uint8_t kTracksHeader[] = {
60 0x16, 0x54, 0xAE, 0x6B, // Tracks ID
61 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // tracks(size = 0)
64 const uint8_t kCuesHeader[] = {
65 0x1C, 0x53, 0xBB, 0x6B, // Cues ID
66 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // cues(size = 0)
69 const uint8_t kEncryptedMediaInitData[] = {
70 0x68, 0xFE, 0xF9, 0xA1, 0xB3, 0x0D, 0x6B, 0x4D,
71 0xF2, 0x22, 0xB5, 0x0B, 0x4D, 0xE9, 0xE9, 0x95,
74 const int kTracksHeaderSize = sizeof(kTracksHeader);
75 const int kTracksSizeOffset = 4;
77 // The size of TrackEntry element in test file "webm_vorbis_track_entry" starts
78 // at index 1 and spans 8 bytes.
79 const int kAudioTrackSizeOffset = 1;
80 const int kAudioTrackSizeWidth = 8;
81 const int kAudioTrackEntryHeaderSize =
82 kAudioTrackSizeOffset + kAudioTrackSizeWidth;
84 // The size of TrackEntry element in test file "webm_vp8_track_entry" starts at
85 // index 1 and spans 8 bytes.
86 const int kVideoTrackSizeOffset = 1;
87 const int kVideoTrackSizeWidth = 8;
88 const int kVideoTrackEntryHeaderSize =
89 kVideoTrackSizeOffset + kVideoTrackSizeWidth;
91 const int kVideoTrackNum = 1;
92 const int kAudioTrackNum = 2;
93 const int kAlternateVideoTrackNum = 4;
94 const int kAlternateAudioTrackNum = 5;
95 const int kAlternateTextTrackNum = 6;
97 const int kAudioBlockDuration = 23;
98 const int kVideoBlockDuration = 33;
99 const int kTextBlockDuration = 100;
100 const int kBlockSize = 10;
102 const char kSourceId[] = "SourceId";
103 const char kDefaultFirstClusterRange[] = "{ [0,46) }";
104 const int kDefaultFirstClusterEndTimestamp = 66;
105 const int kDefaultSecondClusterEndTimestamp = 132;
107 base::TimeDelta kDefaultDuration() {
108 return base::Milliseconds(201224);
111 // Write an integer into buffer in the form of vint that spans 8 bytes.
112 // The data pointed by |buffer| should be at least 8 bytes long.
113 // |number| should be in the range 0 <= number < 0x00FFFFFFFFFFFFFF.
114 static void WriteInt64(uint8_t* buffer, int64_t number) {
115 DCHECK(number >= 0 && number < 0x00FFFFFFFFFFFFFFLL);
117 int64_t tmp = number;
118 for (int i = 7; i > 0; i--) {
119 buffer[i] = tmp & 0xff;
124 static void OnReadDone(const base::TimeDelta& expected_time,
126 DemuxerStream::Status status,
127 scoped_refptr<DecoderBuffer> buffer) {
128 EXPECT_EQ(status, DemuxerStream::kOk);
129 EXPECT_EQ(expected_time, buffer->timestamp());
133 static void OnReadDone_AbortExpected(bool* called,
134 DemuxerStream::Status status,
135 scoped_refptr<DecoderBuffer> buffer) {
136 EXPECT_EQ(status, DemuxerStream::kAborted);
137 EXPECT_EQ(NULL, buffer.get());
141 static void OnReadDone_EOSExpected(bool* called,
142 DemuxerStream::Status status,
143 scoped_refptr<DecoderBuffer> buffer) {
144 EXPECT_EQ(status, DemuxerStream::kOk);
145 EXPECT_TRUE(buffer->end_of_stream());
149 static void OnSeekDone_OKExpected(bool* called, PipelineStatus status) {
150 EXPECT_EQ(status, PIPELINE_OK);
154 class ChunkDemuxerTest : public ::testing::Test {
156 // Public method because test cases use it directly.
157 MOCK_METHOD1(DemuxerInitialized, void(PipelineStatus));
166 // Default cluster to append first for simple tests.
167 std::unique_ptr<Cluster> kDefaultFirstCluster() {
168 return GenerateCluster(0, 4);
171 // Default cluster to append after kDefaultFirstCluster()
172 // has been appended. This cluster starts with blocks that
173 // have timestamps consistent with the end times of the blocks
174 // in kDefaultFirstCluster() so that these two clusters represent
175 // a continuous region.
176 std::unique_ptr<Cluster> kDefaultSecondCluster() {
177 return GenerateCluster(46, 66, 5);
181 : did_progress_(false),
182 append_window_end_for_next_append_(kInfiniteDuration) {
183 init_segment_received_cb_ = base::BindRepeating(
184 &ChunkDemuxerTest::InitSegmentReceived, base::Unretained(this));
188 ChunkDemuxerTest(const ChunkDemuxerTest&) = delete;
189 ChunkDemuxerTest& operator=(const ChunkDemuxerTest&) = delete;
191 void CreateNewDemuxer() {
192 base::OnceClosure open_cb = base::BindOnce(&ChunkDemuxerTest::DemuxerOpened,
193 base::Unretained(this));
194 base::RepeatingClosure progress_cb = base::BindRepeating(
195 &ChunkDemuxerTest::OnProgress, base::Unretained(this));
196 Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb =
197 base::BindRepeating(&ChunkDemuxerTest::OnEncryptedMediaInitData,
198 base::Unretained(this));
199 EXPECT_MEDIA_LOG(ChunkDemuxerCtor());
200 demuxer_ = std::make_unique<ChunkDemuxer>(std::move(open_cb), progress_cb,
201 encrypted_media_init_data_cb,
205 ~ChunkDemuxerTest() override { ShutdownDemuxer(); }
207 void CreateInitSegment(int stream_flags,
208 bool is_audio_encrypted,
209 bool is_video_encrypted,
210 std::unique_ptr<uint8_t[]>* buffer,
212 bool has_audio = (stream_flags & HAS_AUDIO) != 0;
213 bool has_video = (stream_flags & HAS_VIDEO) != 0;
214 scoped_refptr<DecoderBuffer> ebml_header;
215 scoped_refptr<DecoderBuffer> info;
216 scoped_refptr<DecoderBuffer> audio_track_entry;
217 scoped_refptr<DecoderBuffer> video_track_entry;
218 scoped_refptr<DecoderBuffer> audio_content_encodings;
219 scoped_refptr<DecoderBuffer> video_content_encodings;
220 scoped_refptr<DecoderBuffer> text_track_entry;
222 ebml_header = ReadTestDataFile("webm_ebml_element");
224 info = ReadTestDataFile("webm_info_element");
226 int tracks_element_size = 0;
229 audio_track_entry = ReadTestDataFile("webm_vorbis_track_entry");
230 tracks_element_size += audio_track_entry->data_size();
231 // Verify that we have TrackNum (0xD7) EBML element at expected offset.
232 DCHECK_EQ(audio_track_entry->data()[9], kWebMIdTrackNumber);
233 // Verify that the size of TrackNum element is 1. The actual value is 0x81
234 // due to how element sizes are encoded in EBML.
235 DCHECK_EQ(audio_track_entry->data()[10], 0x81);
236 // Ensure the track id in TrackNum EBML element matches kAudioTrackNum.
237 DCHECK_EQ(audio_track_entry->data()[11], kAudioTrackNum);
238 if (stream_flags & USE_ALTERNATE_AUDIO_TRACK_ID)
239 audio_track_entry->writable_data()[11] = kAlternateAudioTrackNum;
240 if (is_audio_encrypted) {
241 audio_content_encodings = ReadTestDataFile("webm_content_encodings");
242 tracks_element_size += audio_content_encodings->data_size();
247 video_track_entry = ReadTestDataFile("webm_vp8_track_entry");
248 tracks_element_size += video_track_entry->data_size();
249 // Verify that we have TrackNum (0xD7) EBML element at expected offset.
250 DCHECK_EQ(video_track_entry->data()[9], kWebMIdTrackNumber);
251 // Verify that the size of TrackNum element is 1. The actual value is 0x81
252 // due to how element sizes are encoded in EBML.
253 DCHECK_EQ(video_track_entry->data()[10], 0x81);
254 // Ensure the track id in TrackNum EBML element matches kVideoTrackNum.
255 DCHECK_EQ(video_track_entry->data()[11], kVideoTrackNum);
256 if (stream_flags & USE_ALTERNATE_VIDEO_TRACK_ID)
257 video_track_entry->writable_data()[11] = kAlternateVideoTrackNum;
258 if (is_video_encrypted) {
259 video_content_encodings = ReadTestDataFile("webm_content_encodings");
260 tracks_element_size += video_content_encodings->data_size();
264 *size = ebml_header->data_size() + info->data_size() +
265 kTracksHeaderSize + tracks_element_size;
267 buffer->reset(new uint8_t[*size]);
269 uint8_t* buf = buffer->get();
270 memcpy(buf, ebml_header->data(), ebml_header->data_size());
271 buf += ebml_header->data_size();
273 memcpy(buf, info->data(), info->data_size());
274 buf += info->data_size();
276 memcpy(buf, kTracksHeader, kTracksHeaderSize);
277 WriteInt64(buf + kTracksSizeOffset, tracks_element_size);
278 buf += kTracksHeaderSize;
280 // TODO(xhwang): Simplify this! Probably have test data files that contain
281 // ContentEncodings directly instead of trying to create one at run-time.
283 memcpy(buf, video_track_entry->data(),
284 video_track_entry->data_size());
285 if (is_video_encrypted) {
286 memcpy(buf + video_track_entry->data_size(),
287 video_content_encodings->data(),
288 video_content_encodings->data_size());
289 WriteInt64(buf + kVideoTrackSizeOffset,
290 video_track_entry->data_size() +
291 video_content_encodings->data_size() -
292 kVideoTrackEntryHeaderSize);
293 buf += video_content_encodings->data_size();
295 buf += video_track_entry->data_size();
299 memcpy(buf, audio_track_entry->data(), audio_track_entry->data_size());
300 if (is_audio_encrypted) {
301 memcpy(buf + audio_track_entry->data_size(),
302 audio_content_encodings->data(),
303 audio_content_encodings->data_size());
304 WriteInt64(buf + kAudioTrackSizeOffset,
305 audio_track_entry->data_size() +
306 audio_content_encodings->data_size() -
307 kAudioTrackEntryHeaderSize);
308 buf += audio_content_encodings->data_size();
310 buf += audio_track_entry->data_size();
314 ChunkDemuxer::Status AddId() {
315 return AddId(kSourceId, HAS_AUDIO | HAS_VIDEO);
318 ChunkDemuxer::Status AddId(const std::string& source_id, int stream_flags) {
319 bool has_audio = (stream_flags & HAS_AUDIO) != 0;
320 bool has_video = (stream_flags & HAS_VIDEO) != 0;
337 if (!has_audio && !has_video) {
338 return AddId(kSourceId, HAS_AUDIO | HAS_VIDEO);
341 return AddId(source_id, type, codecs);
344 ChunkDemuxer::Status AddId(const std::string& source_id,
345 const std::string& mime_type,
346 const std::string& codecs) {
347 ChunkDemuxer::Status status = demuxer_->AddId(source_id, mime_type, codecs);
348 if (status == ChunkDemuxer::kOk) {
349 demuxer_->SetTracksWatcher(source_id, init_segment_received_cb_);
350 demuxer_->SetParseWarningCallback(
351 source_id, base::BindRepeating(&ChunkDemuxerTest::OnParseWarningMock,
352 base::Unretained(this)));
357 bool AppendData(const uint8_t* data, size_t length) {
358 return AppendData(kSourceId, data, length);
361 bool AppendCluster(const std::string& source_id,
362 std::unique_ptr<Cluster> cluster) {
363 return AppendData(source_id, cluster->data(), cluster->size());
366 bool AppendCluster(std::unique_ptr<Cluster> cluster) {
367 return AppendCluster(kSourceId, std::move(cluster));
370 bool AppendCluster(int timecode, int block_count) {
371 return AppendCluster(GenerateCluster(timecode, block_count));
374 void AppendSingleStreamCluster(const std::string& source_id, int track_number,
375 int timecode, int block_count) {
376 int block_duration = 0;
377 switch (track_number) {
379 case kAlternateVideoTrackNum:
380 block_duration = kVideoBlockDuration;
383 case kAlternateAudioTrackNum:
384 block_duration = kAudioBlockDuration;
386 case kAlternateTextTrackNum:
387 block_duration = kTextBlockDuration;
390 ASSERT_NE(block_duration, 0);
391 int end_timecode = timecode + block_count * block_duration;
392 ASSERT_TRUE(AppendCluster(
393 source_id, GenerateSingleStreamCluster(timecode, end_timecode,
394 track_number, block_duration)));
405 BlockInfo(int tn, int ts, int f, int d)
417 bool operator< (const BlockInfo& rhs) const {
418 return timestamp_in_ms < rhs.timestamp_in_ms;
422 // |track_number| - The track number to place in
423 // |block_descriptions| - A space delimited string of block info that
424 // is used to populate |blocks|. Each block info has a timestamp in
425 // milliseconds and optionally followed by a 'K' to indicate that a block
426 // should be marked as a key frame. For example "0K 30 60" should populate
427 // |blocks| with 3 BlockInfo objects: a key frame with timestamp 0 and 2
428 // non-key-frames at 30ms and 60ms.
429 // Every block will be a SimpleBlock, with the exception that the last block
430 // may have an optional duration delimited with a 'D' and appended to the
431 // block info timestamp, prior to the optional keyframe 'K'. For example "0K
432 // 30 60D10K" indicates that the last block will be a keyframe BlockGroup
433 // with duration 10ms.
434 void ParseBlockDescriptions(int track_number,
435 const std::string block_descriptions,
436 std::vector<BlockInfo>* blocks) {
437 std::vector<std::string> timestamps = base::SplitString(
438 block_descriptions, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
440 for (size_t i = 0; i < timestamps.size(); ++i) {
441 std::string timestamp_str = timestamps[i];
442 BlockInfo block_info;
443 block_info.track_number = track_number;
444 block_info.flags = 0;
445 block_info.duration = 0;
447 if (base::EndsWith(timestamp_str, "K", base::CompareCase::SENSITIVE)) {
448 block_info.flags = kWebMFlagKeyframe;
449 // Remove the "K" off of the token.
450 timestamp_str = timestamp_str.substr(0, timestamps[i].length() - 1);
453 size_t duration_pos = timestamp_str.find('D');
454 const bool explicit_duration = duration_pos != std::string::npos;
455 const bool is_last_block = i == timestamps.size() - 1;
456 CHECK(!explicit_duration || is_last_block);
457 if (explicit_duration) {
458 CHECK(base::StringToInt(timestamp_str.substr(duration_pos + 1),
459 &block_info.duration));
460 timestamp_str = timestamp_str.substr(0, duration_pos);
463 CHECK(base::StringToInt(timestamp_str, &block_info.timestamp_in_ms));
465 if (track_number == kAlternateTextTrackNum) {
466 block_info.duration = kTextBlockDuration;
467 ASSERT_EQ(kWebMFlagKeyframe, block_info.flags)
468 << "Text block with timestamp " << block_info.timestamp_in_ms
469 << " was not marked as a key frame."
470 << " All text blocks must be key frames";
473 if (track_number == kAudioTrackNum ||
474 track_number == kAlternateAudioTrackNum)
475 ASSERT_TRUE(block_info.flags & kWebMFlagKeyframe);
477 blocks->push_back(block_info);
481 std::unique_ptr<Cluster> GenerateCluster(const std::vector<BlockInfo>& blocks,
483 DCHECK_GT(blocks.size(), 0u);
486 // Ensure we can obtain a valid pointer to a region of data of |block_size_|
488 std::vector<uint8_t> data(block_size_ ? block_size_ : 1);
490 for (size_t i = 0; i < blocks.size(); ++i) {
492 cb.SetClusterTimecode(blocks[i].timestamp_in_ms);
494 if (blocks[i].duration) {
495 cb.AddBlockGroup(blocks[i].track_number, blocks[i].timestamp_in_ms,
496 blocks[i].duration, blocks[i].flags,
497 blocks[i].flags & kWebMFlagKeyframe, &data[0],
500 cb.AddSimpleBlock(blocks[i].track_number, blocks[i].timestamp_in_ms,
501 blocks[i].flags, &data[0], block_size_);
505 return unknown_size ? cb.FinishWithUnknownSize() : cb.Finish();
508 std::unique_ptr<Cluster> GenerateCluster(
509 std::priority_queue<BlockInfo> block_queue,
511 std::vector<BlockInfo> blocks(block_queue.size());
512 for (size_t i = block_queue.size() - 1; !block_queue.empty(); --i) {
513 blocks[i] = block_queue.top();
517 return GenerateCluster(blocks, unknown_size);
520 // |block_descriptions| - The block descriptions used to construct the
521 // cluster. See the documentation for ParseBlockDescriptions() for details on
522 // the string format.
523 void AppendSingleStreamCluster(const std::string& source_id, int track_number,
524 const std::string& block_descriptions) {
525 std::vector<BlockInfo> blocks;
526 ParseBlockDescriptions(track_number, block_descriptions, &blocks);
527 ASSERT_TRUE(AppendCluster(source_id, GenerateCluster(blocks, false)));
530 struct MuxedStreamInfo {
533 block_descriptions(""),
534 last_blocks_estimated_duration(-1) {}
536 MuxedStreamInfo(int track_num, const char* block_desc)
537 : track_number(track_num),
538 block_descriptions(block_desc),
539 last_blocks_estimated_duration(-1) {}
541 MuxedStreamInfo(int track_num,
542 const char* block_desc,
543 int last_block_duration_estimate)
544 : track_number(track_num),
545 block_descriptions(block_desc),
546 last_blocks_estimated_duration(last_block_duration_estimate) {}
549 // The block description passed to ParseBlockDescriptions().
550 // See the documentation for that method for details on the string format.
551 const char* block_descriptions;
553 // If -1, no WebMSimpleBlockDurationEstimated MediaLog expectation is added
554 // when appending the resulting cluster. Otherwise, an expectation (in ms)
556 int last_blocks_estimated_duration;
559 void AppendMuxedCluster(const MuxedStreamInfo& msi_1,
560 const MuxedStreamInfo& msi_2) {
561 std::vector<MuxedStreamInfo> msi(2);
564 AppendMuxedCluster(msi);
567 void AppendMuxedCluster(const MuxedStreamInfo& msi_1,
568 const MuxedStreamInfo& msi_2,
569 const MuxedStreamInfo& msi_3) {
570 std::vector<MuxedStreamInfo> msi(3);
574 AppendMuxedCluster(msi);
577 std::unique_ptr<Cluster> GenerateMuxedCluster(
578 const std::vector<MuxedStreamInfo> msi) {
579 std::priority_queue<BlockInfo> block_queue;
580 for (size_t i = 0; i < msi.size(); ++i) {
581 std::vector<BlockInfo> track_blocks;
582 ParseBlockDescriptions(msi[i].track_number, msi[i].block_descriptions,
585 for (size_t j = 0; j < track_blocks.size(); ++j) {
586 block_queue.push(track_blocks[j]);
589 if (msi[i].last_blocks_estimated_duration != -1) {
590 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(
591 msi[i].last_blocks_estimated_duration));
594 return GenerateCluster(block_queue, false);
597 void AppendMuxedCluster(const std::vector<MuxedStreamInfo> msi) {
598 ASSERT_TRUE(AppendCluster(kSourceId, GenerateMuxedCluster(msi)));
601 bool AppendData(const std::string& source_id,
604 EXPECT_CALL(host_, OnBufferedTimeRangesChanged(_)).Times(AnyNumber());
606 return demuxer_->AppendData(
607 source_id, data, length, append_window_start_for_next_append_,
608 append_window_end_for_next_append_, ×tamp_offset_map_[source_id]);
611 bool AppendDataInPieces(const uint8_t* data, size_t length) {
612 return AppendDataInPieces(data, length, 7);
615 bool AppendDataInPieces(const uint8_t* data,
618 const uint8_t* start = data;
619 const uint8_t* end = data + length;
620 while (start < end) {
621 size_t append_size = std::min(piece_size,
622 static_cast<size_t>(end - start));
623 if (!AppendData(start, append_size))
625 start += append_size;
630 bool AppendInitSegment(int stream_flags) {
631 return AppendInitSegmentWithSourceId(kSourceId, stream_flags);
634 bool AppendInitSegmentWithSourceId(const std::string& source_id,
636 return AppendInitSegmentWithEncryptedInfo(source_id, stream_flags, false,
640 bool AppendInitSegmentWithEncryptedInfo(const std::string& source_id,
642 bool is_audio_encrypted,
643 bool is_video_encrypted) {
644 std::unique_ptr<uint8_t[]> info_tracks;
645 int info_tracks_size = 0;
646 CreateInitSegment(stream_flags,
647 is_audio_encrypted, is_video_encrypted,
648 &info_tracks, &info_tracks_size);
649 return AppendData(source_id, info_tracks.get(), info_tracks_size);
652 void AppendGarbage() {
653 // Fill up an array with gibberish.
654 int garbage_cluster_size = 10;
655 std::unique_ptr<uint8_t[]> garbage_cluster(
656 new uint8_t[garbage_cluster_size]);
657 for (int i = 0; i < garbage_cluster_size; ++i)
658 garbage_cluster[i] = i;
659 ASSERT_FALSE(AppendData(garbage_cluster.get(), garbage_cluster_size));
662 PipelineStatusCallback CreateInitDoneCallback(
663 base::TimeDelta expected_duration,
664 PipelineStatus expected_status) {
665 if (expected_duration != kNoTimestamp)
666 EXPECT_CALL(host_, SetDuration(expected_duration));
667 return CreateInitDoneCallback(expected_status);
670 PipelineStatusCallback CreateInitDoneCallback(
671 PipelineStatus expected_status) {
672 EXPECT_CALL(*this, DemuxerInitialized(expected_status));
673 return base::BindOnce(&ChunkDemuxerTest::DemuxerInitialized,
674 base::Unretained(this));
680 USE_ALTERNATE_AUDIO_TRACK_ID = 1 << 3,
681 USE_ALTERNATE_VIDEO_TRACK_ID = 1 << 4,
682 USE_ALTERNATE_TEXT_TRACK_ID = 1 << 5,
685 bool InitDemuxer(int stream_flags) {
686 return InitDemuxerWithEncryptionInfo(stream_flags, false, false);
689 void ExpectInitMediaLogs(int stream_flags) {
690 if (stream_flags & HAS_VIDEO)
691 EXPECT_FOUND_CODEC_NAME(Video, "vp8");
692 if (stream_flags & HAS_AUDIO)
693 EXPECT_FOUND_CODEC_NAME(Audio, "vorbis");
696 bool InitDemuxerWithEncryptionInfo(
697 int stream_flags, bool is_audio_encrypted, bool is_video_encrypted) {
698 PipelineStatus expected_status =
699 (stream_flags != 0) ? PIPELINE_OK : CHUNK_DEMUXER_ERROR_APPEND_FAILED;
701 base::TimeDelta expected_duration = kNoTimestamp;
702 if (expected_status == PIPELINE_OK)
703 expected_duration = kDefaultDuration();
705 EXPECT_CALL(*this, DemuxerOpened());
707 if (is_audio_encrypted || is_video_encrypted) {
708 DCHECK(!is_audio_encrypted || stream_flags & HAS_AUDIO);
709 DCHECK(!is_video_encrypted || stream_flags & HAS_VIDEO);
712 (is_audio_encrypted ? 1 : 0) + (is_video_encrypted ? 1 : 0);
713 EXPECT_CALL(*this, OnEncryptedMediaInitData(
714 EmeInitDataType::WEBM,
715 std::vector<uint8_t>(
716 kEncryptedMediaInitData,
717 kEncryptedMediaInitData +
718 std::size(kEncryptedMediaInitData))))
719 .Times(Exactly(need_key_count));
722 // Adding expectations prior to CreateInitDoneCallback() here because
723 // InSequence tests require init segment received before duration set. Also,
724 // only expect an init segment received callback if there is actually a
726 if (stream_flags != 0) {
727 ExpectInitMediaLogs(stream_flags);
728 EXPECT_CALL(*this, InitSegmentReceivedMock(_));
730 // OnNewConfigs() requires at least one audio, video, or text track.
731 EXPECT_MEDIA_LOG(InitSegmentMissesExpectedTrack("vorbis"));
732 EXPECT_MEDIA_LOG(InitSegmentMissesExpectedTrack("vp8"));
733 EXPECT_MEDIA_LOG(StreamParsingFailed());
736 demuxer_->Initialize(
737 &host_, CreateInitDoneCallback(expected_duration, expected_status));
739 if (AddId(kSourceId, stream_flags) != ChunkDemuxer::kOk)
742 return AppendInitSegmentWithEncryptedInfo(
743 kSourceId, stream_flags, is_audio_encrypted, is_video_encrypted);
746 bool InitDemuxerAudioAndVideoSourcesText(const std::string& audio_id,
747 const std::string& video_id) {
748 EXPECT_CALL(*this, DemuxerOpened());
749 demuxer_->Initialize(
750 &host_, CreateInitDoneCallback(kDefaultDuration(), PIPELINE_OK));
752 if (AddId(audio_id, HAS_AUDIO) != ChunkDemuxer::kOk)
754 if (AddId(video_id, HAS_VIDEO) != ChunkDemuxer::kOk)
757 int audio_flags = HAS_AUDIO;
758 int video_flags = HAS_VIDEO;
760 // Note: Unlike InitDemuxerWithEncryptionInfo, this method is currently
761 // incompatible with InSequence tests. Refactoring of the duration
762 // set expectation to not be added during CreateInitDoneCallback() could fix
764 ExpectInitMediaLogs(audio_flags);
765 EXPECT_CALL(*this, InitSegmentReceivedMock(_));
766 EXPECT_TRUE(AppendInitSegmentWithSourceId(audio_id, audio_flags));
768 ExpectInitMediaLogs(video_flags);
769 EXPECT_CALL(*this, InitSegmentReceivedMock(_));
770 EXPECT_TRUE(AppendInitSegmentWithSourceId(video_id, video_flags));
774 bool InitDemuxerAudioAndVideoSources(const std::string& audio_id,
775 const std::string& video_id) {
776 return InitDemuxerAudioAndVideoSourcesText(audio_id, video_id);
779 // Initializes the demuxer with data from 2 files with different
780 // decoder configurations. This is used to test the decoder config change
783 // bear-320x240.webm VideoDecoderConfig returns 320x240 for its natural_size()
784 // bear-640x360.webm VideoDecoderConfig returns 640x360 for its natural_size()
785 // The resulting video stream returns data from each file for the following
787 // bear-320x240.webm : [0-501) [801-2736)
788 // bear-640x360.webm : [527-760)
790 // bear-320x240.webm AudioDecoderConfig returns 3863 for its extra_data size.
791 // bear-640x360.webm AudioDecoderConfig returns 3935 for its extra_data size.
792 // The resulting audio stream returns data from each file for the following
794 // bear-320x240.webm : [0-524) [779-2736)
795 // bear-640x360.webm : [527-759)
796 bool InitDemuxerWithConfigChangeData() {
797 scoped_refptr<DecoderBuffer> bear1 = ReadTestDataFile("bear-320x240.webm");
798 scoped_refptr<DecoderBuffer> bear2 = ReadTestDataFile("bear-640x360.webm");
800 EXPECT_CALL(*this, DemuxerOpened());
802 // Adding expectation prior to CreateInitDoneCallback() here because
803 // InSequence tests require init segment received before duration set.
804 ExpectInitMediaLogs(HAS_AUDIO | HAS_VIDEO);
805 EXPECT_CALL(*this, InitSegmentReceivedMock(_));
806 demuxer_->Initialize(
807 &host_, CreateInitDoneCallback(base::Milliseconds(2744), PIPELINE_OK));
809 if (AddId(kSourceId, HAS_AUDIO | HAS_VIDEO) != ChunkDemuxer::kOk)
812 // Append the whole bear1 file.
813 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(2)).Times(7);
814 // Expect duration adjustment since actual duration differs slightly from
815 // duration in the init segment.
816 EXPECT_CALL(host_, SetDuration(base::Milliseconds(2768)));
817 EXPECT_TRUE(AppendData(bear1->data(), bear1->data_size()));
818 // Last audio frame has timestamp 2721 and duration 24 (estimated from max
819 // seen so far for audio track).
820 // Last video frame has timestamp 2703 and duration 33 (from TrackEntry
821 // DefaultDuration for video track).
822 CheckExpectedRanges("{ [0,2736) }");
824 // Append initialization segment for bear2.
825 // Note: Offsets here and below are derived from
826 // media/test/data/bear-640x360-manifest.js and
827 // media/test/data/bear-320x240-manifest.js which were
828 // generated from media/test/data/bear-640x360.webm and
829 // media/test/data/bear-320x240.webm respectively.
830 EXPECT_CALL(*this, InitSegmentReceivedMock(_));
831 EXPECT_TRUE(AppendData(bear2->data(), 4340));
833 // Append a media segment that goes from [0.527000, 1.014000).
834 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(2));
835 EXPECT_MEDIA_LOG(TrimmedSpliceOverlap(527000, 524000, 20000));
836 EXPECT_TRUE(AppendData(bear2->data() + 55290, 18785));
837 CheckExpectedRanges("{ [0,2736) }");
839 // Append initialization segment for bear1 and buffer [779-1197)
841 EXPECT_CALL(*this, InitSegmentReceivedMock(_));
842 EXPECT_TRUE(AppendData(bear1->data(), 4370));
843 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(24));
844 EXPECT_MEDIA_LOG(TrimmedSpliceOverlap(779000, 759000, 3000));
845 EXPECT_TRUE(AppendData(bear1->data() + 72737, 28183));
846 CheckExpectedRanges("{ [0,2736) }");
848 MarkEndOfStream(PIPELINE_OK);
852 void ShutdownDemuxer() {
854 demuxer_->Shutdown();
855 base::RunLoop().RunUntilIdle();
859 void AddSimpleBlock(ClusterBuilder* cb, int track_num, int64_t timecode) {
860 uint8_t data[] = {0x00};
861 cb->AddSimpleBlock(track_num, timecode, 0, data, sizeof(data));
864 std::unique_ptr<Cluster> GenerateCluster(int timecode, int block_count) {
865 return GenerateCluster(timecode, timecode, block_count);
868 std::unique_ptr<Cluster> GenerateCluster(int first_audio_timecode,
869 int first_video_timecode,
871 return GenerateCluster(first_audio_timecode, first_video_timecode,
874 std::unique_ptr<Cluster> GenerateCluster(int first_audio_timecode,
875 int first_video_timecode,
878 CHECK_GT(block_count, 0);
880 std::priority_queue<BlockInfo> block_queue;
882 if (block_count == 1) {
883 block_queue.push(BlockInfo(kAudioTrackNum,
884 first_audio_timecode,
886 kAudioBlockDuration));
887 return GenerateCluster(block_queue, unknown_size);
890 int audio_timecode = first_audio_timecode;
891 int video_timecode = first_video_timecode;
893 // Create simple blocks for everything except the last 2 blocks.
894 // The first video frame must be a key frame.
895 uint8_t video_flag = kWebMFlagKeyframe;
896 for (int i = 0; i < block_count - 2; i++) {
897 if (audio_timecode <= video_timecode) {
898 block_queue.push(BlockInfo(kAudioTrackNum,
902 audio_timecode += kAudioBlockDuration;
906 block_queue.push(BlockInfo(kVideoTrackNum,
910 video_timecode += kVideoBlockDuration;
914 // Make the last 2 blocks BlockGroups so that they don't get delayed by the
915 // block duration calculation logic.
916 block_queue.push(BlockInfo(kAudioTrackNum,
919 kAudioBlockDuration));
920 block_queue.push(BlockInfo(kVideoTrackNum,
923 kVideoBlockDuration));
925 return GenerateCluster(block_queue, unknown_size);
928 std::unique_ptr<Cluster> GenerateSingleStreamCluster(int timecode,
931 int block_duration) {
932 CHECK_GT(end_timecode, timecode);
934 // Ensure we can obtain a valid pointer to a region of data of |block_size_|
936 std::vector<uint8_t> data(block_size_ ? block_size_ : 1);
939 cb.SetClusterTimecode(timecode);
941 // Create simple blocks for everything except the last block.
942 while (timecode < (end_timecode - block_duration)) {
943 cb.AddSimpleBlock(track_number, timecode, kWebMFlagKeyframe, &data[0],
945 timecode += block_duration;
948 cb.AddBlockGroup(track_number, timecode, block_duration, kWebMFlagKeyframe,
949 static_cast<bool>(kWebMFlagKeyframe), &data[0],
955 DemuxerStream* GetStream(DemuxerStream::Type type) {
956 std::vector<DemuxerStream*> streams = demuxer_->GetAllStreams();
957 for (auto* stream : streams) {
958 if (stream->type() == type)
964 void Read(DemuxerStream::Type type, DemuxerStream::ReadCB read_cb) {
965 GetStream(type)->Read(std::move(read_cb));
966 base::RunLoop().RunUntilIdle();
969 void ReadAudio(DemuxerStream::ReadCB read_cb) {
970 Read(DemuxerStream::AUDIO, std::move(read_cb));
973 void ReadVideo(DemuxerStream::ReadCB read_cb) {
974 Read(DemuxerStream::VIDEO, std::move(read_cb));
977 void GenerateExpectedReads(int timecode, int block_count) {
978 GenerateExpectedReads(timecode, timecode, block_count);
981 void GenerateExpectedReads(int start_audio_timecode,
982 int start_video_timecode,
984 CHECK_GT(block_count, 0);
986 if (block_count == 1) {
987 ExpectRead(DemuxerStream::AUDIO, start_audio_timecode);
991 int audio_timecode = start_audio_timecode;
992 int video_timecode = start_video_timecode;
994 for (int i = 0; i < block_count; i++) {
995 if (audio_timecode <= video_timecode) {
996 ExpectRead(DemuxerStream::AUDIO, audio_timecode);
997 audio_timecode += kAudioBlockDuration;
1001 ExpectRead(DemuxerStream::VIDEO, video_timecode);
1002 video_timecode += kVideoBlockDuration;
1006 void GenerateSingleStreamExpectedReads(int timecode,
1008 DemuxerStream::Type type,
1009 int block_duration) {
1010 CHECK_GT(block_count, 0);
1011 int stream_timecode = timecode;
1013 for (int i = 0; i < block_count; i++) {
1014 ExpectRead(type, stream_timecode);
1015 stream_timecode += block_duration;
1019 void GenerateAudioStreamExpectedReads(int timecode, int block_count) {
1020 GenerateSingleStreamExpectedReads(
1021 timecode, block_count, DemuxerStream::AUDIO, kAudioBlockDuration);
1024 void GenerateVideoStreamExpectedReads(int timecode, int block_count) {
1025 GenerateSingleStreamExpectedReads(
1026 timecode, block_count, DemuxerStream::VIDEO, kVideoBlockDuration);
1029 std::unique_ptr<Cluster> GenerateEmptyCluster(int timecode) {
1031 cb.SetClusterTimecode(timecode);
1035 void CheckExpectedRangesForMediaSource(const std::string& expected) {
1036 CheckExpectedRanges(demuxer_->GetBufferedRanges(), expected);
1039 void CheckExpectedRanges(const std::string& expected) {
1040 CheckExpectedRanges(kSourceId, expected);
1041 CheckExpectedRangesForMediaSource(expected);
1044 void CheckExpectedRanges(const std::string& id, const std::string& expected) {
1045 CheckExpectedRanges(demuxer_->GetBufferedRanges(id), expected);
1048 void CheckExpectedRanges(DemuxerStream::Type type,
1049 const std::string& expected) {
1050 ChunkDemuxerStream* stream =
1051 static_cast<ChunkDemuxerStream*>(GetStream(type));
1052 CheckExpectedRanges(stream->GetBufferedRanges(kDefaultDuration()),
1056 void CheckExpectedRanges(const Ranges<base::TimeDelta>& r,
1057 const std::string& expected) {
1058 std::stringstream ss;
1060 for (size_t i = 0; i < r.size(); ++i) {
1061 ss << "[" << r.start(i).InMilliseconds() << ","
1062 << r.end(i).InMilliseconds() << ") ";
1065 EXPECT_EQ(expected, ss.str());
1068 MOCK_METHOD2(ReadDone,
1069 void(DemuxerStream::Status status,
1070 scoped_refptr<DecoderBuffer>));
1072 void StoreStatusAndBuffer(DemuxerStream::Status* status_out,
1073 scoped_refptr<DecoderBuffer>* buffer_out,
1074 DemuxerStream::Status status,
1075 scoped_refptr<DecoderBuffer> buffer) {
1076 *status_out = status;
1077 *buffer_out = buffer;
1080 void ReadUntilNotOkOrEndOfStream(DemuxerStream::Type type,
1081 DemuxerStream::Status* status,
1082 base::TimeDelta* last_timestamp) {
1083 DemuxerStream* stream = GetStream(type);
1084 scoped_refptr<DecoderBuffer> buffer;
1086 *last_timestamp = kNoTimestamp;
1088 stream->Read(base::BindOnce(&ChunkDemuxerTest::StoreStatusAndBuffer,
1089 base::Unretained(this), status, &buffer));
1090 base::RunLoop().RunUntilIdle();
1091 if (*status == DemuxerStream::kOk && !buffer->end_of_stream())
1092 *last_timestamp = buffer->timestamp();
1093 } while (*status == DemuxerStream::kOk && !buffer->end_of_stream());
1096 void ExpectEndOfStream(DemuxerStream::Type type) {
1097 EXPECT_CALL(*this, ReadDone(DemuxerStream::kOk, IsEndOfStream()));
1098 GetStream(type)->Read(
1099 base::BindOnce(&ChunkDemuxerTest::ReadDone, base::Unretained(this)));
1100 base::RunLoop().RunUntilIdle();
1103 void ExpectRead(DemuxerStream::Type type, int64_t timestamp_in_ms) {
1104 EXPECT_CALL(*this, ReadDone(DemuxerStream::kOk,
1105 HasTimestamp(timestamp_in_ms)));
1106 GetStream(type)->Read(
1107 base::BindOnce(&ChunkDemuxerTest::ReadDone, base::Unretained(this)));
1108 base::RunLoop().RunUntilIdle();
1111 void ExpectConfigChanged(DemuxerStream::Type type) {
1112 EXPECT_CALL(*this, ReadDone(DemuxerStream::kConfigChanged, _));
1113 GetStream(type)->Read(
1114 base::BindOnce(&ChunkDemuxerTest::ReadDone, base::Unretained(this)));
1115 base::RunLoop().RunUntilIdle();
1118 void CheckExpectedBuffers(DemuxerStream* stream,
1119 const std::string& expected) {
1120 std::vector<std::string> timestamps = base::SplitString(
1121 expected, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
1122 std::stringstream ss;
1123 for (size_t i = 0; i < timestamps.size(); ++i) {
1124 // Initialize status to kAborted since it's possible for Read() to return
1125 // without calling StoreStatusAndBuffer() if it doesn't have any buffers
1127 DemuxerStream::Status status = DemuxerStream::kAborted;
1128 scoped_refptr<DecoderBuffer> buffer;
1129 stream->Read(base::BindOnce(&ChunkDemuxerTest::StoreStatusAndBuffer,
1130 base::Unretained(this), &status, &buffer));
1131 base::RunLoop().RunUntilIdle();
1132 if (status != DemuxerStream::kOk || buffer->end_of_stream())
1137 ss << buffer->timestamp().InMilliseconds();
1139 if (buffer->is_key_frame())
1142 // Handle preroll buffers.
1143 if (base::EndsWith(timestamps[i], "P", base::CompareCase::SENSITIVE)) {
1144 ASSERT_EQ(kInfiniteDuration, buffer->discard_padding().first);
1145 ASSERT_EQ(base::TimeDelta(), buffer->discard_padding().second);
1149 EXPECT_EQ(expected, ss.str());
1152 MOCK_METHOD1(Checkpoint, void(int id));
1154 struct BufferTimestamps {
1158 static const int kSkip = -1;
1160 // Test parsing a WebM file.
1161 // |filename| - The name of the file in media/test/data to parse.
1162 // |timestamps| - The expected timestamps on the parsed buffers.
1163 // a timestamp of kSkip indicates that a Read() call for that stream
1164 // shouldn't be made on that iteration of the loop. If both streams have
1165 // a kSkip then the loop will terminate.
1166 bool ParseWebMFile(const std::string& filename,
1167 const BufferTimestamps* timestamps,
1168 const base::TimeDelta& duration) {
1169 return ParseWebMFile(filename, timestamps, duration, HAS_AUDIO | HAS_VIDEO);
1172 bool ParseWebMFile(const std::string& filename,
1173 const BufferTimestamps* timestamps,
1174 const base::TimeDelta& duration,
1176 EXPECT_CALL(*this, DemuxerOpened());
1177 demuxer_->Initialize(&host_, CreateInitDoneCallback(duration, PIPELINE_OK));
1179 if (AddId(kSourceId, stream_flags) != ChunkDemuxer::kOk)
1182 // Read a WebM file into memory and send the data to the demuxer.
1183 scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(filename);
1184 EXPECT_CALL(*this, InitSegmentReceivedMock(_));
1186 EXPECT_TRUE(AppendDataInPieces(buffer->data(), buffer->data_size(), 512));
1188 // Verify that the timestamps on the first few packets match what we
1191 (timestamps[i].audio_time_ms != kSkip ||
1192 timestamps[i].video_time_ms != kSkip);
1194 bool audio_read_done = false;
1195 bool video_read_done = false;
1197 if (timestamps[i].audio_time_ms != kSkip) {
1198 ReadAudio(base::BindOnce(
1199 &OnReadDone, base::Milliseconds(timestamps[i].audio_time_ms),
1201 EXPECT_TRUE(audio_read_done);
1204 if (timestamps[i].video_time_ms != kSkip) {
1205 ReadVideo(base::BindOnce(
1206 &OnReadDone, base::Milliseconds(timestamps[i].video_time_ms),
1208 EXPECT_TRUE(video_read_done);
1215 MOCK_METHOD0(DemuxerOpened, void());
1216 MOCK_METHOD2(OnEncryptedMediaInitData,
1217 void(EmeInitDataType init_data_type,
1218 const std::vector<uint8_t>& init_data));
1220 MOCK_METHOD1(InitSegmentReceivedMock, void(std::unique_ptr<MediaTracks>&));
1221 MOCK_METHOD1(OnParseWarningMock, void(const SourceBufferParseWarning));
1223 void OnProgress() { did_progress_ = true; }
1225 bool DidProgress() {
1226 bool result = did_progress_;
1227 did_progress_ = false;
1231 void Seek(base::TimeDelta seek_time) {
1232 demuxer_->StartWaitingForSeek(seek_time);
1233 demuxer_->Seek(seek_time, NewExpectedStatusCB(PIPELINE_OK));
1234 base::RunLoop().RunUntilIdle();
1237 void MarkEndOfStream(PipelineStatus status) {
1238 demuxer_->MarkEndOfStream(status);
1239 base::RunLoop().RunUntilIdle();
1242 bool SetTimestampOffset(const std::string& id,
1243 base::TimeDelta timestamp_offset) {
1244 if (demuxer_->IsParsingMediaSegment(id))
1247 timestamp_offset_map_[id] = timestamp_offset;
1251 base::test::TaskEnvironment task_environment_;
1253 StrictMock<MockMediaLog> media_log_;
1255 MockDemuxerHost host_;
1257 std::unique_ptr<ChunkDemuxer> demuxer_;
1258 Demuxer::MediaTracksUpdatedCB init_segment_received_cb_;
1262 base::TimeDelta append_window_start_for_next_append_;
1263 base::TimeDelta append_window_end_for_next_append_;
1265 // The size of coded frame data for a WebM SimpleBlock or BlockGroup muxed
1266 // into a test cluster. This defaults to |kBlockSize|, but can be changed to
1268 size_t block_size_ = kBlockSize;
1270 // Map of source id to timestamp offset to use for the next AppendData()
1271 // operation for that source id.
1272 std::map<std::string, base::TimeDelta> timestamp_offset_map_;
1275 void InitSegmentReceived(std::unique_ptr<MediaTracks> tracks) {
1276 DCHECK(tracks.get());
1277 DCHECK_GT(tracks->tracks().size(), 0u);
1279 // Verify that track ids are unique.
1280 std::set<MediaTrack::Id> track_ids;
1281 for (const auto& track : tracks->tracks()) {
1282 EXPECT_EQ(track_ids.end(), track_ids.find(track->id()));
1283 track_ids.insert(track->id());
1286 InitSegmentReceivedMock(tracks);
1290 TEST_F(ChunkDemuxerTest, Init) {
1293 // Test no streams, audio-only, video-only, and audio & video scenarios.
1294 // Audio and video streams can be encrypted or not encrypted.
1295 for (int i = 0; i < 16; i++) {
1296 bool has_audio = (i & 0x1) != 0;
1297 bool has_video = (i & 0x2) != 0;
1298 bool is_audio_encrypted = (i & 0x4) != 0;
1299 bool is_video_encrypted = (i & 0x8) != 0;
1301 // No test on invalid combination.
1302 if ((!has_audio && is_audio_encrypted) ||
1303 (!has_video && is_video_encrypted)) {
1309 int stream_flags = 0;
1311 stream_flags |= HAS_AUDIO;
1314 stream_flags |= HAS_VIDEO;
1316 if (has_audio || has_video) {
1317 ASSERT_TRUE(InitDemuxerWithEncryptionInfo(
1318 stream_flags, is_audio_encrypted, is_video_encrypted));
1320 ASSERT_FALSE(InitDemuxerWithEncryptionInfo(
1321 stream_flags, is_audio_encrypted, is_video_encrypted));
1324 DemuxerStream* audio_stream = GetStream(DemuxerStream::AUDIO);
1326 ASSERT_TRUE(audio_stream);
1328 const AudioDecoderConfig& config = audio_stream->audio_decoder_config();
1329 EXPECT_EQ(AudioCodec::kVorbis, config.codec());
1330 EXPECT_EQ(32, config.bits_per_channel());
1331 EXPECT_EQ(CHANNEL_LAYOUT_STEREO, config.channel_layout());
1332 EXPECT_EQ(44100, config.samples_per_second());
1333 EXPECT_GT(config.extra_data().size(), 0u);
1334 EXPECT_EQ(kSampleFormatPlanarF32, config.sample_format());
1335 EXPECT_EQ(is_audio_encrypted,
1336 audio_stream->audio_decoder_config().is_encrypted());
1338 EXPECT_FALSE(audio_stream);
1341 DemuxerStream* video_stream = GetStream(DemuxerStream::VIDEO);
1343 EXPECT_TRUE(video_stream);
1344 EXPECT_EQ(is_video_encrypted,
1345 video_stream->video_decoder_config().is_encrypted());
1347 EXPECT_FALSE(video_stream);
1350 for (auto* stream : demuxer_->GetAllStreams())
1351 EXPECT_TRUE(stream->SupportsConfigChanges());
1358 TEST_F(ChunkDemuxerTest, AddIdDuringOpenCallback) {
1359 // Tests that users may call |ChunkDemuxer::AddId| (or really any method that
1360 // acquires |ChunkDemuxer::lock_|) during the open callback.
1361 EXPECT_CALL(*this, DemuxerOpened()).WillOnce([this]() { this->AddId(); });
1364 demuxer_->Initialize(&host_, base::DoNothing());
1368 TEST_F(ChunkDemuxerTest, AudioVideoTrackIdsChange) {
1369 // Test with 1 audio and 1 video stream. Send a second init segment in which
1370 // the audio and video track IDs change. Verify that appended buffers before
1371 // and after the second init segment map to the same underlying track buffers.
1374 InitDemuxerWithEncryptionInfo(HAS_AUDIO | HAS_VIDEO, false, false));
1375 DemuxerStream* audio_stream = GetStream(DemuxerStream::AUDIO);
1376 DemuxerStream* video_stream = GetStream(DemuxerStream::VIDEO);
1377 ASSERT_TRUE(audio_stream);
1378 ASSERT_TRUE(video_stream);
1380 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "0K 23K", 23),
1381 MuxedStreamInfo(kVideoTrackNum, "0K 30", 30));
1382 CheckExpectedRanges("{ [0,46) }");
1384 EXPECT_CALL(*this, InitSegmentReceivedMock(_));
1385 ASSERT_TRUE(AppendInitSegment(HAS_AUDIO | HAS_VIDEO |
1386 USE_ALTERNATE_AUDIO_TRACK_ID |
1387 USE_ALTERNATE_VIDEO_TRACK_ID));
1388 AppendMuxedCluster(MuxedStreamInfo(kAlternateAudioTrackNum, "46K 69K", 63),
1389 MuxedStreamInfo(kAlternateVideoTrackNum, "60K", 23));
1390 CheckExpectedRanges("{ [0,92) }");
1391 CheckExpectedBuffers(audio_stream, "0K 23K 46K 69K");
1392 CheckExpectedBuffers(video_stream, "0K 30 60K");
1397 TEST_F(ChunkDemuxerTest, InitSegmentSetsNeedRandomAccessPointFlag) {
1398 // Tests that non-key-frames following an init segment are allowed
1399 // and dropped, as expected if the initialization segment received
1400 // algorithm correctly sets the needs random access point flag to true for all
1401 // track buffers. Note that the first initialization segment is insufficient
1402 // to fully test this since needs random access point flag initializes to
1406 InitDemuxerWithEncryptionInfo(HAS_AUDIO | HAS_VIDEO, false, false));
1407 DemuxerStream* audio_stream = GetStream(DemuxerStream::AUDIO);
1408 DemuxerStream* video_stream = GetStream(DemuxerStream::VIDEO);
1409 ASSERT_TRUE(audio_stream && video_stream);
1412 MuxedStreamInfo(kAudioTrackNum, "23K",
1413 WebMClusterParser::kDefaultAudioBufferDurationInMs),
1414 MuxedStreamInfo(kVideoTrackNum, "0 30K", 30));
1415 CheckExpectedRanges("{ [23,46) }");
1417 EXPECT_CALL(*this, InitSegmentReceivedMock(_));
1418 ASSERT_TRUE(AppendInitSegment(HAS_AUDIO | HAS_VIDEO));
1419 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "46K 69K", 23),
1420 MuxedStreamInfo(kVideoTrackNum, "60 90K", 30));
1421 CheckExpectedRanges("{ [23,92) }");
1423 CheckExpectedBuffers(audio_stream, "23K 46K 69K");
1424 CheckExpectedBuffers(video_stream, "30K 90K");
1427 TEST_F(ChunkDemuxerTest, Shutdown_BeforeAllInitSegmentsAppended) {
1428 EXPECT_CALL(*this, DemuxerOpened());
1429 demuxer_->Initialize(&host_,
1430 base::BindOnce(&ChunkDemuxerTest::DemuxerInitialized,
1431 base::Unretained(this)));
1433 EXPECT_EQ(AddId("audio", HAS_AUDIO), ChunkDemuxer::kOk);
1434 EXPECT_EQ(AddId("video", HAS_VIDEO), ChunkDemuxer::kOk);
1436 ExpectInitMediaLogs(HAS_AUDIO);
1437 EXPECT_CALL(*this, InitSegmentReceivedMock(_));
1438 ASSERT_TRUE(AppendInitSegmentWithSourceId("audio", HAS_AUDIO));
1443 // Verifies that all streams waiting for data receive an end of stream
1444 // buffer when Shutdown() is called.
1445 TEST_F(ChunkDemuxerTest, Shutdown_EndOfStreamWhileWaitingForData) {
1446 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1448 DemuxerStream* audio_stream = GetStream(DemuxerStream::AUDIO);
1449 DemuxerStream* video_stream = GetStream(DemuxerStream::VIDEO);
1451 bool audio_read_done = false;
1452 bool video_read_done = false;
1453 audio_stream->Read(base::BindOnce(&OnReadDone_EOSExpected, &audio_read_done));
1454 video_stream->Read(base::BindOnce(&OnReadDone_EOSExpected, &video_read_done));
1455 base::RunLoop().RunUntilIdle();
1457 EXPECT_FALSE(audio_read_done);
1458 EXPECT_FALSE(video_read_done);
1462 EXPECT_TRUE(audio_read_done);
1463 EXPECT_TRUE(video_read_done);
1466 // Test that Seek() completes successfully when the first cluster
1468 TEST_F(ChunkDemuxerTest, AppendDataAfterSeek) {
1469 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1470 ASSERT_TRUE(AppendCluster(kDefaultFirstCluster()));
1474 EXPECT_CALL(*this, Checkpoint(1));
1476 Seek(base::Milliseconds(46));
1478 EXPECT_CALL(*this, Checkpoint(2));
1482 ASSERT_TRUE(AppendCluster(kDefaultSecondCluster()));
1484 base::RunLoop().RunUntilIdle();
1489 // Test that parsing errors are handled for clusters appended after init.
1490 TEST_F(ChunkDemuxerTest, ErrorWhileParsingClusterAfterInit) {
1492 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1494 EXPECT_MEDIA_LOG(StreamParsingFailed());
1496 OnDemuxerError(HasStatusCode(CHUNK_DEMUXER_ERROR_APPEND_FAILED)));
1500 // Test the case where a Seek() is requested while the parser
1501 // is in the middle of cluster. This is to verify that the parser
1502 // does not reset itself on a seek.
1503 TEST_F(ChunkDemuxerTest, SeekWhileParsingCluster) {
1504 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1508 std::unique_ptr<Cluster> cluster_a(GenerateCluster(0, 6));
1510 // Split the cluster into two appends at an arbitrary point near the end.
1511 int first_append_size = cluster_a->size() - 11;
1512 int second_append_size = cluster_a->size() - first_append_size;
1514 // Append the first part of the cluster.
1515 ASSERT_TRUE(AppendData(cluster_a->data(), first_append_size));
1517 ExpectRead(DemuxerStream::AUDIO, 0);
1518 ExpectRead(DemuxerStream::VIDEO, 0);
1519 ExpectRead(DemuxerStream::AUDIO, kAudioBlockDuration);
1521 Seek(base::Seconds(5));
1523 // Append the rest of the cluster.
1525 AppendData(cluster_a->data() + first_append_size, second_append_size));
1527 // Append the new cluster and verify that only the blocks
1528 // in the new cluster are returned.
1529 ASSERT_TRUE(AppendCluster(GenerateCluster(5000, 6)));
1530 GenerateExpectedReads(5000, 6);
1533 // Test the case where AppendData() is called before Init().
1534 TEST_F(ChunkDemuxerTest, AppendDataBeforeInit) {
1535 std::unique_ptr<uint8_t[]> info_tracks;
1536 int info_tracks_size = 0;
1537 CreateInitSegment(HAS_AUDIO | HAS_VIDEO,
1538 false, false, &info_tracks, &info_tracks_size);
1539 ASSERT_FALSE(demuxer_->AppendData(
1540 kSourceId, info_tracks.get(), info_tracks_size,
1541 append_window_start_for_next_append_, append_window_end_for_next_append_,
1542 ×tamp_offset_map_[kSourceId]));
1545 // Make sure Read() callbacks are dispatched with the proper data.
1546 TEST_F(ChunkDemuxerTest, Read) {
1547 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1549 ASSERT_TRUE(AppendCluster(kDefaultFirstCluster()));
1551 bool audio_read_done = false;
1552 bool video_read_done = false;
1554 base::BindOnce(&OnReadDone, base::Milliseconds(0), &audio_read_done));
1556 base::BindOnce(&OnReadDone, base::Milliseconds(0), &video_read_done));
1558 EXPECT_TRUE(audio_read_done);
1559 EXPECT_TRUE(video_read_done);
1562 TEST_F(ChunkDemuxerTest, OutOfOrderClusters) {
1563 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1564 DemuxerStream* audio_stream = GetStream(DemuxerStream::AUDIO);
1565 DemuxerStream* video_stream = GetStream(DemuxerStream::VIDEO);
1567 ASSERT_TRUE(AppendCluster(kDefaultFirstCluster()));
1568 CheckExpectedBuffers(audio_stream, "0K 23K");
1569 CheckExpectedBuffers(video_stream, "0K 33");
1570 // Note: splice trimming changes durations. These are verified in lower level
1571 // tests. See SourceBufferStreamTest.Audio_SpliceTrimmingForOverlap.
1572 EXPECT_MEDIA_LOG(TrimmedSpliceOverlap(10000, 0, 13000));
1573 ASSERT_TRUE(AppendCluster(GenerateCluster(10, 4)));
1574 Seek(base::TimeDelta());
1575 CheckExpectedBuffers(audio_stream, "0K 10K 33K");
1576 CheckExpectedBuffers(video_stream, "0K 10K 43");
1578 // Make sure that AppendCluster() does not fail with a cluster that has
1579 // overlaps with the previously appended cluster.
1580 EXPECT_MEDIA_LOG(TrimmedSpliceOverlap(5000, 0, 5000));
1581 ASSERT_TRUE(AppendCluster(GenerateCluster(5, 4)));
1582 Seek(base::TimeDelta());
1583 CheckExpectedBuffers(audio_stream, "0K 5K 28K");
1584 CheckExpectedBuffers(video_stream, "0K 5K 38");
1586 // Verify that AppendData() can still accept more data.
1587 std::unique_ptr<Cluster> cluster_c(GenerateCluster(45, 2));
1588 EXPECT_MEDIA_LOG(TrimmedSpliceOverlap(45000, 28000, 6000));
1589 ASSERT_TRUE(demuxer_->AppendData(
1590 kSourceId, cluster_c->data(), cluster_c->size(),
1591 append_window_start_for_next_append_, append_window_end_for_next_append_,
1592 ×tamp_offset_map_[kSourceId]));
1593 Seek(base::Milliseconds(45));
1594 CheckExpectedBuffers(audio_stream, "45K");
1595 CheckExpectedBuffers(video_stream, "45K");
1598 TEST_F(ChunkDemuxerTest, NonMonotonicButAboveClusterTimecode) {
1599 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1600 ASSERT_TRUE(AppendCluster(kDefaultFirstCluster()));
1604 // Test the case where block timecodes are not monotonically
1605 // increasing but stay above the cluster timecode.
1606 cb.SetClusterTimecode(5);
1607 AddSimpleBlock(&cb, kAudioTrackNum, 5);
1608 AddSimpleBlock(&cb, kVideoTrackNum, 10);
1609 AddSimpleBlock(&cb, kAudioTrackNum, 7);
1610 AddSimpleBlock(&cb, kVideoTrackNum, 15);
1612 EXPECT_MEDIA_LOG(WebMOutOfOrderTimecode());
1613 EXPECT_MEDIA_LOG(StreamParsingFailed());
1615 OnDemuxerError(HasStatusCode(CHUNK_DEMUXER_ERROR_APPEND_FAILED)));
1616 ASSERT_FALSE(AppendCluster(cb.Finish()));
1618 // Verify that AppendData() ignores data after the error.
1619 std::unique_ptr<Cluster> cluster_b(GenerateCluster(20, 2));
1620 ASSERT_FALSE(demuxer_->AppendData(
1621 kSourceId, cluster_b->data(), cluster_b->size(),
1622 append_window_start_for_next_append_, append_window_end_for_next_append_,
1623 ×tamp_offset_map_[kSourceId]));
1626 TEST_F(ChunkDemuxerTest, BeforeClusterTimecode) {
1627 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1628 ASSERT_TRUE(AppendCluster(kDefaultFirstCluster()));
1631 uint8_t data[] = {0x00};
1633 // Test timecodes before the cluster timecode are allowed now. This next
1634 // cluster mimics the blocks in kDefaultSecondCluster(), but with a cluster
1635 // timecode in the future. The blocks will have relative timestamps that
1636 // should make them appear as if they are precisely those in
1637 // kDefaultSecondCluster().
1638 cb.SetClusterTimecode(1000); // In the future relative to the next blocks.
1639 cb.AddSimpleBlock(kAudioTrackNum, 46, kWebMFlagKeyframe, data, sizeof(data));
1640 cb.AddSimpleBlock(kVideoTrackNum, 66, kWebMFlagKeyframe, data, sizeof(data));
1641 cb.AddSimpleBlock(kAudioTrackNum, 69, kWebMFlagKeyframe, data, sizeof(data));
1642 cb.AddBlockGroup(kAudioTrackNum, 92, kAudioBlockDuration, kWebMFlagKeyframe,
1643 true, data, sizeof(data));
1644 cb.AddBlockGroup(kVideoTrackNum, 99, kVideoBlockDuration, 0, false, data,
1647 ASSERT_TRUE(AppendCluster(cb.Finish()));
1648 GenerateExpectedReads(0, 9);
1651 TEST_F(ChunkDemuxerTest, NonMonotonicButBeforeClusterTimecode) {
1652 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1653 ASSERT_TRUE(AppendCluster(kDefaultFirstCluster()));
1656 uint8_t data[] = {0x00};
1658 // Test timecodes going backwards and including values less than the cluster
1660 cb.SetClusterTimecode(1000);
1661 cb.AddSimpleBlock(kAudioTrackNum, 69, kWebMFlagKeyframe, data, sizeof(data));
1662 cb.AddSimpleBlock(kVideoTrackNum, 99, kWebMFlagKeyframe, data, sizeof(data));
1663 cb.AddSimpleBlock(kAudioTrackNum, 46, kWebMFlagKeyframe, data, sizeof(data));
1665 EXPECT_MEDIA_LOG(WebMOutOfOrderTimecode());
1666 EXPECT_MEDIA_LOG(StreamParsingFailed());
1668 OnDemuxerError(HasStatusCode(CHUNK_DEMUXER_ERROR_APPEND_FAILED)));
1669 ASSERT_FALSE(AppendCluster(cb.Finish()));
1671 // Verify that AppendData() ignores data after the error.
1672 std::unique_ptr<Cluster> cluster_b(GenerateCluster(6, 2));
1673 ASSERT_FALSE(demuxer_->AppendData(
1674 kSourceId, cluster_b->data(), cluster_b->size(),
1675 append_window_start_for_next_append_, append_window_end_for_next_append_,
1676 ×tamp_offset_map_[kSourceId]));
1679 TEST_F(ChunkDemuxerTest, PerStreamMonotonicallyIncreasingTimestamps) {
1680 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1681 ASSERT_TRUE(AppendCluster(kDefaultFirstCluster()));
1685 // Test monotonic increasing timestamps on a per stream
1687 cb.SetClusterTimecode(4);
1688 AddSimpleBlock(&cb, kAudioTrackNum, 5);
1689 AddSimpleBlock(&cb, kVideoTrackNum, 5);
1690 AddSimpleBlock(&cb, kAudioTrackNum, 4);
1691 AddSimpleBlock(&cb, kVideoTrackNum, 7);
1693 EXPECT_MEDIA_LOG(WebMOutOfOrderTimecode());
1694 EXPECT_MEDIA_LOG(StreamParsingFailed());
1696 OnDemuxerError(HasStatusCode(CHUNK_DEMUXER_ERROR_APPEND_FAILED)));
1697 ASSERT_FALSE(AppendCluster(cb.Finish()));
1700 // Test the case where a cluster is passed to AppendCluster() before
1701 // INFO & TRACKS data.
1702 TEST_F(ChunkDemuxerTest, ClusterBeforeInitSegment) {
1703 EXPECT_CALL(*this, DemuxerOpened());
1704 demuxer_->Initialize(&host_,
1705 NewExpectedStatusCB(CHUNK_DEMUXER_ERROR_APPEND_FAILED));
1707 ASSERT_EQ(AddId(), ChunkDemuxer::kOk);
1709 EXPECT_MEDIA_LOG(WebMClusterBeforeFirstInfo());
1710 EXPECT_MEDIA_LOG(StreamParsingFailed());
1711 ASSERT_FALSE(AppendCluster(GenerateCluster(0, 1)));
1714 // Test cases where we get an MarkEndOfStream() call during initialization.
1715 TEST_F(ChunkDemuxerTest, EOSDuringInit) {
1716 EXPECT_CALL(*this, DemuxerOpened());
1717 demuxer_->Initialize(&host_,
1718 NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN));
1719 EXPECT_MEDIA_LOG(EosBeforeHaveMetadata());
1720 MarkEndOfStream(PIPELINE_OK);
1723 TEST_F(ChunkDemuxerTest, EndOfStreamWithNoAppend) {
1724 EXPECT_CALL(*this, DemuxerOpened());
1725 demuxer_->Initialize(&host_,
1726 NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN));
1728 ASSERT_EQ(AddId(), ChunkDemuxer::kOk);
1730 CheckExpectedRanges("{ }");
1732 EXPECT_MEDIA_LOG(EosBeforeHaveMetadata());
1733 MarkEndOfStream(PIPELINE_OK);
1736 CheckExpectedRanges("{ }");
1737 demuxer_->RemoveId(kSourceId);
1741 TEST_F(ChunkDemuxerTest, EndOfStreamWithNoMediaAppend) {
1742 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1744 CheckExpectedRanges("{ }");
1745 MarkEndOfStream(PIPELINE_OK);
1746 CheckExpectedRanges("{ }");
1749 TEST_F(ChunkDemuxerTest, DecodeErrorEndOfStream) {
1750 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1752 ASSERT_TRUE(AppendCluster(kDefaultFirstCluster()));
1753 CheckExpectedRanges(kDefaultFirstClusterRange);
1755 EXPECT_CALL(host_, OnDemuxerError(HasStatusCode(
1756 CHUNK_DEMUXER_ERROR_EOS_STATUS_DECODE_ERROR)));
1757 MarkEndOfStream(CHUNK_DEMUXER_ERROR_EOS_STATUS_DECODE_ERROR);
1758 CheckExpectedRanges(kDefaultFirstClusterRange);
1761 TEST_F(ChunkDemuxerTest, NetworkErrorEndOfStream) {
1762 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1764 ASSERT_TRUE(AppendCluster(kDefaultFirstCluster()));
1765 CheckExpectedRanges(kDefaultFirstClusterRange);
1767 EXPECT_CALL(host_, OnDemuxerError(HasStatusCode(
1768 CHUNK_DEMUXER_ERROR_EOS_STATUS_NETWORK_ERROR)));
1769 MarkEndOfStream(CHUNK_DEMUXER_ERROR_EOS_STATUS_NETWORK_ERROR);
1772 // Helper class to reduce duplicate code when testing end of stream
1774 class EndOfStreamHelper {
1776 explicit EndOfStreamHelper(DemuxerStream* audio, DemuxerStream* video)
1777 : audio_stream_(audio),
1778 video_stream_(video),
1779 audio_read_done_(false),
1780 video_read_done_(false) {}
1782 EndOfStreamHelper(const EndOfStreamHelper&) = delete;
1783 EndOfStreamHelper& operator=(const EndOfStreamHelper&) = delete;
1785 // Request a read on the audio and video streams.
1786 void RequestReads() {
1787 EXPECT_FALSE(audio_read_done_);
1788 EXPECT_FALSE(video_read_done_);
1790 audio_stream_->Read(
1791 base::BindOnce(&OnEndOfStreamReadDone, &audio_read_done_));
1792 video_stream_->Read(
1793 base::BindOnce(&OnEndOfStreamReadDone, &video_read_done_));
1794 base::RunLoop().RunUntilIdle();
1797 // Check to see if |audio_read_done_| and |video_read_done_| variables
1798 // match |expected|.
1799 void CheckIfReadDonesWereCalled(bool expected) {
1800 base::RunLoop().RunUntilIdle();
1801 EXPECT_EQ(expected, audio_read_done_);
1802 EXPECT_EQ(expected, video_read_done_);
1806 static void OnEndOfStreamReadDone(bool* called,
1807 DemuxerStream::Status status,
1808 scoped_refptr<DecoderBuffer> buffer) {
1809 EXPECT_EQ(status, DemuxerStream::kOk);
1810 EXPECT_TRUE(buffer->end_of_stream());
1814 raw_ptr<DemuxerStream> audio_stream_;
1815 raw_ptr<DemuxerStream> video_stream_;
1816 bool audio_read_done_;
1817 bool video_read_done_;
1820 // Make sure that all pending reads that we don't have media data for get an
1821 // "end of stream" buffer when MarkEndOfStream() is called.
1822 TEST_F(ChunkDemuxerTest, EndOfStreamWithPendingReads) {
1823 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1825 ASSERT_TRUE(AppendCluster(GenerateCluster(0, 2)));
1827 bool audio_read_done_1 = false;
1828 bool video_read_done_1 = false;
1829 DemuxerStream* audio_stream = GetStream(DemuxerStream::AUDIO);
1830 DemuxerStream* video_stream = GetStream(DemuxerStream::VIDEO);
1831 EndOfStreamHelper end_of_stream_helper_1(audio_stream, video_stream);
1832 EndOfStreamHelper end_of_stream_helper_2(audio_stream, video_stream);
1835 base::BindOnce(&OnReadDone, base::Milliseconds(0), &audio_read_done_1));
1837 base::BindOnce(&OnReadDone, base::Milliseconds(0), &video_read_done_1));
1838 base::RunLoop().RunUntilIdle();
1840 EXPECT_TRUE(audio_read_done_1);
1841 EXPECT_TRUE(video_read_done_1);
1843 end_of_stream_helper_1.RequestReads();
1845 EXPECT_CALL(host_, SetDuration(base::Milliseconds(kVideoBlockDuration)));
1846 MarkEndOfStream(PIPELINE_OK);
1848 end_of_stream_helper_1.CheckIfReadDonesWereCalled(true);
1850 end_of_stream_helper_2.RequestReads();
1851 end_of_stream_helper_2.CheckIfReadDonesWereCalled(true);
1854 // Make sure that all Read() calls after we get an MarkEndOfStream()
1855 // call return an "end of stream" buffer.
1856 TEST_F(ChunkDemuxerTest, ReadsAfterEndOfStream) {
1857 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1859 ASSERT_TRUE(AppendCluster(GenerateCluster(0, 2)));
1861 bool audio_read_done_1 = false;
1862 bool video_read_done_1 = false;
1863 DemuxerStream* audio_stream = GetStream(DemuxerStream::AUDIO);
1864 DemuxerStream* video_stream = GetStream(DemuxerStream::VIDEO);
1865 EndOfStreamHelper end_of_stream_helper_1(audio_stream, video_stream);
1866 EndOfStreamHelper end_of_stream_helper_2(audio_stream, video_stream);
1867 EndOfStreamHelper end_of_stream_helper_3(audio_stream, video_stream);
1870 base::BindOnce(&OnReadDone, base::Milliseconds(0), &audio_read_done_1));
1872 base::BindOnce(&OnReadDone, base::Milliseconds(0), &video_read_done_1));
1874 end_of_stream_helper_1.RequestReads();
1876 EXPECT_TRUE(audio_read_done_1);
1877 EXPECT_TRUE(video_read_done_1);
1878 end_of_stream_helper_1.CheckIfReadDonesWereCalled(false);
1880 EXPECT_CALL(host_, SetDuration(base::Milliseconds(kVideoBlockDuration)));
1881 MarkEndOfStream(PIPELINE_OK);
1883 end_of_stream_helper_1.CheckIfReadDonesWereCalled(true);
1885 // Request a few more reads and make sure we immediately get
1886 // end of stream buffers.
1887 end_of_stream_helper_2.RequestReads();
1888 end_of_stream_helper_2.CheckIfReadDonesWereCalled(true);
1890 end_of_stream_helper_3.RequestReads();
1891 end_of_stream_helper_3.CheckIfReadDonesWereCalled(true);
1894 TEST_F(ChunkDemuxerTest, EndOfStreamDuringCanceledSeek) {
1895 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1897 ASSERT_TRUE(AppendCluster(0, 10));
1898 EXPECT_CALL(host_, SetDuration(base::Milliseconds(138)));
1899 MarkEndOfStream(PIPELINE_OK);
1901 // Start the first seek.
1902 Seek(base::Milliseconds(20));
1904 // Simulate another seek being requested before the first
1905 // seek has finished prerolling.
1906 base::TimeDelta seek_time2 = base::Milliseconds(30);
1907 demuxer_->CancelPendingSeek(seek_time2);
1909 // Finish second seek.
1912 DemuxerStream::Status status;
1913 base::TimeDelta last_timestamp;
1915 // Make sure audio can reach end of stream.
1916 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp);
1917 ASSERT_EQ(status, DemuxerStream::kOk);
1919 // Make sure video can reach end of stream.
1920 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp);
1921 ASSERT_EQ(status, DemuxerStream::kOk);
1924 // Verify buffered range change behavior for audio/video/text tracks.
1925 TEST_F(ChunkDemuxerTest, EndOfStreamRangeChanges) {
1926 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1928 AppendMuxedCluster(MuxedStreamInfo(kVideoTrackNum, "0K 33", 33),
1929 MuxedStreamInfo(kAudioTrackNum, "0K 23K", 23));
1931 CheckExpectedRanges("{ [0,46) }");
1933 EXPECT_CALL(host_, SetDuration(base::Milliseconds(66)));
1934 MarkEndOfStream(PIPELINE_OK);
1936 CheckExpectedRanges("{ [0,66) }");
1939 // Make sure AppendData() will accept elements that span multiple calls.
1940 TEST_F(ChunkDemuxerTest, AppendingInPieces) {
1941 EXPECT_CALL(*this, DemuxerOpened());
1942 demuxer_->Initialize(&host_,
1943 CreateInitDoneCallback(kDefaultDuration(), PIPELINE_OK));
1945 ASSERT_EQ(AddId(), ChunkDemuxer::kOk);
1947 std::unique_ptr<uint8_t[]> info_tracks;
1948 int info_tracks_size = 0;
1949 CreateInitSegment(HAS_AUDIO | HAS_VIDEO,
1950 false, false, &info_tracks, &info_tracks_size);
1952 std::unique_ptr<Cluster> cluster_a(kDefaultFirstCluster());
1953 std::unique_ptr<Cluster> cluster_b(kDefaultSecondCluster());
1955 size_t buffer_size = info_tracks_size + cluster_a->size() + cluster_b->size();
1956 std::unique_ptr<uint8_t[]> buffer(new uint8_t[buffer_size]);
1957 uint8_t* dst = buffer.get();
1958 memcpy(dst, info_tracks.get(), info_tracks_size);
1959 dst += info_tracks_size;
1961 memcpy(dst, cluster_a->data(), cluster_a->size());
1962 dst += cluster_a->size();
1964 memcpy(dst, cluster_b->data(), cluster_b->size());
1965 dst += cluster_b->size();
1967 ExpectInitMediaLogs(HAS_AUDIO | HAS_VIDEO);
1968 EXPECT_CALL(*this, InitSegmentReceivedMock(_));
1969 EXPECT_FALSE(DidProgress());
1970 ASSERT_TRUE(AppendDataInPieces(buffer.get(), buffer_size));
1971 EXPECT_TRUE(DidProgress());
1973 GenerateExpectedReads(0, 9);
1976 TEST_F(ChunkDemuxerTest, WebMFile_AudioAndVideo) {
1977 struct BufferTimestamps buffer_timestamps[] = {
1986 ExpectInitMediaLogs(HAS_AUDIO | HAS_VIDEO);
1987 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(2)).Times(7);
1989 // Expect duration adjustment since actual duration differs slightly from
1990 // duration in the init segment.
1991 EXPECT_CALL(host_, SetDuration(base::Milliseconds(2768)));
1993 ASSERT_TRUE(ParseWebMFile("bear-320x240.webm", buffer_timestamps,
1994 base::Milliseconds(2744)));
1995 EXPECT_EQ(212949, demuxer_->GetMemoryUsage());
1998 TEST_F(ChunkDemuxerTest, WebMFile_LiveAudioAndVideo) {
1999 struct BufferTimestamps buffer_timestamps[] = {
2008 ExpectInitMediaLogs(HAS_AUDIO | HAS_VIDEO);
2009 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(2)).Times(7);
2010 ASSERT_TRUE(ParseWebMFile("bear-320x240-live.webm", buffer_timestamps,
2011 kInfiniteDuration));
2013 DemuxerStream* audio = GetStream(DemuxerStream::AUDIO);
2014 EXPECT_EQ(StreamLiveness::kLive, audio->liveness());
2015 DemuxerStream* video = GetStream(DemuxerStream::VIDEO);
2016 EXPECT_EQ(StreamLiveness::kLive, video->liveness());
2017 EXPECT_EQ(212949, demuxer_->GetMemoryUsage());
2020 TEST_F(ChunkDemuxerTest, WebMFile_AudioOnly) {
2021 struct BufferTimestamps buffer_timestamps[] = {
2030 ExpectInitMediaLogs(HAS_AUDIO);
2031 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(2));
2033 // Expect duration adjustment since actual duration differs slightly from
2034 // duration in the init segment.
2035 EXPECT_CALL(host_, SetDuration(base::Milliseconds(2768)));
2037 ASSERT_TRUE(ParseWebMFile("bear-320x240-audio-only.webm", buffer_timestamps,
2038 base::Milliseconds(2744), HAS_AUDIO));
2039 EXPECT_EQ(18624, demuxer_->GetMemoryUsage());
2042 TEST_F(ChunkDemuxerTest, WebMFile_VideoOnly) {
2043 struct BufferTimestamps buffer_timestamps[] = {
2052 ExpectInitMediaLogs(HAS_VIDEO);
2054 // Expect duration adjustment since actual duration differs slightly from
2055 // duration in the init segment.
2056 EXPECT_CALL(host_, SetDuration(base::Milliseconds(2736)));
2058 ASSERT_TRUE(ParseWebMFile("bear-320x240-video-only.webm", buffer_timestamps,
2059 base::Milliseconds(2703), HAS_VIDEO));
2060 EXPECT_EQ(194325, demuxer_->GetMemoryUsage());
2063 TEST_F(ChunkDemuxerTest, WebMFile_AltRefFrames) {
2064 struct BufferTimestamps buffer_timestamps[] = {
2073 // Expect duration adjustment since actual duration differs slightly from
2074 // duration in the init segment.
2075 EXPECT_CALL(host_, SetDuration(base::Milliseconds(2768)));
2077 ExpectInitMediaLogs(HAS_AUDIO | HAS_VIDEO);
2078 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(2));
2079 ASSERT_TRUE(ParseWebMFile("bear-320x240-altref.webm", buffer_timestamps,
2080 base::Milliseconds(2767)));
2083 // Verify that we output buffers before the entire cluster has been parsed.
2084 TEST_F(ChunkDemuxerTest, IncrementalClusterParsing) {
2085 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2087 std::unique_ptr<Cluster> cluster(GenerateCluster(0, 6));
2089 bool audio_read_done = false;
2090 bool video_read_done = false;
2092 base::BindOnce(&OnReadDone, base::Milliseconds(0), &audio_read_done));
2094 base::BindOnce(&OnReadDone, base::Milliseconds(0), &video_read_done));
2096 // Make sure the reads haven't completed yet.
2097 EXPECT_FALSE(audio_read_done);
2098 EXPECT_FALSE(video_read_done);
2100 // Append data one byte at a time until one or both reads complete.
2102 for (; i < cluster->size() && !(audio_read_done || video_read_done); ++i) {
2103 ASSERT_TRUE(AppendData(cluster->data() + i, 1));
2104 base::RunLoop().RunUntilIdle();
2107 EXPECT_TRUE(audio_read_done || video_read_done);
2109 EXPECT_LT(i, cluster->size());
2111 audio_read_done = false;
2112 video_read_done = false;
2114 base::BindOnce(&OnReadDone, base::Milliseconds(23), &audio_read_done));
2116 base::BindOnce(&OnReadDone, base::Milliseconds(33), &video_read_done));
2118 // Make sure the reads haven't completed yet.
2119 EXPECT_FALSE(audio_read_done);
2120 EXPECT_FALSE(video_read_done);
2122 // Append the remaining data.
2123 ASSERT_LT(i, cluster->size());
2124 ASSERT_TRUE(AppendData(cluster->data() + i, cluster->size() - i));
2126 base::RunLoop().RunUntilIdle();
2128 EXPECT_TRUE(audio_read_done);
2129 EXPECT_TRUE(video_read_done);
2132 TEST_F(ChunkDemuxerTest, ParseErrorDuringInit) {
2133 EXPECT_CALL(*this, DemuxerOpened());
2134 demuxer_->Initialize(
2136 CreateInitDoneCallback(kNoTimestamp, CHUNK_DEMUXER_ERROR_APPEND_FAILED));
2138 ASSERT_EQ(AddId(), ChunkDemuxer::kOk);
2140 EXPECT_MEDIA_LOG(StreamParsingFailed());
2142 ASSERT_FALSE(demuxer_->AppendData(
2143 kSourceId, &tmp, 1, append_window_start_for_next_append_,
2144 append_window_end_for_next_append_, ×tamp_offset_map_[kSourceId]));
2147 TEST_F(ChunkDemuxerTest, AVHeadersWithAudioOnlyType) {
2148 EXPECT_CALL(*this, DemuxerOpened());
2149 demuxer_->Initialize(
2151 CreateInitDoneCallback(kNoTimestamp, CHUNK_DEMUXER_ERROR_APPEND_FAILED));
2153 ASSERT_EQ(AddId(kSourceId, "audio/webm", "vorbis"), ChunkDemuxer::kOk);
2155 // Video track is unexpected per mimetype.
2156 EXPECT_MEDIA_LOG(InitSegmentMismatchesMimeType("Video", "vp8"));
2157 EXPECT_MEDIA_LOG(StreamParsingFailed());
2158 ASSERT_FALSE(AppendInitSegment(HAS_AUDIO | HAS_VIDEO));
2161 TEST_F(ChunkDemuxerTest, AVHeadersWithVideoOnlyType) {
2162 EXPECT_CALL(*this, DemuxerOpened());
2163 demuxer_->Initialize(
2165 CreateInitDoneCallback(kNoTimestamp, CHUNK_DEMUXER_ERROR_APPEND_FAILED));
2167 ASSERT_EQ(AddId(kSourceId, "video/webm", "vp8"), ChunkDemuxer::kOk);
2169 // Audio track is unexpected per mimetype.
2170 EXPECT_FOUND_CODEC_NAME(Video, "vp8");
2171 EXPECT_MEDIA_LOG(InitSegmentMismatchesMimeType("Audio", "vorbis"));
2172 EXPECT_MEDIA_LOG(StreamParsingFailed());
2173 ASSERT_FALSE(AppendInitSegment(HAS_AUDIO | HAS_VIDEO));
2176 TEST_F(ChunkDemuxerTest, AudioOnlyHeaderWithAVType) {
2177 EXPECT_CALL(*this, DemuxerOpened());
2178 demuxer_->Initialize(
2180 CreateInitDoneCallback(kNoTimestamp, CHUNK_DEMUXER_ERROR_APPEND_FAILED));
2182 ASSERT_EQ(AddId(kSourceId, "video/webm", "vorbis,vp8"), ChunkDemuxer::kOk);
2184 // Video track is also expected per mimetype.
2185 EXPECT_FOUND_CODEC_NAME(Audio, "vorbis");
2186 EXPECT_MEDIA_LOG(InitSegmentMissesExpectedTrack("vp8"));
2187 EXPECT_MEDIA_LOG(StreamParsingFailed());
2188 ASSERT_FALSE(AppendInitSegment(HAS_AUDIO));
2191 TEST_F(ChunkDemuxerTest, VideoOnlyHeaderWithAVType) {
2192 EXPECT_CALL(*this, DemuxerOpened());
2193 demuxer_->Initialize(
2195 CreateInitDoneCallback(kNoTimestamp, CHUNK_DEMUXER_ERROR_APPEND_FAILED));
2197 ASSERT_EQ(AddId(kSourceId, "video/webm", "vorbis,vp8"), ChunkDemuxer::kOk);
2199 // Audio track is also expected per mimetype.
2200 EXPECT_FOUND_CODEC_NAME(Video, "vp8");
2201 EXPECT_MEDIA_LOG(InitSegmentMissesExpectedTrack("vorbis"));
2202 EXPECT_MEDIA_LOG(StreamParsingFailed());
2203 ASSERT_FALSE(AppendInitSegment(HAS_VIDEO));
2206 TEST_F(ChunkDemuxerTest, MultipleHeaders) {
2207 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2209 ASSERT_TRUE(AppendCluster(kDefaultFirstCluster()));
2211 // Append another identical initialization segment.
2212 EXPECT_CALL(*this, InitSegmentReceivedMock(_));
2213 ASSERT_TRUE(AppendInitSegment(HAS_AUDIO | HAS_VIDEO));
2215 ASSERT_TRUE(AppendCluster(kDefaultSecondCluster()));
2217 GenerateExpectedReads(0, 9);
2220 TEST_F(ChunkDemuxerTest, AddSeparateSourcesForAudioAndVideo) {
2221 std::string audio_id = "audio1";
2222 std::string video_id = "video1";
2223 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
2225 // Append audio and video data into separate source ids.
2226 ASSERT_TRUE(AppendCluster(
2228 GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration)));
2229 GenerateAudioStreamExpectedReads(0, 4);
2230 ASSERT_TRUE(AppendCluster(video_id,
2231 GenerateSingleStreamCluster(0, 132, kVideoTrackNum,
2232 kVideoBlockDuration)));
2233 GenerateVideoStreamExpectedReads(0, 4);
2236 TEST_F(ChunkDemuxerTest, AddSeparateSourcesForAudioAndVideoText) {
2237 std::string audio_id = "audio1";
2238 std::string video_id = "video1";
2240 ASSERT_TRUE(InitDemuxerAudioAndVideoSourcesText(audio_id, video_id));
2242 // Append audio and video data into separate source ids.
2243 ASSERT_TRUE(AppendCluster(
2245 GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration)));
2246 GenerateAudioStreamExpectedReads(0, 4);
2247 ASSERT_TRUE(AppendCluster(video_id,
2248 GenerateSingleStreamCluster(0, 132, kVideoTrackNum,
2249 kVideoBlockDuration)));
2250 GenerateVideoStreamExpectedReads(0, 4);
2253 TEST_F(ChunkDemuxerTest, AddIdFailures) {
2254 EXPECT_CALL(*this, DemuxerOpened());
2255 demuxer_->Initialize(&host_,
2256 CreateInitDoneCallback(kDefaultDuration(), PIPELINE_OK));
2258 std::string audio_id = "audio1";
2259 std::string video_id = "video1";
2261 ASSERT_EQ(AddId(audio_id, HAS_AUDIO), ChunkDemuxer::kOk);
2263 ExpectInitMediaLogs(HAS_AUDIO);
2264 EXPECT_CALL(*this, InitSegmentReceivedMock(_));
2265 ASSERT_TRUE(AppendInitSegmentWithSourceId(audio_id, HAS_AUDIO));
2267 // Adding an id after append should fail.
2268 ASSERT_EQ(AddId(video_id, HAS_VIDEO), ChunkDemuxer::kReachedIdLimit);
2271 // Test that Read() calls after a RemoveId() return "end of stream" buffers.
2272 TEST_F(ChunkDemuxerTest, RemoveId) {
2273 std::string audio_id = "audio1";
2274 std::string video_id = "video1";
2275 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
2277 // Append audio and video data into separate source ids.
2278 ASSERT_TRUE(AppendCluster(
2280 GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration)));
2281 ASSERT_TRUE(AppendCluster(video_id,
2282 GenerateSingleStreamCluster(0, 132, kVideoTrackNum,
2283 kVideoBlockDuration)));
2285 // Read() from audio should return normal buffers.
2286 GenerateAudioStreamExpectedReads(0, 4);
2288 // Audio stream will become inaccessible after |audio_id| is removed, so save
2289 // it here to read from it after RemoveId.
2290 DemuxerStream* audio_stream = GetStream(DemuxerStream::AUDIO);
2292 // Remove the audio id.
2293 demuxer_->RemoveId(audio_id);
2295 // Read() from audio should return "end of stream" buffers.
2296 bool audio_read_done = false;
2297 audio_stream->Read(base::BindOnce(&OnReadDone_EOSExpected, &audio_read_done));
2298 base::RunLoop().RunUntilIdle();
2299 EXPECT_TRUE(audio_read_done);
2301 // Read() from video should still return normal buffers.
2302 GenerateVideoStreamExpectedReads(0, 4);
2305 // Test that removing an ID immediately after adding it does not interfere with
2306 // quota for new IDs in the future.
2307 TEST_F(ChunkDemuxerTest, RemoveAndAddId) {
2308 demuxer_->Initialize(&host_,
2309 base::BindOnce(&ChunkDemuxerTest::DemuxerInitialized,
2310 base::Unretained(this)));
2312 std::string audio_id_1 = "audio1";
2313 ASSERT_TRUE(AddId(audio_id_1, HAS_AUDIO) == ChunkDemuxer::kOk);
2314 demuxer_->RemoveId(audio_id_1);
2316 std::string audio_id_2 = "audio2";
2317 ASSERT_TRUE(AddId(audio_id_2, HAS_AUDIO) == ChunkDemuxer::kOk);
2320 TEST_F(ChunkDemuxerTest, SeekCanceled) {
2321 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2323 // Append cluster at the beginning of the stream.
2324 ASSERT_TRUE(AppendCluster(GenerateCluster(0, 4)));
2326 // Seek to an unbuffered region.
2327 Seek(base::Seconds(50));
2329 // Attempt to read in unbuffered area; should not fulfill the read.
2330 bool audio_read_done = false;
2331 bool video_read_done = false;
2332 ReadAudio(base::BindOnce(&OnReadDone_AbortExpected, &audio_read_done));
2333 ReadVideo(base::BindOnce(&OnReadDone_AbortExpected, &video_read_done));
2334 EXPECT_FALSE(audio_read_done);
2335 EXPECT_FALSE(video_read_done);
2337 // Now cancel the pending seek, which should flush the reads with empty
2339 base::TimeDelta seek_time = base::Seconds(0);
2340 demuxer_->CancelPendingSeek(seek_time);
2341 base::RunLoop().RunUntilIdle();
2342 EXPECT_TRUE(audio_read_done);
2343 EXPECT_TRUE(video_read_done);
2345 // A seek back to the buffered region should succeed.
2347 GenerateExpectedReads(0, 4);
2350 TEST_F(ChunkDemuxerTest, SeekCanceledWhileWaitingForSeek) {
2351 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2353 // Append cluster at the beginning of the stream.
2354 ASSERT_TRUE(AppendCluster(GenerateCluster(0, 4)));
2356 // Start waiting for a seek.
2357 base::TimeDelta seek_time1 = base::Seconds(50);
2358 base::TimeDelta seek_time2 = base::Seconds(0);
2359 demuxer_->StartWaitingForSeek(seek_time1);
2361 // Now cancel the upcoming seek to an unbuffered region.
2362 demuxer_->CancelPendingSeek(seek_time2);
2363 demuxer_->Seek(seek_time1, NewExpectedStatusCB(PIPELINE_OK));
2365 // Read requests should be fulfilled with empty buffers.
2366 bool audio_read_done = false;
2367 bool video_read_done = false;
2368 ReadAudio(base::BindOnce(&OnReadDone_AbortExpected, &audio_read_done));
2369 ReadVideo(base::BindOnce(&OnReadDone_AbortExpected, &video_read_done));
2370 EXPECT_TRUE(audio_read_done);
2371 EXPECT_TRUE(video_read_done);
2373 // A seek back to the buffered region should succeed.
2375 GenerateExpectedReads(0, 4);
2378 // Test that Seek() successfully seeks to all source IDs.
2379 TEST_F(ChunkDemuxerTest, SeekAudioAndVideoSources) {
2380 std::string audio_id = "audio1";
2381 std::string video_id = "video1";
2382 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
2384 ASSERT_TRUE(AppendCluster(
2386 GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration)));
2387 ASSERT_TRUE(AppendCluster(video_id,
2388 GenerateSingleStreamCluster(0, 132, kVideoTrackNum,
2389 kVideoBlockDuration)));
2391 // Read() should return buffers at 0.
2392 bool audio_read_done = false;
2393 bool video_read_done = false;
2395 base::BindOnce(&OnReadDone, base::Milliseconds(0), &audio_read_done));
2397 base::BindOnce(&OnReadDone, base::Milliseconds(0), &video_read_done));
2398 EXPECT_TRUE(audio_read_done);
2399 EXPECT_TRUE(video_read_done);
2401 // Seek to 3 (an unbuffered region).
2402 Seek(base::Seconds(3));
2404 audio_read_done = false;
2405 video_read_done = false;
2406 ReadAudio(base::BindOnce(&OnReadDone, base::Seconds(3), &audio_read_done));
2407 ReadVideo(base::BindOnce(&OnReadDone, base::Seconds(3), &video_read_done));
2408 // Read()s should not return until after data is appended at the Seek point.
2409 EXPECT_FALSE(audio_read_done);
2410 EXPECT_FALSE(video_read_done);
2412 ASSERT_TRUE(AppendCluster(
2413 audio_id, GenerateSingleStreamCluster(3000, 3092, kAudioTrackNum,
2414 kAudioBlockDuration)));
2415 ASSERT_TRUE(AppendCluster(
2416 video_id, GenerateSingleStreamCluster(3000, 3132, kVideoTrackNum,
2417 kVideoBlockDuration)));
2419 base::RunLoop().RunUntilIdle();
2421 // Read() should return buffers at 3.
2422 EXPECT_TRUE(audio_read_done);
2423 EXPECT_TRUE(video_read_done);
2426 // Test that Seek() completes successfully when EndOfStream
2427 // is called before data is available for that seek point.
2428 // This scenario might be useful if seeking past the end of stream
2429 // of either audio or video (or both).
2430 TEST_F(ChunkDemuxerTest, EndOfStreamAfterPastEosSeek) {
2431 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2434 MuxedStreamInfo(kAudioTrackNum,
2435 "0K 10K 20K 30K 40K 50K 60K 70K 80K 90K 100K 110K", 10),
2436 MuxedStreamInfo(kVideoTrackNum, "0K 20K 40K 60K 80K", 20));
2437 CheckExpectedRanges("{ [0,100) }");
2439 // Seeking past the end of video.
2440 // Note: audio data is available for that seek point.
2441 bool seek_cb_was_called = false;
2442 base::TimeDelta seek_time = base::Milliseconds(110);
2443 demuxer_->StartWaitingForSeek(seek_time);
2444 demuxer_->Seek(seek_time,
2445 base::BindOnce(OnSeekDone_OKExpected, &seek_cb_was_called));
2446 base::RunLoop().RunUntilIdle();
2448 EXPECT_FALSE(seek_cb_was_called);
2450 EXPECT_CALL(host_, SetDuration(base::Milliseconds(120)));
2451 MarkEndOfStream(PIPELINE_OK);
2452 CheckExpectedRanges("{ [0,120) }");
2453 base::RunLoop().RunUntilIdle();
2455 EXPECT_TRUE(seek_cb_was_called);
2460 // Test that EndOfStream is ignored if coming during a pending seek
2461 // whose seek time is before some existing ranges.
2462 TEST_F(ChunkDemuxerTest, EndOfStreamDuringPendingSeek) {
2463 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2466 MuxedStreamInfo(kAudioTrackNum,
2467 "0K 10K 20K 30K 40K 50K 60K 70K 80K 90K 100K 110K", 10),
2468 MuxedStreamInfo(kVideoTrackNum, "0K 20K 40K 60K 80K", 20));
2470 MuxedStreamInfo(kAudioTrackNum,
2471 "200K 210K 220K 230K 240K 250K 260K 270K 280K 290K", 10),
2472 MuxedStreamInfo(kVideoTrackNum, "200K 220K 240K 260K 280K", 20));
2474 bool seek_cb_was_called = false;
2475 base::TimeDelta seek_time = base::Milliseconds(160);
2476 demuxer_->StartWaitingForSeek(seek_time);
2477 demuxer_->Seek(seek_time,
2478 base::BindOnce(OnSeekDone_OKExpected, &seek_cb_was_called));
2479 base::RunLoop().RunUntilIdle();
2481 EXPECT_FALSE(seek_cb_was_called);
2483 EXPECT_CALL(host_, SetDuration(base::Milliseconds(300)));
2484 MarkEndOfStream(PIPELINE_OK);
2485 base::RunLoop().RunUntilIdle();
2487 EXPECT_FALSE(seek_cb_was_called);
2489 demuxer_->UnmarkEndOfStream();
2492 MuxedStreamInfo(kAudioTrackNum, "140K 150K 160K 170K", 10),
2493 MuxedStreamInfo(kVideoTrackNum, "140K 145K 150K 155K 160K 165K 170K 175K",
2496 base::RunLoop().RunUntilIdle();
2498 EXPECT_TRUE(seek_cb_was_called);
2503 // Test ranges in an audio-only stream.
2504 TEST_F(ChunkDemuxerTest, GetBufferedRanges_AudioIdOnly) {
2505 ASSERT_TRUE(InitDemuxer(HAS_AUDIO));
2507 // Test a simple cluster.
2508 ASSERT_TRUE(AppendCluster(
2509 GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration)));
2511 CheckExpectedRanges("{ [0,92) }");
2513 // Append a disjoint cluster to check for two separate ranges.
2514 ASSERT_TRUE(AppendCluster(GenerateSingleStreamCluster(
2515 150, 219, kAudioTrackNum, kAudioBlockDuration)));
2517 CheckExpectedRanges("{ [0,92) [150,219) }");
2520 // Test ranges in a video-only stream.
2521 TEST_F(ChunkDemuxerTest, GetBufferedRanges_VideoIdOnly) {
2522 ASSERT_TRUE(InitDemuxer(HAS_VIDEO));
2524 // Test a simple cluster.
2525 ASSERT_TRUE(AppendCluster(GenerateSingleStreamCluster(0, 132, kVideoTrackNum,
2526 kVideoBlockDuration)));
2528 CheckExpectedRanges("{ [0,132) }");
2530 // Append a disjoint cluster to check for two separate ranges.
2531 ASSERT_TRUE(AppendCluster(GenerateSingleStreamCluster(
2532 200, 299, kVideoTrackNum, kVideoBlockDuration)));
2534 CheckExpectedRanges("{ [0,132) [200,299) }");
2537 TEST_F(ChunkDemuxerTest, GetBufferedRanges_SeparateStreams) {
2538 std::string audio_id = "audio1";
2539 std::string video_id = "video1";
2540 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
2542 // Append audio and video data into separate source ids.
2544 // Audio block: 0 -> 23
2545 // Video block: 0 -> 33
2546 // Buffered Range: 0 -> 23
2547 // Audio block duration is smaller than video block duration,
2548 // so the buffered ranges should correspond to the audio blocks.
2549 ASSERT_TRUE(AppendCluster(
2550 audio_id, GenerateSingleStreamCluster(0, 23, kAudioTrackNum, 23)));
2551 ASSERT_TRUE(AppendCluster(
2552 video_id, GenerateSingleStreamCluster(0, 33, kVideoTrackNum, 33)));
2553 CheckExpectedRanges(DemuxerStream::AUDIO, "{ [0,23) }");
2554 CheckExpectedRanges(DemuxerStream::VIDEO, "{ [0,33) }");
2555 CheckExpectedRangesForMediaSource("{ [0,23) }");
2557 // Audio blocks: 300 -> 400
2558 // Video blocks: 320 -> 420
2559 // Buffered Range: 320 -> 400 (jagged start and end across SourceBuffers)
2560 ASSERT_TRUE(AppendCluster(
2561 audio_id, GenerateSingleStreamCluster(300, 400, kAudioTrackNum, 50)));
2562 ASSERT_TRUE(AppendCluster(
2563 video_id, GenerateSingleStreamCluster(320, 420, kVideoTrackNum, 50)));
2564 CheckExpectedRanges(DemuxerStream::AUDIO, "{ [0,23) [300,400) }");
2565 CheckExpectedRanges(DemuxerStream::VIDEO, "{ [0,33) [320,420) }");
2566 CheckExpectedRangesForMediaSource("{ [0,23) [320,400) }");
2568 // Audio block: 620 -> 690
2569 // Video block: 600 -> 670
2570 // Buffered Range: 620 -> 670 (jagged start and end across SourceBuffers)
2571 ASSERT_TRUE(AppendCluster(
2572 audio_id, GenerateSingleStreamCluster(620, 690, kAudioTrackNum, 70)));
2573 ASSERT_TRUE(AppendCluster(
2574 video_id, GenerateSingleStreamCluster(600, 670, kVideoTrackNum, 70)));
2575 CheckExpectedRanges(DemuxerStream::AUDIO, "{ [0,23) [300,400) [620,690) }");
2576 CheckExpectedRanges(DemuxerStream::VIDEO, "{ [0,33) [320,420) [600,670) }");
2577 CheckExpectedRangesForMediaSource("{ [0,23) [320,400) [620,670) }");
2579 // Audio block: 920 -> 950
2580 // Video block: 900 -> 970
2581 // Buffered Range: 920 -> 950 (complete overlap of audio)
2582 ASSERT_TRUE(AppendCluster(
2583 audio_id, GenerateSingleStreamCluster(920, 950, kAudioTrackNum, 30)));
2584 ASSERT_TRUE(AppendCluster(
2585 video_id, GenerateSingleStreamCluster(900, 970, kVideoTrackNum, 70)));
2586 CheckExpectedRanges(DemuxerStream::AUDIO,
2587 "{ [0,23) [300,400) [620,690) [920,950) }");
2588 CheckExpectedRanges(DemuxerStream::VIDEO,
2589 "{ [0,33) [320,420) [600,670) [900,970) }");
2590 CheckExpectedRangesForMediaSource("{ [0,23) [320,400) [620,670) [920,950) }");
2592 // Audio block: 1200 -> 1270
2593 // Video block: 1220 -> 1250
2594 // Buffered Range: 1220 -> 1250 (complete overlap of video)
2595 ASSERT_TRUE(AppendCluster(
2596 audio_id, GenerateSingleStreamCluster(1200, 1270, kAudioTrackNum, 70)));
2597 ASSERT_TRUE(AppendCluster(
2598 video_id, GenerateSingleStreamCluster(1220, 1250, kVideoTrackNum, 30)));
2599 CheckExpectedRanges(DemuxerStream::AUDIO,
2600 "{ [0,23) [300,400) [620,690) [920,950) [1200,1270) }");
2601 CheckExpectedRanges(DemuxerStream::VIDEO,
2602 "{ [0,33) [320,420) [600,670) [900,970) [1220,1250) }");
2603 CheckExpectedRangesForMediaSource(
2604 "{ [0,23) [320,400) [620,670) [920,950) [1220,1250) }");
2606 // Audio buffered ranges are trimmed from 1270 to 1250 due to splicing the
2607 // previously buffered audio frame
2608 // - existing frame trimmed from [1200, 1270) to [1200,1230),
2609 // - newly appended audio from [1230, 1250).
2610 EXPECT_MEDIA_LOG(TrimmedSpliceOverlap(1230000, 1200000, 40000));
2611 ASSERT_TRUE(AppendCluster(
2612 audio_id, GenerateSingleStreamCluster(1230, 1250, kAudioTrackNum, 20)));
2613 CheckExpectedRanges(DemuxerStream::AUDIO,
2614 "{ [0,23) [300,400) [620,690) [920,950) [1200,1250) }");
2616 // Video buffer range is unchanged by next append. The time and duration of
2617 // the new key frame line up with previous range boundaries.
2618 ASSERT_TRUE(AppendCluster(
2619 video_id, GenerateSingleStreamCluster(1230, 1250, kVideoTrackNum, 20)));
2620 CheckExpectedRanges(DemuxerStream::VIDEO,
2621 "{ [0,33) [320,420) [600,670) [900,970) [1220,1250) }");
2623 CheckExpectedRangesForMediaSource(
2624 "{ [0,23) [320,400) [620,670) [920,950) [1220,1250) }");
2627 TEST_F(ChunkDemuxerTest, GetBufferedRanges_AudioVideo) {
2628 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2630 // Audio block: 0 -> 23
2631 // Video block: 0 -> 33
2632 // Buffered Range: 0 -> 23
2633 // Audio block duration is smaller than video block duration,
2634 // so the buffered ranges should correspond to the audio blocks.
2635 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "0D23K"),
2636 MuxedStreamInfo(kVideoTrackNum, "0D33K"));
2638 CheckExpectedRanges(DemuxerStream::AUDIO, "{ [0,23) }");
2639 CheckExpectedRanges(DemuxerStream::VIDEO, "{ [0,33) }");
2640 CheckExpectedRanges("{ [0,23) }");
2642 // Audio blocks: 300 -> 400
2643 // Video blocks: 320 -> 420
2644 // Naive Buffered Range: 320 -> 400 (end overlap) **
2645 // **Except these are in the same cluster, with same segment start time of
2646 // 300, so the added buffered range is 300 -> 400 (still with end overlap)
2647 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "300K 350D50K"),
2648 MuxedStreamInfo(kVideoTrackNum, "320K 370D50K"));
2650 CheckExpectedRanges(DemuxerStream::AUDIO, "{ [0,23) [300,400) }");
2651 CheckExpectedRanges(DemuxerStream::VIDEO, "{ [0,33) [300,420) }");
2652 CheckExpectedRanges("{ [0,23) [300,400) }");
2654 // Audio block: 620 -> 690
2655 // Video block: 600 -> 670
2656 // Naive Buffered Range: 620 -> 670 (front overlap) **
2657 // **Except these are in the same cluster, with same segment start time of
2658 // 500, so the added buffered range is 600 -> 670
2659 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "620D70K"),
2660 MuxedStreamInfo(kVideoTrackNum, "600D70K"));
2662 CheckExpectedRanges(DemuxerStream::AUDIO, "{ [0,23) [300,400) [600,690) }");
2663 CheckExpectedRanges(DemuxerStream::VIDEO, "{ [0,33) [300,420) [600,670) }");
2664 CheckExpectedRanges("{ [0,23) [300,400) [600,670) }");
2666 // Audio block: 920 -> 950
2667 // Video block: 900 -> 970
2668 // Naive Buffered Range: 920 -> 950 (complete overlap, audio) **
2669 // **Except these are in the same cluster, with same segment start time of
2670 // 900, so the added buffered range is 900 -> 950
2671 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "920D30K"),
2672 MuxedStreamInfo(kVideoTrackNum, "900D70K"));
2674 CheckExpectedRanges(DemuxerStream::AUDIO,
2675 "{ [0,23) [300,400) [600,690) [900,950) }");
2676 CheckExpectedRanges(DemuxerStream::VIDEO,
2677 "{ [0,33) [300,420) [600,670) [900,970) }");
2678 CheckExpectedRanges("{ [0,23) [300,400) [600,670) [900,950) }");
2680 // Audio block: 1200 -> 1270
2681 // Video block: 1220 -> 1250
2682 // Naive Buffered Range: 1220 -> 1250 (complete overlap, video) **
2683 // **Except these are in the same cluster, with same segment start time of
2684 // 1200, so the added buffered range is 1200 -> 1250
2685 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "1200D70K"),
2686 MuxedStreamInfo(kVideoTrackNum, "1220D30K"));
2688 CheckExpectedRanges(DemuxerStream::AUDIO,
2689 "{ [0,23) [300,400) [600,690) [900,950) [1200,1270) }");
2690 CheckExpectedRanges(DemuxerStream::VIDEO,
2691 "{ [0,33) [300,420) [600,670) [900,970) [1200,1250) }");
2692 CheckExpectedRanges("{ [0,23) [300,400) [600,670) [900,950) [1200,1250) }");
2694 // Appending within existing buffered range.
2695 EXPECT_MEDIA_LOG(TrimmedSpliceOverlap(1230000, 1200000, 40000));
2696 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "1230D20K"),
2697 MuxedStreamInfo(kVideoTrackNum, "1230D20K"));
2698 // Video buffer range is unchanged. The time and duration of the new key frame
2699 // line up with previous range boundaries.
2700 CheckExpectedRanges(DemuxerStream::VIDEO,
2701 "{ [0,33) [300,420) [600,670) [900,970) [1200,1250) }");
2703 // Audio buffered ranges are trimmed from 1270 to 1250 due to splicing the
2704 // previously buffered audio frame.
2705 // - existing frame trimmed from [1200, 1270) to [1200, 1230),
2706 // - newly appended audio from [1230, 1250).
2707 CheckExpectedRanges(DemuxerStream::AUDIO,
2708 "{ [0,23) [300,400) [600,690) [900,950) [1200,1250) }");
2710 CheckExpectedRanges("{ [0,23) [300,400) [600,670) [900,950) [1200,1250) }");
2713 // Once MarkEndOfStream() is called, GetBufferedRanges should not cut off any
2714 // over-hanging tails at the end of the ranges as this is likely due to block
2715 // duration differences.
2716 TEST_F(ChunkDemuxerTest, GetBufferedRanges_EndOfStream) {
2717 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2719 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "0K 23K", 23),
2720 MuxedStreamInfo(kVideoTrackNum, "0K 33", 33));
2722 CheckExpectedRanges("{ [0,46) }");
2724 EXPECT_CALL(host_, SetDuration(base::Milliseconds(66)));
2725 MarkEndOfStream(PIPELINE_OK);
2727 // Verify that the range extends to the end of the video data.
2728 CheckExpectedRanges("{ [0,66) }");
2730 // Verify that the range reverts to the intersection when end of stream
2731 // has been cancelled.
2732 demuxer_->UnmarkEndOfStream();
2733 CheckExpectedRanges("{ [0,46) }");
2735 // Append and remove data so that the 2 streams' end ranges do not overlap.
2736 EXPECT_CALL(host_, SetDuration(base::Milliseconds(398)));
2738 MuxedStreamInfo(kAudioTrackNum, "200K 223K", 23),
2739 MuxedStreamInfo(kVideoTrackNum, "200K 233 266 299 332K 365", 33));
2741 // At this point, the per-stream ranges are as follows:
2742 // Audio: [0,46) [200,246)
2743 // Video: [0,66) [200,398)
2744 CheckExpectedRanges("{ [0,46) [200,246) }");
2746 demuxer_->Remove(kSourceId, base::Milliseconds(200), base::Milliseconds(300));
2748 // At this point, the per-stream ranges are as follows:
2750 // Video: [0,66) [332,398)
2751 CheckExpectedRanges("{ [0,46) }");
2753 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "200K 223K", 23),
2754 MuxedStreamInfo(kVideoTrackNum, "200K 233", 33));
2756 // At this point, the per-stream ranges are as follows:
2757 // Audio: [0,46) [200,246)
2758 // Video: [0,66) [200,266) [332,398)
2759 // NOTE: The last range on each stream do not overlap in time.
2760 CheckExpectedRanges("{ [0,46) [200,246) }");
2762 MarkEndOfStream(PIPELINE_OK);
2764 // NOTE: The last range on each stream gets extended to the highest
2765 // end timestamp according to the spec. The last audio range gets extended
2766 // from [200,246) to [200,398) which is why the intersection results in the
2767 // middle range getting larger AND the new range appearing.
2768 CheckExpectedRanges("{ [0,46) [200,266) [332,398) }");
2771 TEST_F(ChunkDemuxerTest, DifferentStreamTimecodes) {
2772 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2774 // Create a cluster where the video timecode begins 25ms after the audio.
2775 ASSERT_TRUE(AppendCluster(GenerateCluster(0, 25, 8)));
2777 Seek(base::Seconds(0));
2778 GenerateExpectedReads(0, 25, 8);
2780 // Seek to 5 seconds.
2781 Seek(base::Seconds(5));
2783 // Generate a cluster to fulfill this seek, where audio timecode begins 25ms
2785 ASSERT_TRUE(AppendCluster(GenerateCluster(5025, 5000, 8)));
2786 GenerateExpectedReads(5025, 5000, 8);
2789 TEST_F(ChunkDemuxerTest, DifferentStreamTimecodesSeparateSources) {
2790 std::string audio_id = "audio1";
2791 std::string video_id = "video1";
2792 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
2794 // Generate two streams where the video stream starts 5ms after the audio
2795 // stream and append them.
2796 ASSERT_TRUE(AppendCluster(
2798 GenerateSingleStreamCluster(25, 4 * kAudioBlockDuration + 25,
2799 kAudioTrackNum, kAudioBlockDuration)));
2800 ASSERT_TRUE(AppendCluster(
2802 GenerateSingleStreamCluster(30, 4 * kVideoBlockDuration + 30,
2803 kVideoTrackNum, kVideoBlockDuration)));
2805 // Both streams should be able to fulfill a seek to 25.
2806 Seek(base::Milliseconds(25));
2807 GenerateAudioStreamExpectedReads(25, 4);
2808 GenerateVideoStreamExpectedReads(30, 4);
2811 TEST_F(ChunkDemuxerTest, DifferentStreamTimecodesOutOfRange) {
2812 std::string audio_id = "audio1";
2813 std::string video_id = "video1";
2814 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
2816 // Generate two streams where the video stream starts 10s after the audio
2817 // stream and append them.
2818 ASSERT_TRUE(AppendCluster(
2820 GenerateSingleStreamCluster(0, 4 * kAudioBlockDuration + 0,
2821 kAudioTrackNum, kAudioBlockDuration)));
2822 ASSERT_TRUE(AppendCluster(
2824 GenerateSingleStreamCluster(10000, 4 * kVideoBlockDuration + 10000,
2825 kVideoTrackNum, kVideoBlockDuration)));
2827 // Should not be able to fulfill a seek to 0.
2828 base::TimeDelta seek_time = base::Milliseconds(0);
2829 demuxer_->StartWaitingForSeek(seek_time);
2830 demuxer_->Seek(seek_time,
2831 NewExpectedStatusCB(PIPELINE_ERROR_ABORT));
2832 ExpectRead(DemuxerStream::AUDIO, 0);
2833 ExpectEndOfStream(DemuxerStream::VIDEO);
2836 TEST_F(ChunkDemuxerTest, CodecPrefixMatching) {
2837 demuxer_->Initialize(&host_,
2838 base::BindOnce(&ChunkDemuxerTest::DemuxerInitialized,
2839 base::Unretained(this)));
2840 ChunkDemuxer::Status expected = ChunkDemuxer::kNotSupported;
2842 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
2843 expected = ChunkDemuxer::kOk;
2845 EXPECT_MEDIA_LOG(CodecUnsupportedInContainer("avc1.4D4041", "video/mp4"));
2846 #endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
2848 EXPECT_EQ(AddId("source_id", "video/mp4", "avc1.4D4041"), expected);
2851 // Test codec ID's that are not compliant with RFC6381, but have been
2852 // seen in the wild.
2853 TEST_F(ChunkDemuxerTest, CodecIDsThatAreNotRFC6381Compliant) {
2854 ChunkDemuxer::Status expected = ChunkDemuxer::kNotSupported;
2856 const char* codec_ids[] = {
2857 // GPAC places leading zeros on the audio object type.
2862 demuxer_->Initialize(&host_,
2863 base::BindOnce(&ChunkDemuxerTest::DemuxerInitialized,
2864 base::Unretained(this)));
2866 for (size_t i = 0; i < std::size(codec_ids); ++i) {
2867 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
2868 expected = ChunkDemuxer::kOk;
2870 EXPECT_MEDIA_LOG(CodecUnsupportedInContainer(codec_ids[i], "audio/mp4"));
2873 ChunkDemuxer::Status result = AddId("source_id", "audio/mp4", codec_ids[i]);
2875 EXPECT_EQ(result, expected)
2876 << "Fail to add codec_id '" << codec_ids[i] << "'";
2878 if (result == ChunkDemuxer::kOk)
2879 demuxer_->RemoveId("source_id");
2883 TEST_F(ChunkDemuxerTest, EndOfStreamStillSetAfterSeek) {
2884 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2886 EXPECT_CALL(host_, SetDuration(_))
2887 .Times(AnyNumber());
2889 base::TimeDelta kLastAudioTimestamp = base::Milliseconds(92);
2890 base::TimeDelta kLastVideoTimestamp = base::Milliseconds(99);
2892 ASSERT_TRUE(AppendCluster(kDefaultFirstCluster()));
2893 ASSERT_TRUE(AppendCluster(kDefaultSecondCluster()));
2894 MarkEndOfStream(PIPELINE_OK);
2896 DemuxerStream::Status status;
2897 base::TimeDelta last_timestamp;
2899 // Verify that we can read audio & video to the end w/o problems.
2900 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp);
2901 EXPECT_EQ(DemuxerStream::kOk, status);
2902 EXPECT_EQ(kLastAudioTimestamp, last_timestamp);
2904 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp);
2905 EXPECT_EQ(DemuxerStream::kOk, status);
2906 EXPECT_EQ(kLastVideoTimestamp, last_timestamp);
2908 // Seek back to 0 and verify that we can read to the end again..
2909 Seek(base::Milliseconds(0));
2911 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp);
2912 EXPECT_EQ(DemuxerStream::kOk, status);
2913 EXPECT_EQ(kLastAudioTimestamp, last_timestamp);
2915 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp);
2916 EXPECT_EQ(DemuxerStream::kOk, status);
2917 EXPECT_EQ(kLastVideoTimestamp, last_timestamp);
2920 TEST_F(ChunkDemuxerTest, GetBufferedRangesBeforeInitSegment) {
2921 EXPECT_CALL(*this, DemuxerOpened());
2922 demuxer_->Initialize(&host_,
2923 base::BindOnce(&ChunkDemuxerTest::DemuxerInitialized,
2924 base::Unretained(this)));
2925 ASSERT_EQ(AddId("audio", HAS_AUDIO), ChunkDemuxer::kOk);
2926 ASSERT_EQ(AddId("video", HAS_VIDEO), ChunkDemuxer::kOk);
2928 CheckExpectedRanges("audio", "{ }");
2929 CheckExpectedRanges("video", "{ }");
2932 // Test that Seek() completes successfully when the first cluster
2934 TEST_F(ChunkDemuxerTest, EndOfStreamDuringSeek) {
2937 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2939 ASSERT_TRUE(AppendCluster(kDefaultFirstCluster()));
2941 base::TimeDelta seek_time = base::Seconds(0);
2942 demuxer_->StartWaitingForSeek(seek_time);
2944 ASSERT_TRUE(AppendCluster(kDefaultSecondCluster()));
2947 SetDuration(base::Milliseconds(kDefaultSecondClusterEndTimestamp)));
2948 MarkEndOfStream(PIPELINE_OK);
2950 demuxer_->Seek(seek_time, NewExpectedStatusCB(PIPELINE_OK));
2952 GenerateExpectedReads(0, 4);
2953 GenerateExpectedReads(46, 66, 5);
2955 DemuxerStream* audio_stream = GetStream(DemuxerStream::AUDIO);
2956 DemuxerStream* video_stream = GetStream(DemuxerStream::VIDEO);
2957 EndOfStreamHelper end_of_stream_helper(audio_stream, video_stream);
2958 end_of_stream_helper.RequestReads();
2959 end_of_stream_helper.CheckIfReadDonesWereCalled(true);
2962 TEST_F(ChunkDemuxerTest, ConfigChange_Video) {
2965 ASSERT_TRUE(InitDemuxerWithConfigChangeData());
2967 DemuxerStream::Status status;
2968 base::TimeDelta last_timestamp;
2970 DemuxerStream* video = GetStream(DemuxerStream::VIDEO);
2972 // Fetch initial video config and verify it matches what we expect.
2973 const VideoDecoderConfig& video_config_1 = video->video_decoder_config();
2974 ASSERT_TRUE(video_config_1.IsValidConfig());
2975 EXPECT_EQ(video_config_1.natural_size().width(), 320);
2976 EXPECT_EQ(video_config_1.natural_size().height(), 240);
2978 ExpectRead(DemuxerStream::VIDEO, 0);
2980 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp);
2982 ASSERT_EQ(status, DemuxerStream::kConfigChanged);
2983 EXPECT_EQ(last_timestamp.InMilliseconds(), 501);
2985 // Fetch the new decoder config.
2986 const VideoDecoderConfig& video_config_2 = video->video_decoder_config();
2987 ASSERT_TRUE(video_config_2.IsValidConfig());
2988 EXPECT_EQ(video_config_2.natural_size().width(), 640);
2989 EXPECT_EQ(video_config_2.natural_size().height(), 360);
2991 ExpectRead(DemuxerStream::VIDEO, 527);
2993 // Read until the next config change.
2994 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp);
2995 ASSERT_EQ(status, DemuxerStream::kConfigChanged);
2996 EXPECT_EQ(last_timestamp.InMilliseconds(), 760);
2998 // Get the new config and verify that it matches the first one.
2999 ASSERT_TRUE(video_config_1.Matches(video->video_decoder_config()));
3001 ExpectRead(DemuxerStream::VIDEO, 801);
3003 // Read until the end of the stream just to make sure there aren't any other
3005 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp);
3006 ASSERT_EQ(status, DemuxerStream::kOk);
3009 TEST_F(ChunkDemuxerTest, ConfigChange_Audio) {
3012 ASSERT_TRUE(InitDemuxerWithConfigChangeData());
3014 DemuxerStream::Status status;
3015 base::TimeDelta last_timestamp;
3017 DemuxerStream* audio = GetStream(DemuxerStream::AUDIO);
3019 // Fetch initial audio config and verify it matches what we expect.
3020 const AudioDecoderConfig& audio_config_1 = audio->audio_decoder_config();
3021 ASSERT_TRUE(audio_config_1.IsValidConfig());
3022 EXPECT_EQ(audio_config_1.samples_per_second(), 44100);
3023 EXPECT_EQ(audio_config_1.extra_data().size(), 3863u);
3025 ExpectRead(DemuxerStream::AUDIO, 0);
3027 // Read until we encounter config 2.
3028 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp);
3029 ASSERT_EQ(status, DemuxerStream::kConfigChanged);
3030 EXPECT_EQ(last_timestamp.InMilliseconds(), 524);
3032 // Fetch the new decoder config.
3033 const AudioDecoderConfig& audio_config_2 = audio->audio_decoder_config();
3034 ASSERT_TRUE(audio_config_2.IsValidConfig());
3035 EXPECT_EQ(audio_config_2.samples_per_second(), 44100);
3036 EXPECT_EQ(audio_config_2.extra_data().size(), 3935u);
3038 // Read until we encounter config 1 again.
3039 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp);
3040 ASSERT_EQ(status, DemuxerStream::kConfigChanged);
3041 EXPECT_EQ(last_timestamp.InMilliseconds(), 759);
3042 ASSERT_TRUE(audio_config_1.Matches(audio->audio_decoder_config()));
3044 // Read until the end of the stream just to make sure there aren't any other
3046 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp);
3047 ASSERT_EQ(status, DemuxerStream::kOk);
3048 EXPECT_EQ(last_timestamp.InMilliseconds(), 2744);
3051 TEST_F(ChunkDemuxerTest, ConfigChange_Seek) {
3054 ASSERT_TRUE(InitDemuxerWithConfigChangeData());
3056 DemuxerStream* video = GetStream(DemuxerStream::VIDEO);
3058 // Fetch initial video config and verify it matches what we expect.
3059 const VideoDecoderConfig& video_config_1 = video->video_decoder_config();
3060 ASSERT_TRUE(video_config_1.IsValidConfig());
3061 EXPECT_EQ(video_config_1.natural_size().width(), 320);
3062 EXPECT_EQ(video_config_1.natural_size().height(), 240);
3064 ExpectRead(DemuxerStream::VIDEO, 0);
3066 // Seek to a location with a different config.
3067 Seek(base::Milliseconds(527));
3069 // Verify that the config change is signalled.
3070 ExpectConfigChanged(DemuxerStream::VIDEO);
3072 // Fetch the new decoder config and verify it is what we expect.
3073 const VideoDecoderConfig& video_config_2 = video->video_decoder_config();
3074 ASSERT_TRUE(video_config_2.IsValidConfig());
3075 EXPECT_EQ(video_config_2.natural_size().width(), 640);
3076 EXPECT_EQ(video_config_2.natural_size().height(), 360);
3078 // Verify that Read() will return a buffer now.
3079 ExpectRead(DemuxerStream::VIDEO, 527);
3081 // Seek back to the beginning and verify we get another config change.
3082 Seek(base::Milliseconds(0));
3083 ExpectConfigChanged(DemuxerStream::VIDEO);
3084 ASSERT_TRUE(video_config_1.Matches(video->video_decoder_config()));
3085 ExpectRead(DemuxerStream::VIDEO, 0);
3087 // Seek to a location that requires a config change and then
3088 // seek to a new location that has the same configuration as
3089 // the start of the file without a Read() in the middle.
3090 Seek(base::Milliseconds(527));
3091 Seek(base::Milliseconds(801));
3093 // Verify that no config change is signalled.
3094 ExpectRead(DemuxerStream::VIDEO, 801);
3095 ASSERT_TRUE(video_config_1.Matches(video->video_decoder_config()));
3098 TEST_F(ChunkDemuxerTest, TimestampPositiveOffset) {
3099 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
3101 ASSERT_TRUE(SetTimestampOffset(kSourceId, base::Seconds(30)));
3102 ASSERT_TRUE(AppendCluster(GenerateCluster(0, 2)));
3104 Seek(base::Milliseconds(30000));
3106 GenerateExpectedReads(30000, 2);
3109 TEST_F(ChunkDemuxerTest, TimestampNegativeOffset) {
3110 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
3112 ASSERT_TRUE(SetTimestampOffset(kSourceId, base::Seconds(-1)));
3113 ASSERT_TRUE(AppendCluster(GenerateCluster(1000, 2)));
3115 GenerateExpectedReads(0, 2);
3118 TEST_F(ChunkDemuxerTest, TimestampOffsetSeparateStreams) {
3119 std::string audio_id = "audio1";
3120 std::string video_id = "video1";
3121 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
3123 ASSERT_TRUE(SetTimestampOffset(audio_id, base::Milliseconds(-2500)));
3124 ASSERT_TRUE(SetTimestampOffset(video_id, base::Milliseconds(-2500)));
3125 ASSERT_TRUE(AppendCluster(
3127 GenerateSingleStreamCluster(2500, 2500 + kAudioBlockDuration * 4,
3128 kAudioTrackNum, kAudioBlockDuration)));
3129 ASSERT_TRUE(AppendCluster(
3131 GenerateSingleStreamCluster(2500, 2500 + kVideoBlockDuration * 4,
3132 kVideoTrackNum, kVideoBlockDuration)));
3133 GenerateAudioStreamExpectedReads(0, 4);
3134 GenerateVideoStreamExpectedReads(0, 4);
3136 Seek(base::Milliseconds(27300));
3138 ASSERT_TRUE(SetTimestampOffset(audio_id, base::Milliseconds(27300)));
3139 ASSERT_TRUE(SetTimestampOffset(video_id, base::Milliseconds(27300)));
3140 ASSERT_TRUE(AppendCluster(
3142 GenerateSingleStreamCluster(0, kAudioBlockDuration * 4, kAudioTrackNum,
3143 kAudioBlockDuration)));
3144 ASSERT_TRUE(AppendCluster(
3146 GenerateSingleStreamCluster(0, kVideoBlockDuration * 4, kVideoTrackNum,
3147 kVideoBlockDuration)));
3148 GenerateVideoStreamExpectedReads(27300, 4);
3149 GenerateAudioStreamExpectedReads(27300, 4);
3152 TEST_F(ChunkDemuxerTest, IsParsingMediaSegmentMidMediaSegment) {
3153 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
3155 std::unique_ptr<Cluster> cluster = GenerateCluster(0, 2);
3156 // Append only part of the cluster data.
3157 ASSERT_TRUE(AppendData(cluster->data(), cluster->size() - 13));
3159 // Confirm we're in the middle of parsing a media segment.
3160 ASSERT_TRUE(demuxer_->IsParsingMediaSegment(kSourceId));
3162 demuxer_->ResetParserState(kSourceId,
3163 append_window_start_for_next_append_,
3164 append_window_end_for_next_append_,
3165 ×tamp_offset_map_[kSourceId]);
3167 // After ResetParserState(), parsing should no longer be in the middle of a
3169 ASSERT_FALSE(demuxer_->IsParsingMediaSegment(kSourceId));
3172 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
3173 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER)
3175 const char* kMp2tMimeType = "video/mp2t";
3176 const char* kMp2tCodecs = "mp4a.40.2,avc1.640028";
3179 TEST_F(ChunkDemuxerTest, EmitBuffersDuringAbort) {
3180 EXPECT_CALL(*this, DemuxerOpened());
3181 EXPECT_FOUND_CODEC_NAME(Audio, "aac");
3182 EXPECT_FOUND_CODEC_NAME(Video, "h264");
3183 demuxer_->Initialize(&host_,
3184 CreateInitDoneCallback(kInfiniteDuration, PIPELINE_OK));
3185 EXPECT_EQ(ChunkDemuxer::kOk, AddId(kSourceId, kMp2tMimeType, kMp2tCodecs));
3188 // DTS/PTS derived using dvbsnoop -s ts -if bear-1280x720.ts -tssubdecode
3189 // Video: first PES:
3190 // PTS: 126912 (0x0001efc0) [= 90 kHz-Timestamp: 0:00:01.4101]
3191 // DTS: 123909 (0x0001e405) [= 90 kHz-Timestamp: 0:00:01.3767]
3192 // Audio: first PES:
3193 // PTS: 126000 (0x0001ec30) [= 90 kHz-Timestamp: 0:00:01.4000]
3194 // DTS: 123910 (0x0001e406) [= 90 kHz-Timestamp: 0:00:01.3767]
3196 // PTS: 370155 (0x0005a5eb) [= 90 kHz-Timestamp: 0:00:04.1128]
3197 // DTS: 367152 (0x00059a30) [= 90 kHz-Timestamp: 0:00:04.0794]
3199 // PTS: 353788 (0x000565fc) [= 90 kHz-Timestamp: 0:00:03.9309]
3201 scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile("bear-1280x720.ts");
3202 EXPECT_CALL(*this, InitSegmentReceivedMock(_));
3204 // This mp2ts file contains buffers which can trigger media logs related to
3205 // splicing, especially when appending in small chunks.
3206 EXPECT_MEDIA_LOG(TrimmedSpliceOverlap(1655422, 1655419, 23217));
3207 EXPECT_MEDIA_LOG(SkippingSpliceTooLittleOverlap(1957277, 4));
3208 EXPECT_MEDIA_LOG(SkippingSpliceTooLittleOverlap(2514555, 6));
3209 EXPECT_MEDIA_LOG(SkippingSpliceTooLittleOverlap(3071833, 6));
3210 EXPECT_MEDIA_LOG(SkippingSpliceTooLittleOverlap(3652333, 6));
3212 // Append the media in small chunks.
3213 size_t appended_bytes = 0;
3214 const size_t chunk_size = 1024;
3215 while (appended_bytes < buffer->data_size()) {
3216 size_t cur_chunk_size =
3217 std::min(chunk_size, buffer->data_size() - appended_bytes);
3219 AppendData(kSourceId, buffer->data() + appended_bytes, cur_chunk_size));
3220 appended_bytes += cur_chunk_size;
3223 // Confirm we're in the middle of parsing a media segment.
3224 ASSERT_TRUE(demuxer_->IsParsingMediaSegment(kSourceId));
3226 // ResetParserState on the Mpeg2 TS parser triggers the emission of the last
3227 // video buffer which is pending in the stream parser.
3228 Ranges<base::TimeDelta> range_before_abort =
3229 demuxer_->GetBufferedRanges(kSourceId);
3230 demuxer_->ResetParserState(kSourceId,
3231 append_window_start_for_next_append_,
3232 append_window_end_for_next_append_,
3233 ×tamp_offset_map_[kSourceId]);
3234 Ranges<base::TimeDelta> range_after_abort =
3235 demuxer_->GetBufferedRanges(kSourceId);
3237 ASSERT_EQ(range_before_abort.size(), 1u);
3238 ASSERT_EQ(range_after_abort.size(), 1u);
3239 EXPECT_EQ(range_after_abort.start(0), range_before_abort.start(0));
3240 EXPECT_GT(range_after_abort.end(0), range_before_abort.end(0));
3243 TEST_F(ChunkDemuxerTest, SeekCompleteDuringAbort) {
3244 EXPECT_CALL(*this, DemuxerOpened());
3245 EXPECT_FOUND_CODEC_NAME(Video, "h264");
3246 EXPECT_FOUND_CODEC_NAME(Audio, "aac");
3247 demuxer_->Initialize(&host_,
3248 CreateInitDoneCallback(kInfiniteDuration, PIPELINE_OK));
3249 EXPECT_EQ(ChunkDemuxer::kOk, AddId(kSourceId, kMp2tMimeType, kMp2tCodecs));
3252 // DTS/PTS derived using dvbsnoop -s ts -if bear-1280x720.ts -tssubdecode
3253 // Video: first PES:
3254 // PTS: 126912 (0x0001efc0) [= 90 kHz-Timestamp: 0:00:01.4101]
3255 // DTS: 123909 (0x0001e405) [= 90 kHz-Timestamp: 0:00:01.3767]
3256 // Audio: first PES:
3257 // PTS: 126000 (0x0001ec30) [= 90 kHz-Timestamp: 0:00:01.4000]
3258 // DTS: 123910 (0x0001e406) [= 90 kHz-Timestamp: 0:00:01.3767]
3260 // PTS: 370155 (0x0005a5eb) [= 90 kHz-Timestamp: 0:00:04.1128]
3261 // DTS: 367152 (0x00059a30) [= 90 kHz-Timestamp: 0:00:04.0794]
3263 // PTS: 353788 (0x000565fc) [= 90 kHz-Timestamp: 0:00:03.9309]
3265 scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile("bear-1280x720.ts");
3266 EXPECT_CALL(*this, InitSegmentReceivedMock(_));
3268 // This mp2ts file contains buffers which can trigger media logs related to
3269 // splicing, especially when appending in small chunks.
3270 EXPECT_MEDIA_LOG(TrimmedSpliceOverlap(1655422, 1655419, 23217));
3271 EXPECT_MEDIA_LOG(SkippingSpliceTooLittleOverlap(1957277, 4));
3272 EXPECT_MEDIA_LOG(SkippingSpliceTooLittleOverlap(2514555, 6));
3273 EXPECT_MEDIA_LOG(SkippingSpliceTooLittleOverlap(3071833, 6));
3274 EXPECT_MEDIA_LOG(SkippingSpliceTooLittleOverlap(3652333, 6));
3276 // Append the media in small chunks.
3277 size_t appended_bytes = 0;
3278 const size_t chunk_size = 1024;
3279 while (appended_bytes < buffer->data_size()) {
3280 size_t cur_chunk_size =
3281 std::min(chunk_size, buffer->data_size() - appended_bytes);
3283 AppendData(kSourceId, buffer->data() + appended_bytes, cur_chunk_size));
3284 appended_bytes += cur_chunk_size;
3287 // Confirm we're in the middle of parsing a media segment.
3288 ASSERT_TRUE(demuxer_->IsParsingMediaSegment(kSourceId));
3290 // Seek to a time corresponding to buffers that will be emitted during the
3292 Seek(base::Milliseconds(4110));
3294 // ResetParserState on the Mpeg2 TS parser triggers the emission of the last
3295 // video buffer which is pending in the stream parser.
3296 demuxer_->ResetParserState(kSourceId,
3297 append_window_start_for_next_append_,
3298 append_window_end_for_next_append_,
3299 ×tamp_offset_map_[kSourceId]);
3305 TEST_F(ChunkDemuxerTest, WebMIsParsingMediaSegmentDetection) {
3306 const uint8_t kBuffer[] = {
3307 // CLUSTER (size = 10)
3308 0x1F, 0x43, 0xB6, 0x75, 0x8A,
3310 // Cluster TIMECODE (value = 1)
3313 // SIMPLEBLOCK (size = 5)
3316 // Audio Track Number
3317 0x80 | (kAudioTrackNum & 0x7F),
3319 // Timecode (relative to cluster) (value = 0)
3328 // CLUSTER (size = unknown; really 10)
3329 0x1F, 0x43, 0xB6, 0x75, 0xFF,
3331 // Cluster TIMECODE (value = 2)
3334 // SIMPLEBLOCK (size = 5)
3337 // Audio Track Number
3338 0x80 | (kAudioTrackNum & 0x7F),
3340 // Timecode (relative to cluster) (value = 0)
3349 // EBMLHEADER (size = 10, not fully appended)
3350 0x1A, 0x45, 0xDF, 0xA3, 0x8A,
3353 // This array indicates expected return value of IsParsingMediaSegment()
3354 // following each incrementally appended byte in |kBuffer|.
3355 const bool kExpectedReturnValues[] = {
3356 // First Cluster, explicit size
3357 false, false, false, false, true, true, true, true, true, true, true,
3358 true, true, true, false,
3360 // Second Cluster, unknown size
3361 false, false, false, false, true, true, true, true, true, true, true,
3362 true, true, true, true,
3365 true, true, true, true, false,
3368 static_assert(std::size(kBuffer) == std::size(kExpectedReturnValues),
3369 "test arrays out of sync");
3370 static_assert(std::size(kBuffer) == sizeof(kBuffer),
3371 "there should be one byte per index");
3373 ASSERT_TRUE(InitDemuxer(HAS_AUDIO));
3374 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(23)).Times(2);
3375 for (size_t i = 0; i < sizeof(kBuffer); i++) {
3376 DVLOG(3) << "Appending and testing index " << i;
3377 ASSERT_TRUE(AppendData(kBuffer + i, 1));
3378 bool expected_return_value = kExpectedReturnValues[i];
3379 EXPECT_EQ(expected_return_value,
3380 demuxer_->IsParsingMediaSegment(kSourceId));
3384 TEST_F(ChunkDemuxerTest, DurationChange) {
3385 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
3386 const int kStreamDuration = kDefaultDuration().InMilliseconds();
3388 // Add data leading up to the currently set duration.
3390 AppendCluster(GenerateCluster(kStreamDuration - kAudioBlockDuration,
3391 kStreamDuration - kVideoBlockDuration, 2)));
3393 CheckExpectedRanges("{ [201191,201224) }");
3395 // Add data beginning at the currently set duration and expect a new duration
3396 // to be signaled. Note that the last video block will have a higher end
3397 // timestamp than the last audio block.
3398 const int kNewStreamDurationVideo = kStreamDuration + kVideoBlockDuration;
3399 EXPECT_CALL(host_, SetDuration(base::Milliseconds(kNewStreamDurationVideo)));
3401 AppendCluster(GenerateCluster(kDefaultDuration().InMilliseconds(), 2)));
3403 CheckExpectedRanges("{ [201191,201247) }");
3405 // Add more data to the end of each media type. Note that the last audio block
3406 // will have a higher end timestamp than the last video block.
3407 const int kFinalStreamDuration = kStreamDuration + kAudioBlockDuration * 3;
3408 EXPECT_CALL(host_, SetDuration(base::Milliseconds(kFinalStreamDuration)));
3410 AppendCluster(GenerateCluster(kStreamDuration + kAudioBlockDuration,
3411 kStreamDuration + kVideoBlockDuration, 3)));
3413 // See that the range has increased appropriately (but not to the full
3414 // duration of 201293, since there is not enough video appended for that).
3415 CheckExpectedRanges("{ [201191,201290) }");
3418 TEST_F(ChunkDemuxerTest, DurationChangeTimestampOffset) {
3419 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
3420 ASSERT_TRUE(SetTimestampOffset(kSourceId, kDefaultDuration()));
3421 EXPECT_CALL(host_, SetDuration(kDefaultDuration() +
3422 base::Milliseconds(kVideoBlockDuration * 2)));
3423 ASSERT_TRUE(AppendCluster(GenerateCluster(0, 4)));
3426 TEST_F(ChunkDemuxerTest, EndOfStreamTruncateDuration) {
3427 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
3429 ASSERT_TRUE(AppendCluster(kDefaultFirstCluster()));
3432 host_, SetDuration(base::Milliseconds(kDefaultFirstClusterEndTimestamp)));
3433 MarkEndOfStream(PIPELINE_OK);
3436 TEST_F(ChunkDemuxerTest, ZeroLengthAppend) {
3437 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
3438 ASSERT_TRUE(AppendData(NULL, 0));
3441 TEST_F(ChunkDemuxerTest, AppendAfterEndOfStream) {
3442 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
3444 EXPECT_CALL(host_, SetDuration(_))
3445 .Times(AnyNumber());
3447 ASSERT_TRUE(AppendCluster(kDefaultFirstCluster()));
3448 MarkEndOfStream(PIPELINE_OK);
3450 demuxer_->UnmarkEndOfStream();
3452 ASSERT_TRUE(AppendCluster(kDefaultSecondCluster()));
3453 MarkEndOfStream(PIPELINE_OK);
3456 // Test receiving a Shutdown() call before we get an Initialize()
3457 // call. This can happen if video element gets destroyed before
3458 // the pipeline has a chance to initialize the demuxer.
3459 TEST_F(ChunkDemuxerTest, Shutdown_BeforeInitialize) {
3460 demuxer_->Shutdown();
3461 demuxer_->Initialize(&host_,
3462 CreateInitDoneCallback(DEMUXER_ERROR_COULD_NOT_OPEN));
3463 base::RunLoop().RunUntilIdle();
3466 // Verifies that signaling end of stream while stalled at a gap
3467 // boundary does not trigger end of stream buffers to be returned.
3468 TEST_F(ChunkDemuxerTest, EndOfStreamWhileWaitingForGapToBeFilled) {
3469 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
3471 ASSERT_TRUE(AppendCluster(0, 10));
3472 ASSERT_TRUE(AppendCluster(300, 10));
3473 CheckExpectedRanges("{ [0,132) [300,432) }");
3475 GenerateExpectedReads(0, 10);
3477 bool audio_read_done = false;
3478 bool video_read_done = false;
3480 base::BindOnce(&OnReadDone, base::Milliseconds(138), &audio_read_done));
3482 base::BindOnce(&OnReadDone, base::Milliseconds(138), &video_read_done));
3484 // Verify that the reads didn't complete
3485 EXPECT_FALSE(audio_read_done);
3486 EXPECT_FALSE(video_read_done);
3488 EXPECT_CALL(host_, SetDuration(base::Milliseconds(438)));
3489 MarkEndOfStream(PIPELINE_OK);
3491 // Verify that the reads still haven't completed.
3492 EXPECT_FALSE(audio_read_done);
3493 EXPECT_FALSE(video_read_done);
3495 demuxer_->UnmarkEndOfStream();
3497 ASSERT_TRUE(AppendCluster(138, 22));
3499 base::RunLoop().RunUntilIdle();
3501 CheckExpectedRanges("{ [0,435) }");
3503 // Verify that the reads have completed.
3504 EXPECT_TRUE(audio_read_done);
3505 EXPECT_TRUE(video_read_done);
3507 // Read the rest of the buffers.
3508 GenerateExpectedReads(161, 171, 20);
3510 // Verify that reads block because the append cleared the end of stream state.
3511 audio_read_done = false;
3512 video_read_done = false;
3513 ReadAudio(base::BindOnce(&OnReadDone_EOSExpected, &audio_read_done));
3514 ReadVideo(base::BindOnce(&OnReadDone_EOSExpected, &video_read_done));
3516 // Verify that the reads don't complete.
3517 EXPECT_FALSE(audio_read_done);
3518 EXPECT_FALSE(video_read_done);
3520 EXPECT_CALL(host_, SetDuration(base::Milliseconds(437)));
3521 MarkEndOfStream(PIPELINE_OK);
3523 EXPECT_TRUE(audio_read_done);
3524 EXPECT_TRUE(video_read_done);
3527 TEST_F(ChunkDemuxerTest, CanceledSeekDuringInitialPreroll) {
3528 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
3531 base::TimeDelta seek_time = base::Milliseconds(200);
3532 demuxer_->CancelPendingSeek(seek_time);
3534 // Initiate the seek to the new location.
3537 // Append data to satisfy the seek.
3538 ASSERT_TRUE(AppendCluster(seek_time.InMilliseconds(), 10));
3541 TEST_F(ChunkDemuxerTest, SetMemoryLimitType) {
3542 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
3544 // Set different memory limits for audio and video.
3545 demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, 10 * block_size_);
3546 demuxer_->SetMemoryLimitsForTest(DemuxerStream::VIDEO, 5 * block_size_ + 1);
3548 base::TimeDelta seek_time = base::Milliseconds(1000);
3550 // Append data at the start that can be garbage collected:
3552 MuxedStreamInfo(kAudioTrackNum,
3553 "0K 23K 46K 69K 92K 115K 138K 161K 184K 207K", 23),
3554 MuxedStreamInfo(kVideoTrackNum, "0K 33K 66K 99K 132K", 33));
3556 // We should be right at buffer limit, should pass
3557 EXPECT_TRUE(demuxer_->EvictCodedFrames(kSourceId, base::Milliseconds(0), 0));
3559 CheckExpectedRanges(DemuxerStream::AUDIO, "{ [0,230) }");
3560 CheckExpectedRanges(DemuxerStream::VIDEO, "{ [0,165) }");
3562 // Seek so we can garbage collect the data appended above.
3565 // Append data at seek_time.
3569 "1000K 1023K 1046K 1069K 1092K 1115K 1138K 1161K 1184K 1207K", 23),
3570 MuxedStreamInfo(kVideoTrackNum, "1000K 1033K 1066K 1099K 1132K", 33));
3572 // We should delete first append, and be exactly at buffer limit
3573 EXPECT_TRUE(demuxer_->EvictCodedFrames(kSourceId, seek_time, 0));
3575 // Verify that the old data, and nothing more, has been garbage collected.
3576 CheckExpectedRanges(DemuxerStream::AUDIO, "{ [1000,1230) }");
3577 CheckExpectedRanges(DemuxerStream::VIDEO, "{ [1000,1165) }");
3580 TEST_F(ChunkDemuxerTest, GCDuringSeek_SingleRange_SeekForward) {
3581 ASSERT_TRUE(InitDemuxer(HAS_AUDIO));
3582 demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, 10 * block_size_);
3583 // Append some data at position 1000ms
3584 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 1000, 10);
3585 CheckExpectedRanges("{ [1000,1230) }");
3587 // GC should be able to evict frames in the currently buffered range, since
3588 // those frames are earlier than the seek target position.
3589 base::TimeDelta seek_time = base::Milliseconds(2000);
3592 demuxer_->EvictCodedFrames(kSourceId, seek_time, 5 * block_size_));
3594 // Append data to complete seek operation
3595 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 2000, 5);
3596 CheckExpectedRanges("{ [1115,1230) [2000,2115) }");
3599 TEST_F(ChunkDemuxerTest, GCDuringSeek_SingleRange_SeekBack) {
3600 ASSERT_TRUE(InitDemuxer(HAS_AUDIO));
3601 demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, 10 * block_size_);
3602 // Append some data at position 1000ms
3603 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 1000, 10);
3604 CheckExpectedRanges("{ [1000,1230) }");
3606 // GC should be able to evict frames in the currently buffered range, since
3607 // seek target position has no data and so we should allow some frames to be
3608 // evicted to make space for the upcoming append at seek target position.
3609 base::TimeDelta seek_time = base::TimeDelta();
3612 demuxer_->EvictCodedFrames(kSourceId, seek_time, 5 * block_size_));
3614 // Append data to complete seek operation
3615 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 0, 5);
3616 CheckExpectedRanges("{ [0,115) [1115,1230) }");
3619 TEST_F(ChunkDemuxerTest, GCDuringSeek_MultipleRanges_SeekForward) {
3620 ASSERT_TRUE(InitDemuxer(HAS_AUDIO));
3621 demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, 10 * block_size_);
3622 // Append some data at position 1000ms then at 2000ms
3623 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 1000, 5);
3624 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 2000, 5);
3625 CheckExpectedRanges("{ [1000,1115) [2000,2115) }");
3627 // GC should be able to evict frames in the currently buffered ranges, since
3628 // those frames are earlier than the seek target position.
3629 base::TimeDelta seek_time = base::Milliseconds(3000);
3632 demuxer_->EvictCodedFrames(kSourceId, seek_time, 8 * block_size_));
3634 // Append data to complete seek operation
3635 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 3000, 5);
3636 CheckExpectedRanges("{ [2069,2115) [3000,3115) }");
3639 TEST_F(ChunkDemuxerTest, GCDuringSeek_MultipleRanges_SeekInbetween1) {
3640 ASSERT_TRUE(InitDemuxer(HAS_AUDIO));
3641 demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, 10 * block_size_);
3642 // Append some data at position 1000ms then at 2000ms
3643 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 1000, 5);
3644 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 2000, 5);
3645 CheckExpectedRanges("{ [1000,1115) [2000,2115) }");
3647 // GC should be able to evict all frames from the first buffered range, since
3648 // those frames are earlier than the seek target position. But there's only 5
3649 // blocks worth of data in the first range and seek target position has no
3650 // data, so GC proceeds with trying to delete some frames from the back of
3651 // buffered ranges, that doesn't yield anything, since that's the most
3652 // recently appended data, so then GC starts removing data from the front of
3653 // the remaining buffered range (2000ms) to ensure we free up enough space for
3654 // the upcoming append and allow seek to proceed.
3655 base::TimeDelta seek_time = base::Milliseconds(1500);
3658 demuxer_->EvictCodedFrames(kSourceId, seek_time, 8 * block_size_));
3660 // Append data to complete seek operation
3661 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 1500, 5);
3662 CheckExpectedRanges("{ [1500,1615) [2069,2115) }");
3665 TEST_F(ChunkDemuxerTest, GCDuringSeek_MultipleRanges_SeekInbetween2) {
3666 ASSERT_TRUE(InitDemuxer(HAS_AUDIO));
3667 demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, 10 * block_size_);
3669 // Append some data at position 2000ms first, then at 1000ms, so that the last
3670 // appended data position is in the first buffered range (that matters to the
3671 // GC algorithm since it tries to preserve more recently appended data).
3672 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 2000, 5);
3673 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 1000, 5);
3674 CheckExpectedRanges("{ [1000,1115) [2000,2115) }");
3676 // Now try performing garbage collection without announcing seek first, i.e.
3677 // without calling Seek(), the GC algorithm should try to preserve data in the
3678 // first range, since that is most recently appended data.
3679 base::TimeDelta seek_time = base::Milliseconds(2030);
3681 demuxer_->EvictCodedFrames(kSourceId, seek_time, 5 * block_size_));
3683 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 1500, 5);
3684 CheckExpectedRanges("{ [1000,1115) [1500,1615) }");
3687 TEST_F(ChunkDemuxerTest, GCDuringSeek_MultipleRanges_SeekBack) {
3688 ASSERT_TRUE(InitDemuxer(HAS_AUDIO));
3689 demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, 10 * block_size_);
3690 // Append some data at position 1000ms then at 2000ms
3691 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 1000, 5);
3692 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 2000, 5);
3693 CheckExpectedRanges("{ [1000,1115) [2000,2115) }");
3695 // GC should be able to evict frames in the currently buffered ranges, since
3696 // those frames are earlier than the seek target position.
3697 base::TimeDelta seek_time = base::TimeDelta();
3700 demuxer_->EvictCodedFrames(kSourceId, seek_time, 8 * block_size_));
3702 // Append data to complete seek operation
3703 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 0, 5);
3704 CheckExpectedRanges("{ [0,115) [2069,2115) }");
3707 TEST_F(ChunkDemuxerTest, GCDuringSeek) {
3708 ASSERT_TRUE(InitDemuxer(HAS_AUDIO));
3710 demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, 5 * block_size_);
3712 base::TimeDelta seek_time1 = base::Milliseconds(1000);
3713 base::TimeDelta seek_time2 = base::Milliseconds(500);
3715 // Initiate a seek to |seek_time1|.
3718 // Append data to satisfy the first seek request.
3719 AppendSingleStreamCluster(kSourceId, kAudioTrackNum,
3720 seek_time1.InMilliseconds(), 5);
3721 CheckExpectedRanges("{ [1000,1115) }");
3723 // We are under memory limit, so Evict should be a no-op.
3724 EXPECT_TRUE(demuxer_->EvictCodedFrames(kSourceId, seek_time1, 0));
3725 CheckExpectedRanges("{ [1000,1115) }");
3727 // Signal that the second seek is starting.
3728 demuxer_->StartWaitingForSeek(seek_time2);
3730 // Append data to satisfy the second seek.
3731 AppendSingleStreamCluster(kSourceId, kAudioTrackNum,
3732 seek_time2.InMilliseconds(), 5);
3733 CheckExpectedRanges("{ [500,615) [1000,1115) }");
3735 // We are now over our memory usage limit. We have just seeked to |seek_time2|
3736 // so data around 500ms position should be preserved, while the previous
3737 // append at 1000ms should be removed.
3738 EXPECT_TRUE(demuxer_->EvictCodedFrames(kSourceId, seek_time2, 0));
3739 CheckExpectedRanges("{ [500,615) }");
3741 // Complete the seek.
3742 demuxer_->Seek(seek_time2, NewExpectedStatusCB(PIPELINE_OK));
3744 // Append more data and make sure that we preserve both the buffered range
3745 // around |seek_time2|, because that's the current playback position,
3746 // and the newly appended range, since this is the most recent append.
3747 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 700, 5);
3748 EXPECT_FALSE(demuxer_->EvictCodedFrames(kSourceId, seek_time2, 0));
3749 CheckExpectedRanges("{ [500,615) [700,815) }");
3752 TEST_F(ChunkDemuxerTest, GCKeepPlayhead) {
3753 ASSERT_TRUE(InitDemuxer(HAS_AUDIO));
3755 demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, 5 * block_size_);
3757 // Append data at the start that can be garbage collected:
3758 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 0, 10);
3759 CheckExpectedRanges("{ [0,230) }");
3761 // We expect garbage collection to fail, as we don't want to spontaneously
3762 // create gaps in source buffer stream. Gaps could break playback for many
3763 // clients, who don't bother to check ranges after append.
3764 EXPECT_FALSE(demuxer_->EvictCodedFrames(kSourceId, base::Milliseconds(0), 0));
3765 CheckExpectedRanges("{ [0,230) }");
3767 // Increase media_time a bit, this will allow some data to be collected, but
3768 // we are still over memory usage limit.
3769 base::TimeDelta seek_time1 = base::Milliseconds(23 * 2);
3771 EXPECT_FALSE(demuxer_->EvictCodedFrames(kSourceId, seek_time1, 0));
3772 CheckExpectedRanges("{ [46,230) }");
3774 base::TimeDelta seek_time2 = base::Milliseconds(23 * 4);
3776 EXPECT_FALSE(demuxer_->EvictCodedFrames(kSourceId, seek_time2, 0));
3777 CheckExpectedRanges("{ [92,230) }");
3779 // media_time has progressed to a point where we can collect enough data to
3780 // be under memory limit, so Evict should return true.
3781 base::TimeDelta seek_time3 = base::Milliseconds(23 * 6);
3783 EXPECT_TRUE(demuxer_->EvictCodedFrames(kSourceId, seek_time3, 0));
3784 // Strictly speaking the current playback time is 23*6==138ms, so we could
3785 // release data up to 138ms, but we only release as much data as necessary
3786 // to bring memory usage under the limit, so we release only up to 115ms.
3787 CheckExpectedRanges("{ [115,230) }");
3790 TEST_F(ChunkDemuxerTest, AppendWindow_Video) {
3791 ASSERT_TRUE(InitDemuxer(HAS_VIDEO));
3792 DemuxerStream* stream = GetStream(DemuxerStream::VIDEO);
3794 // Set the append window to [50,280).
3795 append_window_start_for_next_append_ = base::Milliseconds(50);
3796 append_window_end_for_next_append_ = base::Milliseconds(280);
3798 // Append a cluster that starts before and ends after the append window.
3799 EXPECT_MEDIA_LOG(DroppedFrame("video", 0));
3800 EXPECT_MEDIA_LOG(DroppedFrame("video", 30000));
3801 EXPECT_MEDIA_LOG(DroppedFrame("video", 270000));
3802 EXPECT_MEDIA_LOG(DroppedFrame("video", 300000));
3803 EXPECT_MEDIA_LOG(DroppedFrame("video", 330000));
3804 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(30));
3805 AppendSingleStreamCluster(kSourceId, kVideoTrackNum,
3806 "0K 30 60 90 120K 150 180 210 240K 270 300 330K");
3808 // Verify that GOPs that start outside the window are not included
3809 // in the buffer. Also verify that buffers that start inside the
3810 // window and extend beyond the end of the window are not included.
3811 CheckExpectedRanges("{ [120,270) }");
3812 CheckExpectedBuffers(stream, "120K 150 180 210 240K");
3814 // Extend the append window to [50,650).
3815 append_window_end_for_next_append_ = base::Milliseconds(650);
3817 // Append more data and verify that adding buffers start at the next
3819 EXPECT_MEDIA_LOG(DroppedFrame("video", 630000));
3820 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(30));
3821 AppendSingleStreamCluster(kSourceId, kVideoTrackNum,
3822 "360 390 420K 450 480 510 540K 570 600 630K");
3823 CheckExpectedRanges("{ [120,270) [420,630) }");
3826 TEST_F(ChunkDemuxerTest, AppendWindow_Audio) {
3827 ASSERT_TRUE(InitDemuxer(HAS_AUDIO));
3828 DemuxerStream* stream = GetStream(DemuxerStream::AUDIO);
3830 // Set the append window to [50,280).
3831 append_window_start_for_next_append_ = base::Milliseconds(50);
3832 append_window_end_for_next_append_ = base::Milliseconds(280);
3834 // Append a cluster that starts before and ends after the append window.
3835 EXPECT_MEDIA_LOG(DroppedFrame("audio", 0));
3836 EXPECT_MEDIA_LOG(TruncatedFrame(30000, 60000, "start", 50000));
3837 EXPECT_MEDIA_LOG(TruncatedFrame(270000, 300000, "end", 280000));
3838 EXPECT_MEDIA_LOG(DroppedFrame("audio", 300000));
3839 EXPECT_MEDIA_LOG(DroppedFrame("audio", 330000));
3840 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(30));
3841 AppendSingleStreamCluster(
3842 kSourceId, kAudioTrackNum,
3843 "0K 30K 60K 90K 120K 150K 180K 210K 240K 270K 300K 330K");
3845 // Verify that frames that end outside the window are not included
3846 // in the buffer. Also verify that buffers that start inside the
3847 // window and extend beyond the end of the window are not included.
3849 // The first 50ms of the range should be truncated since it overlaps
3850 // the start of the append window.
3851 CheckExpectedRanges("{ [50,280) }");
3853 // The "50P" buffer is the "0" buffer marked for complete discard. The next
3854 // "50" buffer is the "30" buffer marked with 20ms of start discard.
3855 CheckExpectedBuffers(stream, "50KP 50K 60K 90K 120K 150K 180K 210K 240K");
3857 // Extend the append window to [50,650).
3858 append_window_end_for_next_append_ = base::Milliseconds(650);
3860 // Append more data and verify that a new range is created.
3861 EXPECT_MEDIA_LOG(TruncatedFrame(630000, 660000, "end", 650000));
3862 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(30));
3863 AppendSingleStreamCluster(
3864 kSourceId, kAudioTrackNum,
3865 "360K 390K 420K 450K 480K 510K 540K 570K 600K 630K");
3866 CheckExpectedRanges("{ [50,280) [360,650) }");
3869 TEST_F(ChunkDemuxerTest, AppendWindow_AudioOverlapStartAndEnd) {
3870 ASSERT_TRUE(InitDemuxer(HAS_AUDIO));
3872 // Set the append window to [10,20).
3873 append_window_start_for_next_append_ = base::Milliseconds(10);
3874 append_window_end_for_next_append_ = base::Milliseconds(20);
3877 TruncatedFrame(0, kAudioBlockDuration * 1000, "start", 10000));
3879 TruncatedFrame(10000, kAudioBlockDuration * 1000, "end", 20000));
3881 // Append a cluster that starts before and ends after the append window.
3882 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(
3883 WebMClusterParser::kDefaultAudioBufferDurationInMs));
3884 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, "0K");
3886 // Verify the append is clipped to the append window.
3887 CheckExpectedRanges("{ [10,20) }");
3890 TEST_F(ChunkDemuxerTest, AppendWindow_WebMFile_AudioOnly) {
3891 EXPECT_CALL(*this, DemuxerOpened());
3892 demuxer_->Initialize(
3893 &host_, CreateInitDoneCallback(base::Milliseconds(2744), PIPELINE_OK));
3894 ASSERT_EQ(ChunkDemuxer::kOk, AddId(kSourceId, HAS_AUDIO));
3896 // Set the append window to [50,150).
3897 append_window_start_for_next_append_ = base::Milliseconds(50);
3898 append_window_end_for_next_append_ = base::Milliseconds(150);
3900 EXPECT_MEDIA_LOG(DroppedFrameCheckAppendWindow(
3902 append_window_start_for_next_append_.InMicroseconds(),
3903 append_window_end_for_next_append_.InMicroseconds()))
3905 EXPECT_MEDIA_LOG(TruncatedFrame(39000, 62000, "start", 50000));
3906 EXPECT_MEDIA_LOG(TruncatedFrame(141000, 164000, "end", 150000));
3908 // Read a WebM file into memory and send the data to the demuxer. The chunk
3909 // size has been chosen carefully to ensure the preroll buffer used by the
3910 // partial append window trim must come from a previous Append() call.
3911 scoped_refptr<DecoderBuffer> buffer =
3912 ReadTestDataFile("bear-320x240-audio-only.webm");
3913 ExpectInitMediaLogs(HAS_AUDIO);
3914 EXPECT_CALL(*this, InitSegmentReceivedMock(_));
3915 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(2));
3916 ASSERT_TRUE(AppendDataInPieces(buffer->data(), buffer->data_size(), 128));
3918 DemuxerStream* stream = GetStream(DemuxerStream::AUDIO);
3919 CheckExpectedBuffers(stream, "50KP 50K 62K 86K 109K 122K 125K 128K");
3922 TEST_F(ChunkDemuxerTest, AppendWindow_AudioConfigUpdateRemovesPreroll) {
3923 EXPECT_CALL(*this, DemuxerOpened());
3924 demuxer_->Initialize(
3925 &host_, CreateInitDoneCallback(base::Milliseconds(2744), PIPELINE_OK));
3926 ASSERT_EQ(ChunkDemuxer::kOk, AddId(kSourceId, HAS_AUDIO));
3928 // Set the append window such that the first file is completely before the
3930 // Expect duration adjustment since actual duration differs slightly from
3931 // duration in the init segment.
3932 const base::TimeDelta duration_1 = base::Milliseconds(2768);
3933 append_window_start_for_next_append_ = duration_1;
3935 EXPECT_MEDIA_LOG(DroppedFrameCheckAppendWindow(
3937 append_window_start_for_next_append_.InMicroseconds(),
3938 append_window_end_for_next_append_.InMicroseconds()))
3941 // Read a WebM file into memory and append the data.
3942 scoped_refptr<DecoderBuffer> buffer =
3943 ReadTestDataFile("bear-320x240-audio-only.webm");
3944 ExpectInitMediaLogs(HAS_AUDIO);
3945 EXPECT_CALL(*this, InitSegmentReceivedMock(_));
3946 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(2));
3947 ASSERT_TRUE(AppendDataInPieces(buffer->data(), buffer->data_size(), 512));
3948 CheckExpectedRanges("{ }");
3950 DemuxerStream* stream = GetStream(DemuxerStream::AUDIO);
3951 AudioDecoderConfig config_1 = stream->audio_decoder_config();
3953 // Read a second WebM with a different config in and append the data.
3954 scoped_refptr<DecoderBuffer> buffer2 =
3955 ReadTestDataFile("bear-320x240-audio-only-48khz.webm");
3956 EXPECT_CALL(*this, InitSegmentReceivedMock(_));
3957 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(22));
3958 EXPECT_CALL(host_, SetDuration(_)).Times(AnyNumber());
3959 ASSERT_TRUE(SetTimestampOffset(kSourceId, duration_1));
3960 ASSERT_TRUE(AppendDataInPieces(buffer2->data(), buffer2->data_size(), 512));
3961 CheckExpectedRanges("{ [2768,5542) }");
3964 ExpectConfigChanged(DemuxerStream::AUDIO);
3965 ASSERT_FALSE(config_1.Matches(stream->audio_decoder_config()));
3966 CheckExpectedBuffers(stream, "2768K 2789K 2811K 2832K");
3969 TEST_F(ChunkDemuxerTest, StartWaitingForSeekAfterParseError) {
3970 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
3971 EXPECT_MEDIA_LOG(StreamParsingFailed());
3973 OnDemuxerError(HasStatusCode(CHUNK_DEMUXER_ERROR_APPEND_FAILED)));
3975 base::TimeDelta seek_time = base::Seconds(50);
3976 demuxer_->StartWaitingForSeek(seek_time);
3979 TEST_F(ChunkDemuxerTest, Remove_AudioVideoText) {
3980 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
3982 DemuxerStream* audio_stream = GetStream(DemuxerStream::AUDIO);
3983 DemuxerStream* video_stream = GetStream(DemuxerStream::VIDEO);
3986 MuxedStreamInfo(kAudioTrackNum, "0K 20K 40K 60K 80K 100K 120K 140K", 20),
3987 MuxedStreamInfo(kVideoTrackNum, "0K 30 60 90 120K 150 180", 30));
3989 CheckExpectedBuffers(audio_stream, "0K 20K 40K 60K 80K 100K 120K 140K");
3990 CheckExpectedBuffers(video_stream, "0K 30 60 90 120K 150 180");
3992 // Remove the buffers that were added.
3993 demuxer_->Remove(kSourceId, base::TimeDelta(), base::Milliseconds(300));
3995 // Verify that all the appended data has been removed.
3996 CheckExpectedRanges("{ }");
3998 // Append new buffers that are clearly different than the original
3999 // ones and verify that only the new buffers are returned.
4001 MuxedStreamInfo(kAudioTrackNum, "1K 21K 41K 61K 81K 101K 121K 141K", 20),
4002 MuxedStreamInfo(kVideoTrackNum, "1K 31 61 91 121K 151 181", 30));
4004 Seek(base::TimeDelta());
4005 CheckExpectedBuffers(audio_stream, "1K 21K 41K 61K 81K 101K 121K 141K");
4006 CheckExpectedBuffers(video_stream, "1K 31 61 91 121K 151 181");
4009 TEST_F(ChunkDemuxerTest, Remove_StartAtDuration) {
4010 ASSERT_TRUE(InitDemuxer(HAS_AUDIO));
4011 DemuxerStream* audio_stream = GetStream(DemuxerStream::AUDIO);
4013 // Set the duration to something small so that the append that
4014 // follows updates the duration to reflect the end of the appended data.
4015 EXPECT_CALL(host_, SetDuration(base::Milliseconds(1)));
4016 demuxer_->SetDuration(0.001);
4018 EXPECT_CALL(host_, SetDuration(base::Milliseconds(160)));
4019 AppendSingleStreamCluster(kSourceId, kAudioTrackNum,
4020 "0K 20K 40K 60K 80K 100K 120K 140D20K");
4022 CheckExpectedRanges("{ [0,160) }");
4023 CheckExpectedBuffers(audio_stream, "0K 20K 40K 60K 80K 100K 120K 140K");
4025 demuxer_->Remove(kSourceId, base::Seconds(demuxer_->GetDuration()),
4028 Seek(base::TimeDelta());
4029 CheckExpectedRanges("{ [0,160) }");
4030 CheckExpectedBuffers(audio_stream, "0K 20K 40K 60K 80K 100K 120K 140K");
4033 // Verifies that a Seek() will complete without text cues for
4034 // the seek point and will return cues after the seek position
4035 // when they are eventually appended.
4036 TEST_F(ChunkDemuxerTest, SeekCompletesWithoutTextCues) {
4037 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
4039 DemuxerStream* audio_stream = GetStream(DemuxerStream::AUDIO);
4040 DemuxerStream* video_stream = GetStream(DemuxerStream::VIDEO);
4042 base::TimeDelta seek_time = base::Milliseconds(120);
4043 bool seek_cb_was_called = false;
4044 demuxer_->StartWaitingForSeek(seek_time);
4045 demuxer_->Seek(seek_time,
4046 base::BindOnce(OnSeekDone_OKExpected, &seek_cb_was_called));
4047 base::RunLoop().RunUntilIdle();
4049 EXPECT_FALSE(seek_cb_was_called);
4051 // Append audio & video data so the seek completes.
4053 MuxedStreamInfo(kAudioTrackNum,
4054 "0K 20K 40K 60K 80K 100K 120K 140K 160K 180K 200K", 20),
4055 MuxedStreamInfo(kVideoTrackNum, "0K 30 60 90 120K 150 180 210", 30));
4057 base::RunLoop().RunUntilIdle();
4058 EXPECT_TRUE(seek_cb_was_called);
4060 // Read some audio & video buffers to further verify seek completion.
4061 CheckExpectedBuffers(audio_stream, "120K 140K");
4062 CheckExpectedBuffers(video_stream, "120K 150");
4064 // Append text cues that start after the seek point and verify that
4065 // they are returned by Read() calls.
4066 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "220K 240K 260K 280K", 20),
4067 MuxedStreamInfo(kVideoTrackNum, "240K 270 300 330", 30));
4069 base::RunLoop().RunUntilIdle();
4071 // Verify that audio & video streams continue to return expected values.
4072 CheckExpectedBuffers(audio_stream, "160K 180K");
4073 CheckExpectedBuffers(video_stream, "180 210");
4076 TEST_F(ChunkDemuxerTest, ClusterWithUnknownSize) {
4077 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
4079 ASSERT_TRUE(AppendCluster(GenerateCluster(0, 0, 4, true)));
4080 CheckExpectedRanges("{ [0,46) }");
4082 // A new cluster indicates end of the previous cluster with unknown size.
4083 ASSERT_TRUE(AppendCluster(GenerateCluster(46, 66, 5, true)));
4084 CheckExpectedRanges("{ [0,115) }");
4087 TEST_F(ChunkDemuxerTest, CuesBetweenClustersWithUnknownSize) {
4088 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
4090 // Add two clusters separated by Cues in a single Append() call.
4091 std::unique_ptr<Cluster> cluster = GenerateCluster(0, 0, 4, true);
4092 std::vector<uint8_t> data(cluster->data(), cluster->data() + cluster->size());
4093 data.insert(data.end(), kCuesHeader, kCuesHeader + sizeof(kCuesHeader));
4094 cluster = GenerateCluster(46, 66, 5, true);
4095 data.insert(data.end(), cluster->data(), cluster->data() + cluster->size());
4096 ASSERT_TRUE(AppendData(&*data.begin(), data.size()));
4098 CheckExpectedRanges("{ [0,115) }");
4101 TEST_F(ChunkDemuxerTest, CuesBetweenClusters) {
4102 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
4104 ASSERT_TRUE(AppendCluster(GenerateCluster(0, 0, 4)));
4105 ASSERT_TRUE(AppendData(kCuesHeader, sizeof(kCuesHeader)));
4106 ASSERT_TRUE(AppendCluster(GenerateCluster(46, 66, 5)));
4107 CheckExpectedRanges("{ [0,115) }");
4110 TEST_F(ChunkDemuxerTest, EvictCodedFramesTest) {
4111 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
4112 demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, 10 * block_size_);
4113 demuxer_->SetMemoryLimitsForTest(DemuxerStream::VIDEO, 15 * block_size_);
4114 DemuxerStream* audio_stream = GetStream(DemuxerStream::AUDIO);
4115 DemuxerStream* video_stream = GetStream(DemuxerStream::VIDEO);
4117 const char* kAudioStreamInfo = "0K 40K 80K 120K 160K 200K 240K 280K";
4118 const char* kVideoStreamInfo = "0K 10 20K 30 40K 50 60K 70 80K 90 100K "
4119 "110 120K 130 140K";
4120 // Append 8 blocks (80 bytes) of data to audio stream and 15 blocks (150
4121 // bytes) to video stream.
4122 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, kAudioStreamInfo, 40),
4123 MuxedStreamInfo(kVideoTrackNum, kVideoStreamInfo, 10));
4124 CheckExpectedBuffers(audio_stream, kAudioStreamInfo);
4125 CheckExpectedBuffers(video_stream, kVideoStreamInfo);
4127 // If we want to append 80 more blocks of muxed a+v data and the current
4128 // position is 0, that will fail, because EvictCodedFrames won't remove the
4129 // data after the current playback position.
4131 demuxer_->EvictCodedFrames(kSourceId, base::Milliseconds(0), 80));
4132 // EvictCodedFrames has failed, so data should be unchanged.
4133 Seek(base::Milliseconds(0));
4134 CheckExpectedBuffers(audio_stream, kAudioStreamInfo);
4135 CheckExpectedBuffers(video_stream, kVideoStreamInfo);
4137 // But if we pretend that playback position has moved to 120ms, that allows
4138 // EvictCodedFrames to garbage-collect enough data to succeed.
4140 demuxer_->EvictCodedFrames(kSourceId, base::Milliseconds(120), 80));
4142 Seek(base::Milliseconds(0));
4143 // Audio stream had 8 buffers, video stream had 15. We told EvictCodedFrames
4144 // that the new data size is 8 blocks muxed, i.e. 80 bytes. Given the current
4145 // ratio of video to the total data size (15 : (8+15) ~= 0.65) the estimated
4146 // sizes of video and audio data in the new 80 byte chunk are 52 bytes for
4147 // video (80*0.65 = 52) and 28 bytes for audio (80 - 52).
4148 // Given these numbers MSE GC will remove just one audio block (since current
4149 // audio size is 80 bytes, new data is 28 bytes, we need to remove just one 10
4150 // byte block to stay under 100 bytes memory limit after append
4151 // 80 - 10 + 28 = 98).
4152 // For video stream 150 + 52 = 202. Video limit is 150 bytes. We need to
4153 // remove at least 6 blocks to stay under limit.
4154 CheckExpectedBuffers(audio_stream, "40K 80K 120K 160K 200K 240K 280K");
4155 CheckExpectedBuffers(video_stream, "60K 70 80K 90 100K 110 120K 130 140K");
4158 TEST_F(ChunkDemuxerTest, SegmentMissingAudioFrame_AudioOnly) {
4159 ASSERT_TRUE(InitDemuxer(HAS_AUDIO));
4160 EXPECT_MEDIA_LOG(SegmentMissingFrames("2"));
4161 ASSERT_TRUE(AppendCluster(GenerateEmptyCluster(0)));
4164 TEST_F(ChunkDemuxerTest, SegmentMissingVideoFrame_VideoOnly) {
4165 ASSERT_TRUE(InitDemuxer(HAS_VIDEO));
4166 EXPECT_MEDIA_LOG(SegmentMissingFrames("1"));
4167 ASSERT_TRUE(AppendCluster(GenerateEmptyCluster(0)));
4170 TEST_F(ChunkDemuxerTest, SegmentMissingAudioFrame_AudioVideo) {
4171 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
4172 EXPECT_MEDIA_LOG(SegmentMissingFrames("2"));
4173 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, 0, 10);
4176 TEST_F(ChunkDemuxerTest, SegmentMissingVideoFrame_AudioVideo) {
4177 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
4178 EXPECT_MEDIA_LOG(SegmentMissingFrames("1"));
4179 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 0, 10);
4182 TEST_F(ChunkDemuxerTest, SegmentMissingAudioVideoFrames) {
4183 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
4184 EXPECT_MEDIA_LOG(SegmentMissingFrames("1"));
4185 EXPECT_MEDIA_LOG(SegmentMissingFrames("2"));
4186 ASSERT_TRUE(AppendCluster(GenerateEmptyCluster(0)));
4189 TEST_F(ChunkDemuxerTest, RelaxedKeyframe_FirstSegmentMissingKeyframe) {
4190 // Append V:[n n n][n n K]
4192 ASSERT_TRUE(InitDemuxer(HAS_VIDEO));
4193 DemuxerStream* video_stream = GetStream(DemuxerStream::VIDEO);
4195 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(10)).Times(2);
4196 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "0 10 20");
4197 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "30 40 50K");
4198 CheckExpectedRanges("{ [50,60) }");
4199 CheckExpectedBuffers(video_stream, "50K");
4202 TEST_F(ChunkDemuxerTest, RelaxedKeyframe_SecondSegmentMissingKeyframe) {
4203 // Append V:[K n n][n n n]
4204 // Expect V:[K n n][n n n]
4205 ASSERT_TRUE(InitDemuxer(HAS_VIDEO));
4206 DemuxerStream* video_stream = GetStream(DemuxerStream::VIDEO);
4208 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(10)).Times(2);
4209 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "0K 10 20");
4210 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "30 40 50");
4211 CheckExpectedRanges("{ [0,60) }");
4212 CheckExpectedBuffers(video_stream, "0K 10 20 30 40 50");
4215 TEST_F(ChunkDemuxerTest, RelaxedKeyframe_RemoveInterruptsCodedFrameGroup_1) {
4218 // Append V: [n n n][n K n]
4220 ASSERT_TRUE(InitDemuxer(HAS_VIDEO));
4221 DemuxerStream* video_stream = GetStream(DemuxerStream::VIDEO);
4223 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(10)).Times(3);
4224 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "0K 10 20");
4225 demuxer_->Remove(kSourceId, base::TimeDelta(), base::Milliseconds(30));
4226 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "30 40 50");
4227 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "60 70K 80");
4228 CheckExpectedRanges("{ [70,90) }");
4229 CheckExpectedBuffers(video_stream, "70K 80");
4232 TEST_F(ChunkDemuxerTest, RelaxedKeyframe_RemoveInterruptsCodedFrameGroup_2) {
4233 // Append V:[K n n][n n n][n K n]
4236 ASSERT_TRUE(InitDemuxer(HAS_VIDEO));
4237 DemuxerStream* video_stream = GetStream(DemuxerStream::VIDEO);
4239 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(10)).Times(3);
4240 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "0K 10 20");
4241 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "30 40 50");
4242 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "60 70K 80");
4243 demuxer_->Remove(kSourceId, base::TimeDelta(), base::Milliseconds(10));
4244 CheckExpectedRanges("{ [70,90) }");
4245 CheckExpectedBuffers(video_stream, "70K 80");
4248 TEST_F(ChunkDemuxerTest, RelaxedKeyframe_RemoveInterruptsCodedFrameGroup_3) {
4249 // Append V:[K n n][n n n][n K n]
4251 // Expect: [K n n..n n] [K n]
4252 ASSERT_TRUE(InitDemuxer(HAS_VIDEO));
4253 DemuxerStream* video_stream = GetStream(DemuxerStream::VIDEO);
4255 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(10)).Times(3);
4256 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "0K 10 20");
4257 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "30 40 50");
4258 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "60 70K 80");
4259 demuxer_->Remove(kSourceId, base::Milliseconds(50), base::Milliseconds(60));
4260 CheckExpectedRanges("{ [0,50) [70,90) }");
4261 CheckExpectedBuffers(video_stream, "0K 10 20 30 40");
4262 Seek(base::Milliseconds(70));
4263 CheckExpectedBuffers(video_stream, "70K 80");
4266 TEST_F(ChunkDemuxerTest,
4267 RelaxedKeyframe_RemoveInterruptsMuxedCodedFrameGroup_1) {
4273 // A: [K K K][K K K]
4274 // V: [n n n][n K n]
4276 // A: [K K K][K K K]
4278 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
4279 DemuxerStream* audio_stream = GetStream(DemuxerStream::AUDIO);
4280 DemuxerStream* video_stream = GetStream(DemuxerStream::VIDEO);
4282 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "0K 10K 20D10K"),
4283 MuxedStreamInfo(kVideoTrackNum, "0K 10 20", 10));
4284 demuxer_->Remove(kSourceId, base::TimeDelta(), base::Milliseconds(30));
4285 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "30K 40K 50D10K"),
4286 MuxedStreamInfo(kVideoTrackNum, "30 40 50", 10));
4287 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "60K 70K 80D10K"),
4288 MuxedStreamInfo(kVideoTrackNum, "60 70K 80", 10));
4289 CheckExpectedRanges(DemuxerStream::AUDIO, "{ [30,90) }");
4290 CheckExpectedRanges(DemuxerStream::VIDEO, "{ [70,90) }");
4291 CheckExpectedRanges("{ [70,90) }");
4292 CheckExpectedBuffers(audio_stream, "30K 40K 50K 60K 70K 80K");
4293 CheckExpectedBuffers(video_stream, "70K 80");
4296 TEST_F(ChunkDemuxerTest,
4297 RelaxedKeyframe_RemoveInterruptsMuxedCodedFrameGroup_2) {
4300 // V:(Nothing, simulating jagged cluster start or a long previous
4304 // A: [K K K][K K K]
4305 // V: [n n n][n K n]
4307 // A: [K K K][K K K]
4308 // V [................K n] (As would occur if there really were a
4309 // jagged cluster start and not badly muxed clusters as used to
4310 // simulate a jagged start in this test.)
4311 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
4312 DemuxerStream* audio_stream = GetStream(DemuxerStream::AUDIO);
4313 DemuxerStream* video_stream = GetStream(DemuxerStream::VIDEO);
4315 EXPECT_MEDIA_LOG(SegmentMissingFrames("1"));
4316 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "0K 10K 20D10K"),
4317 MuxedStreamInfo(kVideoTrackNum, ""));
4318 demuxer_->Remove(kSourceId, base::TimeDelta(), base::Milliseconds(30));
4319 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "30K 40K 50D10K"),
4320 MuxedStreamInfo(kVideoTrackNum, "30 40 50", 10));
4321 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "60K 70K 80D10K"),
4322 MuxedStreamInfo(kVideoTrackNum, "60 70K 80", 10));
4323 CheckExpectedRanges(DemuxerStream::AUDIO, "{ [30,90) }");
4324 CheckExpectedRanges(DemuxerStream::VIDEO, "{ [0,90) }");
4325 CheckExpectedRanges("{ [30,90) }");
4326 CheckExpectedBuffers(audio_stream, "30K 40K 50K 60K 70K 80K");
4327 CheckExpectedBuffers(video_stream, "70K 80");
4330 TEST_F(ChunkDemuxerTest,
4331 RelaxedKeyframe_RemoveInterruptsMuxedCodedFrameGroup_3) {
4334 // V:(Nothing yet. This is a jagged start, not simulated.)
4341 // V [..............K n]
4342 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
4343 DemuxerStream* audio_stream = GetStream(DemuxerStream::AUDIO);
4344 DemuxerStream* video_stream = GetStream(DemuxerStream::VIDEO);
4346 std::vector<MuxedStreamInfo> msi(2);
4348 MuxedStreamInfo(kAudioTrackNum, "0K 10K 20K 30K 40K 50K 60K 70K 80D10K");
4349 msi[1] = MuxedStreamInfo(kVideoTrackNum, "31 41 51 61 71K 81", 10);
4350 std::unique_ptr<Cluster> cluster = GenerateMuxedCluster(msi);
4352 // Append the first part of the cluster, up to the beginning of the first
4353 // video simpleblock. The result should be just 4 audio blocks and no video
4354 // blocks are appended. Since the stream parser does not yet have a duration
4355 // for the 4th audio block in this partial cluster append, it is not yet
4356 // emitted from the parser, and only the first 3 audio blocks are expected to
4357 // be buffered by and available from the demuxer.
4358 ASSERT_EQ(kVideoTrackNum, 1);
4359 int video_start = 0;
4361 while (video_start < cluster->size() - 10) {
4362 if (cluster->data()[video_start] == 0xA3 &&
4363 cluster->data()[video_start + 9] == 0x81) {
4371 ASSERT_GT(video_start, 0);
4372 ASSERT_LT(video_start, cluster->size() - 3);
4374 ASSERT_TRUE(AppendData(kSourceId, cluster->data(), video_start));
4375 CheckExpectedRanges(DemuxerStream::AUDIO, "{ [0,30) }");
4376 CheckExpectedRanges(DemuxerStream::VIDEO, "{ }");
4378 demuxer_->Remove(kSourceId, base::TimeDelta(), base::Milliseconds(30));
4380 // Append the remainder of the cluster
4381 ASSERT_TRUE(AppendData(kSourceId, cluster->data() + video_start,
4382 cluster->size() - video_start));
4384 CheckExpectedRanges(DemuxerStream::AUDIO, "{ [30,90) }");
4385 CheckExpectedRanges(DemuxerStream::VIDEO, "{ [0,91) }");
4386 CheckExpectedRanges("{ [30,90) }");
4387 CheckExpectedBuffers(audio_stream, "30K 40K 50K 60K 70K 80K");
4388 CheckExpectedBuffers(video_stream, "71K 81");
4392 void QuitLoop(base::OnceClosure quit_closure,
4393 DemuxerStream::Type type,
4394 const std::vector<DemuxerStream*>& streams) {
4395 std::move(quit_closure).Run();
4398 void DisableAndEnableDemuxerTracks(
4399 ChunkDemuxer* demuxer,
4400 base::test::TaskEnvironment* task_environment) {
4401 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
4402 base::WaitableEvent::InitialState::NOT_SIGNALED);
4403 std::vector<MediaTrack::Id> audio_tracks;
4404 std::vector<MediaTrack::Id> video_tracks;
4406 base::RunLoop disable_video;
4407 demuxer->OnSelectedVideoTrackChanged(
4408 video_tracks, base::TimeDelta(),
4409 base::BindOnce(QuitLoop, disable_video.QuitClosure()));
4410 disable_video.Run();
4412 base::RunLoop disable_audio;
4413 demuxer->OnEnabledAudioTracksChanged(
4414 audio_tracks, base::TimeDelta(),
4415 base::BindOnce(QuitLoop, disable_audio.QuitClosure()));
4416 disable_audio.Run();
4418 base::RunLoop enable_video;
4419 video_tracks.push_back(MediaTrack::Id("1"));
4420 demuxer->OnSelectedVideoTrackChanged(
4421 video_tracks, base::TimeDelta(),
4422 base::BindOnce(QuitLoop, enable_video.QuitClosure()));
4425 base::RunLoop enable_audio;
4426 audio_tracks.push_back(MediaTrack::Id("2"));
4427 demuxer->OnEnabledAudioTracksChanged(
4428 audio_tracks, base::TimeDelta(),
4429 base::BindOnce(QuitLoop, enable_audio.QuitClosure()));
4432 task_environment->RunUntilIdle();
4436 TEST_F(ChunkDemuxerTest, StreamStatusNotifications) {
4437 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
4438 ChunkDemuxerStream* audio_stream =
4439 static_cast<ChunkDemuxerStream*>(GetStream(DemuxerStream::AUDIO));
4440 EXPECT_NE(nullptr, audio_stream);
4441 ChunkDemuxerStream* video_stream =
4442 static_cast<ChunkDemuxerStream*>(GetStream(DemuxerStream::VIDEO));
4443 EXPECT_NE(nullptr, video_stream);
4445 // Verify stream status changes without pending read.
4446 DisableAndEnableDemuxerTracks(demuxer_.get(), &task_environment_);
4448 // Verify stream status changes with pending read.
4449 bool read_done = false;
4450 audio_stream->Read(base::BindOnce(&OnReadDone_EOSExpected, &read_done));
4451 DisableAndEnableDemuxerTracks(demuxer_.get(), &task_environment_);
4452 EXPECT_TRUE(read_done);
4454 video_stream->Read(base::BindOnce(&OnReadDone_EOSExpected, &read_done));
4455 DisableAndEnableDemuxerTracks(demuxer_.get(), &task_environment_);
4456 EXPECT_TRUE(read_done);
4459 TEST_F(ChunkDemuxerTest, MultipleIds) {
4461 EXPECT_CALL(*this, DemuxerOpened());
4462 EXPECT_CALL(host_, SetDuration(_)).Times(2);
4463 demuxer_->Initialize(&host_,
4464 CreateInitDoneCallback(kNoTimestamp, PIPELINE_OK));
4466 const char* kId1 = "id1";
4467 const char* kId2 = "id2";
4468 EXPECT_EQ(AddId(kId1, "video/webm", "opus,vp9"), ChunkDemuxer::kOk);
4469 EXPECT_EQ(AddId(kId2, "video/webm", "opus,vp9"), ChunkDemuxer::kOk);
4470 scoped_refptr<DecoderBuffer> data1 = ReadTestDataFile("green-a300hz.webm");
4471 scoped_refptr<DecoderBuffer> data2 = ReadTestDataFile("red-a500hz.webm");
4473 EXPECT_FOUND_CODEC_NAME(Video, "vp9").Times(2);
4474 EXPECT_FOUND_CODEC_NAME(Audio, "opus").Times(2);
4475 EXPECT_CALL(*this, InitSegmentReceivedMock(_)).Times(2);
4476 EXPECT_MEDIA_LOG(SegmentMissingFrames("1")).Times(1);
4478 EXPECT_TRUE(AppendData(kId1, data1->data(), data1->data_size()));
4479 EXPECT_TRUE(AppendData(kId2, data2->data(), data2->data_size()));
4480 CheckExpectedRanges(kId1, "{ [0,12007) }");
4481 CheckExpectedRanges(kId2, "{ [0,10007) }");
4484 TEST_F(ChunkDemuxerTest, CompleteInitAfterIdRemoved) {
4486 EXPECT_CALL(*this, DemuxerOpened());
4487 demuxer_->Initialize(&host_,
4488 CreateInitDoneCallback(kDefaultDuration(), PIPELINE_OK));
4490 // Add two ids, then remove one of the ids and verify that adding init segment
4491 // only for the remaining id still triggers the InitDoneCB.
4492 const char* kId1 = "id1";
4493 const char* kId2 = "id2";
4494 EXPECT_EQ(AddId(kId1, "video/webm", "vp8"), ChunkDemuxer::kOk);
4495 EXPECT_EQ(AddId(kId2, "video/webm", "vp9"), ChunkDemuxer::kOk);
4496 demuxer_->RemoveId(kId2);
4498 EXPECT_CALL(*this, InitSegmentReceivedMock(_));
4499 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(30));
4500 EXPECT_FOUND_CODEC_NAME(Video, "vp8");
4502 ASSERT_TRUE(AppendInitSegmentWithSourceId(kId1, HAS_VIDEO));
4503 AppendSingleStreamCluster(kId1, kVideoTrackNum, "0K 30 60 90");
4506 TEST_F(ChunkDemuxerTest, RemovingIdMustRemoveStreams) {
4508 EXPECT_CALL(*this, DemuxerOpened());
4509 demuxer_->Initialize(&host_,
4510 CreateInitDoneCallback(kDefaultDuration(), PIPELINE_OK));
4512 const char* kId1 = "id1";
4513 EXPECT_EQ(AddId(kId1, "video/webm", "vorbis,vp8"), ChunkDemuxer::kOk);
4515 EXPECT_CALL(*this, InitSegmentReceivedMock(_));
4516 EXPECT_FOUND_CODEC_NAME(Video, "vp8");
4517 EXPECT_FOUND_CODEC_NAME(Audio, "vorbis");
4519 // Append init segment to ensure demuxer streams get created.
4520 ASSERT_TRUE(AppendInitSegmentWithSourceId(kId1, HAS_AUDIO | HAS_VIDEO));
4521 EXPECT_NE(nullptr, GetStream(DemuxerStream::AUDIO));
4522 EXPECT_NE(nullptr, GetStream(DemuxerStream::VIDEO));
4524 // Removing the id should remove also the DemuxerStreams.
4525 demuxer_->RemoveId(kId1);
4526 EXPECT_EQ(nullptr, GetStream(DemuxerStream::AUDIO));
4527 EXPECT_EQ(nullptr, GetStream(DemuxerStream::VIDEO));
4530 TEST_F(ChunkDemuxerTest, SequenceModeMuxedAppendShouldWarn) {
4531 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
4533 demuxer_->SetSequenceMode(kSourceId, true);
4535 OnParseWarningMock(SourceBufferParseWarning::kMuxedSequenceMode));
4536 EXPECT_MEDIA_LOG(MuxedSequenceModeWarning());
4538 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "0D10K"),
4539 MuxedStreamInfo(kVideoTrackNum, "0D10K"));
4542 TEST_F(ChunkDemuxerTest, SequenceModeSingleTrackNoWarning) {
4543 std::string audio_id = "audio1";
4544 std::string video_id = "video1";
4547 OnParseWarningMock(SourceBufferParseWarning::kMuxedSequenceMode))
4549 EXPECT_MEDIA_LOG(MuxedSequenceModeWarning()).Times(0);
4551 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
4553 demuxer_->SetSequenceMode(audio_id, true);
4554 demuxer_->SetSequenceMode(video_id, true);
4556 // Append audio and video data into separate source ids.
4557 ASSERT_TRUE(AppendCluster(
4558 audio_id, GenerateSingleStreamCluster(0, 23, kAudioTrackNum, 23)));
4559 ASSERT_TRUE(AppendCluster(
4560 video_id, GenerateSingleStreamCluster(0, 33, kVideoTrackNum, 33)));
4563 TEST_F(ChunkDemuxerTest, Mp4Vp9CodecSupport) {
4564 demuxer_->Initialize(&host_,
4565 base::BindOnce(&ChunkDemuxerTest::DemuxerInitialized,
4566 base::Unretained(this)));
4567 ChunkDemuxer::Status expected = ChunkDemuxer::kOk;
4568 EXPECT_EQ(AddId("source_id", "video/mp4", "vp09.00.10.08"), expected);
4571 TEST_F(ChunkDemuxerTest, UnmarkEOSRetainsParseErrorState_BeforeInit) {
4573 // Trigger a (fatal) parse error prior to successfully reaching source init.
4574 EXPECT_CALL(*this, DemuxerOpened());
4575 EXPECT_MEDIA_LOG(StreamParsingFailed());
4576 demuxer_->Initialize(
4578 CreateInitDoneCallback(kNoTimestamp, CHUNK_DEMUXER_ERROR_APPEND_FAILED));
4580 ASSERT_EQ(AddId(kSourceId, HAS_AUDIO | HAS_VIDEO), ChunkDemuxer::kOk);
4583 // Simulate SourceBuffer Append Error algorithm.
4584 demuxer_->ResetParserState(kSourceId, append_window_start_for_next_append_,
4585 append_window_end_for_next_append_,
4586 ×tamp_offset_map_[kSourceId]);
4587 demuxer_->MarkEndOfStream(CHUNK_DEMUXER_ERROR_EOS_STATUS_DECODE_ERROR);
4589 // UnmarkEndOfStream and verify that attempted append of an initialization
4590 // segment still fails.
4591 demuxer_->UnmarkEndOfStream();
4592 ASSERT_FALSE(AppendInitSegment(HAS_AUDIO | HAS_VIDEO));
4595 TEST_F(ChunkDemuxerTest, UnmarkEOSRetainsParseErrorState_AfterInit) {
4597 // Trigger a (fatal) parse error after successfully reaching source init.
4598 InitDemuxer(HAS_AUDIO | HAS_VIDEO);
4599 EXPECT_MEDIA_LOG(StreamParsingFailed());
4601 OnDemuxerError(HasStatusCode(CHUNK_DEMUXER_ERROR_APPEND_FAILED)));
4604 // Simulate SourceBuffer Append Error algorithm.
4605 demuxer_->ResetParserState(kSourceId, append_window_start_for_next_append_,
4606 append_window_end_for_next_append_,
4607 ×tamp_offset_map_[kSourceId]);
4608 demuxer_->MarkEndOfStream(CHUNK_DEMUXER_ERROR_EOS_STATUS_DECODE_ERROR);
4610 // UnmarkEndOfStream and verify that attempted append of another
4611 // initialization segment still fails.
4612 demuxer_->UnmarkEndOfStream();
4613 ASSERT_FALSE(AppendInitSegment(HAS_AUDIO | HAS_VIDEO));
4616 struct ZeroLengthFrameCase {
4617 DemuxerStream::Type stream_type;
4622 // Test that 0-length audio and video coded frames are dropped gracefully.
4623 TEST_F(ChunkDemuxerTest, ZeroLengthFramesDropped) {
4624 struct ZeroLengthFrameCase cases[] = {
4625 {DemuxerStream::AUDIO, HAS_AUDIO, kAudioTrackNum},
4626 {DemuxerStream::VIDEO, HAS_VIDEO, kVideoTrackNum}};
4628 for (const auto& c : cases) {
4632 ASSERT_TRUE(InitDemuxer(c.flags));
4633 DemuxerStream* stream = GetStream(c.stream_type);
4635 // Append a cluster containing nonzero-sized frames. Use end of stream to
4636 // ensure we read back precisely the expected buffers.
4637 ASSERT_GT(block_size_, 0U);
4638 AppendSingleStreamCluster(kSourceId, c.track_number, "0K 10K 20K 30D10K");
4639 EXPECT_CALL(host_, SetDuration(base::Milliseconds(40)));
4640 MarkEndOfStream(PIPELINE_OK);
4641 CheckExpectedRanges("{ [0,40) }");
4642 CheckExpectedBuffers(stream, "0K 10K 20K 30K");
4643 ExpectEndOfStream(c.stream_type);
4645 // Append a cluster containing a 0-sized frame. Verify there is nothing new
4647 demuxer_->UnmarkEndOfStream();
4648 EXPECT_MEDIA_LOG(DiscardingEmptyFrame(40000, 40000));
4650 AppendSingleStreamCluster(kSourceId, c.track_number, "40D10K");
4651 MarkEndOfStream(PIPELINE_OK);
4652 Seek(base::Milliseconds(0));
4653 CheckExpectedRanges("{ [0,40) }");
4654 CheckExpectedBuffers(stream, "0K 10K 20K 30K");
4655 ExpectEndOfStream(c.stream_type);
4657 // Append a cluster containing a nonzero-sized frame. Verify it is buffered.
4658 demuxer_->UnmarkEndOfStream();
4659 EXPECT_CALL(host_, SetDuration(base::Milliseconds(50)));
4660 block_size_ = kBlockSize;
4661 AppendSingleStreamCluster(kSourceId, c.track_number, "40D10K");
4662 MarkEndOfStream(PIPELINE_OK);
4663 Seek(base::Milliseconds(0));
4664 CheckExpectedRanges("{ [0,50) }");
4665 CheckExpectedBuffers(stream, "0K 10K 20K 30K 40K");
4666 ExpectEndOfStream(c.stream_type);
4670 // TODO(servolk): Add a unit test with multiple audio/video tracks using the
4671 // same codec type in a single SourceBufferState, when WebM parser supports
4672 // multiple tracks. crbug.com/646900
4674 } // namespace media