NaCl: Update revision in DEPS, r12770 -> r12773
[chromium-blink-merge.git] / media / filters / chunk_demuxer_unittest.cc
blobd2c410da9c02c7040b36b8490254b88b8b8cd447
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include <algorithm>
7 #include "base/bind.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/string_split.h"
11 #include "base/strings/string_util.h"
12 #include "media/base/audio_decoder_config.h"
13 #include "media/base/decoder_buffer.h"
14 #include "media/base/decrypt_config.h"
15 #include "media/base/mock_demuxer_host.h"
16 #include "media/base/test_data_util.h"
17 #include "media/base/test_helpers.h"
18 #include "media/filters/chunk_demuxer.h"
19 #include "media/formats/webm/cluster_builder.h"
20 #include "media/formats/webm/webm_constants.h"
21 #include "media/formats/webm/webm_crypto_helpers.h"
22 #include "testing/gtest/include/gtest/gtest.h"
24 using ::testing::AnyNumber;
25 using ::testing::Exactly;
26 using ::testing::InSequence;
27 using ::testing::NotNull;
28 using ::testing::Return;
29 using ::testing::SaveArg;
30 using ::testing::SetArgumentPointee;
31 using ::testing::_;
33 namespace media {
35 const uint8 kTracksHeader[] = {
36 0x16, 0x54, 0xAE, 0x6B, // Tracks ID
37 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // tracks(size = 0)
40 // WebM Block bytes that represent a VP8 keyframe.
41 const uint8 kVP8Keyframe[] = {
42 0x010, 0x00, 0x00, 0x9d, 0x01, 0x2a, 0x00, 0x10, 0x00, 0x10, 0x00
45 // WebM Block bytes that represent a VP8 interframe.
46 const uint8 kVP8Interframe[] = { 0x11, 0x00, 0x00 };
48 const int kTracksHeaderSize = sizeof(kTracksHeader);
49 const int kTracksSizeOffset = 4;
51 // The size of TrackEntry element in test file "webm_vorbis_track_entry" starts
52 // at index 1 and spans 8 bytes.
53 const int kAudioTrackSizeOffset = 1;
54 const int kAudioTrackSizeWidth = 8;
55 const int kAudioTrackEntryHeaderSize =
56 kAudioTrackSizeOffset + kAudioTrackSizeWidth;
58 // The size of TrackEntry element in test file "webm_vp8_track_entry" starts at
59 // index 1 and spans 8 bytes.
60 const int kVideoTrackSizeOffset = 1;
61 const int kVideoTrackSizeWidth = 8;
62 const int kVideoTrackEntryHeaderSize =
63 kVideoTrackSizeOffset + kVideoTrackSizeWidth;
65 const int kVideoTrackNum = 1;
66 const int kAudioTrackNum = 2;
67 const int kTextTrackNum = 3;
69 const int kAudioBlockDuration = 23;
70 const int kVideoBlockDuration = 33;
71 const int kTextBlockDuration = 100;
72 const int kBlockSize = 10;
74 const char kSourceId[] = "SourceId";
75 const char kDefaultFirstClusterRange[] = "{ [0,46) }";
76 const int kDefaultFirstClusterEndTimestamp = 66;
77 const int kDefaultSecondClusterEndTimestamp = 132;
79 base::TimeDelta kDefaultDuration() {
80 return base::TimeDelta::FromMilliseconds(201224);
83 // Write an integer into buffer in the form of vint that spans 8 bytes.
84 // The data pointed by |buffer| should be at least 8 bytes long.
85 // |number| should be in the range 0 <= number < 0x00FFFFFFFFFFFFFF.
86 static void WriteInt64(uint8* buffer, int64 number) {
87 DCHECK(number >= 0 && number < GG_LONGLONG(0x00FFFFFFFFFFFFFF));
88 buffer[0] = 0x01;
89 int64 tmp = number;
90 for (int i = 7; i > 0; i--) {
91 buffer[i] = tmp & 0xff;
92 tmp >>= 8;
96 MATCHER_P(HasTimestamp, timestamp_in_ms, "") {
97 return arg.get() && !arg->end_of_stream() &&
98 arg->timestamp().InMilliseconds() == timestamp_in_ms;
101 MATCHER(IsEndOfStream, "") { return arg.get() && arg->end_of_stream(); }
103 static void OnReadDone(const base::TimeDelta& expected_time,
104 bool* called,
105 DemuxerStream::Status status,
106 const scoped_refptr<DecoderBuffer>& buffer) {
107 EXPECT_EQ(status, DemuxerStream::kOk);
108 EXPECT_EQ(expected_time, buffer->timestamp());
109 *called = true;
112 static void OnReadDone_AbortExpected(
113 bool* called, DemuxerStream::Status status,
114 const scoped_refptr<DecoderBuffer>& buffer) {
115 EXPECT_EQ(status, DemuxerStream::kAborted);
116 EXPECT_EQ(NULL, buffer.get());
117 *called = true;
120 static void OnReadDone_EOSExpected(bool* called,
121 DemuxerStream::Status status,
122 const scoped_refptr<DecoderBuffer>& buffer) {
123 EXPECT_EQ(status, DemuxerStream::kOk);
124 EXPECT_TRUE(buffer->end_of_stream());
125 *called = true;
128 static void OnSeekDone_OKExpected(bool* called, PipelineStatus status) {
129 EXPECT_EQ(status, PIPELINE_OK);
130 *called = true;
133 static void LogFunc(const std::string& str) { DVLOG(1) << str; }
135 class ChunkDemuxerTest : public testing::Test {
136 protected:
137 enum CodecsIndex {
138 AUDIO,
139 VIDEO,
140 MAX_CODECS_INDEX
143 // Default cluster to append first for simple tests.
144 scoped_ptr<Cluster> kDefaultFirstCluster() {
145 return GenerateCluster(0, 4);
148 // Default cluster to append after kDefaultFirstCluster()
149 // has been appended. This cluster starts with blocks that
150 // have timestamps consistent with the end times of the blocks
151 // in kDefaultFirstCluster() so that these two clusters represent
152 // a continuous region.
153 scoped_ptr<Cluster> kDefaultSecondCluster() {
154 return GenerateCluster(46, 66, 5);
157 ChunkDemuxerTest() {
158 CreateNewDemuxer();
161 void CreateNewDemuxer() {
162 base::Closure open_cb =
163 base::Bind(&ChunkDemuxerTest::DemuxerOpened, base::Unretained(this));
164 Demuxer::NeedKeyCB need_key_cb =
165 base::Bind(&ChunkDemuxerTest::DemuxerNeedKey, base::Unretained(this));
166 demuxer_.reset(new ChunkDemuxer(open_cb, need_key_cb,
167 base::Bind(&LogFunc)));
170 virtual ~ChunkDemuxerTest() {
171 ShutdownDemuxer();
174 void CreateInitSegment(int stream_flags,
175 bool is_audio_encrypted, bool is_video_encrypted,
176 scoped_ptr<uint8[]>* buffer,
177 int* size) {
178 bool has_audio = (stream_flags & HAS_AUDIO) != 0;
179 bool has_video = (stream_flags & HAS_VIDEO) != 0;
180 bool has_text = (stream_flags & HAS_TEXT) != 0;
181 scoped_refptr<DecoderBuffer> ebml_header;
182 scoped_refptr<DecoderBuffer> info;
183 scoped_refptr<DecoderBuffer> audio_track_entry;
184 scoped_refptr<DecoderBuffer> video_track_entry;
185 scoped_refptr<DecoderBuffer> audio_content_encodings;
186 scoped_refptr<DecoderBuffer> video_content_encodings;
187 scoped_refptr<DecoderBuffer> text_track_entry;
189 ebml_header = ReadTestDataFile("webm_ebml_element");
191 info = ReadTestDataFile("webm_info_element");
193 int tracks_element_size = 0;
195 if (has_audio) {
196 audio_track_entry = ReadTestDataFile("webm_vorbis_track_entry");
197 tracks_element_size += audio_track_entry->data_size();
198 if (is_audio_encrypted) {
199 audio_content_encodings = ReadTestDataFile("webm_content_encodings");
200 tracks_element_size += audio_content_encodings->data_size();
204 if (has_video) {
205 video_track_entry = ReadTestDataFile("webm_vp8_track_entry");
206 tracks_element_size += video_track_entry->data_size();
207 if (is_video_encrypted) {
208 video_content_encodings = ReadTestDataFile("webm_content_encodings");
209 tracks_element_size += video_content_encodings->data_size();
213 if (has_text) {
214 // TODO(matthewjheaney): create an abstraction to do
215 // this (http://crbug/321454).
216 // We need it to also handle the creation of multiple text tracks.
218 // This is the track entry for a text track,
219 // TrackEntry [AE], size=30
220 // TrackNum [D7], size=1, val=3
221 // TrackUID [73] [C5], size=1, value=3
222 // TrackType [83], size=1, val=0x11
223 // CodecId [86], size=18, val="D_WEBVTT/SUBTITLES"
224 const char str[] = "\xAE\x9E\xD7\x81\x03\x73\xC5\x81\x03"
225 "\x83\x81\x11\x86\x92"
226 "D_WEBVTT/SUBTITLES";
227 const int len = strlen(str);
228 DCHECK_EQ(len, 32);
229 const uint8* const buf = reinterpret_cast<const uint8*>(str);
230 text_track_entry = DecoderBuffer::CopyFrom(buf, len);
231 tracks_element_size += text_track_entry->data_size();
234 *size = ebml_header->data_size() + info->data_size() +
235 kTracksHeaderSize + tracks_element_size;
237 buffer->reset(new uint8[*size]);
239 uint8* buf = buffer->get();
240 memcpy(buf, ebml_header->data(), ebml_header->data_size());
241 buf += ebml_header->data_size();
243 memcpy(buf, info->data(), info->data_size());
244 buf += info->data_size();
246 memcpy(buf, kTracksHeader, kTracksHeaderSize);
247 WriteInt64(buf + kTracksSizeOffset, tracks_element_size);
248 buf += kTracksHeaderSize;
250 // TODO(xhwang): Simplify this! Probably have test data files that contain
251 // ContentEncodings directly instead of trying to create one at run-time.
252 if (has_audio) {
253 memcpy(buf, audio_track_entry->data(),
254 audio_track_entry->data_size());
255 if (is_audio_encrypted) {
256 memcpy(buf + audio_track_entry->data_size(),
257 audio_content_encodings->data(),
258 audio_content_encodings->data_size());
259 WriteInt64(buf + kAudioTrackSizeOffset,
260 audio_track_entry->data_size() +
261 audio_content_encodings->data_size() -
262 kAudioTrackEntryHeaderSize);
263 buf += audio_content_encodings->data_size();
265 buf += audio_track_entry->data_size();
268 if (has_video) {
269 memcpy(buf, video_track_entry->data(),
270 video_track_entry->data_size());
271 if (is_video_encrypted) {
272 memcpy(buf + video_track_entry->data_size(),
273 video_content_encodings->data(),
274 video_content_encodings->data_size());
275 WriteInt64(buf + kVideoTrackSizeOffset,
276 video_track_entry->data_size() +
277 video_content_encodings->data_size() -
278 kVideoTrackEntryHeaderSize);
279 buf += video_content_encodings->data_size();
281 buf += video_track_entry->data_size();
284 if (has_text) {
285 memcpy(buf, text_track_entry->data(),
286 text_track_entry->data_size());
287 buf += text_track_entry->data_size();
291 ChunkDemuxer::Status AddId() {
292 return AddId(kSourceId, HAS_AUDIO | HAS_VIDEO);
295 ChunkDemuxer::Status AddId(const std::string& source_id, int stream_flags) {
296 bool has_audio = (stream_flags & HAS_AUDIO) != 0;
297 bool has_video = (stream_flags & HAS_VIDEO) != 0;
298 std::vector<std::string> codecs;
299 std::string type;
301 if (has_audio) {
302 codecs.push_back("vorbis");
303 type = "audio/webm";
306 if (has_video) {
307 codecs.push_back("vp8");
308 type = "video/webm";
311 if (!has_audio && !has_video) {
312 return AddId(kSourceId, HAS_AUDIO | HAS_VIDEO);
315 return demuxer_->AddId(source_id, type, codecs);
318 void AppendData(const uint8* data, size_t length) {
319 AppendData(kSourceId, data, length);
322 void AppendCluster(const std::string& source_id,
323 scoped_ptr<Cluster> cluster) {
324 AppendData(source_id, cluster->data(), cluster->size());
327 void AppendCluster(scoped_ptr<Cluster> cluster) {
328 AppendCluster(kSourceId, cluster.Pass());
331 void AppendCluster(int timecode, int block_count) {
332 AppendCluster(GenerateCluster(timecode, block_count));
335 void AppendSingleStreamCluster(const std::string& source_id, int track_number,
336 int timecode, int block_count) {
337 int block_duration = 0;
338 switch (track_number) {
339 case kVideoTrackNum:
340 block_duration = kVideoBlockDuration;
341 break;
342 case kAudioTrackNum:
343 block_duration = kAudioBlockDuration;
344 break;
345 case kTextTrackNum:
346 block_duration = kTextBlockDuration;
347 break;
349 ASSERT_NE(block_duration, 0);
350 int end_timecode = timecode + block_count * block_duration;
351 AppendCluster(source_id,
352 GenerateSingleStreamCluster(
353 timecode, end_timecode, track_number, block_duration));
356 // |cluster_description| - A space delimited string of buffer info that
357 // is used to construct a cluster. Each buffer info is a timestamp in
358 // milliseconds and optionally followed by a 'K' to indicate that a buffer
359 // should be marked as a keyframe. For example "0K 30 60" should constuct
360 // a cluster with 3 blocks: a keyframe with timestamp 0 and 2 non-keyframes
361 // at 30ms and 60ms.
362 void AppendSingleStreamCluster(const std::string& source_id, int track_number,
363 const std::string& cluster_description) {
364 std::vector<std::string> timestamps;
365 base::SplitString(cluster_description, ' ', &timestamps);
367 ClusterBuilder cb;
368 std::vector<uint8> data(10);
369 for (size_t i = 0; i < timestamps.size(); ++i) {
370 std::string timestamp_str = timestamps[i];
371 int block_flags = 0;
372 if (EndsWith(timestamp_str, "K", true)) {
373 block_flags = kWebMFlagKeyframe;
374 // Remove the "K" off of the token.
375 timestamp_str = timestamp_str.substr(0, timestamps[i].length() - 1);
377 int timestamp_in_ms;
378 CHECK(base::StringToInt(timestamp_str, &timestamp_in_ms));
380 if (i == 0)
381 cb.SetClusterTimecode(timestamp_in_ms);
383 if (track_number == kTextTrackNum) {
384 cb.AddBlockGroup(track_number, timestamp_in_ms, kTextBlockDuration,
385 block_flags, &data[0], data.size());
386 } else {
387 cb.AddSimpleBlock(track_number, timestamp_in_ms, block_flags,
388 &data[0], data.size());
391 AppendCluster(source_id, cb.Finish());
394 void AppendData(const std::string& source_id,
395 const uint8* data, size_t length) {
396 EXPECT_CALL(host_, AddBufferedTimeRange(_, _)).Times(AnyNumber());
397 demuxer_->AppendData(source_id, data, length);
400 void AppendDataInPieces(const uint8* data, size_t length) {
401 AppendDataInPieces(data, length, 7);
404 void AppendDataInPieces(const uint8* data, size_t length, size_t piece_size) {
405 const uint8* start = data;
406 const uint8* end = data + length;
407 while (start < end) {
408 size_t append_size = std::min(piece_size,
409 static_cast<size_t>(end - start));
410 AppendData(start, append_size);
411 start += append_size;
415 void AppendInitSegment(int stream_flags) {
416 AppendInitSegmentWithSourceId(kSourceId, stream_flags);
419 void AppendInitSegmentWithSourceId(const std::string& source_id,
420 int stream_flags) {
421 AppendInitSegmentWithEncryptedInfo(source_id, stream_flags, false, false);
424 void AppendInitSegmentWithEncryptedInfo(const std::string& source_id,
425 int stream_flags,
426 bool is_audio_encrypted,
427 bool is_video_encrypted) {
428 scoped_ptr<uint8[]> info_tracks;
429 int info_tracks_size = 0;
430 CreateInitSegment(stream_flags,
431 is_audio_encrypted, is_video_encrypted,
432 &info_tracks, &info_tracks_size);
433 AppendData(source_id, info_tracks.get(), info_tracks_size);
436 void AppendGarbage() {
437 // Fill up an array with gibberish.
438 int garbage_cluster_size = 10;
439 scoped_ptr<uint8[]> garbage_cluster(new uint8[garbage_cluster_size]);
440 for (int i = 0; i < garbage_cluster_size; ++i)
441 garbage_cluster[i] = i;
442 AppendData(garbage_cluster.get(), garbage_cluster_size);
445 void InitDoneCalled(PipelineStatus expected_status,
446 PipelineStatus status) {
447 EXPECT_EQ(status, expected_status);
450 void AppendEmptyCluster(int timecode) {
451 AppendCluster(GenerateEmptyCluster(timecode));
454 PipelineStatusCB CreateInitDoneCB(const base::TimeDelta& expected_duration,
455 PipelineStatus expected_status) {
456 if (expected_duration != kNoTimestamp())
457 EXPECT_CALL(host_, SetDuration(expected_duration));
458 return CreateInitDoneCB(expected_status);
461 PipelineStatusCB CreateInitDoneCB(PipelineStatus expected_status) {
462 return base::Bind(&ChunkDemuxerTest::InitDoneCalled,
463 base::Unretained(this),
464 expected_status);
467 enum StreamFlags {
468 HAS_AUDIO = 1 << 0,
469 HAS_VIDEO = 1 << 1,
470 HAS_TEXT = 1 << 2
473 bool InitDemuxer(int stream_flags) {
474 return InitDemuxerWithEncryptionInfo(stream_flags, false, false);
477 bool InitDemuxerWithEncryptionInfo(
478 int stream_flags, bool is_audio_encrypted, bool is_video_encrypted) {
480 PipelineStatus expected_status =
481 (stream_flags != 0) ? PIPELINE_OK : DEMUXER_ERROR_COULD_NOT_OPEN;
483 base::TimeDelta expected_duration = kNoTimestamp();
484 if (expected_status == PIPELINE_OK)
485 expected_duration = kDefaultDuration();
487 EXPECT_CALL(*this, DemuxerOpened());
488 demuxer_->Initialize(
489 &host_, CreateInitDoneCB(expected_duration, expected_status), true);
491 if (AddId(kSourceId, stream_flags) != ChunkDemuxer::kOk)
492 return false;
494 AppendInitSegmentWithEncryptedInfo(
495 kSourceId, stream_flags,
496 is_audio_encrypted, is_video_encrypted);
497 return true;
500 bool InitDemuxerAudioAndVideoSourcesText(const std::string& audio_id,
501 const std::string& video_id,
502 bool has_text) {
503 EXPECT_CALL(*this, DemuxerOpened());
504 demuxer_->Initialize(
505 &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true);
507 if (AddId(audio_id, HAS_AUDIO) != ChunkDemuxer::kOk)
508 return false;
509 if (AddId(video_id, HAS_VIDEO) != ChunkDemuxer::kOk)
510 return false;
512 int audio_flags = HAS_AUDIO;
513 int video_flags = HAS_VIDEO;
515 if (has_text) {
516 audio_flags |= HAS_TEXT;
517 video_flags |= HAS_TEXT;
520 AppendInitSegmentWithSourceId(audio_id, audio_flags);
521 AppendInitSegmentWithSourceId(video_id, video_flags);
522 return true;
525 bool InitDemuxerAudioAndVideoSources(const std::string& audio_id,
526 const std::string& video_id) {
527 return InitDemuxerAudioAndVideoSourcesText(audio_id, video_id, false);
530 // Initializes the demuxer with data from 2 files with different
531 // decoder configurations. This is used to test the decoder config change
532 // logic.
534 // bear-320x240.webm VideoDecoderConfig returns 320x240 for its natural_size()
535 // bear-640x360.webm VideoDecoderConfig returns 640x360 for its natural_size()
536 // The resulting video stream returns data from each file for the following
537 // time ranges.
538 // bear-320x240.webm : [0-501) [801-2737)
539 // bear-640x360.webm : [527-793)
541 // bear-320x240.webm AudioDecoderConfig returns 3863 for its extra_data_size()
542 // bear-640x360.webm AudioDecoderConfig returns 3935 for its extra_data_size()
543 // The resulting audio stream returns data from each file for the following
544 // time ranges.
545 // bear-320x240.webm : [0-524) [779-2737)
546 // bear-640x360.webm : [527-759)
547 bool InitDemuxerWithConfigChangeData() {
548 scoped_refptr<DecoderBuffer> bear1 = ReadTestDataFile("bear-320x240.webm");
549 scoped_refptr<DecoderBuffer> bear2 = ReadTestDataFile("bear-640x360.webm");
551 EXPECT_CALL(*this, DemuxerOpened());
552 demuxer_->Initialize(
553 &host_, CreateInitDoneCB(base::TimeDelta::FromMilliseconds(2744),
554 PIPELINE_OK), true);
556 if (AddId(kSourceId, HAS_AUDIO | HAS_VIDEO) != ChunkDemuxer::kOk)
557 return false;
559 // Append the whole bear1 file.
560 AppendData(bear1->data(), bear1->data_size());
561 CheckExpectedRanges(kSourceId, "{ [0,2737) }");
563 // Append initialization segment for bear2.
564 // Note: Offsets here and below are derived from
565 // media/test/data/bear-640x360-manifest.js and
566 // media/test/data/bear-320x240-manifest.js which were
567 // generated from media/test/data/bear-640x360.webm and
568 // media/test/data/bear-320x240.webm respectively.
569 AppendData(bear2->data(), 4340);
571 // Append a media segment that goes from [0.527000, 1.014000).
572 AppendData(bear2->data() + 55290, 18785);
573 CheckExpectedRanges(kSourceId, "{ [0,1028) [1201,2737) }");
575 // Append initialization segment for bear1 & fill gap with [779-1197)
576 // segment.
577 AppendData(bear1->data(), 4370);
578 AppendData(bear1->data() + 72737, 28183);
579 CheckExpectedRanges(kSourceId, "{ [0,2737) }");
581 MarkEndOfStream(PIPELINE_OK);
582 return true;
585 void ShutdownDemuxer() {
586 if (demuxer_) {
587 demuxer_->Shutdown();
588 message_loop_.RunUntilIdle();
592 void AddSimpleBlock(ClusterBuilder* cb, int track_num, int64 timecode) {
593 uint8 data[] = { 0x00 };
594 cb->AddSimpleBlock(track_num, timecode, 0, data, sizeof(data));
597 scoped_ptr<Cluster> GenerateCluster(int timecode, int block_count) {
598 return GenerateCluster(timecode, timecode, block_count);
601 void AddVideoBlockGroup(ClusterBuilder* cb, int track_num, int64 timecode,
602 int duration, int flags) {
603 const uint8* data =
604 (flags & kWebMFlagKeyframe) != 0 ? kVP8Keyframe : kVP8Interframe;
605 int size = (flags & kWebMFlagKeyframe) != 0 ? sizeof(kVP8Keyframe) :
606 sizeof(kVP8Interframe);
607 cb->AddBlockGroup(track_num, timecode, duration, flags, data, size);
610 scoped_ptr<Cluster> GenerateCluster(int first_audio_timecode,
611 int first_video_timecode,
612 int block_count) {
613 CHECK_GT(block_count, 0);
615 int size = 10;
616 scoped_ptr<uint8[]> data(new uint8[size]);
618 ClusterBuilder cb;
619 cb.SetClusterTimecode(std::min(first_audio_timecode, first_video_timecode));
621 if (block_count == 1) {
622 cb.AddBlockGroup(kAudioTrackNum, first_audio_timecode,
623 kAudioBlockDuration, kWebMFlagKeyframe,
624 data.get(), size);
625 return cb.Finish();
628 int audio_timecode = first_audio_timecode;
629 int video_timecode = first_video_timecode;
631 // Create simple blocks for everything except the last 2 blocks.
632 // The first video frame must be a keyframe.
633 uint8 video_flag = kWebMFlagKeyframe;
634 for (int i = 0; i < block_count - 2; i++) {
635 if (audio_timecode <= video_timecode) {
636 cb.AddSimpleBlock(kAudioTrackNum, audio_timecode, kWebMFlagKeyframe,
637 data.get(), size);
638 audio_timecode += kAudioBlockDuration;
639 continue;
642 cb.AddSimpleBlock(kVideoTrackNum, video_timecode, video_flag, data.get(),
643 size);
644 video_timecode += kVideoBlockDuration;
645 video_flag = 0;
648 // Make the last 2 blocks BlockGroups so that they don't get delayed by the
649 // block duration calculation logic.
650 if (audio_timecode <= video_timecode) {
651 cb.AddBlockGroup(kAudioTrackNum, audio_timecode, kAudioBlockDuration,
652 kWebMFlagKeyframe, data.get(), size);
653 AddVideoBlockGroup(&cb, kVideoTrackNum, video_timecode,
654 kVideoBlockDuration, video_flag);
655 } else {
656 AddVideoBlockGroup(&cb, kVideoTrackNum, video_timecode,
657 kVideoBlockDuration, video_flag);
658 cb.AddBlockGroup(kAudioTrackNum, audio_timecode, kAudioBlockDuration,
659 kWebMFlagKeyframe, data.get(), size);
662 return cb.Finish();
665 scoped_ptr<Cluster> GenerateSingleStreamCluster(int timecode,
666 int end_timecode,
667 int track_number,
668 int block_duration) {
669 CHECK_GT(end_timecode, timecode);
671 std::vector<uint8> data(kBlockSize);
673 ClusterBuilder cb;
674 cb.SetClusterTimecode(timecode);
676 // Create simple blocks for everything except the last block.
677 for (int i = 0; timecode < (end_timecode - block_duration); i++) {
678 cb.AddSimpleBlock(track_number, timecode, kWebMFlagKeyframe,
679 &data[0], data.size());
680 timecode += block_duration;
683 // Make the last block a BlockGroup so that it doesn't get delayed by the
684 // block duration calculation logic.
685 if (track_number == kVideoTrackNum) {
686 AddVideoBlockGroup(&cb, track_number, timecode, block_duration,
687 kWebMFlagKeyframe);
688 } else {
689 cb.AddBlockGroup(track_number, timecode, block_duration,
690 kWebMFlagKeyframe, &data[0], data.size());
692 return cb.Finish();
695 void Read(DemuxerStream::Type type, const DemuxerStream::ReadCB& read_cb) {
696 demuxer_->GetStream(type)->Read(read_cb);
697 message_loop_.RunUntilIdle();
700 void ReadAudio(const DemuxerStream::ReadCB& read_cb) {
701 Read(DemuxerStream::AUDIO, read_cb);
704 void ReadVideo(const DemuxerStream::ReadCB& read_cb) {
705 Read(DemuxerStream::VIDEO, read_cb);
708 void GenerateExpectedReads(int timecode, int block_count) {
709 GenerateExpectedReads(timecode, timecode, block_count);
712 void GenerateExpectedReads(int start_audio_timecode,
713 int start_video_timecode,
714 int block_count) {
715 CHECK_GT(block_count, 0);
717 if (block_count == 1) {
718 ExpectRead(DemuxerStream::AUDIO, start_audio_timecode);
719 return;
722 int audio_timecode = start_audio_timecode;
723 int video_timecode = start_video_timecode;
725 for (int i = 0; i < block_count; i++) {
726 if (audio_timecode <= video_timecode) {
727 ExpectRead(DemuxerStream::AUDIO, audio_timecode);
728 audio_timecode += kAudioBlockDuration;
729 continue;
732 ExpectRead(DemuxerStream::VIDEO, video_timecode);
733 video_timecode += kVideoBlockDuration;
737 void GenerateSingleStreamExpectedReads(int timecode,
738 int block_count,
739 DemuxerStream::Type type,
740 int block_duration) {
741 CHECK_GT(block_count, 0);
742 int stream_timecode = timecode;
744 for (int i = 0; i < block_count; i++) {
745 ExpectRead(type, stream_timecode);
746 stream_timecode += block_duration;
750 void GenerateAudioStreamExpectedReads(int timecode, int block_count) {
751 GenerateSingleStreamExpectedReads(
752 timecode, block_count, DemuxerStream::AUDIO, kAudioBlockDuration);
755 void GenerateVideoStreamExpectedReads(int timecode, int block_count) {
756 GenerateSingleStreamExpectedReads(
757 timecode, block_count, DemuxerStream::VIDEO, kVideoBlockDuration);
760 scoped_ptr<Cluster> GenerateEmptyCluster(int timecode) {
761 ClusterBuilder cb;
762 cb.SetClusterTimecode(timecode);
763 return cb.Finish();
766 void CheckExpectedRanges(const std::string& expected) {
767 CheckExpectedRanges(kSourceId, expected);
770 void CheckExpectedRanges(const std::string& id,
771 const std::string& expected) {
772 Ranges<base::TimeDelta> r = demuxer_->GetBufferedRanges(id);
774 std::stringstream ss;
775 ss << "{ ";
776 for (size_t i = 0; i < r.size(); ++i) {
777 ss << "[" << r.start(i).InMilliseconds() << ","
778 << r.end(i).InMilliseconds() << ") ";
780 ss << "}";
781 EXPECT_EQ(expected, ss.str());
784 MOCK_METHOD2(ReadDone, void(DemuxerStream::Status status,
785 const scoped_refptr<DecoderBuffer>&));
787 void StoreStatusAndBuffer(DemuxerStream::Status* status_out,
788 scoped_refptr<DecoderBuffer>* buffer_out,
789 DemuxerStream::Status status,
790 const scoped_refptr<DecoderBuffer>& buffer) {
791 *status_out = status;
792 *buffer_out = buffer;
795 void ReadUntilNotOkOrEndOfStream(DemuxerStream::Type type,
796 DemuxerStream::Status* status,
797 base::TimeDelta* last_timestamp) {
798 DemuxerStream* stream = demuxer_->GetStream(type);
799 scoped_refptr<DecoderBuffer> buffer;
801 *last_timestamp = kNoTimestamp();
802 do {
803 stream->Read(base::Bind(&ChunkDemuxerTest::StoreStatusAndBuffer,
804 base::Unretained(this), status, &buffer));
805 base::MessageLoop::current()->RunUntilIdle();
806 if (*status == DemuxerStream::kOk && !buffer->end_of_stream())
807 *last_timestamp = buffer->timestamp();
808 } while (*status == DemuxerStream::kOk && !buffer->end_of_stream());
811 void ExpectEndOfStream(DemuxerStream::Type type) {
812 EXPECT_CALL(*this, ReadDone(DemuxerStream::kOk, IsEndOfStream()));
813 demuxer_->GetStream(type)->Read(base::Bind(
814 &ChunkDemuxerTest::ReadDone, base::Unretained(this)));
815 message_loop_.RunUntilIdle();
818 void ExpectRead(DemuxerStream::Type type, int64 timestamp_in_ms) {
819 EXPECT_CALL(*this, ReadDone(DemuxerStream::kOk,
820 HasTimestamp(timestamp_in_ms)));
821 demuxer_->GetStream(type)->Read(base::Bind(
822 &ChunkDemuxerTest::ReadDone, base::Unretained(this)));
823 message_loop_.RunUntilIdle();
826 void ExpectConfigChanged(DemuxerStream::Type type) {
827 EXPECT_CALL(*this, ReadDone(DemuxerStream::kConfigChanged, _));
828 demuxer_->GetStream(type)->Read(base::Bind(
829 &ChunkDemuxerTest::ReadDone, base::Unretained(this)));
830 message_loop_.RunUntilIdle();
833 void CheckExpectedBuffers(DemuxerStream* stream,
834 const std::string& expected) {
835 std::vector<std::string> timestamps;
836 base::SplitString(expected, ' ', &timestamps);
837 std::stringstream ss;
838 for (size_t i = 0; i < timestamps.size(); ++i) {
839 DemuxerStream::Status status;
840 scoped_refptr<DecoderBuffer> buffer;
841 stream->Read(base::Bind(&ChunkDemuxerTest::StoreStatusAndBuffer,
842 base::Unretained(this), &status, &buffer));
843 base::MessageLoop::current()->RunUntilIdle();
844 if (status != DemuxerStream::kOk || buffer->end_of_stream())
845 break;
847 if (i > 0)
848 ss << " ";
849 ss << buffer->timestamp().InMilliseconds();
851 EXPECT_EQ(expected, ss.str());
854 MOCK_METHOD1(Checkpoint, void(int id));
856 struct BufferTimestamps {
857 int video_time_ms;
858 int audio_time_ms;
860 static const int kSkip = -1;
862 // Test parsing a WebM file.
863 // |filename| - The name of the file in media/test/data to parse.
864 // |timestamps| - The expected timestamps on the parsed buffers.
865 // a timestamp of kSkip indicates that a Read() call for that stream
866 // shouldn't be made on that iteration of the loop. If both streams have
867 // a kSkip then the loop will terminate.
868 bool ParseWebMFile(const std::string& filename,
869 const BufferTimestamps* timestamps,
870 const base::TimeDelta& duration) {
871 return ParseWebMFile(filename, timestamps, duration, HAS_AUDIO | HAS_VIDEO);
874 bool ParseWebMFile(const std::string& filename,
875 const BufferTimestamps* timestamps,
876 const base::TimeDelta& duration,
877 int stream_flags) {
878 EXPECT_CALL(*this, DemuxerOpened());
879 demuxer_->Initialize(
880 &host_, CreateInitDoneCB(duration, PIPELINE_OK), true);
882 if (AddId(kSourceId, stream_flags) != ChunkDemuxer::kOk)
883 return false;
885 // Read a WebM file into memory and send the data to the demuxer.
886 scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(filename);
887 AppendDataInPieces(buffer->data(), buffer->data_size(), 512);
889 // Verify that the timestamps on the first few packets match what we
890 // expect.
891 for (size_t i = 0;
892 (timestamps[i].audio_time_ms != kSkip ||
893 timestamps[i].video_time_ms != kSkip);
894 i++) {
895 bool audio_read_done = false;
896 bool video_read_done = false;
898 if (timestamps[i].audio_time_ms != kSkip) {
899 ReadAudio(base::Bind(&OnReadDone,
900 base::TimeDelta::FromMilliseconds(
901 timestamps[i].audio_time_ms),
902 &audio_read_done));
903 EXPECT_TRUE(audio_read_done);
906 if (timestamps[i].video_time_ms != kSkip) {
907 ReadVideo(base::Bind(&OnReadDone,
908 base::TimeDelta::FromMilliseconds(
909 timestamps[i].video_time_ms),
910 &video_read_done));
911 EXPECT_TRUE(video_read_done);
915 return true;
918 MOCK_METHOD0(DemuxerOpened, void());
919 // TODO(xhwang): This is a workaround of the issue that move-only parameters
920 // are not supported in mocked methods. Remove this when the issue is fixed
921 // (http://code.google.com/p/googletest/issues/detail?id=395) or when we use
922 // std::string instead of scoped_ptr<uint8[]> (http://crbug.com/130689).
923 MOCK_METHOD3(NeedKeyMock, void(const std::string& type,
924 const uint8* init_data, int init_data_size));
925 void DemuxerNeedKey(const std::string& type,
926 const std::vector<uint8>& init_data) {
927 const uint8* init_data_ptr = init_data.empty() ? NULL : &init_data[0];
928 NeedKeyMock(type, init_data_ptr, init_data.size());
931 void Seek(base::TimeDelta seek_time) {
932 demuxer_->StartWaitingForSeek(seek_time);
933 demuxer_->Seek(seek_time, NewExpectedStatusCB(PIPELINE_OK));
934 message_loop_.RunUntilIdle();
937 void MarkEndOfStream(PipelineStatus status) {
938 demuxer_->MarkEndOfStream(status);
939 message_loop_.RunUntilIdle();
942 base::MessageLoop message_loop_;
943 MockDemuxerHost host_;
945 scoped_ptr<ChunkDemuxer> demuxer_;
947 private:
948 DISALLOW_COPY_AND_ASSIGN(ChunkDemuxerTest);
951 TEST_F(ChunkDemuxerTest, Init) {
952 // Test no streams, audio-only, video-only, and audio & video scenarios.
953 // Audio and video streams can be encrypted or not encrypted.
954 for (int i = 0; i < 16; i++) {
955 bool has_audio = (i & 0x1) != 0;
956 bool has_video = (i & 0x2) != 0;
957 bool is_audio_encrypted = (i & 0x4) != 0;
958 bool is_video_encrypted = (i & 0x8) != 0;
960 // No test on invalid combination.
961 if ((!has_audio && is_audio_encrypted) ||
962 (!has_video && is_video_encrypted)) {
963 continue;
966 CreateNewDemuxer();
968 if (is_audio_encrypted || is_video_encrypted) {
969 int need_key_count = (is_audio_encrypted ? 1 : 0) +
970 (is_video_encrypted ? 1 : 0);
971 EXPECT_CALL(*this, NeedKeyMock(kWebMEncryptInitDataType, NotNull(),
972 DecryptConfig::kDecryptionKeySize))
973 .Times(Exactly(need_key_count));
976 int stream_flags = 0;
977 if (has_audio)
978 stream_flags |= HAS_AUDIO;
980 if (has_video)
981 stream_flags |= HAS_VIDEO;
983 ASSERT_TRUE(InitDemuxerWithEncryptionInfo(
984 stream_flags, is_audio_encrypted, is_video_encrypted));
986 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO);
987 if (has_audio) {
988 ASSERT_TRUE(audio_stream);
990 const AudioDecoderConfig& config = audio_stream->audio_decoder_config();
991 EXPECT_EQ(kCodecVorbis, config.codec());
992 EXPECT_EQ(32, config.bits_per_channel());
993 EXPECT_EQ(CHANNEL_LAYOUT_STEREO, config.channel_layout());
994 EXPECT_EQ(44100, config.samples_per_second());
995 EXPECT_TRUE(config.extra_data());
996 EXPECT_GT(config.extra_data_size(), 0u);
997 EXPECT_EQ(kSampleFormatPlanarF32, config.sample_format());
998 EXPECT_EQ(is_audio_encrypted,
999 audio_stream->audio_decoder_config().is_encrypted());
1000 } else {
1001 EXPECT_FALSE(audio_stream);
1004 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO);
1005 if (has_video) {
1006 EXPECT_TRUE(video_stream);
1007 EXPECT_EQ(is_video_encrypted,
1008 video_stream->video_decoder_config().is_encrypted());
1009 } else {
1010 EXPECT_FALSE(video_stream);
1013 ShutdownDemuxer();
1014 demuxer_.reset();
1018 // TODO(acolwell): Fold this test into Init tests since the tests are
1019 // almost identical.
1020 TEST_F(ChunkDemuxerTest, InitText) {
1021 // Test with 1 video stream and 1 text streams, and 0 or 1 audio streams.
1022 // No encryption cases handled here.
1023 bool has_video = true;
1024 bool is_audio_encrypted = false;
1025 bool is_video_encrypted = false;
1026 for (int i = 0; i < 2; i++) {
1027 bool has_audio = (i & 0x1) != 0;
1029 CreateNewDemuxer();
1031 DemuxerStream* text_stream = NULL;
1032 TextTrackConfig text_config;
1033 EXPECT_CALL(host_, AddTextStream(_, _))
1034 .WillOnce(DoAll(SaveArg<0>(&text_stream),
1035 SaveArg<1>(&text_config)));
1037 int stream_flags = HAS_TEXT;
1038 if (has_audio)
1039 stream_flags |= HAS_AUDIO;
1041 if (has_video)
1042 stream_flags |= HAS_VIDEO;
1044 ASSERT_TRUE(InitDemuxerWithEncryptionInfo(
1045 stream_flags, is_audio_encrypted, is_video_encrypted));
1046 ASSERT_TRUE(text_stream);
1047 EXPECT_EQ(DemuxerStream::TEXT, text_stream->type());
1048 EXPECT_EQ(kTextSubtitles, text_config.kind());
1050 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO);
1051 if (has_audio) {
1052 ASSERT_TRUE(audio_stream);
1054 const AudioDecoderConfig& config = audio_stream->audio_decoder_config();
1055 EXPECT_EQ(kCodecVorbis, config.codec());
1056 EXPECT_EQ(32, config.bits_per_channel());
1057 EXPECT_EQ(CHANNEL_LAYOUT_STEREO, config.channel_layout());
1058 EXPECT_EQ(44100, config.samples_per_second());
1059 EXPECT_TRUE(config.extra_data());
1060 EXPECT_GT(config.extra_data_size(), 0u);
1061 EXPECT_EQ(kSampleFormatPlanarF32, config.sample_format());
1062 EXPECT_EQ(is_audio_encrypted,
1063 audio_stream->audio_decoder_config().is_encrypted());
1064 } else {
1065 EXPECT_FALSE(audio_stream);
1068 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO);
1069 if (has_video) {
1070 EXPECT_TRUE(video_stream);
1071 EXPECT_EQ(is_video_encrypted,
1072 video_stream->video_decoder_config().is_encrypted());
1073 } else {
1074 EXPECT_FALSE(video_stream);
1077 ShutdownDemuxer();
1078 demuxer_.reset();
1082 // Make sure that the demuxer reports an error if Shutdown()
1083 // is called before all the initialization segments are appended.
1084 TEST_F(ChunkDemuxerTest, Shutdown_BeforeAllInitSegmentsAppended) {
1085 EXPECT_CALL(*this, DemuxerOpened());
1086 demuxer_->Initialize(
1087 &host_, CreateInitDoneCB(
1088 kDefaultDuration(), DEMUXER_ERROR_COULD_NOT_OPEN), true);
1090 EXPECT_EQ(AddId("audio", HAS_AUDIO), ChunkDemuxer::kOk);
1091 EXPECT_EQ(AddId("video", HAS_VIDEO), ChunkDemuxer::kOk);
1093 AppendInitSegmentWithSourceId("audio", HAS_AUDIO);
1095 ShutdownDemuxer();
1098 TEST_F(ChunkDemuxerTest, Shutdown_BeforeAllInitSegmentsAppendedText) {
1099 EXPECT_CALL(*this, DemuxerOpened());
1100 demuxer_->Initialize(
1101 &host_, CreateInitDoneCB(
1102 kDefaultDuration(), DEMUXER_ERROR_COULD_NOT_OPEN), true);
1104 EXPECT_EQ(AddId("audio", HAS_AUDIO), ChunkDemuxer::kOk);
1105 EXPECT_EQ(AddId("video_and_text", HAS_VIDEO), ChunkDemuxer::kOk);
1107 EXPECT_CALL(host_, AddTextStream(_, _))
1108 .Times(Exactly(1));
1110 AppendInitSegmentWithSourceId("video_and_text", HAS_VIDEO | HAS_TEXT);
1112 ShutdownDemuxer();
1115 // Verifies that all streams waiting for data receive an end of stream
1116 // buffer when Shutdown() is called.
1117 TEST_F(ChunkDemuxerTest, Shutdown_EndOfStreamWhileWaitingForData) {
1118 DemuxerStream* text_stream = NULL;
1119 EXPECT_CALL(host_, AddTextStream(_, _))
1120 .WillOnce(SaveArg<0>(&text_stream));
1121 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO | HAS_TEXT));
1123 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO);
1124 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO);
1126 bool audio_read_done = false;
1127 bool video_read_done = false;
1128 bool text_read_done = false;
1129 audio_stream->Read(base::Bind(&OnReadDone_EOSExpected, &audio_read_done));
1130 video_stream->Read(base::Bind(&OnReadDone_EOSExpected, &video_read_done));
1131 text_stream->Read(base::Bind(&OnReadDone_EOSExpected, &text_read_done));
1132 message_loop_.RunUntilIdle();
1134 EXPECT_FALSE(audio_read_done);
1135 EXPECT_FALSE(video_read_done);
1136 EXPECT_FALSE(text_read_done);
1138 ShutdownDemuxer();
1140 EXPECT_TRUE(audio_read_done);
1141 EXPECT_TRUE(video_read_done);
1142 EXPECT_TRUE(text_read_done);
1145 // Test that Seek() completes successfully when the first cluster
1146 // arrives.
1147 TEST_F(ChunkDemuxerTest, AppendDataAfterSeek) {
1148 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1149 AppendCluster(kDefaultFirstCluster());
1151 InSequence s;
1153 EXPECT_CALL(*this, Checkpoint(1));
1155 Seek(base::TimeDelta::FromMilliseconds(46));
1157 EXPECT_CALL(*this, Checkpoint(2));
1159 Checkpoint(1);
1161 AppendCluster(kDefaultSecondCluster());
1163 message_loop_.RunUntilIdle();
1165 Checkpoint(2);
1168 // Test that parsing errors are handled for clusters appended after init.
1169 TEST_F(ChunkDemuxerTest, ErrorWhileParsingClusterAfterInit) {
1170 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1171 AppendCluster(kDefaultFirstCluster());
1173 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE));
1174 AppendGarbage();
1177 // Test the case where a Seek() is requested while the parser
1178 // is in the middle of cluster. This is to verify that the parser
1179 // does not reset itself on a seek.
1180 TEST_F(ChunkDemuxerTest, SeekWhileParsingCluster) {
1181 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1183 InSequence s;
1185 scoped_ptr<Cluster> cluster_a(GenerateCluster(0, 6));
1187 // Split the cluster into two appends at an arbitrary point near the end.
1188 int first_append_size = cluster_a->size() - 11;
1189 int second_append_size = cluster_a->size() - first_append_size;
1191 // Append the first part of the cluster.
1192 AppendData(cluster_a->data(), first_append_size);
1194 ExpectRead(DemuxerStream::AUDIO, 0);
1195 ExpectRead(DemuxerStream::VIDEO, 0);
1196 ExpectRead(DemuxerStream::AUDIO, kAudioBlockDuration);
1197 // Note: We skip trying to read a video buffer here because computing
1198 // the duration for this block relies on successfully parsing the last block
1199 // in the cluster the cluster.
1200 ExpectRead(DemuxerStream::AUDIO, 2 * kAudioBlockDuration);
1202 Seek(base::TimeDelta::FromSeconds(5));
1204 // Append the rest of the cluster.
1205 AppendData(cluster_a->data() + first_append_size, second_append_size);
1207 // Append the new cluster and verify that only the blocks
1208 // in the new cluster are returned.
1209 AppendCluster(GenerateCluster(5000, 6));
1210 GenerateExpectedReads(5000, 6);
1213 // Test the case where AppendData() is called before Init().
1214 TEST_F(ChunkDemuxerTest, AppendDataBeforeInit) {
1215 scoped_ptr<uint8[]> info_tracks;
1216 int info_tracks_size = 0;
1217 CreateInitSegment(HAS_AUDIO | HAS_VIDEO,
1218 false, false, &info_tracks, &info_tracks_size);
1220 demuxer_->AppendData(kSourceId, info_tracks.get(), info_tracks_size);
1223 // Make sure Read() callbacks are dispatched with the proper data.
1224 TEST_F(ChunkDemuxerTest, Read) {
1225 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1227 AppendCluster(kDefaultFirstCluster());
1229 bool audio_read_done = false;
1230 bool video_read_done = false;
1231 ReadAudio(base::Bind(&OnReadDone,
1232 base::TimeDelta::FromMilliseconds(0),
1233 &audio_read_done));
1234 ReadVideo(base::Bind(&OnReadDone,
1235 base::TimeDelta::FromMilliseconds(0),
1236 &video_read_done));
1238 EXPECT_TRUE(audio_read_done);
1239 EXPECT_TRUE(video_read_done);
1242 TEST_F(ChunkDemuxerTest, OutOfOrderClusters) {
1243 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1244 AppendCluster(kDefaultFirstCluster());
1245 AppendCluster(GenerateCluster(10, 4));
1247 // Make sure that AppendCluster() does not fail with a cluster that has
1248 // overlaps with the previously appended cluster.
1249 AppendCluster(GenerateCluster(5, 4));
1251 // Verify that AppendData() can still accept more data.
1252 scoped_ptr<Cluster> cluster_c(GenerateCluster(45, 2));
1253 demuxer_->AppendData(kSourceId, cluster_c->data(), cluster_c->size());
1256 TEST_F(ChunkDemuxerTest, NonMonotonicButAboveClusterTimecode) {
1257 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1258 AppendCluster(kDefaultFirstCluster());
1260 ClusterBuilder cb;
1262 // Test the case where block timecodes are not monotonically
1263 // increasing but stay above the cluster timecode.
1264 cb.SetClusterTimecode(5);
1265 AddSimpleBlock(&cb, kAudioTrackNum, 5);
1266 AddSimpleBlock(&cb, kVideoTrackNum, 10);
1267 AddSimpleBlock(&cb, kAudioTrackNum, 7);
1268 AddSimpleBlock(&cb, kVideoTrackNum, 15);
1270 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE));
1271 AppendCluster(cb.Finish());
1273 // Verify that AppendData() ignores data after the error.
1274 scoped_ptr<Cluster> cluster_b(GenerateCluster(20, 2));
1275 demuxer_->AppendData(kSourceId, cluster_b->data(), cluster_b->size());
1278 TEST_F(ChunkDemuxerTest, BackwardsAndBeforeClusterTimecode) {
1279 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1280 AppendCluster(kDefaultFirstCluster());
1282 ClusterBuilder cb;
1284 // Test timecodes going backwards and including values less than the cluster
1285 // timecode.
1286 cb.SetClusterTimecode(5);
1287 AddSimpleBlock(&cb, kAudioTrackNum, 5);
1288 AddSimpleBlock(&cb, kVideoTrackNum, 5);
1289 AddSimpleBlock(&cb, kAudioTrackNum, 3);
1290 AddSimpleBlock(&cb, kVideoTrackNum, 3);
1292 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE));
1293 AppendCluster(cb.Finish());
1295 // Verify that AppendData() ignores data after the error.
1296 scoped_ptr<Cluster> cluster_b(GenerateCluster(6, 2));
1297 demuxer_->AppendData(kSourceId, cluster_b->data(), cluster_b->size());
1301 TEST_F(ChunkDemuxerTest, PerStreamMonotonicallyIncreasingTimestamps) {
1302 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1303 AppendCluster(kDefaultFirstCluster());
1305 ClusterBuilder cb;
1307 // Test monotonic increasing timestamps on a per stream
1308 // basis.
1309 cb.SetClusterTimecode(5);
1310 AddSimpleBlock(&cb, kAudioTrackNum, 5);
1311 AddSimpleBlock(&cb, kVideoTrackNum, 5);
1312 AddSimpleBlock(&cb, kAudioTrackNum, 4);
1313 AddSimpleBlock(&cb, kVideoTrackNum, 7);
1315 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE));
1316 AppendCluster(cb.Finish());
1319 // Test the case where a cluster is passed to AppendCluster() before
1320 // INFO & TRACKS data.
1321 TEST_F(ChunkDemuxerTest, ClusterBeforeInitSegment) {
1322 EXPECT_CALL(*this, DemuxerOpened());
1323 demuxer_->Initialize(
1324 &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN), true);
1326 ASSERT_EQ(AddId(), ChunkDemuxer::kOk);
1328 AppendCluster(GenerateCluster(0, 1));
1331 // Test cases where we get an MarkEndOfStream() call during initialization.
1332 TEST_F(ChunkDemuxerTest, EOSDuringInit) {
1333 EXPECT_CALL(*this, DemuxerOpened());
1334 demuxer_->Initialize(
1335 &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN), true);
1336 MarkEndOfStream(PIPELINE_OK);
1339 TEST_F(ChunkDemuxerTest, EndOfStreamWithNoAppend) {
1340 EXPECT_CALL(*this, DemuxerOpened());
1341 demuxer_->Initialize(
1342 &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN), true);
1344 ASSERT_EQ(AddId(), ChunkDemuxer::kOk);
1346 CheckExpectedRanges("{ }");
1347 MarkEndOfStream(PIPELINE_OK);
1348 ShutdownDemuxer();
1349 CheckExpectedRanges("{ }");
1350 demuxer_->RemoveId(kSourceId);
1351 demuxer_.reset();
1354 TEST_F(ChunkDemuxerTest, EndOfStreamWithNoMediaAppend) {
1355 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1357 CheckExpectedRanges("{ }");
1358 MarkEndOfStream(PIPELINE_OK);
1359 CheckExpectedRanges("{ }");
1362 TEST_F(ChunkDemuxerTest, DecodeErrorEndOfStream) {
1363 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1365 AppendCluster(kDefaultFirstCluster());
1366 CheckExpectedRanges(kDefaultFirstClusterRange);
1368 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE));
1369 MarkEndOfStream(PIPELINE_ERROR_DECODE);
1370 CheckExpectedRanges(kDefaultFirstClusterRange);
1373 TEST_F(ChunkDemuxerTest, NetworkErrorEndOfStream) {
1374 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1376 AppendCluster(kDefaultFirstCluster());
1377 CheckExpectedRanges(kDefaultFirstClusterRange);
1379 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_NETWORK));
1380 MarkEndOfStream(PIPELINE_ERROR_NETWORK);
1383 // Helper class to reduce duplicate code when testing end of stream
1384 // Read() behavior.
1385 class EndOfStreamHelper {
1386 public:
1387 explicit EndOfStreamHelper(Demuxer* demuxer)
1388 : demuxer_(demuxer),
1389 audio_read_done_(false),
1390 video_read_done_(false) {
1393 // Request a read on the audio and video streams.
1394 void RequestReads() {
1395 EXPECT_FALSE(audio_read_done_);
1396 EXPECT_FALSE(video_read_done_);
1398 DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
1399 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
1401 audio->Read(base::Bind(&OnEndOfStreamReadDone, &audio_read_done_));
1402 video->Read(base::Bind(&OnEndOfStreamReadDone, &video_read_done_));
1403 base::MessageLoop::current()->RunUntilIdle();
1406 // Check to see if |audio_read_done_| and |video_read_done_| variables
1407 // match |expected|.
1408 void CheckIfReadDonesWereCalled(bool expected) {
1409 base::MessageLoop::current()->RunUntilIdle();
1410 EXPECT_EQ(expected, audio_read_done_);
1411 EXPECT_EQ(expected, video_read_done_);
1414 private:
1415 static void OnEndOfStreamReadDone(
1416 bool* called,
1417 DemuxerStream::Status status,
1418 const scoped_refptr<DecoderBuffer>& buffer) {
1419 EXPECT_EQ(status, DemuxerStream::kOk);
1420 EXPECT_TRUE(buffer->end_of_stream());
1421 *called = true;
1424 Demuxer* demuxer_;
1425 bool audio_read_done_;
1426 bool video_read_done_;
1428 DISALLOW_COPY_AND_ASSIGN(EndOfStreamHelper);
1431 // Make sure that all pending reads that we don't have media data for get an
1432 // "end of stream" buffer when MarkEndOfStream() is called.
1433 TEST_F(ChunkDemuxerTest, EndOfStreamWithPendingReads) {
1434 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1436 AppendCluster(GenerateCluster(0, 2));
1438 bool audio_read_done_1 = false;
1439 bool video_read_done_1 = false;
1440 EndOfStreamHelper end_of_stream_helper_1(demuxer_.get());
1441 EndOfStreamHelper end_of_stream_helper_2(demuxer_.get());
1443 ReadAudio(base::Bind(&OnReadDone,
1444 base::TimeDelta::FromMilliseconds(0),
1445 &audio_read_done_1));
1446 ReadVideo(base::Bind(&OnReadDone,
1447 base::TimeDelta::FromMilliseconds(0),
1448 &video_read_done_1));
1449 message_loop_.RunUntilIdle();
1451 EXPECT_TRUE(audio_read_done_1);
1452 EXPECT_TRUE(video_read_done_1);
1454 end_of_stream_helper_1.RequestReads();
1456 EXPECT_CALL(host_, SetDuration(
1457 base::TimeDelta::FromMilliseconds(kVideoBlockDuration)));
1458 MarkEndOfStream(PIPELINE_OK);
1460 end_of_stream_helper_1.CheckIfReadDonesWereCalled(true);
1462 end_of_stream_helper_2.RequestReads();
1463 end_of_stream_helper_2.CheckIfReadDonesWereCalled(true);
1466 // Make sure that all Read() calls after we get an MarkEndOfStream()
1467 // call return an "end of stream" buffer.
1468 TEST_F(ChunkDemuxerTest, ReadsAfterEndOfStream) {
1469 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1471 AppendCluster(GenerateCluster(0, 2));
1473 bool audio_read_done_1 = false;
1474 bool video_read_done_1 = false;
1475 EndOfStreamHelper end_of_stream_helper_1(demuxer_.get());
1476 EndOfStreamHelper end_of_stream_helper_2(demuxer_.get());
1477 EndOfStreamHelper end_of_stream_helper_3(demuxer_.get());
1479 ReadAudio(base::Bind(&OnReadDone,
1480 base::TimeDelta::FromMilliseconds(0),
1481 &audio_read_done_1));
1482 ReadVideo(base::Bind(&OnReadDone,
1483 base::TimeDelta::FromMilliseconds(0),
1484 &video_read_done_1));
1486 end_of_stream_helper_1.RequestReads();
1488 EXPECT_TRUE(audio_read_done_1);
1489 EXPECT_TRUE(video_read_done_1);
1490 end_of_stream_helper_1.CheckIfReadDonesWereCalled(false);
1492 EXPECT_CALL(host_, SetDuration(
1493 base::TimeDelta::FromMilliseconds(kVideoBlockDuration)));
1494 MarkEndOfStream(PIPELINE_OK);
1496 end_of_stream_helper_1.CheckIfReadDonesWereCalled(true);
1498 // Request a few more reads and make sure we immediately get
1499 // end of stream buffers.
1500 end_of_stream_helper_2.RequestReads();
1501 end_of_stream_helper_2.CheckIfReadDonesWereCalled(true);
1503 end_of_stream_helper_3.RequestReads();
1504 end_of_stream_helper_3.CheckIfReadDonesWereCalled(true);
1507 TEST_F(ChunkDemuxerTest, EndOfStreamDuringCanceledSeek) {
1508 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1510 AppendCluster(0, 10);
1511 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(138)));
1512 MarkEndOfStream(PIPELINE_OK);
1514 // Start the first seek.
1515 Seek(base::TimeDelta::FromMilliseconds(20));
1517 // Simulate another seek being requested before the first
1518 // seek has finished prerolling.
1519 base::TimeDelta seek_time2 = base::TimeDelta::FromMilliseconds(30);
1520 demuxer_->CancelPendingSeek(seek_time2);
1522 // Finish second seek.
1523 Seek(seek_time2);
1525 DemuxerStream::Status status;
1526 base::TimeDelta last_timestamp;
1528 // Make sure audio can reach end of stream.
1529 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp);
1530 ASSERT_EQ(status, DemuxerStream::kOk);
1532 // Make sure video can reach end of stream.
1533 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp);
1534 ASSERT_EQ(status, DemuxerStream::kOk);
1537 // Verify buffered range change behavior for audio/video/text tracks.
1538 TEST_F(ChunkDemuxerTest, EndOfStreamRangeChanges) {
1539 DemuxerStream* text_stream = NULL;
1541 EXPECT_CALL(host_, AddTextStream(_, _))
1542 .WillOnce(SaveArg<0>(&text_stream));
1543 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO | HAS_TEXT));
1545 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "0K 30");
1546 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, "0K 23K");
1548 // Check expected ranges and verify that an empty text track does not
1549 // affect the expected ranges.
1550 CheckExpectedRanges(kSourceId, "{ [0,46) }");
1552 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(60)));
1553 MarkEndOfStream(PIPELINE_OK);
1555 // Check expected ranges and verify that an empty text track does not
1556 // affect the expected ranges.
1557 CheckExpectedRanges(kSourceId, "{ [0,60) }");
1559 // Unmark end of stream state and verify that the ranges return to
1560 // their pre-"end of stream" values.
1561 demuxer_->UnmarkEndOfStream();
1562 CheckExpectedRanges(kSourceId, "{ [0,46) }");
1564 // Add text track data and verify that the buffered ranges don't change
1565 // since the intersection of all the tracks doesn't change.
1566 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(200)));
1567 AppendSingleStreamCluster(kSourceId, kTextTrackNum, "0K 100K");
1568 CheckExpectedRanges(kSourceId, "{ [0,46) }");
1570 // Mark end of stream and verify that text track data is reflected in
1571 // the new range.
1572 MarkEndOfStream(PIPELINE_OK);
1573 CheckExpectedRanges(kSourceId, "{ [0,200) }");
1576 // Make sure AppendData() will accept elements that span multiple calls.
1577 TEST_F(ChunkDemuxerTest, AppendingInPieces) {
1578 EXPECT_CALL(*this, DemuxerOpened());
1579 demuxer_->Initialize(
1580 &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true);
1582 ASSERT_EQ(AddId(), ChunkDemuxer::kOk);
1584 scoped_ptr<uint8[]> info_tracks;
1585 int info_tracks_size = 0;
1586 CreateInitSegment(HAS_AUDIO | HAS_VIDEO,
1587 false, false, &info_tracks, &info_tracks_size);
1589 scoped_ptr<Cluster> cluster_a(kDefaultFirstCluster());
1590 scoped_ptr<Cluster> cluster_b(kDefaultSecondCluster());
1592 size_t buffer_size = info_tracks_size + cluster_a->size() + cluster_b->size();
1593 scoped_ptr<uint8[]> buffer(new uint8[buffer_size]);
1594 uint8* dst = buffer.get();
1595 memcpy(dst, info_tracks.get(), info_tracks_size);
1596 dst += info_tracks_size;
1598 memcpy(dst, cluster_a->data(), cluster_a->size());
1599 dst += cluster_a->size();
1601 memcpy(dst, cluster_b->data(), cluster_b->size());
1602 dst += cluster_b->size();
1604 AppendDataInPieces(buffer.get(), buffer_size);
1606 GenerateExpectedReads(0, 9);
1609 TEST_F(ChunkDemuxerTest, WebMFile_AudioAndVideo) {
1610 struct BufferTimestamps buffer_timestamps[] = {
1611 {0, 0},
1612 {33, 3},
1613 {67, 6},
1614 {100, 9},
1615 {133, 12},
1616 {kSkip, kSkip},
1619 ASSERT_TRUE(ParseWebMFile("bear-320x240.webm", buffer_timestamps,
1620 base::TimeDelta::FromMilliseconds(2744)));
1623 TEST_F(ChunkDemuxerTest, WebMFile_LiveAudioAndVideo) {
1624 struct BufferTimestamps buffer_timestamps[] = {
1625 {0, 0},
1626 {33, 3},
1627 {67, 6},
1628 {100, 9},
1629 {133, 12},
1630 {kSkip, kSkip},
1633 ASSERT_TRUE(ParseWebMFile("bear-320x240-live.webm", buffer_timestamps,
1634 kInfiniteDuration()));
1637 TEST_F(ChunkDemuxerTest, WebMFile_AudioOnly) {
1638 struct BufferTimestamps buffer_timestamps[] = {
1639 {kSkip, 0},
1640 {kSkip, 3},
1641 {kSkip, 6},
1642 {kSkip, 9},
1643 {kSkip, 12},
1644 {kSkip, kSkip},
1647 ASSERT_TRUE(ParseWebMFile("bear-320x240-audio-only.webm", buffer_timestamps,
1648 base::TimeDelta::FromMilliseconds(2744),
1649 HAS_AUDIO));
1652 TEST_F(ChunkDemuxerTest, WebMFile_VideoOnly) {
1653 struct BufferTimestamps buffer_timestamps[] = {
1654 {0, kSkip},
1655 {33, kSkip},
1656 {67, kSkip},
1657 {100, kSkip},
1658 {133, kSkip},
1659 {kSkip, kSkip},
1662 ASSERT_TRUE(ParseWebMFile("bear-320x240-video-only.webm", buffer_timestamps,
1663 base::TimeDelta::FromMilliseconds(2703),
1664 HAS_VIDEO));
1667 TEST_F(ChunkDemuxerTest, WebMFile_AltRefFrames) {
1668 struct BufferTimestamps buffer_timestamps[] = {
1669 {0, 0},
1670 {33, 3},
1671 {33, 6},
1672 {67, 9},
1673 {100, 12},
1674 {kSkip, kSkip},
1677 ASSERT_TRUE(ParseWebMFile("bear-320x240-altref.webm", buffer_timestamps,
1678 base::TimeDelta::FromMilliseconds(2767)));
1681 // Verify that we output buffers before the entire cluster has been parsed.
1682 TEST_F(ChunkDemuxerTest, IncrementalClusterParsing) {
1683 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1684 AppendEmptyCluster(0);
1686 scoped_ptr<Cluster> cluster(GenerateCluster(0, 6));
1688 bool audio_read_done = false;
1689 bool video_read_done = false;
1690 ReadAudio(base::Bind(&OnReadDone,
1691 base::TimeDelta::FromMilliseconds(0),
1692 &audio_read_done));
1693 ReadVideo(base::Bind(&OnReadDone,
1694 base::TimeDelta::FromMilliseconds(0),
1695 &video_read_done));
1697 // Make sure the reads haven't completed yet.
1698 EXPECT_FALSE(audio_read_done);
1699 EXPECT_FALSE(video_read_done);
1701 // Append data one byte at a time until the audio read completes.
1702 int i = 0;
1703 for (; i < cluster->size() && !audio_read_done; ++i) {
1704 AppendData(cluster->data() + i, 1);
1705 message_loop_.RunUntilIdle();
1708 EXPECT_TRUE(audio_read_done);
1709 EXPECT_FALSE(video_read_done);
1710 EXPECT_GT(i, 0);
1711 EXPECT_LT(i, cluster->size());
1713 // Append data one byte at a time until the video read completes.
1714 for (; i < cluster->size() && !video_read_done; ++i) {
1715 AppendData(cluster->data() + i, 1);
1716 message_loop_.RunUntilIdle();
1719 EXPECT_TRUE(video_read_done);
1720 EXPECT_LT(i, cluster->size());
1722 audio_read_done = false;
1723 video_read_done = false;
1724 ReadAudio(base::Bind(&OnReadDone,
1725 base::TimeDelta::FromMilliseconds(23),
1726 &audio_read_done));
1727 ReadVideo(base::Bind(&OnReadDone,
1728 base::TimeDelta::FromMilliseconds(33),
1729 &video_read_done));
1731 // Make sure the reads haven't completed yet.
1732 EXPECT_FALSE(audio_read_done);
1733 EXPECT_FALSE(video_read_done);
1735 // Append the remaining data.
1736 ASSERT_LT(i, cluster->size());
1737 AppendData(cluster->data() + i, cluster->size() - i);
1739 message_loop_.RunUntilIdle();
1741 EXPECT_TRUE(audio_read_done);
1742 EXPECT_TRUE(video_read_done);
1745 TEST_F(ChunkDemuxerTest, ParseErrorDuringInit) {
1746 EXPECT_CALL(*this, DemuxerOpened());
1747 demuxer_->Initialize(
1748 &host_, CreateInitDoneCB(
1749 kNoTimestamp(), DEMUXER_ERROR_COULD_NOT_OPEN), true);
1751 ASSERT_EQ(AddId(), ChunkDemuxer::kOk);
1753 uint8 tmp = 0;
1754 demuxer_->AppendData(kSourceId, &tmp, 1);
1757 TEST_F(ChunkDemuxerTest, AVHeadersWithAudioOnlyType) {
1758 EXPECT_CALL(*this, DemuxerOpened());
1759 demuxer_->Initialize(
1760 &host_, CreateInitDoneCB(kNoTimestamp(),
1761 DEMUXER_ERROR_COULD_NOT_OPEN), true);
1763 std::vector<std::string> codecs(1);
1764 codecs[0] = "vorbis";
1765 ASSERT_EQ(demuxer_->AddId(kSourceId, "audio/webm", codecs),
1766 ChunkDemuxer::kOk);
1768 AppendInitSegment(HAS_AUDIO | HAS_VIDEO);
1771 TEST_F(ChunkDemuxerTest, AVHeadersWithVideoOnlyType) {
1772 EXPECT_CALL(*this, DemuxerOpened());
1773 demuxer_->Initialize(
1774 &host_, CreateInitDoneCB(kNoTimestamp(),
1775 DEMUXER_ERROR_COULD_NOT_OPEN), true);
1777 std::vector<std::string> codecs(1);
1778 codecs[0] = "vp8";
1779 ASSERT_EQ(demuxer_->AddId(kSourceId, "video/webm", codecs),
1780 ChunkDemuxer::kOk);
1782 AppendInitSegment(HAS_AUDIO | HAS_VIDEO);
1785 TEST_F(ChunkDemuxerTest, MultipleHeaders) {
1786 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1788 AppendCluster(kDefaultFirstCluster());
1790 // Append another identical initialization segment.
1791 AppendInitSegment(HAS_AUDIO | HAS_VIDEO);
1793 AppendCluster(kDefaultSecondCluster());
1795 GenerateExpectedReads(0, 9);
1798 TEST_F(ChunkDemuxerTest, AddSeparateSourcesForAudioAndVideo) {
1799 std::string audio_id = "audio1";
1800 std::string video_id = "video1";
1801 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
1803 // Append audio and video data into separate source ids.
1804 AppendCluster(audio_id,
1805 GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration));
1806 GenerateAudioStreamExpectedReads(0, 4);
1807 AppendCluster(video_id,
1808 GenerateSingleStreamCluster(0, 132, kVideoTrackNum, kVideoBlockDuration));
1809 GenerateVideoStreamExpectedReads(0, 4);
1812 TEST_F(ChunkDemuxerTest, AddSeparateSourcesForAudioAndVideoText) {
1813 // TODO(matthewjheaney): Here and elsewhere, we need more tests
1814 // for inband text tracks (http://crbug/321455).
1816 std::string audio_id = "audio1";
1817 std::string video_id = "video1";
1819 EXPECT_CALL(host_, AddTextStream(_, _))
1820 .Times(Exactly(2));
1821 ASSERT_TRUE(InitDemuxerAudioAndVideoSourcesText(audio_id, video_id, true));
1823 // Append audio and video data into separate source ids.
1824 AppendCluster(audio_id,
1825 GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration));
1826 GenerateAudioStreamExpectedReads(0, 4);
1827 AppendCluster(video_id,
1828 GenerateSingleStreamCluster(0, 132, kVideoTrackNum, kVideoBlockDuration));
1829 GenerateVideoStreamExpectedReads(0, 4);
1832 TEST_F(ChunkDemuxerTest, AddIdFailures) {
1833 EXPECT_CALL(*this, DemuxerOpened());
1834 demuxer_->Initialize(
1835 &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true);
1837 std::string audio_id = "audio1";
1838 std::string video_id = "video1";
1840 ASSERT_EQ(AddId(audio_id, HAS_AUDIO), ChunkDemuxer::kOk);
1842 // Adding an id with audio/video should fail because we already added audio.
1843 ASSERT_EQ(AddId(), ChunkDemuxer::kReachedIdLimit);
1845 AppendInitSegmentWithSourceId(audio_id, HAS_AUDIO);
1847 // Adding an id after append should fail.
1848 ASSERT_EQ(AddId(video_id, HAS_VIDEO), ChunkDemuxer::kReachedIdLimit);
1851 // Test that Read() calls after a RemoveId() return "end of stream" buffers.
1852 TEST_F(ChunkDemuxerTest, RemoveId) {
1853 std::string audio_id = "audio1";
1854 std::string video_id = "video1";
1855 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
1857 // Append audio and video data into separate source ids.
1858 AppendCluster(audio_id,
1859 GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration));
1860 AppendCluster(video_id,
1861 GenerateSingleStreamCluster(0, 132, kVideoTrackNum, kVideoBlockDuration));
1863 // Read() from audio should return normal buffers.
1864 GenerateAudioStreamExpectedReads(0, 4);
1866 // Remove the audio id.
1867 demuxer_->RemoveId(audio_id);
1869 // Read() from audio should return "end of stream" buffers.
1870 bool audio_read_done = false;
1871 ReadAudio(base::Bind(&OnReadDone_EOSExpected, &audio_read_done));
1872 message_loop_.RunUntilIdle();
1873 EXPECT_TRUE(audio_read_done);
1875 // Read() from video should still return normal buffers.
1876 GenerateVideoStreamExpectedReads(0, 4);
1879 // Test that removing an ID immediately after adding it does not interfere with
1880 // quota for new IDs in the future.
1881 TEST_F(ChunkDemuxerTest, RemoveAndAddId) {
1882 std::string audio_id_1 = "audio1";
1883 ASSERT_TRUE(AddId(audio_id_1, HAS_AUDIO) == ChunkDemuxer::kOk);
1884 demuxer_->RemoveId(audio_id_1);
1886 std::string audio_id_2 = "audio2";
1887 ASSERT_TRUE(AddId(audio_id_2, HAS_AUDIO) == ChunkDemuxer::kOk);
1890 TEST_F(ChunkDemuxerTest, SeekCanceled) {
1891 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1893 // Append cluster at the beginning of the stream.
1894 AppendCluster(GenerateCluster(0, 4));
1896 // Seek to an unbuffered region.
1897 Seek(base::TimeDelta::FromSeconds(50));
1899 // Attempt to read in unbuffered area; should not fulfill the read.
1900 bool audio_read_done = false;
1901 bool video_read_done = false;
1902 ReadAudio(base::Bind(&OnReadDone_AbortExpected, &audio_read_done));
1903 ReadVideo(base::Bind(&OnReadDone_AbortExpected, &video_read_done));
1904 EXPECT_FALSE(audio_read_done);
1905 EXPECT_FALSE(video_read_done);
1907 // Now cancel the pending seek, which should flush the reads with empty
1908 // buffers.
1909 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(0);
1910 demuxer_->CancelPendingSeek(seek_time);
1911 message_loop_.RunUntilIdle();
1912 EXPECT_TRUE(audio_read_done);
1913 EXPECT_TRUE(video_read_done);
1915 // A seek back to the buffered region should succeed.
1916 Seek(seek_time);
1917 GenerateExpectedReads(0, 4);
1920 TEST_F(ChunkDemuxerTest, SeekCanceledWhileWaitingForSeek) {
1921 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1923 // Append cluster at the beginning of the stream.
1924 AppendCluster(GenerateCluster(0, 4));
1926 // Start waiting for a seek.
1927 base::TimeDelta seek_time1 = base::TimeDelta::FromSeconds(50);
1928 base::TimeDelta seek_time2 = base::TimeDelta::FromSeconds(0);
1929 demuxer_->StartWaitingForSeek(seek_time1);
1931 // Now cancel the upcoming seek to an unbuffered region.
1932 demuxer_->CancelPendingSeek(seek_time2);
1933 demuxer_->Seek(seek_time1, NewExpectedStatusCB(PIPELINE_OK));
1935 // Read requests should be fulfilled with empty buffers.
1936 bool audio_read_done = false;
1937 bool video_read_done = false;
1938 ReadAudio(base::Bind(&OnReadDone_AbortExpected, &audio_read_done));
1939 ReadVideo(base::Bind(&OnReadDone_AbortExpected, &video_read_done));
1940 EXPECT_TRUE(audio_read_done);
1941 EXPECT_TRUE(video_read_done);
1943 // A seek back to the buffered region should succeed.
1944 Seek(seek_time2);
1945 GenerateExpectedReads(0, 4);
1948 // Test that Seek() successfully seeks to all source IDs.
1949 TEST_F(ChunkDemuxerTest, SeekAudioAndVideoSources) {
1950 std::string audio_id = "audio1";
1951 std::string video_id = "video1";
1952 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
1954 AppendCluster(
1955 audio_id,
1956 GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration));
1957 AppendCluster(
1958 video_id,
1959 GenerateSingleStreamCluster(0, 132, kVideoTrackNum, kVideoBlockDuration));
1961 // Read() should return buffers at 0.
1962 bool audio_read_done = false;
1963 bool video_read_done = false;
1964 ReadAudio(base::Bind(&OnReadDone,
1965 base::TimeDelta::FromMilliseconds(0),
1966 &audio_read_done));
1967 ReadVideo(base::Bind(&OnReadDone,
1968 base::TimeDelta::FromMilliseconds(0),
1969 &video_read_done));
1970 EXPECT_TRUE(audio_read_done);
1971 EXPECT_TRUE(video_read_done);
1973 // Seek to 3 (an unbuffered region).
1974 Seek(base::TimeDelta::FromSeconds(3));
1976 audio_read_done = false;
1977 video_read_done = false;
1978 ReadAudio(base::Bind(&OnReadDone,
1979 base::TimeDelta::FromSeconds(3),
1980 &audio_read_done));
1981 ReadVideo(base::Bind(&OnReadDone,
1982 base::TimeDelta::FromSeconds(3),
1983 &video_read_done));
1984 // Read()s should not return until after data is appended at the Seek point.
1985 EXPECT_FALSE(audio_read_done);
1986 EXPECT_FALSE(video_read_done);
1988 AppendCluster(audio_id,
1989 GenerateSingleStreamCluster(
1990 3000, 3092, kAudioTrackNum, kAudioBlockDuration));
1991 AppendCluster(video_id,
1992 GenerateSingleStreamCluster(
1993 3000, 3132, kVideoTrackNum, kVideoBlockDuration));
1995 message_loop_.RunUntilIdle();
1997 // Read() should return buffers at 3.
1998 EXPECT_TRUE(audio_read_done);
1999 EXPECT_TRUE(video_read_done);
2002 // Test that Seek() completes successfully when EndOfStream
2003 // is called before data is available for that seek point.
2004 // This scenario might be useful if seeking past the end of stream
2005 // of either audio or video (or both).
2006 TEST_F(ChunkDemuxerTest, EndOfStreamAfterPastEosSeek) {
2007 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2009 AppendCluster(GenerateSingleStreamCluster(0, 120, kAudioTrackNum, 10));
2010 AppendCluster(GenerateSingleStreamCluster(0, 100, kVideoTrackNum, 5));
2012 // Seeking past the end of video.
2013 // Note: audio data is available for that seek point.
2014 bool seek_cb_was_called = false;
2015 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(110);
2016 demuxer_->StartWaitingForSeek(seek_time);
2017 demuxer_->Seek(seek_time,
2018 base::Bind(OnSeekDone_OKExpected, &seek_cb_was_called));
2019 message_loop_.RunUntilIdle();
2021 EXPECT_FALSE(seek_cb_was_called);
2023 EXPECT_CALL(host_, SetDuration(
2024 base::TimeDelta::FromMilliseconds(120)));
2025 MarkEndOfStream(PIPELINE_OK);
2026 message_loop_.RunUntilIdle();
2028 EXPECT_TRUE(seek_cb_was_called);
2030 ShutdownDemuxer();
2033 // Test that EndOfStream is ignored if coming during a pending seek
2034 // whose seek time is before some existing ranges.
2035 TEST_F(ChunkDemuxerTest, EndOfStreamDuringPendingSeek) {
2036 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2038 AppendCluster(GenerateSingleStreamCluster(0, 120, kAudioTrackNum, 10));
2039 AppendCluster(GenerateSingleStreamCluster(0, 100, kVideoTrackNum, 5));
2040 AppendCluster(GenerateSingleStreamCluster(200, 300, kAudioTrackNum, 10));
2041 AppendCluster(GenerateSingleStreamCluster(200, 300, kVideoTrackNum, 5));
2043 bool seek_cb_was_called = false;
2044 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(160);
2045 demuxer_->StartWaitingForSeek(seek_time);
2046 demuxer_->Seek(seek_time,
2047 base::Bind(OnSeekDone_OKExpected, &seek_cb_was_called));
2048 message_loop_.RunUntilIdle();
2050 EXPECT_FALSE(seek_cb_was_called);
2052 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(300)));
2053 MarkEndOfStream(PIPELINE_OK);
2054 message_loop_.RunUntilIdle();
2056 EXPECT_FALSE(seek_cb_was_called);
2058 demuxer_->UnmarkEndOfStream();
2060 AppendCluster(GenerateSingleStreamCluster(140, 180, kAudioTrackNum, 10));
2061 AppendCluster(GenerateSingleStreamCluster(140, 180, kVideoTrackNum, 5));
2063 message_loop_.RunUntilIdle();
2065 EXPECT_TRUE(seek_cb_was_called);
2067 ShutdownDemuxer();
2070 // Test ranges in an audio-only stream.
2071 TEST_F(ChunkDemuxerTest, GetBufferedRanges_AudioIdOnly) {
2072 EXPECT_CALL(*this, DemuxerOpened());
2073 demuxer_->Initialize(
2074 &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true);
2076 ASSERT_EQ(AddId(kSourceId, HAS_AUDIO), ChunkDemuxer::kOk);
2077 AppendInitSegment(HAS_AUDIO);
2079 // Test a simple cluster.
2080 AppendCluster(
2081 GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration));
2083 CheckExpectedRanges("{ [0,92) }");
2085 // Append a disjoint cluster to check for two separate ranges.
2086 AppendCluster(GenerateSingleStreamCluster(
2087 150, 219, kAudioTrackNum, kAudioBlockDuration));
2089 CheckExpectedRanges("{ [0,92) [150,219) }");
2092 // Test ranges in a video-only stream.
2093 TEST_F(ChunkDemuxerTest, GetBufferedRanges_VideoIdOnly) {
2094 EXPECT_CALL(*this, DemuxerOpened());
2095 demuxer_->Initialize(
2096 &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true);
2098 ASSERT_EQ(AddId(kSourceId, HAS_VIDEO), ChunkDemuxer::kOk);
2099 AppendInitSegment(HAS_VIDEO);
2101 // Test a simple cluster.
2102 AppendCluster(
2103 GenerateSingleStreamCluster(0, 132, kVideoTrackNum, kVideoBlockDuration));
2105 CheckExpectedRanges("{ [0,132) }");
2107 // Append a disjoint cluster to check for two separate ranges.
2108 AppendCluster(GenerateSingleStreamCluster(
2109 200, 299, kVideoTrackNum, kVideoBlockDuration));
2111 CheckExpectedRanges("{ [0,132) [200,299) }");
2114 TEST_F(ChunkDemuxerTest, GetBufferedRanges_AudioVideo) {
2115 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2117 // Audio: 0 -> 23
2118 // Video: 0 -> 33
2119 // Buffered Range: 0 -> 23
2120 // Audio block duration is smaller than video block duration,
2121 // so the buffered ranges should correspond to the audio blocks.
2122 AppendCluster(GenerateSingleStreamCluster(
2123 0, kAudioBlockDuration, kAudioTrackNum, kAudioBlockDuration));
2124 AppendCluster(GenerateSingleStreamCluster(
2125 0, kVideoBlockDuration, kVideoTrackNum, kVideoBlockDuration));
2127 CheckExpectedRanges("{ [0,23) }");
2129 // Audio: 300 -> 400
2130 // Video: 320 -> 420
2131 // Buffered Range: 320 -> 400 (end overlap)
2132 AppendCluster(GenerateSingleStreamCluster(300, 400, kAudioTrackNum, 50));
2133 AppendCluster(GenerateSingleStreamCluster(320, 420, kVideoTrackNum, 50));
2135 CheckExpectedRanges("{ [0,23) [320,400) }");
2137 // Audio: 520 -> 590
2138 // Video: 500 -> 570
2139 // Buffered Range: 520 -> 570 (front overlap)
2140 AppendCluster(GenerateSingleStreamCluster(520, 590, kAudioTrackNum, 70));
2141 AppendCluster(GenerateSingleStreamCluster(500, 570, kVideoTrackNum, 70));
2143 CheckExpectedRanges("{ [0,23) [320,400) [520,570) }");
2145 // Audio: 720 -> 750
2146 // Video: 700 -> 770
2147 // Buffered Range: 720 -> 750 (complete overlap, audio)
2148 AppendCluster(GenerateSingleStreamCluster(720, 750, kAudioTrackNum, 30));
2149 AppendCluster(GenerateSingleStreamCluster(700, 770, kVideoTrackNum, 70));
2151 CheckExpectedRanges("{ [0,23) [320,400) [520,570) [720,750) }");
2153 // Audio: 900 -> 970
2154 // Video: 920 -> 950
2155 // Buffered Range: 920 -> 950 (complete overlap, video)
2156 AppendCluster(GenerateSingleStreamCluster(900, 970, kAudioTrackNum, 70));
2157 AppendCluster(GenerateSingleStreamCluster(920, 950, kVideoTrackNum, 30));
2159 CheckExpectedRanges("{ [0,23) [320,400) [520,570) [720,750) [920,950) }");
2161 // Appending within buffered range should not affect buffered ranges.
2162 AppendCluster(GenerateSingleStreamCluster(930, 950, kAudioTrackNum, 20));
2163 CheckExpectedRanges("{ [0,23) [320,400) [520,570) [720,750) [920,950) }");
2165 // Appending to single stream outside buffered ranges should not affect
2166 // buffered ranges.
2167 AppendCluster(GenerateSingleStreamCluster(1230, 1240, kVideoTrackNum, 10));
2168 CheckExpectedRanges("{ [0,23) [320,400) [520,570) [720,750) [920,950) }");
2171 TEST_F(ChunkDemuxerTest, GetBufferedRanges_AudioVideoText) {
2172 EXPECT_CALL(host_, AddTextStream(_, _));
2173 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO | HAS_TEXT));
2175 // Append audio & video data
2176 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, "0K 23");
2177 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "0K 33");
2179 // Verify that a text track with no cues does not result in an empty buffered
2180 // range.
2181 CheckExpectedRanges("{ [0,46) }");
2183 // Add some text cues.
2184 AppendSingleStreamCluster(kSourceId, kTextTrackNum, "0K 100K");
2186 // Verify that the new cues did not affect the buffered ranges.
2187 CheckExpectedRanges("{ [0,46) }");
2189 // Remove the buffered range.
2190 demuxer_->Remove(kSourceId, base::TimeDelta(),
2191 base::TimeDelta::FromMilliseconds(46));
2192 CheckExpectedRanges("{ }");
2195 // Once MarkEndOfStream() is called, GetBufferedRanges should not cut off any
2196 // over-hanging tails at the end of the ranges as this is likely due to block
2197 // duration differences.
2198 TEST_F(ChunkDemuxerTest, GetBufferedRanges_EndOfStream) {
2199 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2201 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, "0K 23K");
2202 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "0K 33");
2204 CheckExpectedRanges("{ [0,46) }");
2206 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(66)));
2207 MarkEndOfStream(PIPELINE_OK);
2209 // Verify that the range extends to the end of the video data.
2210 CheckExpectedRanges("{ [0,66) }");
2212 // Verify that the range reverts to the intersection when end of stream
2213 // has been cancelled.
2214 demuxer_->UnmarkEndOfStream();
2215 CheckExpectedRanges("{ [0,46) }");
2217 // Append and remove data so that the 2 streams' end ranges do not overlap.
2219 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(246)));
2220 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(366)));
2221 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, "200K 223K");
2222 AppendSingleStreamCluster(kSourceId, kVideoTrackNum,
2223 "200K 233 266 299 300K 333");
2225 // At this point, the per-stream ranges are as follows:
2226 // Audio: [0,46) [200,246)
2227 // Video: [0,66) [200,366)
2228 CheckExpectedRanges("{ [0,46) [200,246) }");
2230 demuxer_->Remove(kSourceId, base::TimeDelta::FromMilliseconds(200),
2231 base::TimeDelta::FromMilliseconds(300));
2233 // At this point, the per-stream ranges are as follows:
2234 // Audio: [0,46)
2235 // Video: [0,66) [300,366)
2236 CheckExpectedRanges("{ [0,46) }");
2238 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, "200K 223K");
2239 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "200K 233");
2241 // At this point, the per-stream ranges are as follows:
2242 // Audio: [0,46) [200,246)
2243 // Video: [0,66) [200,266) [300,366)
2244 // NOTE: The last range on each stream do not overlap in time.
2245 CheckExpectedRanges("{ [0,46) [200,246) }");
2247 MarkEndOfStream(PIPELINE_OK);
2249 // NOTE: The last range on each stream gets extended to the highest
2250 // end timestamp according to the spec. The last audio range gets extended
2251 // from [200,246) to [200,366) which is why the intersection results in the
2252 // middle range getting larger AND the new range appearing.
2253 CheckExpectedRanges("{ [0,46) [200,266) [300,366) }");
2256 TEST_F(ChunkDemuxerTest, DifferentStreamTimecodes) {
2257 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2259 // Create a cluster where the video timecode begins 25ms after the audio.
2260 AppendCluster(GenerateCluster(0, 25, 8));
2262 Seek(base::TimeDelta::FromSeconds(0));
2263 GenerateExpectedReads(0, 25, 8);
2265 // Seek to 5 seconds.
2266 Seek(base::TimeDelta::FromSeconds(5));
2268 // Generate a cluster to fulfill this seek, where audio timecode begins 25ms
2269 // after the video.
2270 AppendCluster(GenerateCluster(5025, 5000, 8));
2271 GenerateExpectedReads(5025, 5000, 8);
2274 TEST_F(ChunkDemuxerTest, DifferentStreamTimecodesSeparateSources) {
2275 std::string audio_id = "audio1";
2276 std::string video_id = "video1";
2277 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
2279 // Generate two streams where the video stream starts 5ms after the audio
2280 // stream and append them.
2281 AppendCluster(audio_id, GenerateSingleStreamCluster(
2282 25, 4 * kAudioBlockDuration + 25, kAudioTrackNum, kAudioBlockDuration));
2283 AppendCluster(video_id, GenerateSingleStreamCluster(
2284 30, 4 * kVideoBlockDuration + 30, kVideoTrackNum, kVideoBlockDuration));
2286 // Both streams should be able to fulfill a seek to 25.
2287 Seek(base::TimeDelta::FromMilliseconds(25));
2288 GenerateAudioStreamExpectedReads(25, 4);
2289 GenerateVideoStreamExpectedReads(30, 4);
2292 TEST_F(ChunkDemuxerTest, DifferentStreamTimecodesOutOfRange) {
2293 std::string audio_id = "audio1";
2294 std::string video_id = "video1";
2295 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
2297 // Generate two streams where the video stream starts 10s after the audio
2298 // stream and append them.
2299 AppendCluster(audio_id, GenerateSingleStreamCluster(0,
2300 4 * kAudioBlockDuration + 0, kAudioTrackNum, kAudioBlockDuration));
2301 AppendCluster(video_id, GenerateSingleStreamCluster(10000,
2302 4 * kVideoBlockDuration + 10000, kVideoTrackNum, kVideoBlockDuration));
2304 // Should not be able to fulfill a seek to 0.
2305 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(0);
2306 demuxer_->StartWaitingForSeek(seek_time);
2307 demuxer_->Seek(seek_time,
2308 NewExpectedStatusCB(PIPELINE_ERROR_ABORT));
2309 ExpectRead(DemuxerStream::AUDIO, 0);
2310 ExpectEndOfStream(DemuxerStream::VIDEO);
2313 TEST_F(ChunkDemuxerTest, ClusterWithNoBuffers) {
2314 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2316 // Generate and append an empty cluster beginning at 0.
2317 AppendEmptyCluster(0);
2319 // Sanity check that data can be appended after this cluster correctly.
2320 AppendCluster(GenerateCluster(0, 2));
2321 ExpectRead(DemuxerStream::AUDIO, 0);
2322 ExpectRead(DemuxerStream::VIDEO, 0);
2325 TEST_F(ChunkDemuxerTest, CodecPrefixMatching) {
2326 ChunkDemuxer::Status expected = ChunkDemuxer::kNotSupported;
2328 #if defined(USE_PROPRIETARY_CODECS)
2329 expected = ChunkDemuxer::kOk;
2330 #endif
2332 std::vector<std::string> codecs;
2333 codecs.push_back("avc1.4D4041");
2335 EXPECT_EQ(demuxer_->AddId("source_id", "video/mp4", codecs), expected);
2338 // Test codec ID's that are not compliant with RFC6381, but have been
2339 // seen in the wild.
2340 TEST_F(ChunkDemuxerTest, CodecIDsThatAreNotRFC6381Compliant) {
2341 ChunkDemuxer::Status expected = ChunkDemuxer::kNotSupported;
2343 #if defined(USE_PROPRIETARY_CODECS)
2344 expected = ChunkDemuxer::kOk;
2345 #endif
2346 const char* codec_ids[] = {
2347 // GPAC places leading zeros on the audio object type.
2348 "mp4a.40.02",
2349 "mp4a.40.05"
2352 for (size_t i = 0; i < arraysize(codec_ids); ++i) {
2353 std::vector<std::string> codecs;
2354 codecs.push_back(codec_ids[i]);
2356 ChunkDemuxer::Status result =
2357 demuxer_->AddId("source_id", "audio/mp4", codecs);
2359 EXPECT_EQ(result, expected)
2360 << "Fail to add codec_id '" << codec_ids[i] << "'";
2362 if (result == ChunkDemuxer::kOk)
2363 demuxer_->RemoveId("source_id");
2367 TEST_F(ChunkDemuxerTest, EndOfStreamStillSetAfterSeek) {
2368 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2370 EXPECT_CALL(host_, SetDuration(_))
2371 .Times(AnyNumber());
2373 base::TimeDelta kLastAudioTimestamp = base::TimeDelta::FromMilliseconds(92);
2374 base::TimeDelta kLastVideoTimestamp = base::TimeDelta::FromMilliseconds(99);
2376 AppendCluster(kDefaultFirstCluster());
2377 AppendCluster(kDefaultSecondCluster());
2378 MarkEndOfStream(PIPELINE_OK);
2380 DemuxerStream::Status status;
2381 base::TimeDelta last_timestamp;
2383 // Verify that we can read audio & video to the end w/o problems.
2384 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp);
2385 EXPECT_EQ(DemuxerStream::kOk, status);
2386 EXPECT_EQ(kLastAudioTimestamp, last_timestamp);
2388 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp);
2389 EXPECT_EQ(DemuxerStream::kOk, status);
2390 EXPECT_EQ(kLastVideoTimestamp, last_timestamp);
2392 // Seek back to 0 and verify that we can read to the end again..
2393 Seek(base::TimeDelta::FromMilliseconds(0));
2395 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp);
2396 EXPECT_EQ(DemuxerStream::kOk, status);
2397 EXPECT_EQ(kLastAudioTimestamp, last_timestamp);
2399 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp);
2400 EXPECT_EQ(DemuxerStream::kOk, status);
2401 EXPECT_EQ(kLastVideoTimestamp, last_timestamp);
2404 TEST_F(ChunkDemuxerTest, GetBufferedRangesBeforeInitSegment) {
2405 EXPECT_CALL(*this, DemuxerOpened());
2406 demuxer_->Initialize(&host_, CreateInitDoneCB(PIPELINE_OK), true);
2407 ASSERT_EQ(AddId("audio", HAS_AUDIO), ChunkDemuxer::kOk);
2408 ASSERT_EQ(AddId("video", HAS_VIDEO), ChunkDemuxer::kOk);
2410 CheckExpectedRanges("audio", "{ }");
2411 CheckExpectedRanges("video", "{ }");
2414 // Test that Seek() completes successfully when the first cluster
2415 // arrives.
2416 TEST_F(ChunkDemuxerTest, EndOfStreamDuringSeek) {
2417 InSequence s;
2419 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2421 AppendCluster(kDefaultFirstCluster());
2423 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(0);
2424 demuxer_->StartWaitingForSeek(seek_time);
2426 AppendCluster(kDefaultSecondCluster());
2427 EXPECT_CALL(host_, SetDuration(
2428 base::TimeDelta::FromMilliseconds(kDefaultSecondClusterEndTimestamp)));
2429 MarkEndOfStream(PIPELINE_OK);
2431 demuxer_->Seek(seek_time, NewExpectedStatusCB(PIPELINE_OK));
2433 GenerateExpectedReads(0, 4);
2434 GenerateExpectedReads(46, 66, 5);
2436 EndOfStreamHelper end_of_stream_helper(demuxer_.get());
2437 end_of_stream_helper.RequestReads();
2438 end_of_stream_helper.CheckIfReadDonesWereCalled(true);
2441 TEST_F(ChunkDemuxerTest, ConfigChange_Video) {
2442 InSequence s;
2444 ASSERT_TRUE(InitDemuxerWithConfigChangeData());
2446 DemuxerStream::Status status;
2447 base::TimeDelta last_timestamp;
2449 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
2451 // Fetch initial video config and verify it matches what we expect.
2452 const VideoDecoderConfig& video_config_1 = video->video_decoder_config();
2453 ASSERT_TRUE(video_config_1.IsValidConfig());
2454 EXPECT_EQ(video_config_1.natural_size().width(), 320);
2455 EXPECT_EQ(video_config_1.natural_size().height(), 240);
2457 ExpectRead(DemuxerStream::VIDEO, 0);
2459 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp);
2461 ASSERT_EQ(status, DemuxerStream::kConfigChanged);
2462 EXPECT_EQ(last_timestamp.InMilliseconds(), 501);
2464 // Fetch the new decoder config.
2465 const VideoDecoderConfig& video_config_2 = video->video_decoder_config();
2466 ASSERT_TRUE(video_config_2.IsValidConfig());
2467 EXPECT_EQ(video_config_2.natural_size().width(), 640);
2468 EXPECT_EQ(video_config_2.natural_size().height(), 360);
2470 ExpectRead(DemuxerStream::VIDEO, 527);
2472 // Read until the next config change.
2473 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp);
2474 ASSERT_EQ(status, DemuxerStream::kConfigChanged);
2475 EXPECT_EQ(last_timestamp.InMilliseconds(), 793);
2477 // Get the new config and verify that it matches the first one.
2478 ASSERT_TRUE(video_config_1.Matches(video->video_decoder_config()));
2480 ExpectRead(DemuxerStream::VIDEO, 801);
2482 // Read until the end of the stream just to make sure there aren't any other
2483 // config changes.
2484 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp);
2485 ASSERT_EQ(status, DemuxerStream::kOk);
2488 TEST_F(ChunkDemuxerTest, ConfigChange_Audio) {
2489 InSequence s;
2491 ASSERT_TRUE(InitDemuxerWithConfigChangeData());
2493 DemuxerStream::Status status;
2494 base::TimeDelta last_timestamp;
2496 DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
2498 // Fetch initial audio config and verify it matches what we expect.
2499 const AudioDecoderConfig& audio_config_1 = audio->audio_decoder_config();
2500 ASSERT_TRUE(audio_config_1.IsValidConfig());
2501 EXPECT_EQ(audio_config_1.samples_per_second(), 44100);
2502 EXPECT_EQ(audio_config_1.extra_data_size(), 3863u);
2504 ExpectRead(DemuxerStream::AUDIO, 0);
2506 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp);
2508 ASSERT_EQ(status, DemuxerStream::kConfigChanged);
2509 EXPECT_EQ(last_timestamp.InMilliseconds(), 524);
2511 // Fetch the new decoder config.
2512 const AudioDecoderConfig& audio_config_2 = audio->audio_decoder_config();
2513 ASSERT_TRUE(audio_config_2.IsValidConfig());
2514 EXPECT_EQ(audio_config_2.samples_per_second(), 44100);
2515 EXPECT_EQ(audio_config_2.extra_data_size(), 3935u);
2517 ExpectRead(DemuxerStream::AUDIO, 527);
2519 // Read until the next config change.
2520 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp);
2521 ASSERT_EQ(status, DemuxerStream::kConfigChanged);
2522 EXPECT_EQ(last_timestamp.InMilliseconds(), 759);
2524 // Get the new config and verify that it matches the first one.
2525 ASSERT_TRUE(audio_config_1.Matches(audio->audio_decoder_config()));
2527 ExpectRead(DemuxerStream::AUDIO, 779);
2529 // Read until the end of the stream just to make sure there aren't any other
2530 // config changes.
2531 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp);
2532 ASSERT_EQ(status, DemuxerStream::kOk);
2535 TEST_F(ChunkDemuxerTest, ConfigChange_Seek) {
2536 InSequence s;
2538 ASSERT_TRUE(InitDemuxerWithConfigChangeData());
2540 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
2542 // Fetch initial video config and verify it matches what we expect.
2543 const VideoDecoderConfig& video_config_1 = video->video_decoder_config();
2544 ASSERT_TRUE(video_config_1.IsValidConfig());
2545 EXPECT_EQ(video_config_1.natural_size().width(), 320);
2546 EXPECT_EQ(video_config_1.natural_size().height(), 240);
2548 ExpectRead(DemuxerStream::VIDEO, 0);
2550 // Seek to a location with a different config.
2551 Seek(base::TimeDelta::FromMilliseconds(527));
2553 // Verify that the config change is signalled.
2554 ExpectConfigChanged(DemuxerStream::VIDEO);
2556 // Fetch the new decoder config and verify it is what we expect.
2557 const VideoDecoderConfig& video_config_2 = video->video_decoder_config();
2558 ASSERT_TRUE(video_config_2.IsValidConfig());
2559 EXPECT_EQ(video_config_2.natural_size().width(), 640);
2560 EXPECT_EQ(video_config_2.natural_size().height(), 360);
2562 // Verify that Read() will return a buffer now.
2563 ExpectRead(DemuxerStream::VIDEO, 527);
2565 // Seek back to the beginning and verify we get another config change.
2566 Seek(base::TimeDelta::FromMilliseconds(0));
2567 ExpectConfigChanged(DemuxerStream::VIDEO);
2568 ASSERT_TRUE(video_config_1.Matches(video->video_decoder_config()));
2569 ExpectRead(DemuxerStream::VIDEO, 0);
2571 // Seek to a location that requires a config change and then
2572 // seek to a new location that has the same configuration as
2573 // the start of the file without a Read() in the middle.
2574 Seek(base::TimeDelta::FromMilliseconds(527));
2575 Seek(base::TimeDelta::FromMilliseconds(801));
2577 // Verify that no config change is signalled.
2578 ExpectRead(DemuxerStream::VIDEO, 801);
2579 ASSERT_TRUE(video_config_1.Matches(video->video_decoder_config()));
2582 TEST_F(ChunkDemuxerTest, TimestampPositiveOffset) {
2583 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2585 ASSERT_TRUE(demuxer_->SetTimestampOffset(
2586 kSourceId, base::TimeDelta::FromSeconds(30)));
2587 AppendCluster(GenerateCluster(0, 2));
2589 Seek(base::TimeDelta::FromMilliseconds(30000));
2591 GenerateExpectedReads(30000, 2);
2594 TEST_F(ChunkDemuxerTest, TimestampNegativeOffset) {
2595 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2597 ASSERT_TRUE(demuxer_->SetTimestampOffset(
2598 kSourceId, base::TimeDelta::FromSeconds(-1)));
2599 AppendCluster(GenerateCluster(1000, 2));
2601 GenerateExpectedReads(0, 2);
2604 TEST_F(ChunkDemuxerTest, TimestampOffsetSeparateStreams) {
2605 std::string audio_id = "audio1";
2606 std::string video_id = "video1";
2607 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
2609 ASSERT_TRUE(demuxer_->SetTimestampOffset(
2610 audio_id, base::TimeDelta::FromMilliseconds(-2500)));
2611 ASSERT_TRUE(demuxer_->SetTimestampOffset(
2612 video_id, base::TimeDelta::FromMilliseconds(-2500)));
2613 AppendCluster(audio_id, GenerateSingleStreamCluster(2500,
2614 2500 + kAudioBlockDuration * 4, kAudioTrackNum, kAudioBlockDuration));
2615 AppendCluster(video_id, GenerateSingleStreamCluster(2500,
2616 2500 + kVideoBlockDuration * 4, kVideoTrackNum, kVideoBlockDuration));
2617 GenerateAudioStreamExpectedReads(0, 4);
2618 GenerateVideoStreamExpectedReads(0, 4);
2620 Seek(base::TimeDelta::FromMilliseconds(27300));
2622 ASSERT_TRUE(demuxer_->SetTimestampOffset(
2623 audio_id, base::TimeDelta::FromMilliseconds(27300)));
2624 ASSERT_TRUE(demuxer_->SetTimestampOffset(
2625 video_id, base::TimeDelta::FromMilliseconds(27300)));
2626 AppendCluster(audio_id, GenerateSingleStreamCluster(
2627 0, kAudioBlockDuration * 4, kAudioTrackNum, kAudioBlockDuration));
2628 AppendCluster(video_id, GenerateSingleStreamCluster(
2629 0, kVideoBlockDuration * 4, kVideoTrackNum, kVideoBlockDuration));
2630 GenerateVideoStreamExpectedReads(27300, 4);
2631 GenerateAudioStreamExpectedReads(27300, 4);
2634 TEST_F(ChunkDemuxerTest, TimestampOffsetMidMediaSegment) {
2635 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2637 scoped_ptr<Cluster> cluster = GenerateCluster(0, 2);
2638 // Append only part of the cluster data.
2639 AppendData(cluster->data(), cluster->size() - 13);
2641 // Setting a timestamp should fail because we're in the middle of a cluster.
2642 ASSERT_FALSE(demuxer_->SetTimestampOffset(
2643 kSourceId, base::TimeDelta::FromSeconds(25)));
2645 demuxer_->Abort(kSourceId);
2646 // After Abort(), setting a timestamp should succeed since we're no longer
2647 // in the middle of a cluster
2648 ASSERT_TRUE(demuxer_->SetTimestampOffset(
2649 kSourceId, base::TimeDelta::FromSeconds(25)));
2652 TEST_F(ChunkDemuxerTest, WebMParsingMediaSegmentDetection) {
2653 // TODO(wolenetz): Also test 'unknown' sized clusters.
2654 // See http://crbug.com/335676.
2655 const uint8 kBuffer[] = {
2656 0x1F, 0x43, 0xB6, 0x75, 0x83, // CLUSTER (size = 3)
2657 0xE7, 0x81, 0x01, // Cluster TIMECODE (value = 1)
2660 // Setting timestamp offset or append mode is allowed only while not
2661 // parsing a media segment. This array indicates whether or not these
2662 // operations are allowed following each incrementally appended byte in
2663 // |kBuffer|.
2664 const bool kExpectedReturnValues[] = {
2665 true, true, true, true, false,
2666 false, false, true,
2669 COMPILE_ASSERT(arraysize(kBuffer) == arraysize(kExpectedReturnValues),
2670 test_arrays_out_of_sync);
2671 COMPILE_ASSERT(arraysize(kBuffer) == sizeof(kBuffer), not_one_byte_per_index);
2673 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2675 for (size_t i = 0; i < sizeof(kBuffer); i++) {
2676 DVLOG(3) << "Appending and testing index " << i;
2677 AppendData(kBuffer + i, 1);
2678 bool expected_return_value = kExpectedReturnValues[i];
2679 EXPECT_EQ(expected_return_value, demuxer_->SetTimestampOffset(
2680 kSourceId, base::TimeDelta::FromSeconds(25)));
2681 EXPECT_EQ(expected_return_value, demuxer_->SetSequenceMode(
2682 kSourceId, true));
2683 EXPECT_EQ(expected_return_value, demuxer_->SetSequenceMode(
2684 kSourceId, false));
2688 TEST_F(ChunkDemuxerTest, SetSequenceModeMidMediaSegment) {
2689 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2691 scoped_ptr<Cluster> cluster = GenerateCluster(0, 2);
2692 // Append only part of the cluster data.
2693 AppendData(cluster->data(), cluster->size() - 13);
2695 // Setting append mode should fail because we're in the middle of a cluster.
2696 ASSERT_FALSE(demuxer_->SetSequenceMode(kSourceId, true));
2697 ASSERT_FALSE(demuxer_->SetSequenceMode(kSourceId, false));
2699 demuxer_->Abort(kSourceId);
2700 // After Abort(), setting append mode should succeed since we're no longer
2701 // in the middle of a cluster.
2702 ASSERT_TRUE(demuxer_->SetSequenceMode(kSourceId, true));
2703 ASSERT_TRUE(demuxer_->SetSequenceMode(kSourceId, false));
2706 TEST_F(ChunkDemuxerTest, DurationChange) {
2707 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2708 const int kStreamDuration = kDefaultDuration().InMilliseconds();
2710 // Add data leading up to the currently set duration.
2711 AppendCluster(GenerateCluster(kStreamDuration - kAudioBlockDuration,
2712 kStreamDuration - kVideoBlockDuration,
2713 2));
2715 CheckExpectedRanges(kSourceId, "{ [201191,201224) }");
2717 // Add data at the currently set duration. The duration should not increase.
2718 AppendCluster(GenerateCluster(kDefaultDuration().InMilliseconds(), 2));
2720 // Range should not be affected.
2721 CheckExpectedRanges(kSourceId, "{ [201191,201224) }");
2723 // Now add data past the duration and expect a new duration to be signalled.
2724 const int kNewStreamDuration = kStreamDuration + kAudioBlockDuration * 2;
2725 EXPECT_CALL(host_, SetDuration(
2726 base::TimeDelta::FromMilliseconds(kNewStreamDuration)));
2727 AppendCluster(GenerateCluster(kStreamDuration + kAudioBlockDuration,
2728 kStreamDuration + kVideoBlockDuration,
2729 2));
2731 // See that the range has increased appropriately.
2732 CheckExpectedRanges(kSourceId, "{ [201191,201270) }");
2735 TEST_F(ChunkDemuxerTest, DurationChangeTimestampOffset) {
2736 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2738 ASSERT_TRUE(demuxer_->SetTimestampOffset(kSourceId, kDefaultDuration()));
2740 EXPECT_CALL(host_, SetDuration(
2741 kDefaultDuration() + base::TimeDelta::FromMilliseconds(
2742 kAudioBlockDuration * 2)));
2743 AppendCluster(GenerateCluster(0, 4));
2746 TEST_F(ChunkDemuxerTest, EndOfStreamTruncateDuration) {
2747 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2749 AppendCluster(kDefaultFirstCluster());
2751 EXPECT_CALL(host_, SetDuration(
2752 base::TimeDelta::FromMilliseconds(kDefaultFirstClusterEndTimestamp)));
2753 MarkEndOfStream(PIPELINE_OK);
2757 TEST_F(ChunkDemuxerTest, ZeroLengthAppend) {
2758 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2759 AppendData(NULL, 0);
2762 TEST_F(ChunkDemuxerTest, AppendAfterEndOfStream) {
2763 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2765 EXPECT_CALL(host_, SetDuration(_))
2766 .Times(AnyNumber());
2768 AppendCluster(kDefaultFirstCluster());
2769 MarkEndOfStream(PIPELINE_OK);
2771 demuxer_->UnmarkEndOfStream();
2773 AppendCluster(kDefaultSecondCluster());
2774 MarkEndOfStream(PIPELINE_OK);
2777 // Test receiving a Shutdown() call before we get an Initialize()
2778 // call. This can happen if video element gets destroyed before
2779 // the pipeline has a chance to initialize the demuxer.
2780 TEST_F(ChunkDemuxerTest, Shutdown_BeforeInitialize) {
2781 demuxer_->Shutdown();
2782 demuxer_->Initialize(
2783 &host_, CreateInitDoneCB(DEMUXER_ERROR_COULD_NOT_OPEN), true);
2784 message_loop_.RunUntilIdle();
2787 TEST_F(ChunkDemuxerTest, ReadAfterAudioDisabled) {
2788 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2789 AppendCluster(kDefaultFirstCluster());
2791 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::AUDIO);
2792 ASSERT_TRUE(stream);
2794 // The stream should no longer be present.
2795 demuxer_->OnAudioRendererDisabled();
2796 ASSERT_FALSE(demuxer_->GetStream(DemuxerStream::AUDIO));
2798 // Normally this would return an audio buffer at timestamp zero, but
2799 // all reads should return EOS buffers when disabled.
2800 bool audio_read_done = false;
2801 stream->Read(base::Bind(&OnReadDone_EOSExpected, &audio_read_done));
2802 message_loop_.RunUntilIdle();
2804 EXPECT_TRUE(audio_read_done);
2807 // Verifies that signalling end of stream while stalled at a gap
2808 // boundary does not trigger end of stream buffers to be returned.
2809 TEST_F(ChunkDemuxerTest, EndOfStreamWhileWaitingForGapToBeFilled) {
2810 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2812 AppendCluster(0, 10);
2813 AppendCluster(300, 10);
2814 CheckExpectedRanges(kSourceId, "{ [0,132) [300,432) }");
2817 GenerateExpectedReads(0, 10);
2819 bool audio_read_done = false;
2820 bool video_read_done = false;
2821 ReadAudio(base::Bind(&OnReadDone,
2822 base::TimeDelta::FromMilliseconds(138),
2823 &audio_read_done));
2824 ReadVideo(base::Bind(&OnReadDone,
2825 base::TimeDelta::FromMilliseconds(138),
2826 &video_read_done));
2828 // Verify that the reads didn't complete
2829 EXPECT_FALSE(audio_read_done);
2830 EXPECT_FALSE(video_read_done);
2832 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(438)));
2833 MarkEndOfStream(PIPELINE_OK);
2835 // Verify that the reads still haven't completed.
2836 EXPECT_FALSE(audio_read_done);
2837 EXPECT_FALSE(video_read_done);
2839 demuxer_->UnmarkEndOfStream();
2841 AppendCluster(138, 24);
2843 message_loop_.RunUntilIdle();
2845 CheckExpectedRanges(kSourceId, "{ [0,438) }");
2847 // Verify that the reads have completed.
2848 EXPECT_TRUE(audio_read_done);
2849 EXPECT_TRUE(video_read_done);
2851 // Read the rest of the buffers.
2852 GenerateExpectedReads(161, 171, 22);
2854 // Verify that reads block because the append cleared the end of stream state.
2855 audio_read_done = false;
2856 video_read_done = false;
2857 ReadAudio(base::Bind(&OnReadDone_EOSExpected,
2858 &audio_read_done));
2859 ReadVideo(base::Bind(&OnReadDone_EOSExpected,
2860 &video_read_done));
2862 // Verify that the reads don't complete.
2863 EXPECT_FALSE(audio_read_done);
2864 EXPECT_FALSE(video_read_done);
2866 MarkEndOfStream(PIPELINE_OK);
2868 EXPECT_TRUE(audio_read_done);
2869 EXPECT_TRUE(video_read_done);
2872 TEST_F(ChunkDemuxerTest, CanceledSeekDuringInitialPreroll) {
2873 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2875 // Cancel preroll.
2876 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(200);
2877 demuxer_->CancelPendingSeek(seek_time);
2879 // Initiate the seek to the new location.
2880 Seek(seek_time);
2882 // Append data to satisfy the seek.
2883 AppendCluster(seek_time.InMilliseconds(), 10);
2886 TEST_F(ChunkDemuxerTest, GCDuringSeek) {
2887 ASSERT_TRUE(InitDemuxer(HAS_AUDIO));
2889 demuxer_->SetMemoryLimitsForTesting(5 * kBlockSize);
2891 base::TimeDelta seek_time1 = base::TimeDelta::FromMilliseconds(1000);
2892 base::TimeDelta seek_time2 = base::TimeDelta::FromMilliseconds(500);
2894 // Initiate a seek to |seek_time1|.
2895 Seek(seek_time1);
2897 // Append data to satisfy the first seek request.
2898 AppendSingleStreamCluster(kSourceId, kAudioTrackNum,
2899 seek_time1.InMilliseconds(), 5);
2900 CheckExpectedRanges(kSourceId, "{ [1000,1115) }");
2902 // Signal that the second seek is starting.
2903 demuxer_->StartWaitingForSeek(seek_time2);
2905 // Append data to satisfy the second seek. This append triggers
2906 // the garbage collection logic since we set the memory limit to
2907 // 5 blocks.
2908 AppendSingleStreamCluster(kSourceId, kAudioTrackNum,
2909 seek_time2.InMilliseconds(), 5);
2911 // Verify that the buffers that cover |seek_time2| do not get
2912 // garbage collected.
2913 CheckExpectedRanges(kSourceId, "{ [500,615) }");
2915 // Complete the seek.
2916 demuxer_->Seek(seek_time2, NewExpectedStatusCB(PIPELINE_OK));
2919 // Append more data and make sure that the blocks for |seek_time2|
2920 // don't get removed.
2922 // NOTE: The current GC algorithm tries to preserve the GOP at the
2923 // current position as well as the last appended GOP. This is
2924 // why there are 2 ranges in the expectations.
2925 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 700, 5);
2926 CheckExpectedRanges(kSourceId, "{ [500,592) [792,815) }");
2929 TEST_F(ChunkDemuxerTest, RemoveBeforeInitSegment) {
2930 EXPECT_CALL(*this, DemuxerOpened());
2931 demuxer_->Initialize(
2932 &host_, CreateInitDoneCB(kNoTimestamp(), PIPELINE_OK), true);
2934 EXPECT_EQ(ChunkDemuxer::kOk, AddId(kSourceId, HAS_AUDIO | HAS_VIDEO));
2936 demuxer_->Remove(kSourceId, base::TimeDelta::FromMilliseconds(0),
2937 base::TimeDelta::FromMilliseconds(1));
2940 TEST_F(ChunkDemuxerTest, AppendWindow_Video) {
2941 ASSERT_TRUE(InitDemuxer(HAS_VIDEO));
2942 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
2944 // Set the append window to [20,280).
2945 demuxer_->SetAppendWindowStart(kSourceId,
2946 base::TimeDelta::FromMilliseconds(20));
2947 demuxer_->SetAppendWindowEnd(kSourceId,
2948 base::TimeDelta::FromMilliseconds(280));
2950 // Append a cluster that starts before and ends after the append window.
2951 AppendSingleStreamCluster(kSourceId, kVideoTrackNum,
2952 "0K 30 60 90 120K 150 180 210 240K 270 300 330K");
2954 // Verify that GOPs that start outside the window are not included
2955 // in the buffer. Also verify that buffers that start inside the
2956 // window and extend beyond the end of the window are included.
2957 CheckExpectedRanges(kSourceId, "{ [120,300) }");
2958 CheckExpectedBuffers(stream, "120 150 180 210 240 270");
2960 // Extend the append window to [20,650).
2961 demuxer_->SetAppendWindowEnd(kSourceId,
2962 base::TimeDelta::FromMilliseconds(650));
2964 // Append more data and verify that adding buffers start at the next
2965 // keyframe.
2966 AppendSingleStreamCluster(kSourceId, kVideoTrackNum,
2967 "360 390 420K 450 480 510 540K 570 600 630K");
2968 CheckExpectedRanges(kSourceId, "{ [120,300) [420,660) }");
2971 TEST_F(ChunkDemuxerTest, AppendWindow_Audio) {
2972 ASSERT_TRUE(InitDemuxer(HAS_AUDIO));
2973 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::AUDIO);
2975 // Set the append window to [20,280).
2976 demuxer_->SetAppendWindowStart(kSourceId,
2977 base::TimeDelta::FromMilliseconds(20));
2978 demuxer_->SetAppendWindowEnd(kSourceId,
2979 base::TimeDelta::FromMilliseconds(280));
2981 // Append a cluster that starts before and ends after the append window.
2982 AppendSingleStreamCluster(
2983 kSourceId, kAudioTrackNum,
2984 "0K 30K 60K 90K 120K 150K 180K 210K 240K 270K 300K 330K");
2986 // Verify that frames that start outside the window are not included
2987 // in the buffer. Also verify that buffers that start inside the
2988 // window and extend beyond the end of the window are included.
2989 CheckExpectedRanges(kSourceId, "{ [30,300) }");
2990 CheckExpectedBuffers(stream, "30 60 90 120 150 180 210 240 270");
2992 // Extend the append window to [20,650).
2993 demuxer_->SetAppendWindowEnd(kSourceId,
2994 base::TimeDelta::FromMilliseconds(650));
2996 // Append more data and verify that a new range is created.
2997 AppendSingleStreamCluster(
2998 kSourceId, kAudioTrackNum,
2999 "360K 390K 420K 450K 480K 510K 540K 570K 600K 630K");
3000 CheckExpectedRanges(kSourceId, "{ [30,300) [360,660) }");
3003 TEST_F(ChunkDemuxerTest, AppendWindow_Text) {
3004 DemuxerStream* text_stream = NULL;
3005 EXPECT_CALL(host_, AddTextStream(_, _))
3006 .WillOnce(SaveArg<0>(&text_stream));
3007 ASSERT_TRUE(InitDemuxer(HAS_VIDEO | HAS_TEXT));
3008 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO);
3010 // Set the append window to [20,280).
3011 demuxer_->SetAppendWindowStart(kSourceId,
3012 base::TimeDelta::FromMilliseconds(20));
3013 demuxer_->SetAppendWindowEnd(kSourceId,
3014 base::TimeDelta::FromMilliseconds(280));
3016 // Append a cluster that starts before and ends after the append
3017 // window.
3018 AppendSingleStreamCluster(kSourceId, kVideoTrackNum,
3019 "0K 30 60 90 120K 150 180 210 240K 270 300 330K");
3020 AppendSingleStreamCluster(kSourceId, kTextTrackNum, "0K 100K 200K 300K");
3022 // Verify that text cues that start outside the window are not included
3023 // in the buffer. Also verify that cues that extend beyond the
3024 // window are included.
3025 CheckExpectedRanges(kSourceId, "{ [120,300) }");
3026 CheckExpectedBuffers(video_stream, "120 150 180 210 240 270");
3027 CheckExpectedBuffers(text_stream, "100 200");
3029 // Extend the append window to [20,650).
3030 demuxer_->SetAppendWindowEnd(kSourceId,
3031 base::TimeDelta::FromMilliseconds(650));
3033 // Append more data and verify that a new range is created.
3034 AppendSingleStreamCluster(kSourceId, kVideoTrackNum,
3035 "360 390 420K 450 480 510 540K 570 600 630K");
3036 AppendSingleStreamCluster(kSourceId, kTextTrackNum, "400K 500K 600K 700K");
3037 CheckExpectedRanges(kSourceId, "{ [120,300) [420,660) }");
3039 // Seek to the new range and verify that the expected buffers are returned.
3040 Seek(base::TimeDelta::FromMilliseconds(420));
3041 CheckExpectedBuffers(video_stream, "420 450 480 510 540 570 600 630");
3042 CheckExpectedBuffers(text_stream, "400 500 600");
3045 TEST_F(ChunkDemuxerTest, StartWaitingForSeekAfterParseError) {
3046 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
3047 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE));
3048 AppendGarbage();
3049 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(50);
3050 demuxer_->StartWaitingForSeek(seek_time);
3053 TEST_F(ChunkDemuxerTest, Remove_AudioVideoText) {
3054 DemuxerStream* text_stream = NULL;
3055 EXPECT_CALL(host_, AddTextStream(_, _))
3056 .WillOnce(SaveArg<0>(&text_stream));
3057 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO | HAS_TEXT));
3059 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO);
3060 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO);
3062 AppendSingleStreamCluster(kSourceId, kAudioTrackNum,
3063 "0K 20K 40K 60K 80K 100K 120K 140K");
3064 AppendSingleStreamCluster(kSourceId, kVideoTrackNum,
3065 "0K 30 60 90 120K 150 180");
3066 AppendSingleStreamCluster(kSourceId, kTextTrackNum, "0K 100K 200K");
3068 CheckExpectedBuffers(audio_stream, "0 20 40 60 80 100 120 140");
3069 CheckExpectedBuffers(video_stream, "0 30 60 90 120 150 180");
3070 CheckExpectedBuffers(text_stream, "0 100 200");
3072 // Remove the buffers that were added.
3073 demuxer_->Remove(kSourceId, base::TimeDelta(),
3074 base::TimeDelta::FromMilliseconds(300));
3076 // Verify that all the appended data has been removed.
3077 CheckExpectedRanges(kSourceId, "{ }");
3079 // Append new buffers that are clearly different than the original
3080 // ones and verify that only the new buffers are returned.
3081 AppendSingleStreamCluster(kSourceId, kAudioTrackNum,
3082 "1K 21K 41K 61K 81K 101K 121K 141K");
3083 AppendSingleStreamCluster(kSourceId, kVideoTrackNum,
3084 "1K 31 61 91 121K 151 181");
3085 AppendSingleStreamCluster(kSourceId, kTextTrackNum, "1K 101K 201K");
3087 Seek(base::TimeDelta());
3088 CheckExpectedBuffers(audio_stream, "1 21 41 61 81 101 121 141");
3089 CheckExpectedBuffers(video_stream, "1 31 61 91 121 151 181");
3090 CheckExpectedBuffers(text_stream, "1 101 201");
3093 // Verifies that a Seek() will complete without text cues for
3094 // the seek point and will return cues after the seek position
3095 // when they are eventually appended.
3096 TEST_F(ChunkDemuxerTest, SeekCompletesWithoutTextCues) {
3097 DemuxerStream* text_stream = NULL;
3098 EXPECT_CALL(host_, AddTextStream(_, _))
3099 .WillOnce(SaveArg<0>(&text_stream));
3100 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO | HAS_TEXT));
3102 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO);
3103 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO);
3105 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(120);
3106 bool seek_cb_was_called = false;
3107 demuxer_->StartWaitingForSeek(seek_time);
3108 demuxer_->Seek(seek_time,
3109 base::Bind(OnSeekDone_OKExpected, &seek_cb_was_called));
3110 message_loop_.RunUntilIdle();
3112 EXPECT_FALSE(seek_cb_was_called);
3114 bool text_read_done = false;
3115 text_stream->Read(base::Bind(&OnReadDone,
3116 base::TimeDelta::FromMilliseconds(125),
3117 &text_read_done));
3119 // Append audio & video data so the seek completes.
3120 AppendSingleStreamCluster(kSourceId, kAudioTrackNum,
3121 "0K 20K 40K 60K 80K 100K 120K 140K 160K 180K");
3122 AppendSingleStreamCluster(kSourceId, kVideoTrackNum,
3123 "0K 30 60 90 120K 150 180 210");
3125 message_loop_.RunUntilIdle();
3126 EXPECT_TRUE(seek_cb_was_called);
3127 EXPECT_FALSE(text_read_done);
3129 // Read some audio & video buffers to further verify seek completion.
3130 CheckExpectedBuffers(audio_stream, "120 140");
3131 CheckExpectedBuffers(video_stream, "120 150");
3133 EXPECT_FALSE(text_read_done);
3135 // Append text cues that start after the seek point and verify that
3136 // they are returned by Read() calls.
3137 AppendSingleStreamCluster(kSourceId, kTextTrackNum, "125K 175K 225K");
3139 message_loop_.RunUntilIdle();
3140 EXPECT_TRUE(text_read_done);
3142 // NOTE: we start at 175 here because the buffer at 125 was returned
3143 // to the pending read initiated above.
3144 CheckExpectedBuffers(text_stream, "175 225");
3146 // Verify that audio & video streams contiue to return expected values.
3147 CheckExpectedBuffers(audio_stream, "160 180");
3148 CheckExpectedBuffers(video_stream, "180 210");
3151 } // namespace media