Cast: Skip receiver log messages with time delta that can't be encoded.
[chromium-blink-merge.git] / media / filters / chunk_demuxer_unittest.cc
blobc8ca5f2b818149620c9f816d455c8cd7c5715c62
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());
398 // TODO(wolenetz): Test timestamp offset updating once "sequence" append
399 // mode processing is implemented. See http://crbug.com/249422.
400 demuxer_->AppendData(source_id, data, length, NULL);
403 void AppendDataInPieces(const uint8* data, size_t length) {
404 AppendDataInPieces(data, length, 7);
407 void AppendDataInPieces(const uint8* data, size_t length, size_t piece_size) {
408 const uint8* start = data;
409 const uint8* end = data + length;
410 while (start < end) {
411 size_t append_size = std::min(piece_size,
412 static_cast<size_t>(end - start));
413 AppendData(start, append_size);
414 start += append_size;
418 void AppendInitSegment(int stream_flags) {
419 AppendInitSegmentWithSourceId(kSourceId, stream_flags);
422 void AppendInitSegmentWithSourceId(const std::string& source_id,
423 int stream_flags) {
424 AppendInitSegmentWithEncryptedInfo(source_id, stream_flags, false, false);
427 void AppendInitSegmentWithEncryptedInfo(const std::string& source_id,
428 int stream_flags,
429 bool is_audio_encrypted,
430 bool is_video_encrypted) {
431 scoped_ptr<uint8[]> info_tracks;
432 int info_tracks_size = 0;
433 CreateInitSegment(stream_flags,
434 is_audio_encrypted, is_video_encrypted,
435 &info_tracks, &info_tracks_size);
436 AppendData(source_id, info_tracks.get(), info_tracks_size);
439 void AppendGarbage() {
440 // Fill up an array with gibberish.
441 int garbage_cluster_size = 10;
442 scoped_ptr<uint8[]> garbage_cluster(new uint8[garbage_cluster_size]);
443 for (int i = 0; i < garbage_cluster_size; ++i)
444 garbage_cluster[i] = i;
445 AppendData(garbage_cluster.get(), garbage_cluster_size);
448 void InitDoneCalled(PipelineStatus expected_status,
449 PipelineStatus status) {
450 EXPECT_EQ(status, expected_status);
453 void AppendEmptyCluster(int timecode) {
454 AppendCluster(GenerateEmptyCluster(timecode));
457 PipelineStatusCB CreateInitDoneCB(const base::TimeDelta& expected_duration,
458 PipelineStatus expected_status) {
459 if (expected_duration != kNoTimestamp())
460 EXPECT_CALL(host_, SetDuration(expected_duration));
461 return CreateInitDoneCB(expected_status);
464 PipelineStatusCB CreateInitDoneCB(PipelineStatus expected_status) {
465 return base::Bind(&ChunkDemuxerTest::InitDoneCalled,
466 base::Unretained(this),
467 expected_status);
470 enum StreamFlags {
471 HAS_AUDIO = 1 << 0,
472 HAS_VIDEO = 1 << 1,
473 HAS_TEXT = 1 << 2
476 bool InitDemuxer(int stream_flags) {
477 return InitDemuxerWithEncryptionInfo(stream_flags, false, false);
480 bool InitDemuxerWithEncryptionInfo(
481 int stream_flags, bool is_audio_encrypted, bool is_video_encrypted) {
483 PipelineStatus expected_status =
484 (stream_flags != 0) ? PIPELINE_OK : DEMUXER_ERROR_COULD_NOT_OPEN;
486 base::TimeDelta expected_duration = kNoTimestamp();
487 if (expected_status == PIPELINE_OK)
488 expected_duration = kDefaultDuration();
490 EXPECT_CALL(*this, DemuxerOpened());
491 demuxer_->Initialize(
492 &host_, CreateInitDoneCB(expected_duration, expected_status), true);
494 if (AddId(kSourceId, stream_flags) != ChunkDemuxer::kOk)
495 return false;
497 AppendInitSegmentWithEncryptedInfo(
498 kSourceId, stream_flags,
499 is_audio_encrypted, is_video_encrypted);
500 return true;
503 bool InitDemuxerAudioAndVideoSourcesText(const std::string& audio_id,
504 const std::string& video_id,
505 bool has_text) {
506 EXPECT_CALL(*this, DemuxerOpened());
507 demuxer_->Initialize(
508 &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true);
510 if (AddId(audio_id, HAS_AUDIO) != ChunkDemuxer::kOk)
511 return false;
512 if (AddId(video_id, HAS_VIDEO) != ChunkDemuxer::kOk)
513 return false;
515 int audio_flags = HAS_AUDIO;
516 int video_flags = HAS_VIDEO;
518 if (has_text) {
519 audio_flags |= HAS_TEXT;
520 video_flags |= HAS_TEXT;
523 AppendInitSegmentWithSourceId(audio_id, audio_flags);
524 AppendInitSegmentWithSourceId(video_id, video_flags);
525 return true;
528 bool InitDemuxerAudioAndVideoSources(const std::string& audio_id,
529 const std::string& video_id) {
530 return InitDemuxerAudioAndVideoSourcesText(audio_id, video_id, false);
533 // Initializes the demuxer with data from 2 files with different
534 // decoder configurations. This is used to test the decoder config change
535 // logic.
537 // bear-320x240.webm VideoDecoderConfig returns 320x240 for its natural_size()
538 // bear-640x360.webm VideoDecoderConfig returns 640x360 for its natural_size()
539 // The resulting video stream returns data from each file for the following
540 // time ranges.
541 // bear-320x240.webm : [0-501) [801-2737)
542 // bear-640x360.webm : [527-793)
544 // bear-320x240.webm AudioDecoderConfig returns 3863 for its extra_data_size()
545 // bear-640x360.webm AudioDecoderConfig returns 3935 for its extra_data_size()
546 // The resulting audio stream returns data from each file for the following
547 // time ranges.
548 // bear-320x240.webm : [0-524) [779-2737)
549 // bear-640x360.webm : [527-759)
550 bool InitDemuxerWithConfigChangeData() {
551 scoped_refptr<DecoderBuffer> bear1 = ReadTestDataFile("bear-320x240.webm");
552 scoped_refptr<DecoderBuffer> bear2 = ReadTestDataFile("bear-640x360.webm");
554 EXPECT_CALL(*this, DemuxerOpened());
555 demuxer_->Initialize(
556 &host_, CreateInitDoneCB(base::TimeDelta::FromMilliseconds(2744),
557 PIPELINE_OK), true);
559 if (AddId(kSourceId, HAS_AUDIO | HAS_VIDEO) != ChunkDemuxer::kOk)
560 return false;
562 // Append the whole bear1 file.
563 AppendData(bear1->data(), bear1->data_size());
564 CheckExpectedRanges(kSourceId, "{ [0,2737) }");
566 // Append initialization segment for bear2.
567 // Note: Offsets here and below are derived from
568 // media/test/data/bear-640x360-manifest.js and
569 // media/test/data/bear-320x240-manifest.js which were
570 // generated from media/test/data/bear-640x360.webm and
571 // media/test/data/bear-320x240.webm respectively.
572 AppendData(bear2->data(), 4340);
574 // Append a media segment that goes from [0.527000, 1.014000).
575 AppendData(bear2->data() + 55290, 18785);
576 CheckExpectedRanges(kSourceId, "{ [0,1028) [1201,2737) }");
578 // Append initialization segment for bear1 & fill gap with [779-1197)
579 // segment.
580 AppendData(bear1->data(), 4370);
581 AppendData(bear1->data() + 72737, 28183);
582 CheckExpectedRanges(kSourceId, "{ [0,2737) }");
584 MarkEndOfStream(PIPELINE_OK);
585 return true;
588 void ShutdownDemuxer() {
589 if (demuxer_) {
590 demuxer_->Shutdown();
591 message_loop_.RunUntilIdle();
595 void AddSimpleBlock(ClusterBuilder* cb, int track_num, int64 timecode) {
596 uint8 data[] = { 0x00 };
597 cb->AddSimpleBlock(track_num, timecode, 0, data, sizeof(data));
600 scoped_ptr<Cluster> GenerateCluster(int timecode, int block_count) {
601 return GenerateCluster(timecode, timecode, block_count);
604 void AddVideoBlockGroup(ClusterBuilder* cb, int track_num, int64 timecode,
605 int duration, int flags) {
606 const uint8* data =
607 (flags & kWebMFlagKeyframe) != 0 ? kVP8Keyframe : kVP8Interframe;
608 int size = (flags & kWebMFlagKeyframe) != 0 ? sizeof(kVP8Keyframe) :
609 sizeof(kVP8Interframe);
610 cb->AddBlockGroup(track_num, timecode, duration, flags, data, size);
613 scoped_ptr<Cluster> GenerateCluster(int first_audio_timecode,
614 int first_video_timecode,
615 int block_count) {
616 CHECK_GT(block_count, 0);
618 int size = 10;
619 scoped_ptr<uint8[]> data(new uint8[size]);
621 ClusterBuilder cb;
622 cb.SetClusterTimecode(std::min(first_audio_timecode, first_video_timecode));
624 if (block_count == 1) {
625 cb.AddBlockGroup(kAudioTrackNum, first_audio_timecode,
626 kAudioBlockDuration, kWebMFlagKeyframe,
627 data.get(), size);
628 return cb.Finish();
631 int audio_timecode = first_audio_timecode;
632 int video_timecode = first_video_timecode;
634 // Create simple blocks for everything except the last 2 blocks.
635 // The first video frame must be a keyframe.
636 uint8 video_flag = kWebMFlagKeyframe;
637 for (int i = 0; i < block_count - 2; i++) {
638 if (audio_timecode <= video_timecode) {
639 cb.AddSimpleBlock(kAudioTrackNum, audio_timecode, kWebMFlagKeyframe,
640 data.get(), size);
641 audio_timecode += kAudioBlockDuration;
642 continue;
645 cb.AddSimpleBlock(kVideoTrackNum, video_timecode, video_flag, data.get(),
646 size);
647 video_timecode += kVideoBlockDuration;
648 video_flag = 0;
651 // Make the last 2 blocks BlockGroups so that they don't get delayed by the
652 // block duration calculation logic.
653 if (audio_timecode <= video_timecode) {
654 cb.AddBlockGroup(kAudioTrackNum, audio_timecode, kAudioBlockDuration,
655 kWebMFlagKeyframe, data.get(), size);
656 AddVideoBlockGroup(&cb, kVideoTrackNum, video_timecode,
657 kVideoBlockDuration, video_flag);
658 } else {
659 AddVideoBlockGroup(&cb, kVideoTrackNum, video_timecode,
660 kVideoBlockDuration, video_flag);
661 cb.AddBlockGroup(kAudioTrackNum, audio_timecode, kAudioBlockDuration,
662 kWebMFlagKeyframe, data.get(), size);
665 return cb.Finish();
668 scoped_ptr<Cluster> GenerateSingleStreamCluster(int timecode,
669 int end_timecode,
670 int track_number,
671 int block_duration) {
672 CHECK_GT(end_timecode, timecode);
674 std::vector<uint8> data(kBlockSize);
676 ClusterBuilder cb;
677 cb.SetClusterTimecode(timecode);
679 // Create simple blocks for everything except the last block.
680 for (int i = 0; timecode < (end_timecode - block_duration); i++) {
681 cb.AddSimpleBlock(track_number, timecode, kWebMFlagKeyframe,
682 &data[0], data.size());
683 timecode += block_duration;
686 // Make the last block a BlockGroup so that it doesn't get delayed by the
687 // block duration calculation logic.
688 if (track_number == kVideoTrackNum) {
689 AddVideoBlockGroup(&cb, track_number, timecode, block_duration,
690 kWebMFlagKeyframe);
691 } else {
692 cb.AddBlockGroup(track_number, timecode, block_duration,
693 kWebMFlagKeyframe, &data[0], data.size());
695 return cb.Finish();
698 void Read(DemuxerStream::Type type, const DemuxerStream::ReadCB& read_cb) {
699 demuxer_->GetStream(type)->Read(read_cb);
700 message_loop_.RunUntilIdle();
703 void ReadAudio(const DemuxerStream::ReadCB& read_cb) {
704 Read(DemuxerStream::AUDIO, read_cb);
707 void ReadVideo(const DemuxerStream::ReadCB& read_cb) {
708 Read(DemuxerStream::VIDEO, read_cb);
711 void GenerateExpectedReads(int timecode, int block_count) {
712 GenerateExpectedReads(timecode, timecode, block_count);
715 void GenerateExpectedReads(int start_audio_timecode,
716 int start_video_timecode,
717 int block_count) {
718 CHECK_GT(block_count, 0);
720 if (block_count == 1) {
721 ExpectRead(DemuxerStream::AUDIO, start_audio_timecode);
722 return;
725 int audio_timecode = start_audio_timecode;
726 int video_timecode = start_video_timecode;
728 for (int i = 0; i < block_count; i++) {
729 if (audio_timecode <= video_timecode) {
730 ExpectRead(DemuxerStream::AUDIO, audio_timecode);
731 audio_timecode += kAudioBlockDuration;
732 continue;
735 ExpectRead(DemuxerStream::VIDEO, video_timecode);
736 video_timecode += kVideoBlockDuration;
740 void GenerateSingleStreamExpectedReads(int timecode,
741 int block_count,
742 DemuxerStream::Type type,
743 int block_duration) {
744 CHECK_GT(block_count, 0);
745 int stream_timecode = timecode;
747 for (int i = 0; i < block_count; i++) {
748 ExpectRead(type, stream_timecode);
749 stream_timecode += block_duration;
753 void GenerateAudioStreamExpectedReads(int timecode, int block_count) {
754 GenerateSingleStreamExpectedReads(
755 timecode, block_count, DemuxerStream::AUDIO, kAudioBlockDuration);
758 void GenerateVideoStreamExpectedReads(int timecode, int block_count) {
759 GenerateSingleStreamExpectedReads(
760 timecode, block_count, DemuxerStream::VIDEO, kVideoBlockDuration);
763 scoped_ptr<Cluster> GenerateEmptyCluster(int timecode) {
764 ClusterBuilder cb;
765 cb.SetClusterTimecode(timecode);
766 return cb.Finish();
769 void CheckExpectedRanges(const std::string& expected) {
770 CheckExpectedRanges(kSourceId, expected);
773 void CheckExpectedRanges(const std::string& id,
774 const std::string& expected) {
775 Ranges<base::TimeDelta> r = demuxer_->GetBufferedRanges(id);
777 std::stringstream ss;
778 ss << "{ ";
779 for (size_t i = 0; i < r.size(); ++i) {
780 ss << "[" << r.start(i).InMilliseconds() << ","
781 << r.end(i).InMilliseconds() << ") ";
783 ss << "}";
784 EXPECT_EQ(expected, ss.str());
787 MOCK_METHOD2(ReadDone, void(DemuxerStream::Status status,
788 const scoped_refptr<DecoderBuffer>&));
790 void StoreStatusAndBuffer(DemuxerStream::Status* status_out,
791 scoped_refptr<DecoderBuffer>* buffer_out,
792 DemuxerStream::Status status,
793 const scoped_refptr<DecoderBuffer>& buffer) {
794 *status_out = status;
795 *buffer_out = buffer;
798 void ReadUntilNotOkOrEndOfStream(DemuxerStream::Type type,
799 DemuxerStream::Status* status,
800 base::TimeDelta* last_timestamp) {
801 DemuxerStream* stream = demuxer_->GetStream(type);
802 scoped_refptr<DecoderBuffer> buffer;
804 *last_timestamp = kNoTimestamp();
805 do {
806 stream->Read(base::Bind(&ChunkDemuxerTest::StoreStatusAndBuffer,
807 base::Unretained(this), status, &buffer));
808 base::MessageLoop::current()->RunUntilIdle();
809 if (*status == DemuxerStream::kOk && !buffer->end_of_stream())
810 *last_timestamp = buffer->timestamp();
811 } while (*status == DemuxerStream::kOk && !buffer->end_of_stream());
814 void ExpectEndOfStream(DemuxerStream::Type type) {
815 EXPECT_CALL(*this, ReadDone(DemuxerStream::kOk, IsEndOfStream()));
816 demuxer_->GetStream(type)->Read(base::Bind(
817 &ChunkDemuxerTest::ReadDone, base::Unretained(this)));
818 message_loop_.RunUntilIdle();
821 void ExpectRead(DemuxerStream::Type type, int64 timestamp_in_ms) {
822 EXPECT_CALL(*this, ReadDone(DemuxerStream::kOk,
823 HasTimestamp(timestamp_in_ms)));
824 demuxer_->GetStream(type)->Read(base::Bind(
825 &ChunkDemuxerTest::ReadDone, base::Unretained(this)));
826 message_loop_.RunUntilIdle();
829 void ExpectConfigChanged(DemuxerStream::Type type) {
830 EXPECT_CALL(*this, ReadDone(DemuxerStream::kConfigChanged, _));
831 demuxer_->GetStream(type)->Read(base::Bind(
832 &ChunkDemuxerTest::ReadDone, base::Unretained(this)));
833 message_loop_.RunUntilIdle();
836 void CheckExpectedBuffers(DemuxerStream* stream,
837 const std::string& expected) {
838 std::vector<std::string> timestamps;
839 base::SplitString(expected, ' ', &timestamps);
840 std::stringstream ss;
841 for (size_t i = 0; i < timestamps.size(); ++i) {
842 DemuxerStream::Status status;
843 scoped_refptr<DecoderBuffer> buffer;
844 stream->Read(base::Bind(&ChunkDemuxerTest::StoreStatusAndBuffer,
845 base::Unretained(this), &status, &buffer));
846 base::MessageLoop::current()->RunUntilIdle();
847 if (status != DemuxerStream::kOk || buffer->end_of_stream())
848 break;
850 if (i > 0)
851 ss << " ";
852 ss << buffer->timestamp().InMilliseconds();
854 EXPECT_EQ(expected, ss.str());
857 MOCK_METHOD1(Checkpoint, void(int id));
859 struct BufferTimestamps {
860 int video_time_ms;
861 int audio_time_ms;
863 static const int kSkip = -1;
865 // Test parsing a WebM file.
866 // |filename| - The name of the file in media/test/data to parse.
867 // |timestamps| - The expected timestamps on the parsed buffers.
868 // a timestamp of kSkip indicates that a Read() call for that stream
869 // shouldn't be made on that iteration of the loop. If both streams have
870 // a kSkip then the loop will terminate.
871 bool ParseWebMFile(const std::string& filename,
872 const BufferTimestamps* timestamps,
873 const base::TimeDelta& duration) {
874 return ParseWebMFile(filename, timestamps, duration, HAS_AUDIO | HAS_VIDEO);
877 bool ParseWebMFile(const std::string& filename,
878 const BufferTimestamps* timestamps,
879 const base::TimeDelta& duration,
880 int stream_flags) {
881 EXPECT_CALL(*this, DemuxerOpened());
882 demuxer_->Initialize(
883 &host_, CreateInitDoneCB(duration, PIPELINE_OK), true);
885 if (AddId(kSourceId, stream_flags) != ChunkDemuxer::kOk)
886 return false;
888 // Read a WebM file into memory and send the data to the demuxer.
889 scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(filename);
890 AppendDataInPieces(buffer->data(), buffer->data_size(), 512);
892 // Verify that the timestamps on the first few packets match what we
893 // expect.
894 for (size_t i = 0;
895 (timestamps[i].audio_time_ms != kSkip ||
896 timestamps[i].video_time_ms != kSkip);
897 i++) {
898 bool audio_read_done = false;
899 bool video_read_done = false;
901 if (timestamps[i].audio_time_ms != kSkip) {
902 ReadAudio(base::Bind(&OnReadDone,
903 base::TimeDelta::FromMilliseconds(
904 timestamps[i].audio_time_ms),
905 &audio_read_done));
906 EXPECT_TRUE(audio_read_done);
909 if (timestamps[i].video_time_ms != kSkip) {
910 ReadVideo(base::Bind(&OnReadDone,
911 base::TimeDelta::FromMilliseconds(
912 timestamps[i].video_time_ms),
913 &video_read_done));
914 EXPECT_TRUE(video_read_done);
918 return true;
921 MOCK_METHOD0(DemuxerOpened, void());
922 // TODO(xhwang): This is a workaround of the issue that move-only parameters
923 // are not supported in mocked methods. Remove this when the issue is fixed
924 // (http://code.google.com/p/googletest/issues/detail?id=395) or when we use
925 // std::string instead of scoped_ptr<uint8[]> (http://crbug.com/130689).
926 MOCK_METHOD3(NeedKeyMock, void(const std::string& type,
927 const uint8* init_data, int init_data_size));
928 void DemuxerNeedKey(const std::string& type,
929 const std::vector<uint8>& init_data) {
930 const uint8* init_data_ptr = init_data.empty() ? NULL : &init_data[0];
931 NeedKeyMock(type, init_data_ptr, init_data.size());
934 void Seek(base::TimeDelta seek_time) {
935 demuxer_->StartWaitingForSeek(seek_time);
936 demuxer_->Seek(seek_time, NewExpectedStatusCB(PIPELINE_OK));
937 message_loop_.RunUntilIdle();
940 void MarkEndOfStream(PipelineStatus status) {
941 demuxer_->MarkEndOfStream(status);
942 message_loop_.RunUntilIdle();
945 base::MessageLoop message_loop_;
946 MockDemuxerHost host_;
948 scoped_ptr<ChunkDemuxer> demuxer_;
950 private:
951 DISALLOW_COPY_AND_ASSIGN(ChunkDemuxerTest);
954 TEST_F(ChunkDemuxerTest, Init) {
955 // Test no streams, audio-only, video-only, and audio & video scenarios.
956 // Audio and video streams can be encrypted or not encrypted.
957 for (int i = 0; i < 16; i++) {
958 bool has_audio = (i & 0x1) != 0;
959 bool has_video = (i & 0x2) != 0;
960 bool is_audio_encrypted = (i & 0x4) != 0;
961 bool is_video_encrypted = (i & 0x8) != 0;
963 // No test on invalid combination.
964 if ((!has_audio && is_audio_encrypted) ||
965 (!has_video && is_video_encrypted)) {
966 continue;
969 CreateNewDemuxer();
971 if (is_audio_encrypted || is_video_encrypted) {
972 int need_key_count = (is_audio_encrypted ? 1 : 0) +
973 (is_video_encrypted ? 1 : 0);
974 EXPECT_CALL(*this, NeedKeyMock(kWebMEncryptInitDataType, NotNull(),
975 DecryptConfig::kDecryptionKeySize))
976 .Times(Exactly(need_key_count));
979 int stream_flags = 0;
980 if (has_audio)
981 stream_flags |= HAS_AUDIO;
983 if (has_video)
984 stream_flags |= HAS_VIDEO;
986 ASSERT_TRUE(InitDemuxerWithEncryptionInfo(
987 stream_flags, is_audio_encrypted, is_video_encrypted));
989 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO);
990 if (has_audio) {
991 ASSERT_TRUE(audio_stream);
993 const AudioDecoderConfig& config = audio_stream->audio_decoder_config();
994 EXPECT_EQ(kCodecVorbis, config.codec());
995 EXPECT_EQ(32, config.bits_per_channel());
996 EXPECT_EQ(CHANNEL_LAYOUT_STEREO, config.channel_layout());
997 EXPECT_EQ(44100, config.samples_per_second());
998 EXPECT_TRUE(config.extra_data());
999 EXPECT_GT(config.extra_data_size(), 0u);
1000 EXPECT_EQ(kSampleFormatPlanarF32, config.sample_format());
1001 EXPECT_EQ(is_audio_encrypted,
1002 audio_stream->audio_decoder_config().is_encrypted());
1003 } else {
1004 EXPECT_FALSE(audio_stream);
1007 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO);
1008 if (has_video) {
1009 EXPECT_TRUE(video_stream);
1010 EXPECT_EQ(is_video_encrypted,
1011 video_stream->video_decoder_config().is_encrypted());
1012 } else {
1013 EXPECT_FALSE(video_stream);
1016 ShutdownDemuxer();
1017 demuxer_.reset();
1021 // TODO(acolwell): Fold this test into Init tests since the tests are
1022 // almost identical.
1023 TEST_F(ChunkDemuxerTest, InitText) {
1024 // Test with 1 video stream and 1 text streams, and 0 or 1 audio streams.
1025 // No encryption cases handled here.
1026 bool has_video = true;
1027 bool is_audio_encrypted = false;
1028 bool is_video_encrypted = false;
1029 for (int i = 0; i < 2; i++) {
1030 bool has_audio = (i & 0x1) != 0;
1032 CreateNewDemuxer();
1034 DemuxerStream* text_stream = NULL;
1035 TextTrackConfig text_config;
1036 EXPECT_CALL(host_, AddTextStream(_, _))
1037 .WillOnce(DoAll(SaveArg<0>(&text_stream),
1038 SaveArg<1>(&text_config)));
1040 int stream_flags = HAS_TEXT;
1041 if (has_audio)
1042 stream_flags |= HAS_AUDIO;
1044 if (has_video)
1045 stream_flags |= HAS_VIDEO;
1047 ASSERT_TRUE(InitDemuxerWithEncryptionInfo(
1048 stream_flags, is_audio_encrypted, is_video_encrypted));
1049 ASSERT_TRUE(text_stream);
1050 EXPECT_EQ(DemuxerStream::TEXT, text_stream->type());
1051 EXPECT_EQ(kTextSubtitles, text_config.kind());
1053 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO);
1054 if (has_audio) {
1055 ASSERT_TRUE(audio_stream);
1057 const AudioDecoderConfig& config = audio_stream->audio_decoder_config();
1058 EXPECT_EQ(kCodecVorbis, config.codec());
1059 EXPECT_EQ(32, config.bits_per_channel());
1060 EXPECT_EQ(CHANNEL_LAYOUT_STEREO, config.channel_layout());
1061 EXPECT_EQ(44100, config.samples_per_second());
1062 EXPECT_TRUE(config.extra_data());
1063 EXPECT_GT(config.extra_data_size(), 0u);
1064 EXPECT_EQ(kSampleFormatPlanarF32, config.sample_format());
1065 EXPECT_EQ(is_audio_encrypted,
1066 audio_stream->audio_decoder_config().is_encrypted());
1067 } else {
1068 EXPECT_FALSE(audio_stream);
1071 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO);
1072 if (has_video) {
1073 EXPECT_TRUE(video_stream);
1074 EXPECT_EQ(is_video_encrypted,
1075 video_stream->video_decoder_config().is_encrypted());
1076 } else {
1077 EXPECT_FALSE(video_stream);
1080 ShutdownDemuxer();
1081 demuxer_.reset();
1085 // Make sure that the demuxer reports an error if Shutdown()
1086 // is called before all the initialization segments are appended.
1087 TEST_F(ChunkDemuxerTest, Shutdown_BeforeAllInitSegmentsAppended) {
1088 EXPECT_CALL(*this, DemuxerOpened());
1089 demuxer_->Initialize(
1090 &host_, CreateInitDoneCB(
1091 kDefaultDuration(), DEMUXER_ERROR_COULD_NOT_OPEN), true);
1093 EXPECT_EQ(AddId("audio", HAS_AUDIO), ChunkDemuxer::kOk);
1094 EXPECT_EQ(AddId("video", HAS_VIDEO), ChunkDemuxer::kOk);
1096 AppendInitSegmentWithSourceId("audio", HAS_AUDIO);
1098 ShutdownDemuxer();
1101 TEST_F(ChunkDemuxerTest, Shutdown_BeforeAllInitSegmentsAppendedText) {
1102 EXPECT_CALL(*this, DemuxerOpened());
1103 demuxer_->Initialize(
1104 &host_, CreateInitDoneCB(
1105 kDefaultDuration(), DEMUXER_ERROR_COULD_NOT_OPEN), true);
1107 EXPECT_EQ(AddId("audio", HAS_AUDIO), ChunkDemuxer::kOk);
1108 EXPECT_EQ(AddId("video_and_text", HAS_VIDEO), ChunkDemuxer::kOk);
1110 EXPECT_CALL(host_, AddTextStream(_, _))
1111 .Times(Exactly(1));
1113 AppendInitSegmentWithSourceId("video_and_text", HAS_VIDEO | HAS_TEXT);
1115 ShutdownDemuxer();
1118 // Verifies that all streams waiting for data receive an end of stream
1119 // buffer when Shutdown() is called.
1120 TEST_F(ChunkDemuxerTest, Shutdown_EndOfStreamWhileWaitingForData) {
1121 DemuxerStream* text_stream = NULL;
1122 EXPECT_CALL(host_, AddTextStream(_, _))
1123 .WillOnce(SaveArg<0>(&text_stream));
1124 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO | HAS_TEXT));
1126 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO);
1127 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO);
1129 bool audio_read_done = false;
1130 bool video_read_done = false;
1131 bool text_read_done = false;
1132 audio_stream->Read(base::Bind(&OnReadDone_EOSExpected, &audio_read_done));
1133 video_stream->Read(base::Bind(&OnReadDone_EOSExpected, &video_read_done));
1134 text_stream->Read(base::Bind(&OnReadDone_EOSExpected, &text_read_done));
1135 message_loop_.RunUntilIdle();
1137 EXPECT_FALSE(audio_read_done);
1138 EXPECT_FALSE(video_read_done);
1139 EXPECT_FALSE(text_read_done);
1141 ShutdownDemuxer();
1143 EXPECT_TRUE(audio_read_done);
1144 EXPECT_TRUE(video_read_done);
1145 EXPECT_TRUE(text_read_done);
1148 // Test that Seek() completes successfully when the first cluster
1149 // arrives.
1150 TEST_F(ChunkDemuxerTest, AppendDataAfterSeek) {
1151 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1152 AppendCluster(kDefaultFirstCluster());
1154 InSequence s;
1156 EXPECT_CALL(*this, Checkpoint(1));
1158 Seek(base::TimeDelta::FromMilliseconds(46));
1160 EXPECT_CALL(*this, Checkpoint(2));
1162 Checkpoint(1);
1164 AppendCluster(kDefaultSecondCluster());
1166 message_loop_.RunUntilIdle();
1168 Checkpoint(2);
1171 // Test that parsing errors are handled for clusters appended after init.
1172 TEST_F(ChunkDemuxerTest, ErrorWhileParsingClusterAfterInit) {
1173 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1174 AppendCluster(kDefaultFirstCluster());
1176 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE));
1177 AppendGarbage();
1180 // Test the case where a Seek() is requested while the parser
1181 // is in the middle of cluster. This is to verify that the parser
1182 // does not reset itself on a seek.
1183 TEST_F(ChunkDemuxerTest, SeekWhileParsingCluster) {
1184 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1186 InSequence s;
1188 scoped_ptr<Cluster> cluster_a(GenerateCluster(0, 6));
1190 // Split the cluster into two appends at an arbitrary point near the end.
1191 int first_append_size = cluster_a->size() - 11;
1192 int second_append_size = cluster_a->size() - first_append_size;
1194 // Append the first part of the cluster.
1195 AppendData(cluster_a->data(), first_append_size);
1197 ExpectRead(DemuxerStream::AUDIO, 0);
1198 ExpectRead(DemuxerStream::VIDEO, 0);
1199 ExpectRead(DemuxerStream::AUDIO, kAudioBlockDuration);
1200 // Note: We skip trying to read a video buffer here because computing
1201 // the duration for this block relies on successfully parsing the last block
1202 // in the cluster the cluster.
1203 ExpectRead(DemuxerStream::AUDIO, 2 * kAudioBlockDuration);
1205 Seek(base::TimeDelta::FromSeconds(5));
1207 // Append the rest of the cluster.
1208 AppendData(cluster_a->data() + first_append_size, second_append_size);
1210 // Append the new cluster and verify that only the blocks
1211 // in the new cluster are returned.
1212 AppendCluster(GenerateCluster(5000, 6));
1213 GenerateExpectedReads(5000, 6);
1216 // Test the case where AppendData() is called before Init().
1217 TEST_F(ChunkDemuxerTest, AppendDataBeforeInit) {
1218 scoped_ptr<uint8[]> info_tracks;
1219 int info_tracks_size = 0;
1220 CreateInitSegment(HAS_AUDIO | HAS_VIDEO,
1221 false, false, &info_tracks, &info_tracks_size);
1222 demuxer_->AppendData(kSourceId, info_tracks.get(), info_tracks_size, NULL);
1225 // Make sure Read() callbacks are dispatched with the proper data.
1226 TEST_F(ChunkDemuxerTest, Read) {
1227 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1229 AppendCluster(kDefaultFirstCluster());
1231 bool audio_read_done = false;
1232 bool video_read_done = false;
1233 ReadAudio(base::Bind(&OnReadDone,
1234 base::TimeDelta::FromMilliseconds(0),
1235 &audio_read_done));
1236 ReadVideo(base::Bind(&OnReadDone,
1237 base::TimeDelta::FromMilliseconds(0),
1238 &video_read_done));
1240 EXPECT_TRUE(audio_read_done);
1241 EXPECT_TRUE(video_read_done);
1244 TEST_F(ChunkDemuxerTest, OutOfOrderClusters) {
1245 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1246 AppendCluster(kDefaultFirstCluster());
1247 AppendCluster(GenerateCluster(10, 4));
1249 // Make sure that AppendCluster() does not fail with a cluster that has
1250 // overlaps with the previously appended cluster.
1251 AppendCluster(GenerateCluster(5, 4));
1253 // Verify that AppendData() can still accept more data.
1254 scoped_ptr<Cluster> cluster_c(GenerateCluster(45, 2));
1255 demuxer_->AppendData(kSourceId, cluster_c->data(), cluster_c->size(), NULL);
1258 TEST_F(ChunkDemuxerTest, NonMonotonicButAboveClusterTimecode) {
1259 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1260 AppendCluster(kDefaultFirstCluster());
1262 ClusterBuilder cb;
1264 // Test the case where block timecodes are not monotonically
1265 // increasing but stay above the cluster timecode.
1266 cb.SetClusterTimecode(5);
1267 AddSimpleBlock(&cb, kAudioTrackNum, 5);
1268 AddSimpleBlock(&cb, kVideoTrackNum, 10);
1269 AddSimpleBlock(&cb, kAudioTrackNum, 7);
1270 AddSimpleBlock(&cb, kVideoTrackNum, 15);
1272 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE));
1273 AppendCluster(cb.Finish());
1275 // Verify that AppendData() ignores data after the error.
1276 scoped_ptr<Cluster> cluster_b(GenerateCluster(20, 2));
1277 demuxer_->AppendData(kSourceId, cluster_b->data(), cluster_b->size(), NULL);
1280 TEST_F(ChunkDemuxerTest, BackwardsAndBeforeClusterTimecode) {
1281 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1282 AppendCluster(kDefaultFirstCluster());
1284 ClusterBuilder cb;
1286 // Test timecodes going backwards and including values less than the cluster
1287 // timecode.
1288 cb.SetClusterTimecode(5);
1289 AddSimpleBlock(&cb, kAudioTrackNum, 5);
1290 AddSimpleBlock(&cb, kVideoTrackNum, 5);
1291 AddSimpleBlock(&cb, kAudioTrackNum, 3);
1292 AddSimpleBlock(&cb, kVideoTrackNum, 3);
1294 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE));
1295 AppendCluster(cb.Finish());
1297 // Verify that AppendData() ignores data after the error.
1298 scoped_ptr<Cluster> cluster_b(GenerateCluster(6, 2));
1299 demuxer_->AppendData(kSourceId, cluster_b->data(), cluster_b->size(), NULL);
1303 TEST_F(ChunkDemuxerTest, PerStreamMonotonicallyIncreasingTimestamps) {
1304 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1305 AppendCluster(kDefaultFirstCluster());
1307 ClusterBuilder cb;
1309 // Test monotonic increasing timestamps on a per stream
1310 // basis.
1311 cb.SetClusterTimecode(5);
1312 AddSimpleBlock(&cb, kAudioTrackNum, 5);
1313 AddSimpleBlock(&cb, kVideoTrackNum, 5);
1314 AddSimpleBlock(&cb, kAudioTrackNum, 4);
1315 AddSimpleBlock(&cb, kVideoTrackNum, 7);
1317 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE));
1318 AppendCluster(cb.Finish());
1321 // Test the case where a cluster is passed to AppendCluster() before
1322 // INFO & TRACKS data.
1323 TEST_F(ChunkDemuxerTest, ClusterBeforeInitSegment) {
1324 EXPECT_CALL(*this, DemuxerOpened());
1325 demuxer_->Initialize(
1326 &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN), true);
1328 ASSERT_EQ(AddId(), ChunkDemuxer::kOk);
1330 AppendCluster(GenerateCluster(0, 1));
1333 // Test cases where we get an MarkEndOfStream() call during initialization.
1334 TEST_F(ChunkDemuxerTest, EOSDuringInit) {
1335 EXPECT_CALL(*this, DemuxerOpened());
1336 demuxer_->Initialize(
1337 &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN), true);
1338 MarkEndOfStream(PIPELINE_OK);
1341 TEST_F(ChunkDemuxerTest, EndOfStreamWithNoAppend) {
1342 EXPECT_CALL(*this, DemuxerOpened());
1343 demuxer_->Initialize(
1344 &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN), true);
1346 ASSERT_EQ(AddId(), ChunkDemuxer::kOk);
1348 CheckExpectedRanges("{ }");
1349 MarkEndOfStream(PIPELINE_OK);
1350 ShutdownDemuxer();
1351 CheckExpectedRanges("{ }");
1352 demuxer_->RemoveId(kSourceId);
1353 demuxer_.reset();
1356 TEST_F(ChunkDemuxerTest, EndOfStreamWithNoMediaAppend) {
1357 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1359 CheckExpectedRanges("{ }");
1360 MarkEndOfStream(PIPELINE_OK);
1361 CheckExpectedRanges("{ }");
1364 TEST_F(ChunkDemuxerTest, DecodeErrorEndOfStream) {
1365 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1367 AppendCluster(kDefaultFirstCluster());
1368 CheckExpectedRanges(kDefaultFirstClusterRange);
1370 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE));
1371 MarkEndOfStream(PIPELINE_ERROR_DECODE);
1372 CheckExpectedRanges(kDefaultFirstClusterRange);
1375 TEST_F(ChunkDemuxerTest, NetworkErrorEndOfStream) {
1376 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1378 AppendCluster(kDefaultFirstCluster());
1379 CheckExpectedRanges(kDefaultFirstClusterRange);
1381 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_NETWORK));
1382 MarkEndOfStream(PIPELINE_ERROR_NETWORK);
1385 // Helper class to reduce duplicate code when testing end of stream
1386 // Read() behavior.
1387 class EndOfStreamHelper {
1388 public:
1389 explicit EndOfStreamHelper(Demuxer* demuxer)
1390 : demuxer_(demuxer),
1391 audio_read_done_(false),
1392 video_read_done_(false) {
1395 // Request a read on the audio and video streams.
1396 void RequestReads() {
1397 EXPECT_FALSE(audio_read_done_);
1398 EXPECT_FALSE(video_read_done_);
1400 DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
1401 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
1403 audio->Read(base::Bind(&OnEndOfStreamReadDone, &audio_read_done_));
1404 video->Read(base::Bind(&OnEndOfStreamReadDone, &video_read_done_));
1405 base::MessageLoop::current()->RunUntilIdle();
1408 // Check to see if |audio_read_done_| and |video_read_done_| variables
1409 // match |expected|.
1410 void CheckIfReadDonesWereCalled(bool expected) {
1411 base::MessageLoop::current()->RunUntilIdle();
1412 EXPECT_EQ(expected, audio_read_done_);
1413 EXPECT_EQ(expected, video_read_done_);
1416 private:
1417 static void OnEndOfStreamReadDone(
1418 bool* called,
1419 DemuxerStream::Status status,
1420 const scoped_refptr<DecoderBuffer>& buffer) {
1421 EXPECT_EQ(status, DemuxerStream::kOk);
1422 EXPECT_TRUE(buffer->end_of_stream());
1423 *called = true;
1426 Demuxer* demuxer_;
1427 bool audio_read_done_;
1428 bool video_read_done_;
1430 DISALLOW_COPY_AND_ASSIGN(EndOfStreamHelper);
1433 // Make sure that all pending reads that we don't have media data for get an
1434 // "end of stream" buffer when MarkEndOfStream() is called.
1435 TEST_F(ChunkDemuxerTest, EndOfStreamWithPendingReads) {
1436 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1438 AppendCluster(GenerateCluster(0, 2));
1440 bool audio_read_done_1 = false;
1441 bool video_read_done_1 = false;
1442 EndOfStreamHelper end_of_stream_helper_1(demuxer_.get());
1443 EndOfStreamHelper end_of_stream_helper_2(demuxer_.get());
1445 ReadAudio(base::Bind(&OnReadDone,
1446 base::TimeDelta::FromMilliseconds(0),
1447 &audio_read_done_1));
1448 ReadVideo(base::Bind(&OnReadDone,
1449 base::TimeDelta::FromMilliseconds(0),
1450 &video_read_done_1));
1451 message_loop_.RunUntilIdle();
1453 EXPECT_TRUE(audio_read_done_1);
1454 EXPECT_TRUE(video_read_done_1);
1456 end_of_stream_helper_1.RequestReads();
1458 EXPECT_CALL(host_, SetDuration(
1459 base::TimeDelta::FromMilliseconds(kVideoBlockDuration)));
1460 MarkEndOfStream(PIPELINE_OK);
1462 end_of_stream_helper_1.CheckIfReadDonesWereCalled(true);
1464 end_of_stream_helper_2.RequestReads();
1465 end_of_stream_helper_2.CheckIfReadDonesWereCalled(true);
1468 // Make sure that all Read() calls after we get an MarkEndOfStream()
1469 // call return an "end of stream" buffer.
1470 TEST_F(ChunkDemuxerTest, ReadsAfterEndOfStream) {
1471 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1473 AppendCluster(GenerateCluster(0, 2));
1475 bool audio_read_done_1 = false;
1476 bool video_read_done_1 = false;
1477 EndOfStreamHelper end_of_stream_helper_1(demuxer_.get());
1478 EndOfStreamHelper end_of_stream_helper_2(demuxer_.get());
1479 EndOfStreamHelper end_of_stream_helper_3(demuxer_.get());
1481 ReadAudio(base::Bind(&OnReadDone,
1482 base::TimeDelta::FromMilliseconds(0),
1483 &audio_read_done_1));
1484 ReadVideo(base::Bind(&OnReadDone,
1485 base::TimeDelta::FromMilliseconds(0),
1486 &video_read_done_1));
1488 end_of_stream_helper_1.RequestReads();
1490 EXPECT_TRUE(audio_read_done_1);
1491 EXPECT_TRUE(video_read_done_1);
1492 end_of_stream_helper_1.CheckIfReadDonesWereCalled(false);
1494 EXPECT_CALL(host_, SetDuration(
1495 base::TimeDelta::FromMilliseconds(kVideoBlockDuration)));
1496 MarkEndOfStream(PIPELINE_OK);
1498 end_of_stream_helper_1.CheckIfReadDonesWereCalled(true);
1500 // Request a few more reads and make sure we immediately get
1501 // end of stream buffers.
1502 end_of_stream_helper_2.RequestReads();
1503 end_of_stream_helper_2.CheckIfReadDonesWereCalled(true);
1505 end_of_stream_helper_3.RequestReads();
1506 end_of_stream_helper_3.CheckIfReadDonesWereCalled(true);
1509 TEST_F(ChunkDemuxerTest, EndOfStreamDuringCanceledSeek) {
1510 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1512 AppendCluster(0, 10);
1513 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(138)));
1514 MarkEndOfStream(PIPELINE_OK);
1516 // Start the first seek.
1517 Seek(base::TimeDelta::FromMilliseconds(20));
1519 // Simulate another seek being requested before the first
1520 // seek has finished prerolling.
1521 base::TimeDelta seek_time2 = base::TimeDelta::FromMilliseconds(30);
1522 demuxer_->CancelPendingSeek(seek_time2);
1524 // Finish second seek.
1525 Seek(seek_time2);
1527 DemuxerStream::Status status;
1528 base::TimeDelta last_timestamp;
1530 // Make sure audio can reach end of stream.
1531 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp);
1532 ASSERT_EQ(status, DemuxerStream::kOk);
1534 // Make sure video can reach end of stream.
1535 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp);
1536 ASSERT_EQ(status, DemuxerStream::kOk);
1539 // Verify buffered range change behavior for audio/video/text tracks.
1540 TEST_F(ChunkDemuxerTest, EndOfStreamRangeChanges) {
1541 DemuxerStream* text_stream = NULL;
1543 EXPECT_CALL(host_, AddTextStream(_, _))
1544 .WillOnce(SaveArg<0>(&text_stream));
1545 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO | HAS_TEXT));
1547 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "0K 30");
1548 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, "0K 23K");
1550 // Check expected ranges and verify that an empty text track does not
1551 // affect the expected ranges.
1552 CheckExpectedRanges(kSourceId, "{ [0,46) }");
1554 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(60)));
1555 MarkEndOfStream(PIPELINE_OK);
1557 // Check expected ranges and verify that an empty text track does not
1558 // affect the expected ranges.
1559 CheckExpectedRanges(kSourceId, "{ [0,60) }");
1561 // Unmark end of stream state and verify that the ranges return to
1562 // their pre-"end of stream" values.
1563 demuxer_->UnmarkEndOfStream();
1564 CheckExpectedRanges(kSourceId, "{ [0,46) }");
1566 // Add text track data and verify that the buffered ranges don't change
1567 // since the intersection of all the tracks doesn't change.
1568 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(200)));
1569 AppendSingleStreamCluster(kSourceId, kTextTrackNum, "0K 100K");
1570 CheckExpectedRanges(kSourceId, "{ [0,46) }");
1572 // Mark end of stream and verify that text track data is reflected in
1573 // the new range.
1574 MarkEndOfStream(PIPELINE_OK);
1575 CheckExpectedRanges(kSourceId, "{ [0,200) }");
1578 // Make sure AppendData() will accept elements that span multiple calls.
1579 TEST_F(ChunkDemuxerTest, AppendingInPieces) {
1580 EXPECT_CALL(*this, DemuxerOpened());
1581 demuxer_->Initialize(
1582 &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true);
1584 ASSERT_EQ(AddId(), ChunkDemuxer::kOk);
1586 scoped_ptr<uint8[]> info_tracks;
1587 int info_tracks_size = 0;
1588 CreateInitSegment(HAS_AUDIO | HAS_VIDEO,
1589 false, false, &info_tracks, &info_tracks_size);
1591 scoped_ptr<Cluster> cluster_a(kDefaultFirstCluster());
1592 scoped_ptr<Cluster> cluster_b(kDefaultSecondCluster());
1594 size_t buffer_size = info_tracks_size + cluster_a->size() + cluster_b->size();
1595 scoped_ptr<uint8[]> buffer(new uint8[buffer_size]);
1596 uint8* dst = buffer.get();
1597 memcpy(dst, info_tracks.get(), info_tracks_size);
1598 dst += info_tracks_size;
1600 memcpy(dst, cluster_a->data(), cluster_a->size());
1601 dst += cluster_a->size();
1603 memcpy(dst, cluster_b->data(), cluster_b->size());
1604 dst += cluster_b->size();
1606 AppendDataInPieces(buffer.get(), buffer_size);
1608 GenerateExpectedReads(0, 9);
1611 TEST_F(ChunkDemuxerTest, WebMFile_AudioAndVideo) {
1612 struct BufferTimestamps buffer_timestamps[] = {
1613 {0, 0},
1614 {33, 3},
1615 {67, 6},
1616 {100, 9},
1617 {133, 12},
1618 {kSkip, kSkip},
1621 ASSERT_TRUE(ParseWebMFile("bear-320x240.webm", buffer_timestamps,
1622 base::TimeDelta::FromMilliseconds(2744)));
1625 TEST_F(ChunkDemuxerTest, WebMFile_LiveAudioAndVideo) {
1626 struct BufferTimestamps buffer_timestamps[] = {
1627 {0, 0},
1628 {33, 3},
1629 {67, 6},
1630 {100, 9},
1631 {133, 12},
1632 {kSkip, kSkip},
1635 ASSERT_TRUE(ParseWebMFile("bear-320x240-live.webm", buffer_timestamps,
1636 kInfiniteDuration()));
1639 TEST_F(ChunkDemuxerTest, WebMFile_AudioOnly) {
1640 struct BufferTimestamps buffer_timestamps[] = {
1641 {kSkip, 0},
1642 {kSkip, 3},
1643 {kSkip, 6},
1644 {kSkip, 9},
1645 {kSkip, 12},
1646 {kSkip, kSkip},
1649 ASSERT_TRUE(ParseWebMFile("bear-320x240-audio-only.webm", buffer_timestamps,
1650 base::TimeDelta::FromMilliseconds(2744),
1651 HAS_AUDIO));
1654 TEST_F(ChunkDemuxerTest, WebMFile_VideoOnly) {
1655 struct BufferTimestamps buffer_timestamps[] = {
1656 {0, kSkip},
1657 {33, kSkip},
1658 {67, kSkip},
1659 {100, kSkip},
1660 {133, kSkip},
1661 {kSkip, kSkip},
1664 ASSERT_TRUE(ParseWebMFile("bear-320x240-video-only.webm", buffer_timestamps,
1665 base::TimeDelta::FromMilliseconds(2703),
1666 HAS_VIDEO));
1669 TEST_F(ChunkDemuxerTest, WebMFile_AltRefFrames) {
1670 struct BufferTimestamps buffer_timestamps[] = {
1671 {0, 0},
1672 {33, 3},
1673 {33, 6},
1674 {67, 9},
1675 {100, 12},
1676 {kSkip, kSkip},
1679 ASSERT_TRUE(ParseWebMFile("bear-320x240-altref.webm", buffer_timestamps,
1680 base::TimeDelta::FromMilliseconds(2767)));
1683 // Verify that we output buffers before the entire cluster has been parsed.
1684 TEST_F(ChunkDemuxerTest, IncrementalClusterParsing) {
1685 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1686 AppendEmptyCluster(0);
1688 scoped_ptr<Cluster> cluster(GenerateCluster(0, 6));
1690 bool audio_read_done = false;
1691 bool video_read_done = false;
1692 ReadAudio(base::Bind(&OnReadDone,
1693 base::TimeDelta::FromMilliseconds(0),
1694 &audio_read_done));
1695 ReadVideo(base::Bind(&OnReadDone,
1696 base::TimeDelta::FromMilliseconds(0),
1697 &video_read_done));
1699 // Make sure the reads haven't completed yet.
1700 EXPECT_FALSE(audio_read_done);
1701 EXPECT_FALSE(video_read_done);
1703 // Append data one byte at a time until the audio read completes.
1704 int i = 0;
1705 for (; i < cluster->size() && !audio_read_done; ++i) {
1706 AppendData(cluster->data() + i, 1);
1707 message_loop_.RunUntilIdle();
1710 EXPECT_TRUE(audio_read_done);
1711 EXPECT_FALSE(video_read_done);
1712 EXPECT_GT(i, 0);
1713 EXPECT_LT(i, cluster->size());
1715 // Append data one byte at a time until the video read completes.
1716 for (; i < cluster->size() && !video_read_done; ++i) {
1717 AppendData(cluster->data() + i, 1);
1718 message_loop_.RunUntilIdle();
1721 EXPECT_TRUE(video_read_done);
1722 EXPECT_LT(i, cluster->size());
1724 audio_read_done = false;
1725 video_read_done = false;
1726 ReadAudio(base::Bind(&OnReadDone,
1727 base::TimeDelta::FromMilliseconds(23),
1728 &audio_read_done));
1729 ReadVideo(base::Bind(&OnReadDone,
1730 base::TimeDelta::FromMilliseconds(33),
1731 &video_read_done));
1733 // Make sure the reads haven't completed yet.
1734 EXPECT_FALSE(audio_read_done);
1735 EXPECT_FALSE(video_read_done);
1737 // Append the remaining data.
1738 ASSERT_LT(i, cluster->size());
1739 AppendData(cluster->data() + i, cluster->size() - i);
1741 message_loop_.RunUntilIdle();
1743 EXPECT_TRUE(audio_read_done);
1744 EXPECT_TRUE(video_read_done);
1747 TEST_F(ChunkDemuxerTest, ParseErrorDuringInit) {
1748 EXPECT_CALL(*this, DemuxerOpened());
1749 demuxer_->Initialize(
1750 &host_, CreateInitDoneCB(
1751 kNoTimestamp(), DEMUXER_ERROR_COULD_NOT_OPEN), true);
1753 ASSERT_EQ(AddId(), ChunkDemuxer::kOk);
1755 uint8 tmp = 0;
1756 demuxer_->AppendData(kSourceId, &tmp, 1, NULL);
1759 TEST_F(ChunkDemuxerTest, AVHeadersWithAudioOnlyType) {
1760 EXPECT_CALL(*this, DemuxerOpened());
1761 demuxer_->Initialize(
1762 &host_, CreateInitDoneCB(kNoTimestamp(),
1763 DEMUXER_ERROR_COULD_NOT_OPEN), true);
1765 std::vector<std::string> codecs(1);
1766 codecs[0] = "vorbis";
1767 ASSERT_EQ(demuxer_->AddId(kSourceId, "audio/webm", codecs),
1768 ChunkDemuxer::kOk);
1770 AppendInitSegment(HAS_AUDIO | HAS_VIDEO);
1773 TEST_F(ChunkDemuxerTest, AVHeadersWithVideoOnlyType) {
1774 EXPECT_CALL(*this, DemuxerOpened());
1775 demuxer_->Initialize(
1776 &host_, CreateInitDoneCB(kNoTimestamp(),
1777 DEMUXER_ERROR_COULD_NOT_OPEN), true);
1779 std::vector<std::string> codecs(1);
1780 codecs[0] = "vp8";
1781 ASSERT_EQ(demuxer_->AddId(kSourceId, "video/webm", codecs),
1782 ChunkDemuxer::kOk);
1784 AppendInitSegment(HAS_AUDIO | HAS_VIDEO);
1787 TEST_F(ChunkDemuxerTest, MultipleHeaders) {
1788 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1790 AppendCluster(kDefaultFirstCluster());
1792 // Append another identical initialization segment.
1793 AppendInitSegment(HAS_AUDIO | HAS_VIDEO);
1795 AppendCluster(kDefaultSecondCluster());
1797 GenerateExpectedReads(0, 9);
1800 TEST_F(ChunkDemuxerTest, AddSeparateSourcesForAudioAndVideo) {
1801 std::string audio_id = "audio1";
1802 std::string video_id = "video1";
1803 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
1805 // Append audio and video data into separate source ids.
1806 AppendCluster(audio_id,
1807 GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration));
1808 GenerateAudioStreamExpectedReads(0, 4);
1809 AppendCluster(video_id,
1810 GenerateSingleStreamCluster(0, 132, kVideoTrackNum, kVideoBlockDuration));
1811 GenerateVideoStreamExpectedReads(0, 4);
1814 TEST_F(ChunkDemuxerTest, AddSeparateSourcesForAudioAndVideoText) {
1815 // TODO(matthewjheaney): Here and elsewhere, we need more tests
1816 // for inband text tracks (http://crbug/321455).
1818 std::string audio_id = "audio1";
1819 std::string video_id = "video1";
1821 EXPECT_CALL(host_, AddTextStream(_, _))
1822 .Times(Exactly(2));
1823 ASSERT_TRUE(InitDemuxerAudioAndVideoSourcesText(audio_id, video_id, true));
1825 // Append audio and video data into separate source ids.
1826 AppendCluster(audio_id,
1827 GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration));
1828 GenerateAudioStreamExpectedReads(0, 4);
1829 AppendCluster(video_id,
1830 GenerateSingleStreamCluster(0, 132, kVideoTrackNum, kVideoBlockDuration));
1831 GenerateVideoStreamExpectedReads(0, 4);
1834 TEST_F(ChunkDemuxerTest, AddIdFailures) {
1835 EXPECT_CALL(*this, DemuxerOpened());
1836 demuxer_->Initialize(
1837 &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true);
1839 std::string audio_id = "audio1";
1840 std::string video_id = "video1";
1842 ASSERT_EQ(AddId(audio_id, HAS_AUDIO), ChunkDemuxer::kOk);
1844 // Adding an id with audio/video should fail because we already added audio.
1845 ASSERT_EQ(AddId(), ChunkDemuxer::kReachedIdLimit);
1847 AppendInitSegmentWithSourceId(audio_id, HAS_AUDIO);
1849 // Adding an id after append should fail.
1850 ASSERT_EQ(AddId(video_id, HAS_VIDEO), ChunkDemuxer::kReachedIdLimit);
1853 // Test that Read() calls after a RemoveId() return "end of stream" buffers.
1854 TEST_F(ChunkDemuxerTest, RemoveId) {
1855 std::string audio_id = "audio1";
1856 std::string video_id = "video1";
1857 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
1859 // Append audio and video data into separate source ids.
1860 AppendCluster(audio_id,
1861 GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration));
1862 AppendCluster(video_id,
1863 GenerateSingleStreamCluster(0, 132, kVideoTrackNum, kVideoBlockDuration));
1865 // Read() from audio should return normal buffers.
1866 GenerateAudioStreamExpectedReads(0, 4);
1868 // Remove the audio id.
1869 demuxer_->RemoveId(audio_id);
1871 // Read() from audio should return "end of stream" buffers.
1872 bool audio_read_done = false;
1873 ReadAudio(base::Bind(&OnReadDone_EOSExpected, &audio_read_done));
1874 message_loop_.RunUntilIdle();
1875 EXPECT_TRUE(audio_read_done);
1877 // Read() from video should still return normal buffers.
1878 GenerateVideoStreamExpectedReads(0, 4);
1881 // Test that removing an ID immediately after adding it does not interfere with
1882 // quota for new IDs in the future.
1883 TEST_F(ChunkDemuxerTest, RemoveAndAddId) {
1884 std::string audio_id_1 = "audio1";
1885 ASSERT_TRUE(AddId(audio_id_1, HAS_AUDIO) == ChunkDemuxer::kOk);
1886 demuxer_->RemoveId(audio_id_1);
1888 std::string audio_id_2 = "audio2";
1889 ASSERT_TRUE(AddId(audio_id_2, HAS_AUDIO) == ChunkDemuxer::kOk);
1892 TEST_F(ChunkDemuxerTest, SeekCanceled) {
1893 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1895 // Append cluster at the beginning of the stream.
1896 AppendCluster(GenerateCluster(0, 4));
1898 // Seek to an unbuffered region.
1899 Seek(base::TimeDelta::FromSeconds(50));
1901 // Attempt to read in unbuffered area; should not fulfill the read.
1902 bool audio_read_done = false;
1903 bool video_read_done = false;
1904 ReadAudio(base::Bind(&OnReadDone_AbortExpected, &audio_read_done));
1905 ReadVideo(base::Bind(&OnReadDone_AbortExpected, &video_read_done));
1906 EXPECT_FALSE(audio_read_done);
1907 EXPECT_FALSE(video_read_done);
1909 // Now cancel the pending seek, which should flush the reads with empty
1910 // buffers.
1911 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(0);
1912 demuxer_->CancelPendingSeek(seek_time);
1913 message_loop_.RunUntilIdle();
1914 EXPECT_TRUE(audio_read_done);
1915 EXPECT_TRUE(video_read_done);
1917 // A seek back to the buffered region should succeed.
1918 Seek(seek_time);
1919 GenerateExpectedReads(0, 4);
1922 TEST_F(ChunkDemuxerTest, SeekCanceledWhileWaitingForSeek) {
1923 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
1925 // Append cluster at the beginning of the stream.
1926 AppendCluster(GenerateCluster(0, 4));
1928 // Start waiting for a seek.
1929 base::TimeDelta seek_time1 = base::TimeDelta::FromSeconds(50);
1930 base::TimeDelta seek_time2 = base::TimeDelta::FromSeconds(0);
1931 demuxer_->StartWaitingForSeek(seek_time1);
1933 // Now cancel the upcoming seek to an unbuffered region.
1934 demuxer_->CancelPendingSeek(seek_time2);
1935 demuxer_->Seek(seek_time1, NewExpectedStatusCB(PIPELINE_OK));
1937 // Read requests should be fulfilled with empty buffers.
1938 bool audio_read_done = false;
1939 bool video_read_done = false;
1940 ReadAudio(base::Bind(&OnReadDone_AbortExpected, &audio_read_done));
1941 ReadVideo(base::Bind(&OnReadDone_AbortExpected, &video_read_done));
1942 EXPECT_TRUE(audio_read_done);
1943 EXPECT_TRUE(video_read_done);
1945 // A seek back to the buffered region should succeed.
1946 Seek(seek_time2);
1947 GenerateExpectedReads(0, 4);
1950 // Test that Seek() successfully seeks to all source IDs.
1951 TEST_F(ChunkDemuxerTest, SeekAudioAndVideoSources) {
1952 std::string audio_id = "audio1";
1953 std::string video_id = "video1";
1954 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
1956 AppendCluster(
1957 audio_id,
1958 GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration));
1959 AppendCluster(
1960 video_id,
1961 GenerateSingleStreamCluster(0, 132, kVideoTrackNum, kVideoBlockDuration));
1963 // Read() should return buffers at 0.
1964 bool audio_read_done = false;
1965 bool video_read_done = false;
1966 ReadAudio(base::Bind(&OnReadDone,
1967 base::TimeDelta::FromMilliseconds(0),
1968 &audio_read_done));
1969 ReadVideo(base::Bind(&OnReadDone,
1970 base::TimeDelta::FromMilliseconds(0),
1971 &video_read_done));
1972 EXPECT_TRUE(audio_read_done);
1973 EXPECT_TRUE(video_read_done);
1975 // Seek to 3 (an unbuffered region).
1976 Seek(base::TimeDelta::FromSeconds(3));
1978 audio_read_done = false;
1979 video_read_done = false;
1980 ReadAudio(base::Bind(&OnReadDone,
1981 base::TimeDelta::FromSeconds(3),
1982 &audio_read_done));
1983 ReadVideo(base::Bind(&OnReadDone,
1984 base::TimeDelta::FromSeconds(3),
1985 &video_read_done));
1986 // Read()s should not return until after data is appended at the Seek point.
1987 EXPECT_FALSE(audio_read_done);
1988 EXPECT_FALSE(video_read_done);
1990 AppendCluster(audio_id,
1991 GenerateSingleStreamCluster(
1992 3000, 3092, kAudioTrackNum, kAudioBlockDuration));
1993 AppendCluster(video_id,
1994 GenerateSingleStreamCluster(
1995 3000, 3132, kVideoTrackNum, kVideoBlockDuration));
1997 message_loop_.RunUntilIdle();
1999 // Read() should return buffers at 3.
2000 EXPECT_TRUE(audio_read_done);
2001 EXPECT_TRUE(video_read_done);
2004 // Test that Seek() completes successfully when EndOfStream
2005 // is called before data is available for that seek point.
2006 // This scenario might be useful if seeking past the end of stream
2007 // of either audio or video (or both).
2008 TEST_F(ChunkDemuxerTest, EndOfStreamAfterPastEosSeek) {
2009 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2011 AppendCluster(GenerateSingleStreamCluster(0, 120, kAudioTrackNum, 10));
2012 AppendCluster(GenerateSingleStreamCluster(0, 100, kVideoTrackNum, 5));
2014 // Seeking past the end of video.
2015 // Note: audio data is available for that seek point.
2016 bool seek_cb_was_called = false;
2017 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(110);
2018 demuxer_->StartWaitingForSeek(seek_time);
2019 demuxer_->Seek(seek_time,
2020 base::Bind(OnSeekDone_OKExpected, &seek_cb_was_called));
2021 message_loop_.RunUntilIdle();
2023 EXPECT_FALSE(seek_cb_was_called);
2025 EXPECT_CALL(host_, SetDuration(
2026 base::TimeDelta::FromMilliseconds(120)));
2027 MarkEndOfStream(PIPELINE_OK);
2028 message_loop_.RunUntilIdle();
2030 EXPECT_TRUE(seek_cb_was_called);
2032 ShutdownDemuxer();
2035 // Test that EndOfStream is ignored if coming during a pending seek
2036 // whose seek time is before some existing ranges.
2037 TEST_F(ChunkDemuxerTest, EndOfStreamDuringPendingSeek) {
2038 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2040 AppendCluster(GenerateSingleStreamCluster(0, 120, kAudioTrackNum, 10));
2041 AppendCluster(GenerateSingleStreamCluster(0, 100, kVideoTrackNum, 5));
2042 AppendCluster(GenerateSingleStreamCluster(200, 300, kAudioTrackNum, 10));
2043 AppendCluster(GenerateSingleStreamCluster(200, 300, kVideoTrackNum, 5));
2045 bool seek_cb_was_called = false;
2046 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(160);
2047 demuxer_->StartWaitingForSeek(seek_time);
2048 demuxer_->Seek(seek_time,
2049 base::Bind(OnSeekDone_OKExpected, &seek_cb_was_called));
2050 message_loop_.RunUntilIdle();
2052 EXPECT_FALSE(seek_cb_was_called);
2054 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(300)));
2055 MarkEndOfStream(PIPELINE_OK);
2056 message_loop_.RunUntilIdle();
2058 EXPECT_FALSE(seek_cb_was_called);
2060 demuxer_->UnmarkEndOfStream();
2062 AppendCluster(GenerateSingleStreamCluster(140, 180, kAudioTrackNum, 10));
2063 AppendCluster(GenerateSingleStreamCluster(140, 180, kVideoTrackNum, 5));
2065 message_loop_.RunUntilIdle();
2067 EXPECT_TRUE(seek_cb_was_called);
2069 ShutdownDemuxer();
2072 // Test ranges in an audio-only stream.
2073 TEST_F(ChunkDemuxerTest, GetBufferedRanges_AudioIdOnly) {
2074 EXPECT_CALL(*this, DemuxerOpened());
2075 demuxer_->Initialize(
2076 &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true);
2078 ASSERT_EQ(AddId(kSourceId, HAS_AUDIO), ChunkDemuxer::kOk);
2079 AppendInitSegment(HAS_AUDIO);
2081 // Test a simple cluster.
2082 AppendCluster(
2083 GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration));
2085 CheckExpectedRanges("{ [0,92) }");
2087 // Append a disjoint cluster to check for two separate ranges.
2088 AppendCluster(GenerateSingleStreamCluster(
2089 150, 219, kAudioTrackNum, kAudioBlockDuration));
2091 CheckExpectedRanges("{ [0,92) [150,219) }");
2094 // Test ranges in a video-only stream.
2095 TEST_F(ChunkDemuxerTest, GetBufferedRanges_VideoIdOnly) {
2096 EXPECT_CALL(*this, DemuxerOpened());
2097 demuxer_->Initialize(
2098 &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true);
2100 ASSERT_EQ(AddId(kSourceId, HAS_VIDEO), ChunkDemuxer::kOk);
2101 AppendInitSegment(HAS_VIDEO);
2103 // Test a simple cluster.
2104 AppendCluster(
2105 GenerateSingleStreamCluster(0, 132, kVideoTrackNum, kVideoBlockDuration));
2107 CheckExpectedRanges("{ [0,132) }");
2109 // Append a disjoint cluster to check for two separate ranges.
2110 AppendCluster(GenerateSingleStreamCluster(
2111 200, 299, kVideoTrackNum, kVideoBlockDuration));
2113 CheckExpectedRanges("{ [0,132) [200,299) }");
2116 TEST_F(ChunkDemuxerTest, GetBufferedRanges_AudioVideo) {
2117 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2119 // Audio: 0 -> 23
2120 // Video: 0 -> 33
2121 // Buffered Range: 0 -> 23
2122 // Audio block duration is smaller than video block duration,
2123 // so the buffered ranges should correspond to the audio blocks.
2124 AppendCluster(GenerateSingleStreamCluster(
2125 0, kAudioBlockDuration, kAudioTrackNum, kAudioBlockDuration));
2126 AppendCluster(GenerateSingleStreamCluster(
2127 0, kVideoBlockDuration, kVideoTrackNum, kVideoBlockDuration));
2129 CheckExpectedRanges("{ [0,23) }");
2131 // Audio: 300 -> 400
2132 // Video: 320 -> 420
2133 // Buffered Range: 320 -> 400 (end overlap)
2134 AppendCluster(GenerateSingleStreamCluster(300, 400, kAudioTrackNum, 50));
2135 AppendCluster(GenerateSingleStreamCluster(320, 420, kVideoTrackNum, 50));
2137 CheckExpectedRanges("{ [0,23) [320,400) }");
2139 // Audio: 520 -> 590
2140 // Video: 500 -> 570
2141 // Buffered Range: 520 -> 570 (front overlap)
2142 AppendCluster(GenerateSingleStreamCluster(520, 590, kAudioTrackNum, 70));
2143 AppendCluster(GenerateSingleStreamCluster(500, 570, kVideoTrackNum, 70));
2145 CheckExpectedRanges("{ [0,23) [320,400) [520,570) }");
2147 // Audio: 720 -> 750
2148 // Video: 700 -> 770
2149 // Buffered Range: 720 -> 750 (complete overlap, audio)
2150 AppendCluster(GenerateSingleStreamCluster(720, 750, kAudioTrackNum, 30));
2151 AppendCluster(GenerateSingleStreamCluster(700, 770, kVideoTrackNum, 70));
2153 CheckExpectedRanges("{ [0,23) [320,400) [520,570) [720,750) }");
2155 // Audio: 900 -> 970
2156 // Video: 920 -> 950
2157 // Buffered Range: 920 -> 950 (complete overlap, video)
2158 AppendCluster(GenerateSingleStreamCluster(900, 970, kAudioTrackNum, 70));
2159 AppendCluster(GenerateSingleStreamCluster(920, 950, kVideoTrackNum, 30));
2161 CheckExpectedRanges("{ [0,23) [320,400) [520,570) [720,750) [920,950) }");
2163 // Appending within buffered range should not affect buffered ranges.
2164 AppendCluster(GenerateSingleStreamCluster(930, 950, kAudioTrackNum, 20));
2165 CheckExpectedRanges("{ [0,23) [320,400) [520,570) [720,750) [920,950) }");
2167 // Appending to single stream outside buffered ranges should not affect
2168 // buffered ranges.
2169 AppendCluster(GenerateSingleStreamCluster(1230, 1240, kVideoTrackNum, 10));
2170 CheckExpectedRanges("{ [0,23) [320,400) [520,570) [720,750) [920,950) }");
2173 TEST_F(ChunkDemuxerTest, GetBufferedRanges_AudioVideoText) {
2174 EXPECT_CALL(host_, AddTextStream(_, _));
2175 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO | HAS_TEXT));
2177 // Append audio & video data
2178 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, "0K 23");
2179 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "0K 33");
2181 // Verify that a text track with no cues does not result in an empty buffered
2182 // range.
2183 CheckExpectedRanges("{ [0,46) }");
2185 // Add some text cues.
2186 AppendSingleStreamCluster(kSourceId, kTextTrackNum, "0K 100K");
2188 // Verify that the new cues did not affect the buffered ranges.
2189 CheckExpectedRanges("{ [0,46) }");
2191 // Remove the buffered range.
2192 demuxer_->Remove(kSourceId, base::TimeDelta(),
2193 base::TimeDelta::FromMilliseconds(46));
2194 CheckExpectedRanges("{ }");
2197 // Once MarkEndOfStream() is called, GetBufferedRanges should not cut off any
2198 // over-hanging tails at the end of the ranges as this is likely due to block
2199 // duration differences.
2200 TEST_F(ChunkDemuxerTest, GetBufferedRanges_EndOfStream) {
2201 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2203 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, "0K 23K");
2204 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "0K 33");
2206 CheckExpectedRanges("{ [0,46) }");
2208 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(66)));
2209 MarkEndOfStream(PIPELINE_OK);
2211 // Verify that the range extends to the end of the video data.
2212 CheckExpectedRanges("{ [0,66) }");
2214 // Verify that the range reverts to the intersection when end of stream
2215 // has been cancelled.
2216 demuxer_->UnmarkEndOfStream();
2217 CheckExpectedRanges("{ [0,46) }");
2219 // Append and remove data so that the 2 streams' end ranges do not overlap.
2221 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(246)));
2222 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(366)));
2223 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, "200K 223K");
2224 AppendSingleStreamCluster(kSourceId, kVideoTrackNum,
2225 "200K 233 266 299 300K 333");
2227 // At this point, the per-stream ranges are as follows:
2228 // Audio: [0,46) [200,246)
2229 // Video: [0,66) [200,366)
2230 CheckExpectedRanges("{ [0,46) [200,246) }");
2232 demuxer_->Remove(kSourceId, base::TimeDelta::FromMilliseconds(200),
2233 base::TimeDelta::FromMilliseconds(300));
2235 // At this point, the per-stream ranges are as follows:
2236 // Audio: [0,46)
2237 // Video: [0,66) [300,366)
2238 CheckExpectedRanges("{ [0,46) }");
2240 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, "200K 223K");
2241 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, "200K 233");
2243 // At this point, the per-stream ranges are as follows:
2244 // Audio: [0,46) [200,246)
2245 // Video: [0,66) [200,266) [300,366)
2246 // NOTE: The last range on each stream do not overlap in time.
2247 CheckExpectedRanges("{ [0,46) [200,246) }");
2249 MarkEndOfStream(PIPELINE_OK);
2251 // NOTE: The last range on each stream gets extended to the highest
2252 // end timestamp according to the spec. The last audio range gets extended
2253 // from [200,246) to [200,366) which is why the intersection results in the
2254 // middle range getting larger AND the new range appearing.
2255 CheckExpectedRanges("{ [0,46) [200,266) [300,366) }");
2258 TEST_F(ChunkDemuxerTest, DifferentStreamTimecodes) {
2259 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2261 // Create a cluster where the video timecode begins 25ms after the audio.
2262 AppendCluster(GenerateCluster(0, 25, 8));
2264 Seek(base::TimeDelta::FromSeconds(0));
2265 GenerateExpectedReads(0, 25, 8);
2267 // Seek to 5 seconds.
2268 Seek(base::TimeDelta::FromSeconds(5));
2270 // Generate a cluster to fulfill this seek, where audio timecode begins 25ms
2271 // after the video.
2272 AppendCluster(GenerateCluster(5025, 5000, 8));
2273 GenerateExpectedReads(5025, 5000, 8);
2276 TEST_F(ChunkDemuxerTest, DifferentStreamTimecodesSeparateSources) {
2277 std::string audio_id = "audio1";
2278 std::string video_id = "video1";
2279 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
2281 // Generate two streams where the video stream starts 5ms after the audio
2282 // stream and append them.
2283 AppendCluster(audio_id, GenerateSingleStreamCluster(
2284 25, 4 * kAudioBlockDuration + 25, kAudioTrackNum, kAudioBlockDuration));
2285 AppendCluster(video_id, GenerateSingleStreamCluster(
2286 30, 4 * kVideoBlockDuration + 30, kVideoTrackNum, kVideoBlockDuration));
2288 // Both streams should be able to fulfill a seek to 25.
2289 Seek(base::TimeDelta::FromMilliseconds(25));
2290 GenerateAudioStreamExpectedReads(25, 4);
2291 GenerateVideoStreamExpectedReads(30, 4);
2294 TEST_F(ChunkDemuxerTest, DifferentStreamTimecodesOutOfRange) {
2295 std::string audio_id = "audio1";
2296 std::string video_id = "video1";
2297 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
2299 // Generate two streams where the video stream starts 10s after the audio
2300 // stream and append them.
2301 AppendCluster(audio_id, GenerateSingleStreamCluster(0,
2302 4 * kAudioBlockDuration + 0, kAudioTrackNum, kAudioBlockDuration));
2303 AppendCluster(video_id, GenerateSingleStreamCluster(10000,
2304 4 * kVideoBlockDuration + 10000, kVideoTrackNum, kVideoBlockDuration));
2306 // Should not be able to fulfill a seek to 0.
2307 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(0);
2308 demuxer_->StartWaitingForSeek(seek_time);
2309 demuxer_->Seek(seek_time,
2310 NewExpectedStatusCB(PIPELINE_ERROR_ABORT));
2311 ExpectRead(DemuxerStream::AUDIO, 0);
2312 ExpectEndOfStream(DemuxerStream::VIDEO);
2315 TEST_F(ChunkDemuxerTest, ClusterWithNoBuffers) {
2316 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2318 // Generate and append an empty cluster beginning at 0.
2319 AppendEmptyCluster(0);
2321 // Sanity check that data can be appended after this cluster correctly.
2322 AppendCluster(GenerateCluster(0, 2));
2323 ExpectRead(DemuxerStream::AUDIO, 0);
2324 ExpectRead(DemuxerStream::VIDEO, 0);
2327 TEST_F(ChunkDemuxerTest, CodecPrefixMatching) {
2328 ChunkDemuxer::Status expected = ChunkDemuxer::kNotSupported;
2330 #if defined(USE_PROPRIETARY_CODECS)
2331 expected = ChunkDemuxer::kOk;
2332 #endif
2334 std::vector<std::string> codecs;
2335 codecs.push_back("avc1.4D4041");
2337 EXPECT_EQ(demuxer_->AddId("source_id", "video/mp4", codecs), expected);
2340 // Test codec ID's that are not compliant with RFC6381, but have been
2341 // seen in the wild.
2342 TEST_F(ChunkDemuxerTest, CodecIDsThatAreNotRFC6381Compliant) {
2343 ChunkDemuxer::Status expected = ChunkDemuxer::kNotSupported;
2345 #if defined(USE_PROPRIETARY_CODECS)
2346 expected = ChunkDemuxer::kOk;
2347 #endif
2348 const char* codec_ids[] = {
2349 // GPAC places leading zeros on the audio object type.
2350 "mp4a.40.02",
2351 "mp4a.40.05"
2354 for (size_t i = 0; i < arraysize(codec_ids); ++i) {
2355 std::vector<std::string> codecs;
2356 codecs.push_back(codec_ids[i]);
2358 ChunkDemuxer::Status result =
2359 demuxer_->AddId("source_id", "audio/mp4", codecs);
2361 EXPECT_EQ(result, expected)
2362 << "Fail to add codec_id '" << codec_ids[i] << "'";
2364 if (result == ChunkDemuxer::kOk)
2365 demuxer_->RemoveId("source_id");
2369 TEST_F(ChunkDemuxerTest, EndOfStreamStillSetAfterSeek) {
2370 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2372 EXPECT_CALL(host_, SetDuration(_))
2373 .Times(AnyNumber());
2375 base::TimeDelta kLastAudioTimestamp = base::TimeDelta::FromMilliseconds(92);
2376 base::TimeDelta kLastVideoTimestamp = base::TimeDelta::FromMilliseconds(99);
2378 AppendCluster(kDefaultFirstCluster());
2379 AppendCluster(kDefaultSecondCluster());
2380 MarkEndOfStream(PIPELINE_OK);
2382 DemuxerStream::Status status;
2383 base::TimeDelta last_timestamp;
2385 // Verify that we can read audio & video to the end w/o problems.
2386 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp);
2387 EXPECT_EQ(DemuxerStream::kOk, status);
2388 EXPECT_EQ(kLastAudioTimestamp, last_timestamp);
2390 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp);
2391 EXPECT_EQ(DemuxerStream::kOk, status);
2392 EXPECT_EQ(kLastVideoTimestamp, last_timestamp);
2394 // Seek back to 0 and verify that we can read to the end again..
2395 Seek(base::TimeDelta::FromMilliseconds(0));
2397 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp);
2398 EXPECT_EQ(DemuxerStream::kOk, status);
2399 EXPECT_EQ(kLastAudioTimestamp, last_timestamp);
2401 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp);
2402 EXPECT_EQ(DemuxerStream::kOk, status);
2403 EXPECT_EQ(kLastVideoTimestamp, last_timestamp);
2406 TEST_F(ChunkDemuxerTest, GetBufferedRangesBeforeInitSegment) {
2407 EXPECT_CALL(*this, DemuxerOpened());
2408 demuxer_->Initialize(&host_, CreateInitDoneCB(PIPELINE_OK), true);
2409 ASSERT_EQ(AddId("audio", HAS_AUDIO), ChunkDemuxer::kOk);
2410 ASSERT_EQ(AddId("video", HAS_VIDEO), ChunkDemuxer::kOk);
2412 CheckExpectedRanges("audio", "{ }");
2413 CheckExpectedRanges("video", "{ }");
2416 // Test that Seek() completes successfully when the first cluster
2417 // arrives.
2418 TEST_F(ChunkDemuxerTest, EndOfStreamDuringSeek) {
2419 InSequence s;
2421 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2423 AppendCluster(kDefaultFirstCluster());
2425 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(0);
2426 demuxer_->StartWaitingForSeek(seek_time);
2428 AppendCluster(kDefaultSecondCluster());
2429 EXPECT_CALL(host_, SetDuration(
2430 base::TimeDelta::FromMilliseconds(kDefaultSecondClusterEndTimestamp)));
2431 MarkEndOfStream(PIPELINE_OK);
2433 demuxer_->Seek(seek_time, NewExpectedStatusCB(PIPELINE_OK));
2435 GenerateExpectedReads(0, 4);
2436 GenerateExpectedReads(46, 66, 5);
2438 EndOfStreamHelper end_of_stream_helper(demuxer_.get());
2439 end_of_stream_helper.RequestReads();
2440 end_of_stream_helper.CheckIfReadDonesWereCalled(true);
2443 TEST_F(ChunkDemuxerTest, ConfigChange_Video) {
2444 InSequence s;
2446 ASSERT_TRUE(InitDemuxerWithConfigChangeData());
2448 DemuxerStream::Status status;
2449 base::TimeDelta last_timestamp;
2451 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
2453 // Fetch initial video config and verify it matches what we expect.
2454 const VideoDecoderConfig& video_config_1 = video->video_decoder_config();
2455 ASSERT_TRUE(video_config_1.IsValidConfig());
2456 EXPECT_EQ(video_config_1.natural_size().width(), 320);
2457 EXPECT_EQ(video_config_1.natural_size().height(), 240);
2459 ExpectRead(DemuxerStream::VIDEO, 0);
2461 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp);
2463 ASSERT_EQ(status, DemuxerStream::kConfigChanged);
2464 EXPECT_EQ(last_timestamp.InMilliseconds(), 501);
2466 // Fetch the new decoder config.
2467 const VideoDecoderConfig& video_config_2 = video->video_decoder_config();
2468 ASSERT_TRUE(video_config_2.IsValidConfig());
2469 EXPECT_EQ(video_config_2.natural_size().width(), 640);
2470 EXPECT_EQ(video_config_2.natural_size().height(), 360);
2472 ExpectRead(DemuxerStream::VIDEO, 527);
2474 // Read until the next config change.
2475 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp);
2476 ASSERT_EQ(status, DemuxerStream::kConfigChanged);
2477 EXPECT_EQ(last_timestamp.InMilliseconds(), 793);
2479 // Get the new config and verify that it matches the first one.
2480 ASSERT_TRUE(video_config_1.Matches(video->video_decoder_config()));
2482 ExpectRead(DemuxerStream::VIDEO, 801);
2484 // Read until the end of the stream just to make sure there aren't any other
2485 // config changes.
2486 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp);
2487 ASSERT_EQ(status, DemuxerStream::kOk);
2490 TEST_F(ChunkDemuxerTest, ConfigChange_Audio) {
2491 InSequence s;
2493 ASSERT_TRUE(InitDemuxerWithConfigChangeData());
2495 DemuxerStream::Status status;
2496 base::TimeDelta last_timestamp;
2498 DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
2500 // Fetch initial audio config and verify it matches what we expect.
2501 const AudioDecoderConfig& audio_config_1 = audio->audio_decoder_config();
2502 ASSERT_TRUE(audio_config_1.IsValidConfig());
2503 EXPECT_EQ(audio_config_1.samples_per_second(), 44100);
2504 EXPECT_EQ(audio_config_1.extra_data_size(), 3863u);
2506 ExpectRead(DemuxerStream::AUDIO, 0);
2508 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp);
2510 ASSERT_EQ(status, DemuxerStream::kConfigChanged);
2511 EXPECT_EQ(last_timestamp.InMilliseconds(), 524);
2513 // Fetch the new decoder config.
2514 const AudioDecoderConfig& audio_config_2 = audio->audio_decoder_config();
2515 ASSERT_TRUE(audio_config_2.IsValidConfig());
2516 EXPECT_EQ(audio_config_2.samples_per_second(), 44100);
2517 EXPECT_EQ(audio_config_2.extra_data_size(), 3935u);
2519 ExpectRead(DemuxerStream::AUDIO, 527);
2521 // Read until the next config change.
2522 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp);
2523 ASSERT_EQ(status, DemuxerStream::kConfigChanged);
2524 EXPECT_EQ(last_timestamp.InMilliseconds(), 759);
2526 // Get the new config and verify that it matches the first one.
2527 ASSERT_TRUE(audio_config_1.Matches(audio->audio_decoder_config()));
2529 ExpectRead(DemuxerStream::AUDIO, 779);
2531 // Read until the end of the stream just to make sure there aren't any other
2532 // config changes.
2533 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp);
2534 ASSERT_EQ(status, DemuxerStream::kOk);
2537 TEST_F(ChunkDemuxerTest, ConfigChange_Seek) {
2538 InSequence s;
2540 ASSERT_TRUE(InitDemuxerWithConfigChangeData());
2542 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
2544 // Fetch initial video config and verify it matches what we expect.
2545 const VideoDecoderConfig& video_config_1 = video->video_decoder_config();
2546 ASSERT_TRUE(video_config_1.IsValidConfig());
2547 EXPECT_EQ(video_config_1.natural_size().width(), 320);
2548 EXPECT_EQ(video_config_1.natural_size().height(), 240);
2550 ExpectRead(DemuxerStream::VIDEO, 0);
2552 // Seek to a location with a different config.
2553 Seek(base::TimeDelta::FromMilliseconds(527));
2555 // Verify that the config change is signalled.
2556 ExpectConfigChanged(DemuxerStream::VIDEO);
2558 // Fetch the new decoder config and verify it is what we expect.
2559 const VideoDecoderConfig& video_config_2 = video->video_decoder_config();
2560 ASSERT_TRUE(video_config_2.IsValidConfig());
2561 EXPECT_EQ(video_config_2.natural_size().width(), 640);
2562 EXPECT_EQ(video_config_2.natural_size().height(), 360);
2564 // Verify that Read() will return a buffer now.
2565 ExpectRead(DemuxerStream::VIDEO, 527);
2567 // Seek back to the beginning and verify we get another config change.
2568 Seek(base::TimeDelta::FromMilliseconds(0));
2569 ExpectConfigChanged(DemuxerStream::VIDEO);
2570 ASSERT_TRUE(video_config_1.Matches(video->video_decoder_config()));
2571 ExpectRead(DemuxerStream::VIDEO, 0);
2573 // Seek to a location that requires a config change and then
2574 // seek to a new location that has the same configuration as
2575 // the start of the file without a Read() in the middle.
2576 Seek(base::TimeDelta::FromMilliseconds(527));
2577 Seek(base::TimeDelta::FromMilliseconds(801));
2579 // Verify that no config change is signalled.
2580 ExpectRead(DemuxerStream::VIDEO, 801);
2581 ASSERT_TRUE(video_config_1.Matches(video->video_decoder_config()));
2584 TEST_F(ChunkDemuxerTest, TimestampPositiveOffset) {
2585 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2587 ASSERT_TRUE(demuxer_->SetTimestampOffset(
2588 kSourceId, base::TimeDelta::FromSeconds(30)));
2589 AppendCluster(GenerateCluster(0, 2));
2591 Seek(base::TimeDelta::FromMilliseconds(30000));
2593 GenerateExpectedReads(30000, 2);
2596 TEST_F(ChunkDemuxerTest, TimestampNegativeOffset) {
2597 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2599 ASSERT_TRUE(demuxer_->SetTimestampOffset(
2600 kSourceId, base::TimeDelta::FromSeconds(-1)));
2601 AppendCluster(GenerateCluster(1000, 2));
2603 GenerateExpectedReads(0, 2);
2606 TEST_F(ChunkDemuxerTest, TimestampOffsetSeparateStreams) {
2607 std::string audio_id = "audio1";
2608 std::string video_id = "video1";
2609 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
2611 ASSERT_TRUE(demuxer_->SetTimestampOffset(
2612 audio_id, base::TimeDelta::FromMilliseconds(-2500)));
2613 ASSERT_TRUE(demuxer_->SetTimestampOffset(
2614 video_id, base::TimeDelta::FromMilliseconds(-2500)));
2615 AppendCluster(audio_id, GenerateSingleStreamCluster(2500,
2616 2500 + kAudioBlockDuration * 4, kAudioTrackNum, kAudioBlockDuration));
2617 AppendCluster(video_id, GenerateSingleStreamCluster(2500,
2618 2500 + kVideoBlockDuration * 4, kVideoTrackNum, kVideoBlockDuration));
2619 GenerateAudioStreamExpectedReads(0, 4);
2620 GenerateVideoStreamExpectedReads(0, 4);
2622 Seek(base::TimeDelta::FromMilliseconds(27300));
2624 ASSERT_TRUE(demuxer_->SetTimestampOffset(
2625 audio_id, base::TimeDelta::FromMilliseconds(27300)));
2626 ASSERT_TRUE(demuxer_->SetTimestampOffset(
2627 video_id, base::TimeDelta::FromMilliseconds(27300)));
2628 AppendCluster(audio_id, GenerateSingleStreamCluster(
2629 0, kAudioBlockDuration * 4, kAudioTrackNum, kAudioBlockDuration));
2630 AppendCluster(video_id, GenerateSingleStreamCluster(
2631 0, kVideoBlockDuration * 4, kVideoTrackNum, kVideoBlockDuration));
2632 GenerateVideoStreamExpectedReads(27300, 4);
2633 GenerateAudioStreamExpectedReads(27300, 4);
2636 TEST_F(ChunkDemuxerTest, TimestampOffsetMidMediaSegment) {
2637 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2639 scoped_ptr<Cluster> cluster = GenerateCluster(0, 2);
2640 // Append only part of the cluster data.
2641 AppendData(cluster->data(), cluster->size() - 13);
2643 // Setting a timestamp should fail because we're in the middle of a cluster.
2644 ASSERT_FALSE(demuxer_->SetTimestampOffset(
2645 kSourceId, base::TimeDelta::FromSeconds(25)));
2647 demuxer_->Abort(kSourceId);
2648 // After Abort(), setting a timestamp should succeed since we're no longer
2649 // in the middle of a cluster
2650 ASSERT_TRUE(demuxer_->SetTimestampOffset(
2651 kSourceId, base::TimeDelta::FromSeconds(25)));
2654 TEST_F(ChunkDemuxerTest, WebMParsingMediaSegmentDetection) {
2655 // TODO(wolenetz): Also test 'unknown' sized clusters.
2656 // See http://crbug.com/335676.
2657 const uint8 kBuffer[] = {
2658 0x1F, 0x43, 0xB6, 0x75, 0x83, // CLUSTER (size = 3)
2659 0xE7, 0x81, 0x01, // Cluster TIMECODE (value = 1)
2662 // Setting timestamp offset or append mode is allowed only while not
2663 // parsing a media segment. This array indicates whether or not these
2664 // operations are allowed following each incrementally appended byte in
2665 // |kBuffer|.
2666 const bool kExpectedReturnValues[] = {
2667 true, true, true, true, false,
2668 false, false, true,
2671 COMPILE_ASSERT(arraysize(kBuffer) == arraysize(kExpectedReturnValues),
2672 test_arrays_out_of_sync);
2673 COMPILE_ASSERT(arraysize(kBuffer) == sizeof(kBuffer), not_one_byte_per_index);
2675 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2677 for (size_t i = 0; i < sizeof(kBuffer); i++) {
2678 DVLOG(3) << "Appending and testing index " << i;
2679 AppendData(kBuffer + i, 1);
2680 bool expected_return_value = kExpectedReturnValues[i];
2681 EXPECT_EQ(expected_return_value, demuxer_->SetTimestampOffset(
2682 kSourceId, base::TimeDelta::FromSeconds(25)));
2683 EXPECT_EQ(expected_return_value, demuxer_->SetSequenceMode(
2684 kSourceId, true));
2685 EXPECT_EQ(expected_return_value, demuxer_->SetSequenceMode(
2686 kSourceId, false));
2690 TEST_F(ChunkDemuxerTest, SetSequenceModeMidMediaSegment) {
2691 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2693 scoped_ptr<Cluster> cluster = GenerateCluster(0, 2);
2694 // Append only part of the cluster data.
2695 AppendData(cluster->data(), cluster->size() - 13);
2697 // Setting append mode should fail because we're in the middle of a cluster.
2698 ASSERT_FALSE(demuxer_->SetSequenceMode(kSourceId, true));
2699 ASSERT_FALSE(demuxer_->SetSequenceMode(kSourceId, false));
2701 demuxer_->Abort(kSourceId);
2702 // After Abort(), setting append mode should succeed since we're no longer
2703 // in the middle of a cluster.
2704 ASSERT_TRUE(demuxer_->SetSequenceMode(kSourceId, true));
2705 ASSERT_TRUE(demuxer_->SetSequenceMode(kSourceId, false));
2708 TEST_F(ChunkDemuxerTest, DurationChange) {
2709 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2710 const int kStreamDuration = kDefaultDuration().InMilliseconds();
2712 // Add data leading up to the currently set duration.
2713 AppendCluster(GenerateCluster(kStreamDuration - kAudioBlockDuration,
2714 kStreamDuration - kVideoBlockDuration,
2715 2));
2717 CheckExpectedRanges(kSourceId, "{ [201191,201224) }");
2719 // Add data at the currently set duration. The duration should not increase.
2720 AppendCluster(GenerateCluster(kDefaultDuration().InMilliseconds(), 2));
2722 // Range should not be affected.
2723 CheckExpectedRanges(kSourceId, "{ [201191,201224) }");
2725 // Now add data past the duration and expect a new duration to be signalled.
2726 const int kNewStreamDuration = kStreamDuration + kAudioBlockDuration * 2;
2727 EXPECT_CALL(host_, SetDuration(
2728 base::TimeDelta::FromMilliseconds(kNewStreamDuration)));
2729 AppendCluster(GenerateCluster(kStreamDuration + kAudioBlockDuration,
2730 kStreamDuration + kVideoBlockDuration,
2731 2));
2733 // See that the range has increased appropriately.
2734 CheckExpectedRanges(kSourceId, "{ [201191,201270) }");
2737 TEST_F(ChunkDemuxerTest, DurationChangeTimestampOffset) {
2738 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2740 ASSERT_TRUE(demuxer_->SetTimestampOffset(kSourceId, kDefaultDuration()));
2742 EXPECT_CALL(host_, SetDuration(
2743 kDefaultDuration() + base::TimeDelta::FromMilliseconds(
2744 kAudioBlockDuration * 2)));
2745 AppendCluster(GenerateCluster(0, 4));
2748 TEST_F(ChunkDemuxerTest, EndOfStreamTruncateDuration) {
2749 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2751 AppendCluster(kDefaultFirstCluster());
2753 EXPECT_CALL(host_, SetDuration(
2754 base::TimeDelta::FromMilliseconds(kDefaultFirstClusterEndTimestamp)));
2755 MarkEndOfStream(PIPELINE_OK);
2759 TEST_F(ChunkDemuxerTest, ZeroLengthAppend) {
2760 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2761 AppendData(NULL, 0);
2764 TEST_F(ChunkDemuxerTest, AppendAfterEndOfStream) {
2765 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2767 EXPECT_CALL(host_, SetDuration(_))
2768 .Times(AnyNumber());
2770 AppendCluster(kDefaultFirstCluster());
2771 MarkEndOfStream(PIPELINE_OK);
2773 demuxer_->UnmarkEndOfStream();
2775 AppendCluster(kDefaultSecondCluster());
2776 MarkEndOfStream(PIPELINE_OK);
2779 // Test receiving a Shutdown() call before we get an Initialize()
2780 // call. This can happen if video element gets destroyed before
2781 // the pipeline has a chance to initialize the demuxer.
2782 TEST_F(ChunkDemuxerTest, Shutdown_BeforeInitialize) {
2783 demuxer_->Shutdown();
2784 demuxer_->Initialize(
2785 &host_, CreateInitDoneCB(DEMUXER_ERROR_COULD_NOT_OPEN), true);
2786 message_loop_.RunUntilIdle();
2789 TEST_F(ChunkDemuxerTest, ReadAfterAudioDisabled) {
2790 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2791 AppendCluster(kDefaultFirstCluster());
2793 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::AUDIO);
2794 ASSERT_TRUE(stream);
2796 // The stream should no longer be present.
2797 demuxer_->OnAudioRendererDisabled();
2798 ASSERT_FALSE(demuxer_->GetStream(DemuxerStream::AUDIO));
2800 // Normally this would return an audio buffer at timestamp zero, but
2801 // all reads should return EOS buffers when disabled.
2802 bool audio_read_done = false;
2803 stream->Read(base::Bind(&OnReadDone_EOSExpected, &audio_read_done));
2804 message_loop_.RunUntilIdle();
2806 EXPECT_TRUE(audio_read_done);
2809 // Verifies that signalling end of stream while stalled at a gap
2810 // boundary does not trigger end of stream buffers to be returned.
2811 TEST_F(ChunkDemuxerTest, EndOfStreamWhileWaitingForGapToBeFilled) {
2812 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2814 AppendCluster(0, 10);
2815 AppendCluster(300, 10);
2816 CheckExpectedRanges(kSourceId, "{ [0,132) [300,432) }");
2819 GenerateExpectedReads(0, 10);
2821 bool audio_read_done = false;
2822 bool video_read_done = false;
2823 ReadAudio(base::Bind(&OnReadDone,
2824 base::TimeDelta::FromMilliseconds(138),
2825 &audio_read_done));
2826 ReadVideo(base::Bind(&OnReadDone,
2827 base::TimeDelta::FromMilliseconds(138),
2828 &video_read_done));
2830 // Verify that the reads didn't complete
2831 EXPECT_FALSE(audio_read_done);
2832 EXPECT_FALSE(video_read_done);
2834 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(438)));
2835 MarkEndOfStream(PIPELINE_OK);
2837 // Verify that the reads still haven't completed.
2838 EXPECT_FALSE(audio_read_done);
2839 EXPECT_FALSE(video_read_done);
2841 demuxer_->UnmarkEndOfStream();
2843 AppendCluster(138, 24);
2845 message_loop_.RunUntilIdle();
2847 CheckExpectedRanges(kSourceId, "{ [0,438) }");
2849 // Verify that the reads have completed.
2850 EXPECT_TRUE(audio_read_done);
2851 EXPECT_TRUE(video_read_done);
2853 // Read the rest of the buffers.
2854 GenerateExpectedReads(161, 171, 22);
2856 // Verify that reads block because the append cleared the end of stream state.
2857 audio_read_done = false;
2858 video_read_done = false;
2859 ReadAudio(base::Bind(&OnReadDone_EOSExpected,
2860 &audio_read_done));
2861 ReadVideo(base::Bind(&OnReadDone_EOSExpected,
2862 &video_read_done));
2864 // Verify that the reads don't complete.
2865 EXPECT_FALSE(audio_read_done);
2866 EXPECT_FALSE(video_read_done);
2868 MarkEndOfStream(PIPELINE_OK);
2870 EXPECT_TRUE(audio_read_done);
2871 EXPECT_TRUE(video_read_done);
2874 TEST_F(ChunkDemuxerTest, CanceledSeekDuringInitialPreroll) {
2875 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
2877 // Cancel preroll.
2878 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(200);
2879 demuxer_->CancelPendingSeek(seek_time);
2881 // Initiate the seek to the new location.
2882 Seek(seek_time);
2884 // Append data to satisfy the seek.
2885 AppendCluster(seek_time.InMilliseconds(), 10);
2888 TEST_F(ChunkDemuxerTest, GCDuringSeek) {
2889 ASSERT_TRUE(InitDemuxer(HAS_AUDIO));
2891 demuxer_->SetMemoryLimitsForTesting(5 * kBlockSize);
2893 base::TimeDelta seek_time1 = base::TimeDelta::FromMilliseconds(1000);
2894 base::TimeDelta seek_time2 = base::TimeDelta::FromMilliseconds(500);
2896 // Initiate a seek to |seek_time1|.
2897 Seek(seek_time1);
2899 // Append data to satisfy the first seek request.
2900 AppendSingleStreamCluster(kSourceId, kAudioTrackNum,
2901 seek_time1.InMilliseconds(), 5);
2902 CheckExpectedRanges(kSourceId, "{ [1000,1115) }");
2904 // Signal that the second seek is starting.
2905 demuxer_->StartWaitingForSeek(seek_time2);
2907 // Append data to satisfy the second seek. This append triggers
2908 // the garbage collection logic since we set the memory limit to
2909 // 5 blocks.
2910 AppendSingleStreamCluster(kSourceId, kAudioTrackNum,
2911 seek_time2.InMilliseconds(), 5);
2913 // Verify that the buffers that cover |seek_time2| do not get
2914 // garbage collected.
2915 CheckExpectedRanges(kSourceId, "{ [500,615) }");
2917 // Complete the seek.
2918 demuxer_->Seek(seek_time2, NewExpectedStatusCB(PIPELINE_OK));
2921 // Append more data and make sure that the blocks for |seek_time2|
2922 // don't get removed.
2924 // NOTE: The current GC algorithm tries to preserve the GOP at the
2925 // current position as well as the last appended GOP. This is
2926 // why there are 2 ranges in the expectations.
2927 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 700, 5);
2928 CheckExpectedRanges(kSourceId, "{ [500,592) [792,815) }");
2931 TEST_F(ChunkDemuxerTest, RemoveBeforeInitSegment) {
2932 EXPECT_CALL(*this, DemuxerOpened());
2933 demuxer_->Initialize(
2934 &host_, CreateInitDoneCB(kNoTimestamp(), PIPELINE_OK), true);
2936 EXPECT_EQ(ChunkDemuxer::kOk, AddId(kSourceId, HAS_AUDIO | HAS_VIDEO));
2938 demuxer_->Remove(kSourceId, base::TimeDelta::FromMilliseconds(0),
2939 base::TimeDelta::FromMilliseconds(1));
2942 TEST_F(ChunkDemuxerTest, AppendWindow_Video) {
2943 ASSERT_TRUE(InitDemuxer(HAS_VIDEO));
2944 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
2946 // Set the append window to [20,280).
2947 demuxer_->SetAppendWindowStart(kSourceId,
2948 base::TimeDelta::FromMilliseconds(20));
2949 demuxer_->SetAppendWindowEnd(kSourceId,
2950 base::TimeDelta::FromMilliseconds(280));
2952 // Append a cluster that starts before and ends after the append window.
2953 AppendSingleStreamCluster(kSourceId, kVideoTrackNum,
2954 "0K 30 60 90 120K 150 180 210 240K 270 300 330K");
2956 // Verify that GOPs that start outside the window are not included
2957 // in the buffer. Also verify that buffers that start inside the
2958 // window and extend beyond the end of the window are included.
2959 CheckExpectedRanges(kSourceId, "{ [120,300) }");
2960 CheckExpectedBuffers(stream, "120 150 180 210 240 270");
2962 // Extend the append window to [20,650).
2963 demuxer_->SetAppendWindowEnd(kSourceId,
2964 base::TimeDelta::FromMilliseconds(650));
2966 // Append more data and verify that adding buffers start at the next
2967 // keyframe.
2968 AppendSingleStreamCluster(kSourceId, kVideoTrackNum,
2969 "360 390 420K 450 480 510 540K 570 600 630K");
2970 CheckExpectedRanges(kSourceId, "{ [120,300) [420,660) }");
2973 TEST_F(ChunkDemuxerTest, AppendWindow_Audio) {
2974 ASSERT_TRUE(InitDemuxer(HAS_AUDIO));
2975 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::AUDIO);
2977 // Set the append window to [20,280).
2978 demuxer_->SetAppendWindowStart(kSourceId,
2979 base::TimeDelta::FromMilliseconds(20));
2980 demuxer_->SetAppendWindowEnd(kSourceId,
2981 base::TimeDelta::FromMilliseconds(280));
2983 // Append a cluster that starts before and ends after the append window.
2984 AppendSingleStreamCluster(
2985 kSourceId, kAudioTrackNum,
2986 "0K 30K 60K 90K 120K 150K 180K 210K 240K 270K 300K 330K");
2988 // Verify that frames that start outside the window are not included
2989 // in the buffer. Also verify that buffers that start inside the
2990 // window and extend beyond the end of the window are included.
2991 CheckExpectedRanges(kSourceId, "{ [30,300) }");
2992 CheckExpectedBuffers(stream, "30 60 90 120 150 180 210 240 270");
2994 // Extend the append window to [20,650).
2995 demuxer_->SetAppendWindowEnd(kSourceId,
2996 base::TimeDelta::FromMilliseconds(650));
2998 // Append more data and verify that a new range is created.
2999 AppendSingleStreamCluster(
3000 kSourceId, kAudioTrackNum,
3001 "360K 390K 420K 450K 480K 510K 540K 570K 600K 630K");
3002 CheckExpectedRanges(kSourceId, "{ [30,300) [360,660) }");
3005 TEST_F(ChunkDemuxerTest, AppendWindow_Text) {
3006 DemuxerStream* text_stream = NULL;
3007 EXPECT_CALL(host_, AddTextStream(_, _))
3008 .WillOnce(SaveArg<0>(&text_stream));
3009 ASSERT_TRUE(InitDemuxer(HAS_VIDEO | HAS_TEXT));
3010 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO);
3012 // Set the append window to [20,280).
3013 demuxer_->SetAppendWindowStart(kSourceId,
3014 base::TimeDelta::FromMilliseconds(20));
3015 demuxer_->SetAppendWindowEnd(kSourceId,
3016 base::TimeDelta::FromMilliseconds(280));
3018 // Append a cluster that starts before and ends after the append
3019 // window.
3020 AppendSingleStreamCluster(kSourceId, kVideoTrackNum,
3021 "0K 30 60 90 120K 150 180 210 240K 270 300 330K");
3022 AppendSingleStreamCluster(kSourceId, kTextTrackNum, "0K 100K 200K 300K");
3024 // Verify that text cues that start outside the window are not included
3025 // in the buffer. Also verify that cues that extend beyond the
3026 // window are included.
3027 CheckExpectedRanges(kSourceId, "{ [120,300) }");
3028 CheckExpectedBuffers(video_stream, "120 150 180 210 240 270");
3029 CheckExpectedBuffers(text_stream, "100 200");
3031 // Extend the append window to [20,650).
3032 demuxer_->SetAppendWindowEnd(kSourceId,
3033 base::TimeDelta::FromMilliseconds(650));
3035 // Append more data and verify that a new range is created.
3036 AppendSingleStreamCluster(kSourceId, kVideoTrackNum,
3037 "360 390 420K 450 480 510 540K 570 600 630K");
3038 AppendSingleStreamCluster(kSourceId, kTextTrackNum, "400K 500K 600K 700K");
3039 CheckExpectedRanges(kSourceId, "{ [120,300) [420,660) }");
3041 // Seek to the new range and verify that the expected buffers are returned.
3042 Seek(base::TimeDelta::FromMilliseconds(420));
3043 CheckExpectedBuffers(video_stream, "420 450 480 510 540 570 600 630");
3044 CheckExpectedBuffers(text_stream, "400 500 600");
3047 TEST_F(ChunkDemuxerTest, StartWaitingForSeekAfterParseError) {
3048 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
3049 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE));
3050 AppendGarbage();
3051 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(50);
3052 demuxer_->StartWaitingForSeek(seek_time);
3055 TEST_F(ChunkDemuxerTest, Remove_AudioVideoText) {
3056 DemuxerStream* text_stream = NULL;
3057 EXPECT_CALL(host_, AddTextStream(_, _))
3058 .WillOnce(SaveArg<0>(&text_stream));
3059 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO | HAS_TEXT));
3061 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO);
3062 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO);
3064 AppendSingleStreamCluster(kSourceId, kAudioTrackNum,
3065 "0K 20K 40K 60K 80K 100K 120K 140K");
3066 AppendSingleStreamCluster(kSourceId, kVideoTrackNum,
3067 "0K 30 60 90 120K 150 180");
3068 AppendSingleStreamCluster(kSourceId, kTextTrackNum, "0K 100K 200K");
3070 CheckExpectedBuffers(audio_stream, "0 20 40 60 80 100 120 140");
3071 CheckExpectedBuffers(video_stream, "0 30 60 90 120 150 180");
3072 CheckExpectedBuffers(text_stream, "0 100 200");
3074 // Remove the buffers that were added.
3075 demuxer_->Remove(kSourceId, base::TimeDelta(),
3076 base::TimeDelta::FromMilliseconds(300));
3078 // Verify that all the appended data has been removed.
3079 CheckExpectedRanges(kSourceId, "{ }");
3081 // Append new buffers that are clearly different than the original
3082 // ones and verify that only the new buffers are returned.
3083 AppendSingleStreamCluster(kSourceId, kAudioTrackNum,
3084 "1K 21K 41K 61K 81K 101K 121K 141K");
3085 AppendSingleStreamCluster(kSourceId, kVideoTrackNum,
3086 "1K 31 61 91 121K 151 181");
3087 AppendSingleStreamCluster(kSourceId, kTextTrackNum, "1K 101K 201K");
3089 Seek(base::TimeDelta());
3090 CheckExpectedBuffers(audio_stream, "1 21 41 61 81 101 121 141");
3091 CheckExpectedBuffers(video_stream, "1 31 61 91 121 151 181");
3092 CheckExpectedBuffers(text_stream, "1 101 201");
3095 // Verifies that a Seek() will complete without text cues for
3096 // the seek point and will return cues after the seek position
3097 // when they are eventually appended.
3098 TEST_F(ChunkDemuxerTest, SeekCompletesWithoutTextCues) {
3099 DemuxerStream* text_stream = NULL;
3100 EXPECT_CALL(host_, AddTextStream(_, _))
3101 .WillOnce(SaveArg<0>(&text_stream));
3102 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO | HAS_TEXT));
3104 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO);
3105 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO);
3107 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(120);
3108 bool seek_cb_was_called = false;
3109 demuxer_->StartWaitingForSeek(seek_time);
3110 demuxer_->Seek(seek_time,
3111 base::Bind(OnSeekDone_OKExpected, &seek_cb_was_called));
3112 message_loop_.RunUntilIdle();
3114 EXPECT_FALSE(seek_cb_was_called);
3116 bool text_read_done = false;
3117 text_stream->Read(base::Bind(&OnReadDone,
3118 base::TimeDelta::FromMilliseconds(125),
3119 &text_read_done));
3121 // Append audio & video data so the seek completes.
3122 AppendSingleStreamCluster(kSourceId, kAudioTrackNum,
3123 "0K 20K 40K 60K 80K 100K 120K 140K 160K 180K");
3124 AppendSingleStreamCluster(kSourceId, kVideoTrackNum,
3125 "0K 30 60 90 120K 150 180 210");
3127 message_loop_.RunUntilIdle();
3128 EXPECT_TRUE(seek_cb_was_called);
3129 EXPECT_FALSE(text_read_done);
3131 // Read some audio & video buffers to further verify seek completion.
3132 CheckExpectedBuffers(audio_stream, "120 140");
3133 CheckExpectedBuffers(video_stream, "120 150");
3135 EXPECT_FALSE(text_read_done);
3137 // Append text cues that start after the seek point and verify that
3138 // they are returned by Read() calls.
3139 AppendSingleStreamCluster(kSourceId, kTextTrackNum, "125K 175K 225K");
3141 message_loop_.RunUntilIdle();
3142 EXPECT_TRUE(text_read_done);
3144 // NOTE: we start at 175 here because the buffer at 125 was returned
3145 // to the pending read initiated above.
3146 CheckExpectedBuffers(text_stream, "175 225");
3148 // Verify that audio & video streams contiue to return expected values.
3149 CheckExpectedBuffers(audio_stream, "160 180");
3150 CheckExpectedBuffers(video_stream, "180 210");
3153 } // namespace media