Report errors from ChromiumEnv::GetChildren in Posix.
[chromium-blink-merge.git] / media / filters / chunk_demuxer_unittest.cc
blob3d9b26f681ccb956b64f3efea7fdf5ec9e548a66
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/webm/cluster_builder.h"
20 #include "media/webm/webm_constants.h"
21 #include "media/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 static 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 static 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 static const uint8 kVP8Interframe[] = { 0x11, 0x00, 0x00 };
48 static const int kTracksHeaderSize = sizeof(kTracksHeader);
49 static 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 static const int kAudioTrackSizeOffset = 1;
54 static const int kAudioTrackSizeWidth = 8;
55 static const int kAudioTrackEntryHeaderSize = kAudioTrackSizeOffset +
56 kAudioTrackSizeWidth;
58 // The size of TrackEntry element in test file "webm_vp8_track_entry" starts at
59 // index 1 and spans 8 bytes.
60 static const int kVideoTrackSizeOffset = 1;
61 static const int kVideoTrackSizeWidth = 8;
62 static const int kVideoTrackEntryHeaderSize = kVideoTrackSizeOffset +
63 kVideoTrackSizeWidth;
65 static const int kVideoTrackNum = 1;
66 static const int kAudioTrackNum = 2;
68 static const int kAudioBlockDuration = 23;
69 static const int kVideoBlockDuration = 33;
70 static const int kBlockSize = 10;
72 static const char kSourceId[] = "SourceId";
73 static const char kDefaultFirstClusterRange[] = "{ [0,46) }";
74 static const int kDefaultFirstClusterEndTimestamp = 66;
75 static const int kDefaultSecondClusterEndTimestamp = 132;
77 base::TimeDelta kDefaultDuration() {
78 return base::TimeDelta::FromMilliseconds(201224);
81 // Write an integer into buffer in the form of vint that spans 8 bytes.
82 // The data pointed by |buffer| should be at least 8 bytes long.
83 // |number| should be in the range 0 <= number < 0x00FFFFFFFFFFFFFF.
84 static void WriteInt64(uint8* buffer, int64 number) {
85 DCHECK(number >= 0 && number < GG_LONGLONG(0x00FFFFFFFFFFFFFF));
86 buffer[0] = 0x01;
87 int64 tmp = number;
88 for (int i = 7; i > 0; i--) {
89 buffer[i] = tmp & 0xff;
90 tmp >>= 8;
94 MATCHER_P(HasTimestamp, timestamp_in_ms, "") {
95 return arg.get() && !arg->end_of_stream() &&
96 arg->timestamp().InMilliseconds() == timestamp_in_ms;
99 MATCHER(IsEndOfStream, "") { return arg.get() && arg->end_of_stream(); }
101 static void OnReadDone(const base::TimeDelta& expected_time,
102 bool* called,
103 DemuxerStream::Status status,
104 const scoped_refptr<DecoderBuffer>& buffer) {
105 EXPECT_EQ(status, DemuxerStream::kOk);
106 EXPECT_EQ(expected_time, buffer->timestamp());
107 *called = true;
110 static void OnReadDone_AbortExpected(
111 bool* called, DemuxerStream::Status status,
112 const scoped_refptr<DecoderBuffer>& buffer) {
113 EXPECT_EQ(status, DemuxerStream::kAborted);
114 EXPECT_EQ(NULL, buffer.get());
115 *called = true;
118 static void OnReadDone_EOSExpected(bool* called,
119 DemuxerStream::Status status,
120 const scoped_refptr<DecoderBuffer>& buffer) {
121 EXPECT_EQ(status, DemuxerStream::kOk);
122 EXPECT_TRUE(buffer->end_of_stream());
123 *called = true;
126 static void OnSeekDone_OKExpected(bool* called, PipelineStatus status) {
127 EXPECT_EQ(status, PIPELINE_OK);
128 *called = true;
131 class ChunkDemuxerTest : public testing::Test {
132 protected:
133 enum CodecsIndex {
134 AUDIO,
135 VIDEO,
136 MAX_CODECS_INDEX
139 // Default cluster to append first for simple tests.
140 scoped_ptr<Cluster> kDefaultFirstCluster() {
141 return GenerateCluster(0, 4);
144 // Default cluster to append after kDefaultFirstCluster()
145 // has been appended. This cluster starts with blocks that
146 // have timestamps consistent with the end times of the blocks
147 // in kDefaultFirstCluster() so that these two clusters represent
148 // a continuous region.
149 scoped_ptr<Cluster> kDefaultSecondCluster() {
150 return GenerateCluster(46, 66, 5);
153 ChunkDemuxerTest() {
154 CreateNewDemuxer();
157 void CreateNewDemuxer() {
158 base::Closure open_cb =
159 base::Bind(&ChunkDemuxerTest::DemuxerOpened, base::Unretained(this));
160 Demuxer::NeedKeyCB need_key_cb =
161 base::Bind(&ChunkDemuxerTest::DemuxerNeedKey, base::Unretained(this));
162 AddTextTrackCB add_text_track_cb =
163 base::Bind(&ChunkDemuxerTest::OnTextTrack, base::Unretained(this));
164 demuxer_.reset(new ChunkDemuxer(open_cb, need_key_cb,
165 add_text_track_cb, LogCB()));
168 virtual ~ChunkDemuxerTest() {
169 ShutdownDemuxer();
172 void CreateInitSegment(bool has_audio, bool has_video,
173 bool is_audio_encrypted, bool is_video_encrypted,
174 scoped_ptr<uint8[]>* buffer,
175 int* size) {
176 scoped_refptr<DecoderBuffer> ebml_header;
177 scoped_refptr<DecoderBuffer> info;
178 scoped_refptr<DecoderBuffer> audio_track_entry;
179 scoped_refptr<DecoderBuffer> video_track_entry;
180 scoped_refptr<DecoderBuffer> audio_content_encodings;
181 scoped_refptr<DecoderBuffer> video_content_encodings;
183 ebml_header = ReadTestDataFile("webm_ebml_element");
185 info = ReadTestDataFile("webm_info_element");
187 int tracks_element_size = 0;
189 if (has_audio) {
190 audio_track_entry = ReadTestDataFile("webm_vorbis_track_entry");
191 tracks_element_size += audio_track_entry->data_size();
192 if (is_audio_encrypted) {
193 audio_content_encodings = ReadTestDataFile("webm_content_encodings");
194 tracks_element_size += audio_content_encodings->data_size();
198 if (has_video) {
199 video_track_entry = ReadTestDataFile("webm_vp8_track_entry");
200 tracks_element_size += video_track_entry->data_size();
201 if (is_video_encrypted) {
202 video_content_encodings = ReadTestDataFile("webm_content_encodings");
203 tracks_element_size += video_content_encodings->data_size();
207 *size = ebml_header->data_size() + info->data_size() +
208 kTracksHeaderSize + tracks_element_size;
210 buffer->reset(new uint8[*size]);
212 uint8* buf = buffer->get();
213 memcpy(buf, ebml_header->data(), ebml_header->data_size());
214 buf += ebml_header->data_size();
216 memcpy(buf, info->data(), info->data_size());
217 buf += info->data_size();
219 memcpy(buf, kTracksHeader, kTracksHeaderSize);
220 WriteInt64(buf + kTracksSizeOffset, tracks_element_size);
221 buf += kTracksHeaderSize;
223 // TODO(xhwang): Simplify this! Probably have test data files that contain
224 // ContentEncodings directly instead of trying to create one at run-time.
225 if (has_audio) {
226 memcpy(buf, audio_track_entry->data(),
227 audio_track_entry->data_size());
228 if (is_audio_encrypted) {
229 memcpy(buf + audio_track_entry->data_size(),
230 audio_content_encodings->data(),
231 audio_content_encodings->data_size());
232 WriteInt64(buf + kAudioTrackSizeOffset,
233 audio_track_entry->data_size() +
234 audio_content_encodings->data_size() -
235 kAudioTrackEntryHeaderSize);
236 buf += audio_content_encodings->data_size();
238 buf += audio_track_entry->data_size();
241 if (has_video) {
242 memcpy(buf, video_track_entry->data(),
243 video_track_entry->data_size());
244 if (is_video_encrypted) {
245 memcpy(buf + video_track_entry->data_size(),
246 video_content_encodings->data(),
247 video_content_encodings->data_size());
248 WriteInt64(buf + kVideoTrackSizeOffset,
249 video_track_entry->data_size() +
250 video_content_encodings->data_size() -
251 kVideoTrackEntryHeaderSize);
252 buf += video_content_encodings->data_size();
254 buf += video_track_entry->data_size();
258 ChunkDemuxer::Status AddId() {
259 return AddId(kSourceId, true, true);
262 ChunkDemuxer::Status AddId(const std::string& source_id,
263 bool has_audio, bool has_video) {
264 std::vector<std::string> codecs;
265 std::string type;
267 if (has_audio) {
268 codecs.push_back("vorbis");
269 type = "audio/webm";
272 if (has_video) {
273 codecs.push_back("vp8");
274 type = "video/webm";
277 if (!has_audio && !has_video) {
278 return AddId(kSourceId, true, true);
281 return demuxer_->AddId(source_id, type, codecs);
284 void AppendData(const uint8* data, size_t length) {
285 AppendData(kSourceId, data, length);
288 void AppendCluster(const std::string& source_id,
289 scoped_ptr<Cluster> cluster) {
290 AppendData(source_id, cluster->data(), cluster->size());
293 void AppendCluster(scoped_ptr<Cluster> cluster) {
294 AppendCluster(kSourceId, cluster.Pass());
297 void AppendCluster(int timecode, int block_count) {
298 AppendCluster(GenerateCluster(timecode, block_count));
301 void AppendSingleStreamCluster(const std::string& source_id, int track_number,
302 int timecode, int block_count) {
303 int block_duration = 0;
304 switch(track_number) {
305 case kVideoTrackNum:
306 block_duration = kVideoBlockDuration;
307 break;
308 case kAudioTrackNum:
309 block_duration = kAudioBlockDuration;
310 break;
312 ASSERT_NE(block_duration, 0);
313 int end_timecode = timecode + block_count * block_duration;
314 AppendCluster(source_id,
315 GenerateSingleStreamCluster(
316 timecode, end_timecode, track_number, block_duration));
319 void AppendSingleStreamCluster(const std::string& source_id, int track_number,
320 const std::string& cluster_description) {
321 std::vector<std::string> timestamps;
322 base::SplitString(cluster_description, ' ', &timestamps);
324 ClusterBuilder cb;
325 std::vector<uint8> data(10);
326 for (size_t i = 0; i < timestamps.size(); ++i) {
327 std::string timestamp_str = timestamps[i];
328 int block_flags = 0;
329 if (EndsWith(timestamp_str, "K", true)) {
330 block_flags = kWebMFlagKeyframe;
331 // Remove the "K" off of the token.
332 timestamp_str = timestamp_str.substr(0, timestamps[i].length() - 1);
334 int timestamp_in_ms;
335 CHECK(base::StringToInt(timestamp_str, &timestamp_in_ms));
337 if (i == 0)
338 cb.SetClusterTimecode(timestamp_in_ms);
340 cb.AddSimpleBlock(track_number, timestamp_in_ms, block_flags,
341 &data[0], data.size());
343 AppendCluster(source_id, cb.Finish());
346 void AppendData(const std::string& source_id,
347 const uint8* data, size_t length) {
348 EXPECT_CALL(host_, AddBufferedTimeRange(_, _)).Times(AnyNumber());
349 demuxer_->AppendData(source_id, data, length);
352 void AppendDataInPieces(const uint8* data, size_t length) {
353 AppendDataInPieces(data, length, 7);
356 void AppendDataInPieces(const uint8* data, size_t length, size_t piece_size) {
357 const uint8* start = data;
358 const uint8* end = data + length;
359 while (start < end) {
360 size_t append_size = std::min(piece_size,
361 static_cast<size_t>(end - start));
362 AppendData(start, append_size);
363 start += append_size;
367 void AppendInitSegment(bool has_audio, bool has_video) {
368 AppendInitSegmentWithSourceId(kSourceId, has_audio, has_video);
371 void AppendInitSegmentWithSourceId(const std::string& source_id,
372 bool has_audio, bool has_video) {
373 AppendInitSegmentWithEncryptedInfo(
374 source_id, has_audio, has_video, false, false);
377 void AppendInitSegmentWithEncryptedInfo(const std::string& source_id,
378 bool has_audio, bool has_video,
379 bool is_audio_encrypted,
380 bool is_video_encrypted) {
381 scoped_ptr<uint8[]> info_tracks;
382 int info_tracks_size = 0;
383 CreateInitSegment(has_audio, has_video,
384 is_audio_encrypted, is_video_encrypted,
385 &info_tracks, &info_tracks_size);
386 AppendData(source_id, info_tracks.get(), info_tracks_size);
389 void AppendGarbage() {
390 // Fill up an array with gibberish.
391 int garbage_cluster_size = 10;
392 scoped_ptr<uint8[]> garbage_cluster(new uint8[garbage_cluster_size]);
393 for (int i = 0; i < garbage_cluster_size; ++i)
394 garbage_cluster[i] = i;
395 AppendData(garbage_cluster.get(), garbage_cluster_size);
398 void InitDoneCalled(PipelineStatus expected_status,
399 PipelineStatus status) {
400 EXPECT_EQ(status, expected_status);
403 void AppendEmptyCluster(int timecode) {
404 AppendCluster(GenerateEmptyCluster(timecode));
407 PipelineStatusCB CreateInitDoneCB(const base::TimeDelta& expected_duration,
408 PipelineStatus expected_status) {
409 if (expected_duration != kNoTimestamp())
410 EXPECT_CALL(host_, SetDuration(expected_duration));
411 return CreateInitDoneCB(expected_status);
414 PipelineStatusCB CreateInitDoneCB(PipelineStatus expected_status) {
415 return base::Bind(&ChunkDemuxerTest::InitDoneCalled,
416 base::Unretained(this),
417 expected_status);
420 bool InitDemuxer(bool has_audio, bool has_video) {
421 return InitDemuxerWithEncryptionInfo(has_audio, has_video, false, false);
424 bool InitDemuxerWithEncryptionInfo(
425 bool has_audio, bool has_video,
426 bool is_audio_encrypted, bool is_video_encrypted) {
427 PipelineStatus expected_status =
428 (has_audio || has_video) ? PIPELINE_OK : DEMUXER_ERROR_COULD_NOT_OPEN;
430 base::TimeDelta expected_duration = kNoTimestamp();
431 if (expected_status == PIPELINE_OK)
432 expected_duration = kDefaultDuration();
434 EXPECT_CALL(*this, DemuxerOpened());
435 demuxer_->Initialize(
436 &host_, CreateInitDoneCB(expected_duration, expected_status));
438 if (AddId(kSourceId, has_audio, has_video) != ChunkDemuxer::kOk)
439 return false;
441 AppendInitSegmentWithEncryptedInfo(
442 kSourceId, has_audio, has_video,
443 is_audio_encrypted, is_video_encrypted);
444 return true;
447 bool InitDemuxerAudioAndVideoSources(const std::string& audio_id,
448 const std::string& video_id) {
449 EXPECT_CALL(*this, DemuxerOpened());
450 demuxer_->Initialize(
451 &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK));
453 if (AddId(audio_id, true, false) != ChunkDemuxer::kOk)
454 return false;
455 if (AddId(video_id, false, true) != ChunkDemuxer::kOk)
456 return false;
458 AppendInitSegmentWithSourceId(audio_id, true, false);
459 AppendInitSegmentWithSourceId(video_id, false, true);
460 return true;
463 // Initializes the demuxer with data from 2 files with different
464 // decoder configurations. This is used to test the decoder config change
465 // logic.
467 // bear-320x240.webm VideoDecoderConfig returns 320x240 for its natural_size()
468 // bear-640x360.webm VideoDecoderConfig returns 640x360 for its natural_size()
469 // The resulting video stream returns data from each file for the following
470 // time ranges.
471 // bear-320x240.webm : [0-501) [801-2737)
472 // bear-640x360.webm : [527-793)
474 // bear-320x240.webm AudioDecoderConfig returns 3863 for its extra_data_size()
475 // bear-640x360.webm AudioDecoderConfig returns 3935 for its extra_data_size()
476 // The resulting audio stream returns data from each file for the following
477 // time ranges.
478 // bear-320x240.webm : [0-524) [779-2737)
479 // bear-640x360.webm : [527-759)
480 bool InitDemuxerWithConfigChangeData() {
481 scoped_refptr<DecoderBuffer> bear1 = ReadTestDataFile("bear-320x240.webm");
482 scoped_refptr<DecoderBuffer> bear2 = ReadTestDataFile("bear-640x360.webm");
484 EXPECT_CALL(*this, DemuxerOpened());
485 demuxer_->Initialize(
486 &host_, CreateInitDoneCB(base::TimeDelta::FromMilliseconds(2744),
487 PIPELINE_OK));
489 if (AddId(kSourceId, true, true) != ChunkDemuxer::kOk)
490 return false;
492 // Append the whole bear1 file.
493 AppendData(bear1->data(), bear1->data_size());
494 CheckExpectedRanges(kSourceId, "{ [0,2737) }");
496 // Append initialization segment for bear2.
497 // Note: Offsets here and below are derived from
498 // media/test/data/bear-640x360-manifest.js and
499 // media/test/data/bear-320x240-manifest.js which were
500 // generated from media/test/data/bear-640x360.webm and
501 // media/test/data/bear-320x240.webm respectively.
502 AppendData(bear2->data(), 4340);
504 // Append a media segment that goes from [0.527000, 1.014000).
505 AppendData(bear2->data() + 55290, 18785);
506 CheckExpectedRanges(kSourceId, "{ [0,1028) [1201,2737) }");
508 // Append initialization segment for bear1 & fill gap with [779-1197)
509 // segment.
510 AppendData(bear1->data(), 4370);
511 AppendData(bear1->data() + 72737, 28183);
512 CheckExpectedRanges(kSourceId, "{ [0,2737) }");
514 MarkEndOfStream(PIPELINE_OK);
515 return true;
518 void ShutdownDemuxer() {
519 if (demuxer_) {
520 demuxer_->Shutdown();
521 message_loop_.RunUntilIdle();
525 void AddSimpleBlock(ClusterBuilder* cb, int track_num, int64 timecode) {
526 uint8 data[] = { 0x00 };
527 cb->AddSimpleBlock(track_num, timecode, 0, data, sizeof(data));
530 scoped_ptr<Cluster> GenerateCluster(int timecode, int block_count) {
531 return GenerateCluster(timecode, timecode, block_count);
534 void AddVideoBlockGroup(ClusterBuilder* cb, int track_num, int64 timecode,
535 int duration, int flags) {
536 const uint8* data =
537 (flags & kWebMFlagKeyframe) != 0 ? kVP8Keyframe : kVP8Interframe;
538 int size = (flags & kWebMFlagKeyframe) != 0 ? sizeof(kVP8Keyframe) :
539 sizeof(kVP8Interframe);
540 cb->AddBlockGroup(track_num, timecode, duration, flags, data, size);
543 scoped_ptr<Cluster> GenerateCluster(int first_audio_timecode,
544 int first_video_timecode,
545 int block_count) {
546 CHECK_GT(block_count, 0);
548 int size = 10;
549 scoped_ptr<uint8[]> data(new uint8[size]);
551 ClusterBuilder cb;
552 cb.SetClusterTimecode(std::min(first_audio_timecode, first_video_timecode));
554 if (block_count == 1) {
555 cb.AddBlockGroup(kAudioTrackNum, first_audio_timecode,
556 kAudioBlockDuration, kWebMFlagKeyframe,
557 data.get(), size);
558 return cb.Finish();
561 int audio_timecode = first_audio_timecode;
562 int video_timecode = first_video_timecode;
564 // Create simple blocks for everything except the last 2 blocks.
565 // The first video frame must be a keyframe.
566 uint8 video_flag = kWebMFlagKeyframe;
567 for (int i = 0; i < block_count - 2; i++) {
568 if (audio_timecode <= video_timecode) {
569 cb.AddSimpleBlock(kAudioTrackNum, audio_timecode, kWebMFlagKeyframe,
570 data.get(), size);
571 audio_timecode += kAudioBlockDuration;
572 continue;
575 cb.AddSimpleBlock(kVideoTrackNum, video_timecode, video_flag, data.get(),
576 size);
577 video_timecode += kVideoBlockDuration;
578 video_flag = 0;
581 // Make the last 2 blocks BlockGroups so that they don't get delayed by the
582 // block duration calculation logic.
583 if (audio_timecode <= video_timecode) {
584 cb.AddBlockGroup(kAudioTrackNum, audio_timecode, kAudioBlockDuration,
585 kWebMFlagKeyframe, data.get(), size);
586 AddVideoBlockGroup(&cb, kVideoTrackNum, video_timecode,
587 kVideoBlockDuration, video_flag);
588 } else {
589 AddVideoBlockGroup(&cb, kVideoTrackNum, video_timecode,
590 kVideoBlockDuration, video_flag);
591 cb.AddBlockGroup(kAudioTrackNum, audio_timecode, kAudioBlockDuration,
592 kWebMFlagKeyframe, data.get(), size);
595 return cb.Finish();
598 scoped_ptr<Cluster> GenerateSingleStreamCluster(int timecode,
599 int end_timecode,
600 int track_number,
601 int block_duration) {
602 CHECK_GT(end_timecode, timecode);
604 std::vector<uint8> data(kBlockSize);
606 ClusterBuilder cb;
607 cb.SetClusterTimecode(timecode);
609 // Create simple blocks for everything except the last block.
610 for (int i = 0; timecode < (end_timecode - block_duration); i++) {
611 cb.AddSimpleBlock(track_number, timecode, kWebMFlagKeyframe,
612 &data[0], data.size());
613 timecode += block_duration;
616 // Make the last block a BlockGroup so that it doesn't get delayed by the
617 // block duration calculation logic.
618 if (track_number == kVideoTrackNum) {
619 AddVideoBlockGroup(&cb, track_number, timecode, block_duration,
620 kWebMFlagKeyframe);
621 } else {
622 cb.AddBlockGroup(track_number, timecode, block_duration,
623 kWebMFlagKeyframe, &data[0], data.size());
625 return cb.Finish();
628 void Read(DemuxerStream::Type type, const DemuxerStream::ReadCB& read_cb) {
629 demuxer_->GetStream(type)->Read(read_cb);
630 message_loop_.RunUntilIdle();
633 void ReadAudio(const DemuxerStream::ReadCB& read_cb) {
634 Read(DemuxerStream::AUDIO, read_cb);
637 void ReadVideo(const DemuxerStream::ReadCB& read_cb) {
638 Read(DemuxerStream::VIDEO, read_cb);
641 void GenerateExpectedReads(int timecode, int block_count) {
642 GenerateExpectedReads(timecode, timecode, block_count);
645 void GenerateExpectedReads(int start_audio_timecode,
646 int start_video_timecode,
647 int block_count) {
648 CHECK_GT(block_count, 0);
650 if (block_count == 1) {
651 ExpectRead(DemuxerStream::AUDIO, start_audio_timecode);
652 return;
655 int audio_timecode = start_audio_timecode;
656 int video_timecode = start_video_timecode;
658 for (int i = 0; i < block_count; i++) {
659 if (audio_timecode <= video_timecode) {
660 ExpectRead(DemuxerStream::AUDIO, audio_timecode);
661 audio_timecode += kAudioBlockDuration;
662 continue;
665 ExpectRead(DemuxerStream::VIDEO, video_timecode);
666 video_timecode += kVideoBlockDuration;
670 void GenerateSingleStreamExpectedReads(int timecode,
671 int block_count,
672 DemuxerStream::Type type,
673 int block_duration) {
674 CHECK_GT(block_count, 0);
675 int stream_timecode = timecode;
677 for (int i = 0; i < block_count; i++) {
678 ExpectRead(type, stream_timecode);
679 stream_timecode += block_duration;
683 void GenerateAudioStreamExpectedReads(int timecode, int block_count) {
684 GenerateSingleStreamExpectedReads(
685 timecode, block_count, DemuxerStream::AUDIO, kAudioBlockDuration);
688 void GenerateVideoStreamExpectedReads(int timecode, int block_count) {
689 GenerateSingleStreamExpectedReads(
690 timecode, block_count, DemuxerStream::VIDEO, kVideoBlockDuration);
693 scoped_ptr<Cluster> GenerateEmptyCluster(int timecode) {
694 ClusterBuilder cb;
695 cb.SetClusterTimecode(timecode);
696 return cb.Finish();
699 void CheckExpectedRanges(const std::string& expected) {
700 CheckExpectedRanges(kSourceId, expected);
703 void CheckExpectedRanges(const std::string& id,
704 const std::string& expected) {
705 Ranges<base::TimeDelta> r = demuxer_->GetBufferedRanges(id);
707 std::stringstream ss;
708 ss << "{ ";
709 for (size_t i = 0; i < r.size(); ++i) {
710 ss << "[" << r.start(i).InMilliseconds() << ","
711 << r.end(i).InMilliseconds() << ") ";
713 ss << "}";
714 EXPECT_EQ(ss.str(), expected);
717 MOCK_METHOD2(ReadDone, void(DemuxerStream::Status status,
718 const scoped_refptr<DecoderBuffer>&));
720 void StoreStatusAndBuffer(DemuxerStream::Status* status_out,
721 scoped_refptr<DecoderBuffer>* buffer_out,
722 DemuxerStream::Status status,
723 const scoped_refptr<DecoderBuffer>& buffer) {
724 *status_out = status;
725 *buffer_out = buffer;
728 void ReadUntilNotOkOrEndOfStream(DemuxerStream::Type type,
729 DemuxerStream::Status* status,
730 base::TimeDelta* last_timestamp) {
731 DemuxerStream* stream = demuxer_->GetStream(type);
732 scoped_refptr<DecoderBuffer> buffer;
734 *last_timestamp = kNoTimestamp();
735 do {
736 stream->Read(base::Bind(&ChunkDemuxerTest::StoreStatusAndBuffer,
737 base::Unretained(this), status, &buffer));
738 base::MessageLoop::current()->RunUntilIdle();
739 if (*status == DemuxerStream::kOk && !buffer->end_of_stream())
740 *last_timestamp = buffer->timestamp();
741 } while (*status == DemuxerStream::kOk && !buffer->end_of_stream());
744 void ExpectEndOfStream(DemuxerStream::Type type) {
745 EXPECT_CALL(*this, ReadDone(DemuxerStream::kOk, IsEndOfStream()));
746 demuxer_->GetStream(type)->Read(base::Bind(
747 &ChunkDemuxerTest::ReadDone, base::Unretained(this)));
748 message_loop_.RunUntilIdle();
751 void ExpectRead(DemuxerStream::Type type, int64 timestamp_in_ms) {
752 EXPECT_CALL(*this, ReadDone(DemuxerStream::kOk,
753 HasTimestamp(timestamp_in_ms)));
754 demuxer_->GetStream(type)->Read(base::Bind(
755 &ChunkDemuxerTest::ReadDone, base::Unretained(this)));
756 message_loop_.RunUntilIdle();
759 void ExpectConfigChanged(DemuxerStream::Type type) {
760 EXPECT_CALL(*this, ReadDone(DemuxerStream::kConfigChanged, _));
761 demuxer_->GetStream(type)->Read(base::Bind(
762 &ChunkDemuxerTest::ReadDone, base::Unretained(this)));
763 message_loop_.RunUntilIdle();
766 void CheckExpectedBuffers(DemuxerStream* stream,
767 const std::string& expected) {
768 std::vector<std::string> timestamps;
769 base::SplitString(expected, ' ', &timestamps);
770 std::stringstream ss;
771 for (size_t i = 0; i < timestamps.size(); ++i) {
772 DemuxerStream::Status status;
773 scoped_refptr<DecoderBuffer> buffer;
774 stream->Read(base::Bind(&ChunkDemuxerTest::StoreStatusAndBuffer,
775 base::Unretained(this), &status, &buffer));
776 base::MessageLoop::current()->RunUntilIdle();
777 if (status != DemuxerStream::kOk || buffer->end_of_stream())
778 break;
780 if (i > 0)
781 ss << " ";
782 ss << buffer->timestamp().InMilliseconds();
784 EXPECT_EQ(expected, ss.str());
787 MOCK_METHOD1(Checkpoint, void(int id));
789 struct BufferTimestamps {
790 int video_time_ms;
791 int audio_time_ms;
793 static const int kSkip = -1;
795 // Test parsing a WebM file.
796 // |filename| - The name of the file in media/test/data to parse.
797 // |timestamps| - The expected timestamps on the parsed buffers.
798 // a timestamp of kSkip indicates that a Read() call for that stream
799 // shouldn't be made on that iteration of the loop. If both streams have
800 // a kSkip then the loop will terminate.
801 bool ParseWebMFile(const std::string& filename,
802 const BufferTimestamps* timestamps,
803 const base::TimeDelta& duration) {
804 return ParseWebMFile(filename, timestamps, duration, true, true);
807 bool ParseWebMFile(const std::string& filename,
808 const BufferTimestamps* timestamps,
809 const base::TimeDelta& duration,
810 bool has_audio, bool has_video) {
811 EXPECT_CALL(*this, DemuxerOpened());
812 demuxer_->Initialize(
813 &host_, CreateInitDoneCB(duration, PIPELINE_OK));
815 if (AddId(kSourceId, has_audio, has_video) != ChunkDemuxer::kOk)
816 return false;
818 // Read a WebM file into memory and send the data to the demuxer.
819 scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(filename);
820 AppendDataInPieces(buffer->data(), buffer->data_size(), 512);
822 // Verify that the timestamps on the first few packets match what we
823 // expect.
824 for (size_t i = 0;
825 (timestamps[i].audio_time_ms != kSkip ||
826 timestamps[i].video_time_ms != kSkip);
827 i++) {
828 bool audio_read_done = false;
829 bool video_read_done = false;
831 if (timestamps[i].audio_time_ms != kSkip) {
832 ReadAudio(base::Bind(&OnReadDone,
833 base::TimeDelta::FromMilliseconds(
834 timestamps[i].audio_time_ms),
835 &audio_read_done));
836 EXPECT_TRUE(audio_read_done);
839 if (timestamps[i].video_time_ms != kSkip) {
840 ReadVideo(base::Bind(&OnReadDone,
841 base::TimeDelta::FromMilliseconds(
842 timestamps[i].video_time_ms),
843 &video_read_done));
844 EXPECT_TRUE(video_read_done);
848 return true;
851 MOCK_METHOD0(DemuxerOpened, void());
852 // TODO(xhwang): This is a workaround of the issue that move-only parameters
853 // are not supported in mocked methods. Remove this when the issue is fixed
854 // (http://code.google.com/p/googletest/issues/detail?id=395) or when we use
855 // std::string instead of scoped_ptr<uint8[]> (http://crbug.com/130689).
856 MOCK_METHOD3(NeedKeyMock, void(const std::string& type,
857 const uint8* init_data, int init_data_size));
858 void DemuxerNeedKey(const std::string& type,
859 const std::vector<uint8>& init_data) {
860 const uint8* init_data_ptr = init_data.empty() ? NULL : &init_data[0];
861 NeedKeyMock(type, init_data_ptr, init_data.size());
864 scoped_ptr<TextTrack> OnTextTrack(TextKind kind,
865 const std::string& label,
866 const std::string& language) {
867 return scoped_ptr<TextTrack>();
870 void Seek(base::TimeDelta seek_time) {
871 demuxer_->StartWaitingForSeek(seek_time);
872 demuxer_->Seek(seek_time, NewExpectedStatusCB(PIPELINE_OK));
873 message_loop_.RunUntilIdle();
876 void MarkEndOfStream(PipelineStatus status) {
877 demuxer_->MarkEndOfStream(status);
878 message_loop_.RunUntilIdle();
881 base::MessageLoop message_loop_;
882 MockDemuxerHost host_;
884 scoped_ptr<ChunkDemuxer> demuxer_;
886 private:
887 DISALLOW_COPY_AND_ASSIGN(ChunkDemuxerTest);
890 TEST_F(ChunkDemuxerTest, Init) {
891 // Test no streams, audio-only, video-only, and audio & video scenarios.
892 // Audio and video streams can be encrypted or not encrypted.
893 for (int i = 0; i < 16; i++) {
894 bool has_audio = (i & 0x1) != 0;
895 bool has_video = (i & 0x2) != 0;
896 bool is_audio_encrypted = (i & 0x4) != 0;
897 bool is_video_encrypted = (i & 0x8) != 0;
899 // No test on invalid combination.
900 if ((!has_audio && is_audio_encrypted) ||
901 (!has_video && is_video_encrypted)) {
902 continue;
905 CreateNewDemuxer();
907 if (is_audio_encrypted || is_video_encrypted) {
908 int need_key_count = (is_audio_encrypted ? 1 : 0) +
909 (is_video_encrypted ? 1 : 0);
910 EXPECT_CALL(*this, NeedKeyMock(kWebMEncryptInitDataType, NotNull(),
911 DecryptConfig::kDecryptionKeySize))
912 .Times(Exactly(need_key_count));
915 ASSERT_TRUE(InitDemuxerWithEncryptionInfo(
916 has_audio, has_video, is_audio_encrypted, is_video_encrypted));
918 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO);
919 if (has_audio) {
920 ASSERT_TRUE(audio_stream);
922 const AudioDecoderConfig& config = audio_stream->audio_decoder_config();
923 EXPECT_EQ(kCodecVorbis, config.codec());
924 EXPECT_EQ(32, config.bits_per_channel());
925 EXPECT_EQ(CHANNEL_LAYOUT_STEREO, config.channel_layout());
926 EXPECT_EQ(44100, config.samples_per_second());
927 EXPECT_TRUE(config.extra_data());
928 EXPECT_GT(config.extra_data_size(), 0u);
929 EXPECT_EQ(kSampleFormatPlanarF32, config.sample_format());
930 EXPECT_EQ(is_audio_encrypted,
931 audio_stream->audio_decoder_config().is_encrypted());
932 } else {
933 EXPECT_FALSE(audio_stream);
936 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO);
937 if (has_video) {
938 EXPECT_TRUE(video_stream);
939 EXPECT_EQ(is_video_encrypted,
940 video_stream->video_decoder_config().is_encrypted());
941 } else {
942 EXPECT_FALSE(video_stream);
945 ShutdownDemuxer();
946 demuxer_.reset();
950 // Make sure that the demuxer reports an error if Shutdown()
951 // is called before all the initialization segments are appended.
952 TEST_F(ChunkDemuxerTest, ShutdownBeforeAllInitSegmentsAppended) {
953 EXPECT_CALL(*this, DemuxerOpened());
954 demuxer_->Initialize(
955 &host_, CreateInitDoneCB(
956 kDefaultDuration(), DEMUXER_ERROR_COULD_NOT_OPEN));
958 EXPECT_EQ(AddId("audio", true, false), ChunkDemuxer::kOk);
959 EXPECT_EQ(AddId("video", false, true), ChunkDemuxer::kOk);
961 AppendInitSegmentWithSourceId("audio", true, false);
964 // Test that Seek() completes successfully when the first cluster
965 // arrives.
966 TEST_F(ChunkDemuxerTest, AppendDataAfterSeek) {
967 ASSERT_TRUE(InitDemuxer(true, true));
968 AppendCluster(kDefaultFirstCluster());
970 InSequence s;
972 EXPECT_CALL(*this, Checkpoint(1));
974 Seek(base::TimeDelta::FromMilliseconds(46));
976 EXPECT_CALL(*this, Checkpoint(2));
978 Checkpoint(1);
980 AppendCluster(kDefaultSecondCluster());
982 message_loop_.RunUntilIdle();
984 Checkpoint(2);
987 // Test that parsing errors are handled for clusters appended after init.
988 TEST_F(ChunkDemuxerTest, ErrorWhileParsingClusterAfterInit) {
989 ASSERT_TRUE(InitDemuxer(true, true));
990 AppendCluster(kDefaultFirstCluster());
992 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE));
993 AppendGarbage();
996 // Test the case where a Seek() is requested while the parser
997 // is in the middle of cluster. This is to verify that the parser
998 // does not reset itself on a seek.
999 TEST_F(ChunkDemuxerTest, SeekWhileParsingCluster) {
1000 ASSERT_TRUE(InitDemuxer(true, true));
1002 InSequence s;
1004 scoped_ptr<Cluster> cluster_a(GenerateCluster(0, 6));
1006 // Split the cluster into two appends at an arbitrary point near the end.
1007 int first_append_size = cluster_a->size() - 11;
1008 int second_append_size = cluster_a->size() - first_append_size;
1010 // Append the first part of the cluster.
1011 AppendData(cluster_a->data(), first_append_size);
1013 ExpectRead(DemuxerStream::AUDIO, 0);
1014 ExpectRead(DemuxerStream::VIDEO, 0);
1015 ExpectRead(DemuxerStream::AUDIO, kAudioBlockDuration);
1016 // Note: We skip trying to read a video buffer here because computing
1017 // the duration for this block relies on successfully parsing the last block
1018 // in the cluster the cluster.
1019 ExpectRead(DemuxerStream::AUDIO, 2 * kAudioBlockDuration);
1021 Seek(base::TimeDelta::FromSeconds(5));
1023 // Append the rest of the cluster.
1024 AppendData(cluster_a->data() + first_append_size, second_append_size);
1026 // Append the new cluster and verify that only the blocks
1027 // in the new cluster are returned.
1028 AppendCluster(GenerateCluster(5000, 6));
1029 GenerateExpectedReads(5000, 6);
1032 // Test the case where AppendData() is called before Init().
1033 TEST_F(ChunkDemuxerTest, AppendDataBeforeInit) {
1034 scoped_ptr<uint8[]> info_tracks;
1035 int info_tracks_size = 0;
1036 CreateInitSegment(true, true, false, false, &info_tracks, &info_tracks_size);
1038 demuxer_->AppendData(kSourceId, info_tracks.get(), info_tracks_size);
1041 // Make sure Read() callbacks are dispatched with the proper data.
1042 TEST_F(ChunkDemuxerTest, Read) {
1043 ASSERT_TRUE(InitDemuxer(true, true));
1045 AppendCluster(kDefaultFirstCluster());
1047 bool audio_read_done = false;
1048 bool video_read_done = false;
1049 ReadAudio(base::Bind(&OnReadDone,
1050 base::TimeDelta::FromMilliseconds(0),
1051 &audio_read_done));
1052 ReadVideo(base::Bind(&OnReadDone,
1053 base::TimeDelta::FromMilliseconds(0),
1054 &video_read_done));
1056 EXPECT_TRUE(audio_read_done);
1057 EXPECT_TRUE(video_read_done);
1060 TEST_F(ChunkDemuxerTest, OutOfOrderClusters) {
1061 ASSERT_TRUE(InitDemuxer(true, true));
1062 AppendCluster(kDefaultFirstCluster());
1063 AppendCluster(GenerateCluster(10, 4));
1065 // Make sure that AppendCluster() does not fail with a cluster that has
1066 // overlaps with the previously appended cluster.
1067 AppendCluster(GenerateCluster(5, 4));
1069 // Verify that AppendData() can still accept more data.
1070 scoped_ptr<Cluster> cluster_c(GenerateCluster(45, 2));
1071 demuxer_->AppendData(kSourceId, cluster_c->data(), cluster_c->size());
1074 TEST_F(ChunkDemuxerTest, NonMonotonicButAboveClusterTimecode) {
1075 ASSERT_TRUE(InitDemuxer(true, true));
1076 AppendCluster(kDefaultFirstCluster());
1078 ClusterBuilder cb;
1080 // Test the case where block timecodes are not monotonically
1081 // increasing but stay above the cluster timecode.
1082 cb.SetClusterTimecode(5);
1083 AddSimpleBlock(&cb, kAudioTrackNum, 5);
1084 AddSimpleBlock(&cb, kVideoTrackNum, 10);
1085 AddSimpleBlock(&cb, kAudioTrackNum, 7);
1086 AddSimpleBlock(&cb, kVideoTrackNum, 15);
1088 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE));
1089 AppendCluster(cb.Finish());
1091 // Verify that AppendData() ignores data after the error.
1092 scoped_ptr<Cluster> cluster_b(GenerateCluster(20, 2));
1093 demuxer_->AppendData(kSourceId, cluster_b->data(), cluster_b->size());
1096 TEST_F(ChunkDemuxerTest, BackwardsAndBeforeClusterTimecode) {
1097 ASSERT_TRUE(InitDemuxer(true, true));
1098 AppendCluster(kDefaultFirstCluster());
1100 ClusterBuilder cb;
1102 // Test timecodes going backwards and including values less than the cluster
1103 // timecode.
1104 cb.SetClusterTimecode(5);
1105 AddSimpleBlock(&cb, kAudioTrackNum, 5);
1106 AddSimpleBlock(&cb, kVideoTrackNum, 5);
1107 AddSimpleBlock(&cb, kAudioTrackNum, 3);
1108 AddSimpleBlock(&cb, kVideoTrackNum, 3);
1110 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE));
1111 AppendCluster(cb.Finish());
1113 // Verify that AppendData() ignores data after the error.
1114 scoped_ptr<Cluster> cluster_b(GenerateCluster(6, 2));
1115 demuxer_->AppendData(kSourceId, cluster_b->data(), cluster_b->size());
1119 TEST_F(ChunkDemuxerTest, PerStreamMonotonicallyIncreasingTimestamps) {
1120 ASSERT_TRUE(InitDemuxer(true, true));
1121 AppendCluster(kDefaultFirstCluster());
1123 ClusterBuilder cb;
1125 // Test monotonic increasing timestamps on a per stream
1126 // basis.
1127 cb.SetClusterTimecode(5);
1128 AddSimpleBlock(&cb, kAudioTrackNum, 5);
1129 AddSimpleBlock(&cb, kVideoTrackNum, 5);
1130 AddSimpleBlock(&cb, kAudioTrackNum, 4);
1131 AddSimpleBlock(&cb, kVideoTrackNum, 7);
1133 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE));
1134 AppendCluster(cb.Finish());
1137 // Test the case where a cluster is passed to AppendCluster() before
1138 // INFO & TRACKS data.
1139 TEST_F(ChunkDemuxerTest, ClusterBeforeInitSegment) {
1140 EXPECT_CALL(*this, DemuxerOpened());
1141 demuxer_->Initialize(
1142 &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN));
1144 ASSERT_EQ(AddId(), ChunkDemuxer::kOk);
1146 AppendCluster(GenerateCluster(0, 1));
1149 // Test cases where we get an MarkEndOfStream() call during initialization.
1150 TEST_F(ChunkDemuxerTest, EOSDuringInit) {
1151 EXPECT_CALL(*this, DemuxerOpened());
1152 demuxer_->Initialize(
1153 &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN));
1154 MarkEndOfStream(PIPELINE_OK);
1157 TEST_F(ChunkDemuxerTest, EndOfStreamWithNoAppend) {
1158 EXPECT_CALL(*this, DemuxerOpened());
1159 demuxer_->Initialize(
1160 &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN));
1162 ASSERT_EQ(AddId(), ChunkDemuxer::kOk);
1164 CheckExpectedRanges("{ }");
1165 MarkEndOfStream(PIPELINE_OK);
1166 ShutdownDemuxer();
1167 CheckExpectedRanges("{ }");
1168 demuxer_->RemoveId(kSourceId);
1169 demuxer_.reset();
1172 TEST_F(ChunkDemuxerTest, EndOfStreamWithNoMediaAppend) {
1173 ASSERT_TRUE(InitDemuxer(true, true));
1175 CheckExpectedRanges("{ }");
1176 MarkEndOfStream(PIPELINE_OK);
1177 CheckExpectedRanges("{ }");
1180 TEST_F(ChunkDemuxerTest, DecodeErrorEndOfStream) {
1181 ASSERT_TRUE(InitDemuxer(true, true));
1183 AppendCluster(kDefaultFirstCluster());
1184 CheckExpectedRanges(kDefaultFirstClusterRange);
1186 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE));
1187 MarkEndOfStream(PIPELINE_ERROR_DECODE);
1188 CheckExpectedRanges(kDefaultFirstClusterRange);
1191 TEST_F(ChunkDemuxerTest, NetworkErrorEndOfStream) {
1192 ASSERT_TRUE(InitDemuxer(true, true));
1194 AppendCluster(kDefaultFirstCluster());
1195 CheckExpectedRanges(kDefaultFirstClusterRange);
1197 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_NETWORK));
1198 MarkEndOfStream(PIPELINE_ERROR_NETWORK);
1201 // Helper class to reduce duplicate code when testing end of stream
1202 // Read() behavior.
1203 class EndOfStreamHelper {
1204 public:
1205 explicit EndOfStreamHelper(Demuxer* demuxer)
1206 : demuxer_(demuxer),
1207 audio_read_done_(false),
1208 video_read_done_(false) {
1211 // Request a read on the audio and video streams.
1212 void RequestReads() {
1213 EXPECT_FALSE(audio_read_done_);
1214 EXPECT_FALSE(video_read_done_);
1216 DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
1217 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
1219 audio->Read(base::Bind(&OnEndOfStreamReadDone, &audio_read_done_));
1220 video->Read(base::Bind(&OnEndOfStreamReadDone, &video_read_done_));
1221 base::MessageLoop::current()->RunUntilIdle();
1224 // Check to see if |audio_read_done_| and |video_read_done_| variables
1225 // match |expected|.
1226 void CheckIfReadDonesWereCalled(bool expected) {
1227 base::MessageLoop::current()->RunUntilIdle();
1228 EXPECT_EQ(expected, audio_read_done_);
1229 EXPECT_EQ(expected, video_read_done_);
1232 private:
1233 static void OnEndOfStreamReadDone(
1234 bool* called,
1235 DemuxerStream::Status status,
1236 const scoped_refptr<DecoderBuffer>& buffer) {
1237 EXPECT_EQ(status, DemuxerStream::kOk);
1238 EXPECT_TRUE(buffer->end_of_stream());
1239 *called = true;
1242 Demuxer* demuxer_;
1243 bool audio_read_done_;
1244 bool video_read_done_;
1246 DISALLOW_COPY_AND_ASSIGN(EndOfStreamHelper);
1249 // Make sure that all pending reads that we don't have media data for get an
1250 // "end of stream" buffer when MarkEndOfStream() is called.
1251 TEST_F(ChunkDemuxerTest, EndOfStreamWithPendingReads) {
1252 ASSERT_TRUE(InitDemuxer(true, true));
1254 AppendCluster(GenerateCluster(0, 2));
1256 bool audio_read_done_1 = false;
1257 bool video_read_done_1 = false;
1258 EndOfStreamHelper end_of_stream_helper_1(demuxer_.get());
1259 EndOfStreamHelper end_of_stream_helper_2(demuxer_.get());
1261 ReadAudio(base::Bind(&OnReadDone,
1262 base::TimeDelta::FromMilliseconds(0),
1263 &audio_read_done_1));
1264 ReadVideo(base::Bind(&OnReadDone,
1265 base::TimeDelta::FromMilliseconds(0),
1266 &video_read_done_1));
1267 message_loop_.RunUntilIdle();
1269 EXPECT_TRUE(audio_read_done_1);
1270 EXPECT_TRUE(video_read_done_1);
1272 end_of_stream_helper_1.RequestReads();
1274 EXPECT_CALL(host_, SetDuration(
1275 base::TimeDelta::FromMilliseconds(kVideoBlockDuration)));
1276 MarkEndOfStream(PIPELINE_OK);
1278 end_of_stream_helper_1.CheckIfReadDonesWereCalled(true);
1280 end_of_stream_helper_2.RequestReads();
1281 end_of_stream_helper_2.CheckIfReadDonesWereCalled(true);
1284 // Make sure that all Read() calls after we get an MarkEndOfStream()
1285 // call return an "end of stream" buffer.
1286 TEST_F(ChunkDemuxerTest, ReadsAfterEndOfStream) {
1287 ASSERT_TRUE(InitDemuxer(true, true));
1289 AppendCluster(GenerateCluster(0, 2));
1291 bool audio_read_done_1 = false;
1292 bool video_read_done_1 = false;
1293 EndOfStreamHelper end_of_stream_helper_1(demuxer_.get());
1294 EndOfStreamHelper end_of_stream_helper_2(demuxer_.get());
1295 EndOfStreamHelper end_of_stream_helper_3(demuxer_.get());
1297 ReadAudio(base::Bind(&OnReadDone,
1298 base::TimeDelta::FromMilliseconds(0),
1299 &audio_read_done_1));
1300 ReadVideo(base::Bind(&OnReadDone,
1301 base::TimeDelta::FromMilliseconds(0),
1302 &video_read_done_1));
1304 end_of_stream_helper_1.RequestReads();
1306 EXPECT_TRUE(audio_read_done_1);
1307 EXPECT_TRUE(video_read_done_1);
1308 end_of_stream_helper_1.CheckIfReadDonesWereCalled(false);
1310 EXPECT_CALL(host_, SetDuration(
1311 base::TimeDelta::FromMilliseconds(kVideoBlockDuration)));
1312 MarkEndOfStream(PIPELINE_OK);
1314 end_of_stream_helper_1.CheckIfReadDonesWereCalled(true);
1316 // Request a few more reads and make sure we immediately get
1317 // end of stream buffers.
1318 end_of_stream_helper_2.RequestReads();
1319 end_of_stream_helper_2.CheckIfReadDonesWereCalled(true);
1321 end_of_stream_helper_3.RequestReads();
1322 end_of_stream_helper_3.CheckIfReadDonesWereCalled(true);
1325 TEST_F(ChunkDemuxerTest, EndOfStreamDuringCanceledSeek) {
1326 ASSERT_TRUE(InitDemuxer(true, true));
1328 AppendCluster(0, 10);
1329 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(138)));
1330 MarkEndOfStream(PIPELINE_OK);
1332 // Start the first seek.
1333 Seek(base::TimeDelta::FromMilliseconds(20));
1335 // Simulate another seek being requested before the first
1336 // seek has finished prerolling.
1337 base::TimeDelta seek_time2 = base::TimeDelta::FromMilliseconds(30);
1338 demuxer_->CancelPendingSeek(seek_time2);
1340 // Finish second seek.
1341 Seek(seek_time2);
1343 DemuxerStream::Status status;
1344 base::TimeDelta last_timestamp;
1346 // Make sure audio can reach end of stream.
1347 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp);
1348 ASSERT_EQ(status, DemuxerStream::kOk);
1350 // Make sure video can reach end of stream.
1351 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp);
1352 ASSERT_EQ(status, DemuxerStream::kOk);
1355 // Make sure AppendData() will accept elements that span multiple calls.
1356 TEST_F(ChunkDemuxerTest, AppendingInPieces) {
1357 EXPECT_CALL(*this, DemuxerOpened());
1358 demuxer_->Initialize(
1359 &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK));
1361 ASSERT_EQ(AddId(), ChunkDemuxer::kOk);
1363 scoped_ptr<uint8[]> info_tracks;
1364 int info_tracks_size = 0;
1365 CreateInitSegment(true, true, false, false, &info_tracks, &info_tracks_size);
1367 scoped_ptr<Cluster> cluster_a(kDefaultFirstCluster());
1368 scoped_ptr<Cluster> cluster_b(kDefaultSecondCluster());
1370 size_t buffer_size = info_tracks_size + cluster_a->size() + cluster_b->size();
1371 scoped_ptr<uint8[]> buffer(new uint8[buffer_size]);
1372 uint8* dst = buffer.get();
1373 memcpy(dst, info_tracks.get(), info_tracks_size);
1374 dst += info_tracks_size;
1376 memcpy(dst, cluster_a->data(), cluster_a->size());
1377 dst += cluster_a->size();
1379 memcpy(dst, cluster_b->data(), cluster_b->size());
1380 dst += cluster_b->size();
1382 AppendDataInPieces(buffer.get(), buffer_size);
1384 GenerateExpectedReads(0, 9);
1387 TEST_F(ChunkDemuxerTest, WebMFile_AudioAndVideo) {
1388 struct BufferTimestamps buffer_timestamps[] = {
1389 {0, 0},
1390 {33, 3},
1391 {67, 6},
1392 {100, 9},
1393 {133, 12},
1394 {kSkip, kSkip},
1397 ASSERT_TRUE(ParseWebMFile("bear-320x240.webm", buffer_timestamps,
1398 base::TimeDelta::FromMilliseconds(2744)));
1401 TEST_F(ChunkDemuxerTest, WebMFile_LiveAudioAndVideo) {
1402 struct BufferTimestamps buffer_timestamps[] = {
1403 {0, 0},
1404 {33, 3},
1405 {67, 6},
1406 {100, 9},
1407 {133, 12},
1408 {kSkip, kSkip},
1411 ASSERT_TRUE(ParseWebMFile("bear-320x240-live.webm", buffer_timestamps,
1412 kInfiniteDuration()));
1415 TEST_F(ChunkDemuxerTest, WebMFile_AudioOnly) {
1416 struct BufferTimestamps buffer_timestamps[] = {
1417 {kSkip, 0},
1418 {kSkip, 3},
1419 {kSkip, 6},
1420 {kSkip, 9},
1421 {kSkip, 12},
1422 {kSkip, kSkip},
1425 ASSERT_TRUE(ParseWebMFile("bear-320x240-audio-only.webm", buffer_timestamps,
1426 base::TimeDelta::FromMilliseconds(2744),
1427 true, false));
1430 TEST_F(ChunkDemuxerTest, WebMFile_VideoOnly) {
1431 struct BufferTimestamps buffer_timestamps[] = {
1432 {0, kSkip},
1433 {33, kSkip},
1434 {67, kSkip},
1435 {100, kSkip},
1436 {133, kSkip},
1437 {kSkip, kSkip},
1440 ASSERT_TRUE(ParseWebMFile("bear-320x240-video-only.webm", buffer_timestamps,
1441 base::TimeDelta::FromMilliseconds(2703),
1442 false, true));
1445 TEST_F(ChunkDemuxerTest, WebMFile_AltRefFrames) {
1446 struct BufferTimestamps buffer_timestamps[] = {
1447 {0, 0},
1448 {33, 3},
1449 {33, 6},
1450 {67, 9},
1451 {100, 12},
1452 {kSkip, kSkip},
1455 ASSERT_TRUE(ParseWebMFile("bear-320x240-altref.webm", buffer_timestamps,
1456 base::TimeDelta::FromMilliseconds(2767)));
1459 // Verify that we output buffers before the entire cluster has been parsed.
1460 TEST_F(ChunkDemuxerTest, IncrementalClusterParsing) {
1461 ASSERT_TRUE(InitDemuxer(true, true));
1462 AppendEmptyCluster(0);
1464 scoped_ptr<Cluster> cluster(GenerateCluster(0, 6));
1466 bool audio_read_done = false;
1467 bool video_read_done = false;
1468 ReadAudio(base::Bind(&OnReadDone,
1469 base::TimeDelta::FromMilliseconds(0),
1470 &audio_read_done));
1471 ReadVideo(base::Bind(&OnReadDone,
1472 base::TimeDelta::FromMilliseconds(0),
1473 &video_read_done));
1475 // Make sure the reads haven't completed yet.
1476 EXPECT_FALSE(audio_read_done);
1477 EXPECT_FALSE(video_read_done);
1479 // Append data one byte at a time until the audio read completes.
1480 int i = 0;
1481 for (; i < cluster->size() && !audio_read_done; ++i) {
1482 AppendData(cluster->data() + i, 1);
1483 message_loop_.RunUntilIdle();
1486 EXPECT_TRUE(audio_read_done);
1487 EXPECT_FALSE(video_read_done);
1488 EXPECT_GT(i, 0);
1489 EXPECT_LT(i, cluster->size());
1491 // Append data one byte at a time until the video read completes.
1492 for (; i < cluster->size() && !video_read_done; ++i) {
1493 AppendData(cluster->data() + i, 1);
1494 message_loop_.RunUntilIdle();
1497 EXPECT_TRUE(video_read_done);
1498 EXPECT_LT(i, cluster->size());
1500 audio_read_done = false;
1501 video_read_done = false;
1502 ReadAudio(base::Bind(&OnReadDone,
1503 base::TimeDelta::FromMilliseconds(23),
1504 &audio_read_done));
1505 ReadVideo(base::Bind(&OnReadDone,
1506 base::TimeDelta::FromMilliseconds(33),
1507 &video_read_done));
1509 // Make sure the reads haven't completed yet.
1510 EXPECT_FALSE(audio_read_done);
1511 EXPECT_FALSE(video_read_done);
1513 // Append the remaining data.
1514 ASSERT_LT(i, cluster->size());
1515 AppendData(cluster->data() + i, cluster->size() - i);
1517 message_loop_.RunUntilIdle();
1519 EXPECT_TRUE(audio_read_done);
1520 EXPECT_TRUE(video_read_done);
1523 TEST_F(ChunkDemuxerTest, ParseErrorDuringInit) {
1524 EXPECT_CALL(*this, DemuxerOpened());
1525 demuxer_->Initialize(
1526 &host_, CreateInitDoneCB(
1527 kNoTimestamp(), DEMUXER_ERROR_COULD_NOT_OPEN));
1529 ASSERT_EQ(AddId(), ChunkDemuxer::kOk);
1531 uint8 tmp = 0;
1532 demuxer_->AppendData(kSourceId, &tmp, 1);
1535 TEST_F(ChunkDemuxerTest, AVHeadersWithAudioOnlyType) {
1536 EXPECT_CALL(*this, DemuxerOpened());
1537 demuxer_->Initialize(
1538 &host_, CreateInitDoneCB(kNoTimestamp(),
1539 DEMUXER_ERROR_COULD_NOT_OPEN));
1541 std::vector<std::string> codecs(1);
1542 codecs[0] = "vorbis";
1543 ASSERT_EQ(demuxer_->AddId(kSourceId, "audio/webm", codecs),
1544 ChunkDemuxer::kOk);
1546 AppendInitSegment(true, true);
1549 TEST_F(ChunkDemuxerTest, AVHeadersWithVideoOnlyType) {
1550 EXPECT_CALL(*this, DemuxerOpened());
1551 demuxer_->Initialize(
1552 &host_, CreateInitDoneCB(kNoTimestamp(),
1553 DEMUXER_ERROR_COULD_NOT_OPEN));
1555 std::vector<std::string> codecs(1);
1556 codecs[0] = "vp8";
1557 ASSERT_EQ(demuxer_->AddId(kSourceId, "video/webm", codecs),
1558 ChunkDemuxer::kOk);
1560 AppendInitSegment(true, true);
1563 TEST_F(ChunkDemuxerTest, MultipleHeaders) {
1564 ASSERT_TRUE(InitDemuxer(true, true));
1566 AppendCluster(kDefaultFirstCluster());
1568 // Append another identical initialization segment.
1569 AppendInitSegment(true, true);
1571 AppendCluster(kDefaultSecondCluster());
1573 GenerateExpectedReads(0, 9);
1576 TEST_F(ChunkDemuxerTest, AddSeparateSourcesForAudioAndVideo) {
1577 std::string audio_id = "audio1";
1578 std::string video_id = "video1";
1579 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
1581 // Append audio and video data into separate source ids.
1582 AppendCluster(audio_id,
1583 GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration));
1584 GenerateAudioStreamExpectedReads(0, 4);
1585 AppendCluster(video_id,
1586 GenerateSingleStreamCluster(0, 132, kVideoTrackNum, kVideoBlockDuration));
1587 GenerateVideoStreamExpectedReads(0, 4);
1590 TEST_F(ChunkDemuxerTest, AddIdFailures) {
1591 EXPECT_CALL(*this, DemuxerOpened());
1592 demuxer_->Initialize(
1593 &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK));
1595 std::string audio_id = "audio1";
1596 std::string video_id = "video1";
1598 ASSERT_EQ(AddId(audio_id, true, false), ChunkDemuxer::kOk);
1600 // Adding an id with audio/video should fail because we already added audio.
1601 ASSERT_EQ(AddId(), ChunkDemuxer::kReachedIdLimit);
1603 AppendInitSegmentWithSourceId(audio_id, true, false);
1605 // Adding an id after append should fail.
1606 ASSERT_EQ(AddId(video_id, false, true), ChunkDemuxer::kReachedIdLimit);
1609 // Test that Read() calls after a RemoveId() return "end of stream" buffers.
1610 TEST_F(ChunkDemuxerTest, RemoveId) {
1611 std::string audio_id = "audio1";
1612 std::string video_id = "video1";
1613 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
1615 // Append audio and video data into separate source ids.
1616 AppendCluster(audio_id,
1617 GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration));
1618 AppendCluster(video_id,
1619 GenerateSingleStreamCluster(0, 132, kVideoTrackNum, kVideoBlockDuration));
1621 // Read() from audio should return normal buffers.
1622 GenerateAudioStreamExpectedReads(0, 4);
1624 // Remove the audio id.
1625 demuxer_->RemoveId(audio_id);
1627 // Read() from audio should return "end of stream" buffers.
1628 bool audio_read_done = false;
1629 ReadAudio(base::Bind(&OnReadDone_EOSExpected, &audio_read_done));
1630 message_loop_.RunUntilIdle();
1631 EXPECT_TRUE(audio_read_done);
1633 // Read() from video should still return normal buffers.
1634 GenerateVideoStreamExpectedReads(0, 4);
1637 // Test that removing an ID immediately after adding it does not interfere with
1638 // quota for new IDs in the future.
1639 TEST_F(ChunkDemuxerTest, RemoveAndAddId) {
1640 std::string audio_id_1 = "audio1";
1641 ASSERT_TRUE(AddId(audio_id_1, true, false) == ChunkDemuxer::kOk);
1642 demuxer_->RemoveId(audio_id_1);
1644 std::string audio_id_2 = "audio2";
1645 ASSERT_TRUE(AddId(audio_id_2, true, false) == ChunkDemuxer::kOk);
1648 TEST_F(ChunkDemuxerTest, SeekCanceled) {
1649 ASSERT_TRUE(InitDemuxer(true, true));
1651 // Append cluster at the beginning of the stream.
1652 AppendCluster(GenerateCluster(0, 4));
1654 // Seek to an unbuffered region.
1655 Seek(base::TimeDelta::FromSeconds(50));
1657 // Attempt to read in unbuffered area; should not fulfill the read.
1658 bool audio_read_done = false;
1659 bool video_read_done = false;
1660 ReadAudio(base::Bind(&OnReadDone_AbortExpected, &audio_read_done));
1661 ReadVideo(base::Bind(&OnReadDone_AbortExpected, &video_read_done));
1662 EXPECT_FALSE(audio_read_done);
1663 EXPECT_FALSE(video_read_done);
1665 // Now cancel the pending seek, which should flush the reads with empty
1666 // buffers.
1667 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(0);
1668 demuxer_->CancelPendingSeek(seek_time);
1669 message_loop_.RunUntilIdle();
1670 EXPECT_TRUE(audio_read_done);
1671 EXPECT_TRUE(video_read_done);
1673 // A seek back to the buffered region should succeed.
1674 Seek(seek_time);
1675 GenerateExpectedReads(0, 4);
1678 TEST_F(ChunkDemuxerTest, SeekCanceledWhileWaitingForSeek) {
1679 ASSERT_TRUE(InitDemuxer(true, true));
1681 // Append cluster at the beginning of the stream.
1682 AppendCluster(GenerateCluster(0, 4));
1684 // Start waiting for a seek.
1685 base::TimeDelta seek_time1 = base::TimeDelta::FromSeconds(50);
1686 base::TimeDelta seek_time2 = base::TimeDelta::FromSeconds(0);
1687 demuxer_->StartWaitingForSeek(seek_time1);
1689 // Now cancel the upcoming seek to an unbuffered region.
1690 demuxer_->CancelPendingSeek(seek_time2);
1691 demuxer_->Seek(seek_time1, NewExpectedStatusCB(PIPELINE_OK));
1693 // Read requests should be fulfilled with empty buffers.
1694 bool audio_read_done = false;
1695 bool video_read_done = false;
1696 ReadAudio(base::Bind(&OnReadDone_AbortExpected, &audio_read_done));
1697 ReadVideo(base::Bind(&OnReadDone_AbortExpected, &video_read_done));
1698 EXPECT_TRUE(audio_read_done);
1699 EXPECT_TRUE(video_read_done);
1701 // A seek back to the buffered region should succeed.
1702 Seek(seek_time2);
1703 GenerateExpectedReads(0, 4);
1706 // Test that Seek() successfully seeks to all source IDs.
1707 TEST_F(ChunkDemuxerTest, SeekAudioAndVideoSources) {
1708 std::string audio_id = "audio1";
1709 std::string video_id = "video1";
1710 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
1712 AppendCluster(
1713 audio_id,
1714 GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration));
1715 AppendCluster(
1716 video_id,
1717 GenerateSingleStreamCluster(0, 132, kVideoTrackNum, kVideoBlockDuration));
1719 // Read() should return buffers at 0.
1720 bool audio_read_done = false;
1721 bool video_read_done = false;
1722 ReadAudio(base::Bind(&OnReadDone,
1723 base::TimeDelta::FromMilliseconds(0),
1724 &audio_read_done));
1725 ReadVideo(base::Bind(&OnReadDone,
1726 base::TimeDelta::FromMilliseconds(0),
1727 &video_read_done));
1728 EXPECT_TRUE(audio_read_done);
1729 EXPECT_TRUE(video_read_done);
1731 // Seek to 3 (an unbuffered region).
1732 Seek(base::TimeDelta::FromSeconds(3));
1734 audio_read_done = false;
1735 video_read_done = false;
1736 ReadAudio(base::Bind(&OnReadDone,
1737 base::TimeDelta::FromSeconds(3),
1738 &audio_read_done));
1739 ReadVideo(base::Bind(&OnReadDone,
1740 base::TimeDelta::FromSeconds(3),
1741 &video_read_done));
1742 // Read()s should not return until after data is appended at the Seek point.
1743 EXPECT_FALSE(audio_read_done);
1744 EXPECT_FALSE(video_read_done);
1746 AppendCluster(audio_id,
1747 GenerateSingleStreamCluster(
1748 3000, 3092, kAudioTrackNum, kAudioBlockDuration));
1749 AppendCluster(video_id,
1750 GenerateSingleStreamCluster(
1751 3000, 3132, kVideoTrackNum, kVideoBlockDuration));
1753 message_loop_.RunUntilIdle();
1755 // Read() should return buffers at 3.
1756 EXPECT_TRUE(audio_read_done);
1757 EXPECT_TRUE(video_read_done);
1760 // Test that Seek() completes successfully when EndOfStream
1761 // is called before data is available for that seek point.
1762 // This scenario might be useful if seeking past the end of stream
1763 // of either audio or video (or both).
1764 TEST_F(ChunkDemuxerTest, EndOfStreamAfterPastEosSeek) {
1765 ASSERT_TRUE(InitDemuxer(true, true));
1767 AppendCluster(GenerateSingleStreamCluster(0, 120, kAudioTrackNum, 10));
1768 AppendCluster(GenerateSingleStreamCluster(0, 100, kVideoTrackNum, 5));
1770 // Seeking past the end of video.
1771 // Note: audio data is available for that seek point.
1772 bool seek_cb_was_called = false;
1773 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(110);
1774 demuxer_->StartWaitingForSeek(seek_time);
1775 demuxer_->Seek(seek_time,
1776 base::Bind(OnSeekDone_OKExpected, &seek_cb_was_called));
1777 message_loop_.RunUntilIdle();
1779 EXPECT_FALSE(seek_cb_was_called);
1781 EXPECT_CALL(host_, SetDuration(
1782 base::TimeDelta::FromMilliseconds(120)));
1783 MarkEndOfStream(PIPELINE_OK);
1784 message_loop_.RunUntilIdle();
1786 EXPECT_TRUE(seek_cb_was_called);
1788 ShutdownDemuxer();
1791 // Test that EndOfStream is ignored if coming during a pending seek
1792 // whose seek time is before some existing ranges.
1793 TEST_F(ChunkDemuxerTest, EndOfStreamDuringPendingSeek) {
1794 ASSERT_TRUE(InitDemuxer(true, true));
1796 AppendCluster(GenerateSingleStreamCluster(0, 120, kAudioTrackNum, 10));
1797 AppendCluster(GenerateSingleStreamCluster(0, 100, kVideoTrackNum, 5));
1798 AppendCluster(GenerateSingleStreamCluster(200, 300, kAudioTrackNum, 10));
1799 AppendCluster(GenerateSingleStreamCluster(200, 300, kVideoTrackNum, 5));
1801 bool seek_cb_was_called = false;
1802 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(160);
1803 demuxer_->StartWaitingForSeek(seek_time);
1804 demuxer_->Seek(seek_time,
1805 base::Bind(OnSeekDone_OKExpected, &seek_cb_was_called));
1806 message_loop_.RunUntilIdle();
1808 EXPECT_FALSE(seek_cb_was_called);
1810 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(300)));
1811 MarkEndOfStream(PIPELINE_OK);
1812 message_loop_.RunUntilIdle();
1814 EXPECT_FALSE(seek_cb_was_called);
1816 demuxer_->UnmarkEndOfStream();
1818 AppendCluster(GenerateSingleStreamCluster(140, 180, kAudioTrackNum, 10));
1819 AppendCluster(GenerateSingleStreamCluster(140, 180, kVideoTrackNum, 5));
1821 message_loop_.RunUntilIdle();
1823 EXPECT_TRUE(seek_cb_was_called);
1825 ShutdownDemuxer();
1828 // Test ranges in an audio-only stream.
1829 TEST_F(ChunkDemuxerTest, GetBufferedRanges_AudioIdOnly) {
1830 EXPECT_CALL(*this, DemuxerOpened());
1831 demuxer_->Initialize(
1832 &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK));
1834 ASSERT_EQ(AddId(kSourceId, true, false), ChunkDemuxer::kOk);
1835 AppendInitSegment(true, false);
1837 // Test a simple cluster.
1838 AppendCluster(
1839 GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration));
1841 CheckExpectedRanges("{ [0,92) }");
1843 // Append a disjoint cluster to check for two separate ranges.
1844 AppendCluster(GenerateSingleStreamCluster(
1845 150, 219, kAudioTrackNum, kAudioBlockDuration));
1847 CheckExpectedRanges("{ [0,92) [150,219) }");
1850 // Test ranges in a video-only stream.
1851 TEST_F(ChunkDemuxerTest, GetBufferedRanges_VideoIdOnly) {
1852 EXPECT_CALL(*this, DemuxerOpened());
1853 demuxer_->Initialize(
1854 &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK));
1856 ASSERT_EQ(AddId(kSourceId, false, true), ChunkDemuxer::kOk);
1857 AppendInitSegment(false, true);
1859 // Test a simple cluster.
1860 AppendCluster(
1861 GenerateSingleStreamCluster(0, 132, kVideoTrackNum, kVideoBlockDuration));
1863 CheckExpectedRanges("{ [0,132) }");
1865 // Append a disjoint cluster to check for two separate ranges.
1866 AppendCluster(GenerateSingleStreamCluster(
1867 200, 299, kVideoTrackNum, kVideoBlockDuration));
1869 CheckExpectedRanges("{ [0,132) [200,299) }");
1872 TEST_F(ChunkDemuxerTest, GetBufferedRanges_AudioVideo) {
1873 ASSERT_TRUE(InitDemuxer(true, true));
1875 // Audio: 0 -> 23
1876 // Video: 0 -> 33
1877 // Buffered Range: 0 -> 23
1878 // Audio block duration is smaller than video block duration,
1879 // so the buffered ranges should correspond to the audio blocks.
1880 AppendCluster(GenerateSingleStreamCluster(
1881 0, kAudioBlockDuration, kAudioTrackNum, kAudioBlockDuration));
1882 AppendCluster(GenerateSingleStreamCluster(
1883 0, kVideoBlockDuration, kVideoTrackNum, kVideoBlockDuration));
1885 CheckExpectedRanges("{ [0,23) }");
1887 // Audio: 300 -> 400
1888 // Video: 320 -> 420
1889 // Buffered Range: 320 -> 400 (end overlap)
1890 AppendCluster(GenerateSingleStreamCluster(300, 400, kAudioTrackNum, 50));
1891 AppendCluster(GenerateSingleStreamCluster(320, 420, kVideoTrackNum, 50));
1893 CheckExpectedRanges("{ [0,23) [320,400) }");
1895 // Audio: 520 -> 590
1896 // Video: 500 -> 570
1897 // Buffered Range: 520 -> 570 (front overlap)
1898 AppendCluster(GenerateSingleStreamCluster(520, 590, kAudioTrackNum, 70));
1899 AppendCluster(GenerateSingleStreamCluster(500, 570, kVideoTrackNum, 70));
1901 CheckExpectedRanges("{ [0,23) [320,400) [520,570) }");
1903 // Audio: 720 -> 750
1904 // Video: 700 -> 770
1905 // Buffered Range: 720 -> 750 (complete overlap, audio)
1906 AppendCluster(GenerateSingleStreamCluster(720, 750, kAudioTrackNum, 30));
1907 AppendCluster(GenerateSingleStreamCluster(700, 770, kVideoTrackNum, 70));
1909 CheckExpectedRanges("{ [0,23) [320,400) [520,570) [720,750) }");
1911 // Audio: 900 -> 970
1912 // Video: 920 -> 950
1913 // Buffered Range: 920 -> 950 (complete overlap, video)
1914 AppendCluster(GenerateSingleStreamCluster(900, 970, kAudioTrackNum, 70));
1915 AppendCluster(GenerateSingleStreamCluster(920, 950, kVideoTrackNum, 30));
1917 CheckExpectedRanges("{ [0,23) [320,400) [520,570) [720,750) [920,950) }");
1919 // Appending within buffered range should not affect buffered ranges.
1920 AppendCluster(GenerateSingleStreamCluster(930, 950, kAudioTrackNum, 20));
1921 CheckExpectedRanges("{ [0,23) [320,400) [520,570) [720,750) [920,950) }");
1923 // Appending to single stream outside buffered ranges should not affect
1924 // buffered ranges.
1925 AppendCluster(GenerateSingleStreamCluster(1230, 1240, kVideoTrackNum, 10));
1926 CheckExpectedRanges("{ [0,23) [320,400) [520,570) [720,750) [920,950) }");
1929 // Once MarkEndOfStream() is called, GetBufferedRanges should not cut off any
1930 // over-hanging tails at the end of the ranges as this is likely due to block
1931 // duration differences.
1932 TEST_F(ChunkDemuxerTest, GetBufferedRanges_EndOfStream) {
1933 ASSERT_TRUE(InitDemuxer(true, true));
1935 AppendCluster(GenerateSingleStreamCluster(0, 90, kAudioTrackNum, 90));
1936 AppendCluster(GenerateSingleStreamCluster(0, 100, kVideoTrackNum, 100));
1938 CheckExpectedRanges("{ [0,90) }");
1940 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(100)));
1941 MarkEndOfStream(PIPELINE_OK);
1943 CheckExpectedRanges("{ [0,100) }");
1946 TEST_F(ChunkDemuxerTest, DifferentStreamTimecodes) {
1947 ASSERT_TRUE(InitDemuxer(true, true));
1949 // Create a cluster where the video timecode begins 25ms after the audio.
1950 AppendCluster(GenerateCluster(0, 25, 8));
1952 Seek(base::TimeDelta::FromSeconds(0));
1953 GenerateExpectedReads(0, 25, 8);
1955 // Seek to 5 seconds.
1956 Seek(base::TimeDelta::FromSeconds(5));
1958 // Generate a cluster to fulfill this seek, where audio timecode begins 25ms
1959 // after the video.
1960 AppendCluster(GenerateCluster(5025, 5000, 8));
1961 GenerateExpectedReads(5025, 5000, 8);
1964 TEST_F(ChunkDemuxerTest, DifferentStreamTimecodesSeparateSources) {
1965 std::string audio_id = "audio1";
1966 std::string video_id = "video1";
1967 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
1969 // Generate two streams where the video stream starts 5ms after the audio
1970 // stream and append them.
1971 AppendCluster(audio_id, GenerateSingleStreamCluster(
1972 25, 4 * kAudioBlockDuration + 25, kAudioTrackNum, kAudioBlockDuration));
1973 AppendCluster(video_id, GenerateSingleStreamCluster(
1974 30, 4 * kVideoBlockDuration + 30, kVideoTrackNum, kVideoBlockDuration));
1976 // Both streams should be able to fulfill a seek to 25.
1977 Seek(base::TimeDelta::FromMilliseconds(25));
1978 GenerateAudioStreamExpectedReads(25, 4);
1979 GenerateVideoStreamExpectedReads(30, 4);
1982 TEST_F(ChunkDemuxerTest, DifferentStreamTimecodesOutOfRange) {
1983 std::string audio_id = "audio1";
1984 std::string video_id = "video1";
1985 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
1987 // Generate two streams where the video stream starts 10s after the audio
1988 // stream and append them.
1989 AppendCluster(audio_id, GenerateSingleStreamCluster(0,
1990 4 * kAudioBlockDuration + 0, kAudioTrackNum, kAudioBlockDuration));
1991 AppendCluster(video_id, GenerateSingleStreamCluster(10000,
1992 4 * kVideoBlockDuration + 10000, kVideoTrackNum, kVideoBlockDuration));
1994 // Should not be able to fulfill a seek to 0.
1995 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(0);
1996 demuxer_->StartWaitingForSeek(seek_time);
1997 demuxer_->Seek(seek_time,
1998 NewExpectedStatusCB(PIPELINE_ERROR_ABORT));
1999 ExpectRead(DemuxerStream::AUDIO, 0);
2000 ExpectEndOfStream(DemuxerStream::VIDEO);
2003 TEST_F(ChunkDemuxerTest, ClusterWithNoBuffers) {
2004 ASSERT_TRUE(InitDemuxer(true, true));
2006 // Generate and append an empty cluster beginning at 0.
2007 AppendEmptyCluster(0);
2009 // Sanity check that data can be appended after this cluster correctly.
2010 AppendCluster(GenerateCluster(0, 2));
2011 ExpectRead(DemuxerStream::AUDIO, 0);
2012 ExpectRead(DemuxerStream::VIDEO, 0);
2015 TEST_F(ChunkDemuxerTest, CodecPrefixMatching) {
2016 ChunkDemuxer::Status expected = ChunkDemuxer::kNotSupported;
2018 #if defined(USE_PROPRIETARY_CODECS)
2019 expected = ChunkDemuxer::kOk;
2020 #endif
2022 std::vector<std::string> codecs;
2023 codecs.push_back("avc1.4D4041");
2025 EXPECT_EQ(demuxer_->AddId("source_id", "video/mp4", codecs), expected);
2028 // Test codec ID's that are not compliant with RFC6381, but have been
2029 // seen in the wild.
2030 TEST_F(ChunkDemuxerTest, CodecIDsThatAreNotRFC6381Compliant) {
2031 ChunkDemuxer::Status expected = ChunkDemuxer::kNotSupported;
2033 #if defined(USE_PROPRIETARY_CODECS)
2034 expected = ChunkDemuxer::kOk;
2035 #endif
2036 const char* codec_ids[] = {
2037 // GPAC places leading zeros on the audio object type.
2038 "mp4a.40.02",
2039 "mp4a.40.05"
2042 for (size_t i = 0; i < arraysize(codec_ids); ++i) {
2043 std::vector<std::string> codecs;
2044 codecs.push_back(codec_ids[i]);
2046 ChunkDemuxer::Status result =
2047 demuxer_->AddId("source_id", "audio/mp4", codecs);
2049 EXPECT_EQ(result, expected)
2050 << "Fail to add codec_id '" << codec_ids[i] << "'";
2052 if (result == ChunkDemuxer::kOk)
2053 demuxer_->RemoveId("source_id");
2057 TEST_F(ChunkDemuxerTest, EndOfStreamStillSetAfterSeek) {
2058 ASSERT_TRUE(InitDemuxer(true, true));
2060 EXPECT_CALL(host_, SetDuration(_))
2061 .Times(AnyNumber());
2063 base::TimeDelta kLastAudioTimestamp = base::TimeDelta::FromMilliseconds(92);
2064 base::TimeDelta kLastVideoTimestamp = base::TimeDelta::FromMilliseconds(99);
2066 AppendCluster(kDefaultFirstCluster());
2067 AppendCluster(kDefaultSecondCluster());
2068 MarkEndOfStream(PIPELINE_OK);
2070 DemuxerStream::Status status;
2071 base::TimeDelta last_timestamp;
2073 // Verify that we can read audio & video to the end w/o problems.
2074 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp);
2075 EXPECT_EQ(DemuxerStream::kOk, status);
2076 EXPECT_EQ(kLastAudioTimestamp, last_timestamp);
2078 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp);
2079 EXPECT_EQ(DemuxerStream::kOk, status);
2080 EXPECT_EQ(kLastVideoTimestamp, last_timestamp);
2082 // Seek back to 0 and verify that we can read to the end again..
2083 Seek(base::TimeDelta::FromMilliseconds(0));
2085 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp);
2086 EXPECT_EQ(DemuxerStream::kOk, status);
2087 EXPECT_EQ(kLastAudioTimestamp, last_timestamp);
2089 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp);
2090 EXPECT_EQ(DemuxerStream::kOk, status);
2091 EXPECT_EQ(kLastVideoTimestamp, last_timestamp);
2094 TEST_F(ChunkDemuxerTest, GetBufferedRangesBeforeInitSegment) {
2095 EXPECT_CALL(*this, DemuxerOpened());
2096 demuxer_->Initialize(&host_, CreateInitDoneCB(PIPELINE_OK));
2097 ASSERT_EQ(AddId("audio", true, false), ChunkDemuxer::kOk);
2098 ASSERT_EQ(AddId("video", false, true), ChunkDemuxer::kOk);
2100 CheckExpectedRanges("audio", "{ }");
2101 CheckExpectedRanges("video", "{ }");
2104 // Test that Seek() completes successfully when the first cluster
2105 // arrives.
2106 TEST_F(ChunkDemuxerTest, EndOfStreamDuringSeek) {
2107 InSequence s;
2109 ASSERT_TRUE(InitDemuxer(true, true));
2111 AppendCluster(kDefaultFirstCluster());
2113 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(0);
2114 demuxer_->StartWaitingForSeek(seek_time);
2116 AppendCluster(kDefaultSecondCluster());
2117 EXPECT_CALL(host_, SetDuration(
2118 base::TimeDelta::FromMilliseconds(kDefaultSecondClusterEndTimestamp)));
2119 MarkEndOfStream(PIPELINE_OK);
2121 demuxer_->Seek(seek_time, NewExpectedStatusCB(PIPELINE_OK));
2123 GenerateExpectedReads(0, 4);
2124 GenerateExpectedReads(46, 66, 5);
2126 EndOfStreamHelper end_of_stream_helper(demuxer_.get());
2127 end_of_stream_helper.RequestReads();
2128 end_of_stream_helper.CheckIfReadDonesWereCalled(true);
2131 TEST_F(ChunkDemuxerTest, ConfigChange_Video) {
2132 InSequence s;
2134 ASSERT_TRUE(InitDemuxerWithConfigChangeData());
2136 DemuxerStream::Status status;
2137 base::TimeDelta last_timestamp;
2139 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
2141 // Fetch initial video config and verify it matches what we expect.
2142 const VideoDecoderConfig& video_config_1 = video->video_decoder_config();
2143 ASSERT_TRUE(video_config_1.IsValidConfig());
2144 EXPECT_EQ(video_config_1.natural_size().width(), 320);
2145 EXPECT_EQ(video_config_1.natural_size().height(), 240);
2147 ExpectRead(DemuxerStream::VIDEO, 0);
2149 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp);
2151 ASSERT_EQ(status, DemuxerStream::kConfigChanged);
2152 EXPECT_EQ(last_timestamp.InMilliseconds(), 501);
2154 // Fetch the new decoder config.
2155 const VideoDecoderConfig& video_config_2 = video->video_decoder_config();
2156 ASSERT_TRUE(video_config_2.IsValidConfig());
2157 EXPECT_EQ(video_config_2.natural_size().width(), 640);
2158 EXPECT_EQ(video_config_2.natural_size().height(), 360);
2160 ExpectRead(DemuxerStream::VIDEO, 527);
2162 // Read until the next config change.
2163 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp);
2164 ASSERT_EQ(status, DemuxerStream::kConfigChanged);
2165 EXPECT_EQ(last_timestamp.InMilliseconds(), 793);
2167 // Get the new config and verify that it matches the first one.
2168 ASSERT_TRUE(video_config_1.Matches(video->video_decoder_config()));
2170 ExpectRead(DemuxerStream::VIDEO, 801);
2172 // Read until the end of the stream just to make sure there aren't any other
2173 // config changes.
2174 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO, &status, &last_timestamp);
2175 ASSERT_EQ(status, DemuxerStream::kOk);
2178 TEST_F(ChunkDemuxerTest, ConfigChange_Audio) {
2179 InSequence s;
2181 ASSERT_TRUE(InitDemuxerWithConfigChangeData());
2183 DemuxerStream::Status status;
2184 base::TimeDelta last_timestamp;
2186 DemuxerStream* audio = demuxer_->GetStream(DemuxerStream::AUDIO);
2188 // Fetch initial audio config and verify it matches what we expect.
2189 const AudioDecoderConfig& audio_config_1 = audio->audio_decoder_config();
2190 ASSERT_TRUE(audio_config_1.IsValidConfig());
2191 EXPECT_EQ(audio_config_1.samples_per_second(), 44100);
2192 EXPECT_EQ(audio_config_1.extra_data_size(), 3863u);
2194 ExpectRead(DemuxerStream::AUDIO, 0);
2196 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp);
2198 ASSERT_EQ(status, DemuxerStream::kConfigChanged);
2199 EXPECT_EQ(last_timestamp.InMilliseconds(), 524);
2201 // Fetch the new decoder config.
2202 const AudioDecoderConfig& audio_config_2 = audio->audio_decoder_config();
2203 ASSERT_TRUE(audio_config_2.IsValidConfig());
2204 EXPECT_EQ(audio_config_2.samples_per_second(), 44100);
2205 EXPECT_EQ(audio_config_2.extra_data_size(), 3935u);
2207 ExpectRead(DemuxerStream::AUDIO, 527);
2209 // Read until the next config change.
2210 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp);
2211 ASSERT_EQ(status, DemuxerStream::kConfigChanged);
2212 EXPECT_EQ(last_timestamp.InMilliseconds(), 759);
2214 // Get the new config and verify that it matches the first one.
2215 ASSERT_TRUE(audio_config_1.Matches(audio->audio_decoder_config()));
2217 ExpectRead(DemuxerStream::AUDIO, 779);
2219 // Read until the end of the stream just to make sure there aren't any other
2220 // config changes.
2221 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO, &status, &last_timestamp);
2222 ASSERT_EQ(status, DemuxerStream::kOk);
2225 TEST_F(ChunkDemuxerTest, ConfigChange_Seek) {
2226 InSequence s;
2228 ASSERT_TRUE(InitDemuxerWithConfigChangeData());
2230 DemuxerStream* video = demuxer_->GetStream(DemuxerStream::VIDEO);
2232 // Fetch initial video config and verify it matches what we expect.
2233 const VideoDecoderConfig& video_config_1 = video->video_decoder_config();
2234 ASSERT_TRUE(video_config_1.IsValidConfig());
2235 EXPECT_EQ(video_config_1.natural_size().width(), 320);
2236 EXPECT_EQ(video_config_1.natural_size().height(), 240);
2238 ExpectRead(DemuxerStream::VIDEO, 0);
2240 // Seek to a location with a different config.
2241 Seek(base::TimeDelta::FromMilliseconds(527));
2243 // Verify that the config change is signalled.
2244 ExpectConfigChanged(DemuxerStream::VIDEO);
2246 // Fetch the new decoder config and verify it is what we expect.
2247 const VideoDecoderConfig& video_config_2 = video->video_decoder_config();
2248 ASSERT_TRUE(video_config_2.IsValidConfig());
2249 EXPECT_EQ(video_config_2.natural_size().width(), 640);
2250 EXPECT_EQ(video_config_2.natural_size().height(), 360);
2252 // Verify that Read() will return a buffer now.
2253 ExpectRead(DemuxerStream::VIDEO, 527);
2255 // Seek back to the beginning and verify we get another config change.
2256 Seek(base::TimeDelta::FromMilliseconds(0));
2257 ExpectConfigChanged(DemuxerStream::VIDEO);
2258 ASSERT_TRUE(video_config_1.Matches(video->video_decoder_config()));
2259 ExpectRead(DemuxerStream::VIDEO, 0);
2261 // Seek to a location that requires a config change and then
2262 // seek to a new location that has the same configuration as
2263 // the start of the file without a Read() in the middle.
2264 Seek(base::TimeDelta::FromMilliseconds(527));
2265 Seek(base::TimeDelta::FromMilliseconds(801));
2267 // Verify that no config change is signalled.
2268 ExpectRead(DemuxerStream::VIDEO, 801);
2269 ASSERT_TRUE(video_config_1.Matches(video->video_decoder_config()));
2272 TEST_F(ChunkDemuxerTest, TimestampPositiveOffset) {
2273 ASSERT_TRUE(InitDemuxer(true, true));
2275 ASSERT_TRUE(demuxer_->SetTimestampOffset(
2276 kSourceId, base::TimeDelta::FromSeconds(30)));
2277 AppendCluster(GenerateCluster(0, 2));
2279 Seek(base::TimeDelta::FromMilliseconds(30000));
2281 GenerateExpectedReads(30000, 2);
2284 TEST_F(ChunkDemuxerTest, TimestampNegativeOffset) {
2285 ASSERT_TRUE(InitDemuxer(true, true));
2287 ASSERT_TRUE(demuxer_->SetTimestampOffset(
2288 kSourceId, base::TimeDelta::FromSeconds(-1)));
2289 AppendCluster(GenerateCluster(1000, 2));
2291 GenerateExpectedReads(0, 2);
2294 TEST_F(ChunkDemuxerTest, TimestampOffsetSeparateStreams) {
2295 std::string audio_id = "audio1";
2296 std::string video_id = "video1";
2297 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id));
2299 ASSERT_TRUE(demuxer_->SetTimestampOffset(
2300 audio_id, base::TimeDelta::FromMilliseconds(-2500)));
2301 ASSERT_TRUE(demuxer_->SetTimestampOffset(
2302 video_id, base::TimeDelta::FromMilliseconds(-2500)));
2303 AppendCluster(audio_id, GenerateSingleStreamCluster(2500,
2304 2500 + kAudioBlockDuration * 4, kAudioTrackNum, kAudioBlockDuration));
2305 AppendCluster(video_id, GenerateSingleStreamCluster(2500,
2306 2500 + kVideoBlockDuration * 4, kVideoTrackNum, kVideoBlockDuration));
2307 GenerateAudioStreamExpectedReads(0, 4);
2308 GenerateVideoStreamExpectedReads(0, 4);
2310 Seek(base::TimeDelta::FromMilliseconds(27300));
2312 ASSERT_TRUE(demuxer_->SetTimestampOffset(
2313 audio_id, base::TimeDelta::FromMilliseconds(27300)));
2314 ASSERT_TRUE(demuxer_->SetTimestampOffset(
2315 video_id, base::TimeDelta::FromMilliseconds(27300)));
2316 AppendCluster(audio_id, GenerateSingleStreamCluster(
2317 0, kAudioBlockDuration * 4, kAudioTrackNum, kAudioBlockDuration));
2318 AppendCluster(video_id, GenerateSingleStreamCluster(
2319 0, kVideoBlockDuration * 4, kVideoTrackNum, kVideoBlockDuration));
2320 GenerateVideoStreamExpectedReads(27300, 4);
2321 GenerateAudioStreamExpectedReads(27300, 4);
2324 TEST_F(ChunkDemuxerTest, TimestampOffsetMidParse) {
2325 ASSERT_TRUE(InitDemuxer(true, true));
2327 scoped_ptr<Cluster> cluster = GenerateCluster(0, 2);
2328 // Append only part of the cluster data.
2329 AppendData(cluster->data(), cluster->size() - 13);
2331 // Setting a timestamp should fail because we're in the middle of a cluster.
2332 ASSERT_FALSE(demuxer_->SetTimestampOffset(
2333 kSourceId, base::TimeDelta::FromSeconds(25)));
2335 demuxer_->Abort(kSourceId);
2336 // After Abort(), setting a timestamp should succeed since we're no longer
2337 // in the middle of a cluster
2338 ASSERT_TRUE(demuxer_->SetTimestampOffset(
2339 kSourceId, base::TimeDelta::FromSeconds(25)));
2342 TEST_F(ChunkDemuxerTest, DurationChange) {
2343 ASSERT_TRUE(InitDemuxer(true, true));
2344 static const int kStreamDuration = kDefaultDuration().InMilliseconds();
2346 // Add data leading up to the currently set duration.
2347 AppendCluster(GenerateCluster(kStreamDuration - kAudioBlockDuration,
2348 kStreamDuration - kVideoBlockDuration,
2349 2));
2351 CheckExpectedRanges(kSourceId, "{ [201191,201224) }");
2353 // Add data at the currently set duration. The duration should not increase.
2354 AppendCluster(GenerateCluster(kDefaultDuration().InMilliseconds(), 2));
2356 // Range should not be affected.
2357 CheckExpectedRanges(kSourceId, "{ [201191,201224) }");
2359 // Now add data past the duration and expect a new duration to be signalled.
2360 static const int kNewStreamDuration =
2361 kStreamDuration + kAudioBlockDuration * 2;
2362 EXPECT_CALL(host_, SetDuration(
2363 base::TimeDelta::FromMilliseconds(kNewStreamDuration)));
2364 AppendCluster(GenerateCluster(kStreamDuration + kAudioBlockDuration,
2365 kStreamDuration + kVideoBlockDuration,
2366 2));
2368 // See that the range has increased appropriately.
2369 CheckExpectedRanges(kSourceId, "{ [201191,201270) }");
2372 TEST_F(ChunkDemuxerTest, DurationChangeTimestampOffset) {
2373 ASSERT_TRUE(InitDemuxer(true, true));
2375 ASSERT_TRUE(demuxer_->SetTimestampOffset(kSourceId, kDefaultDuration()));
2377 EXPECT_CALL(host_, SetDuration(
2378 kDefaultDuration() + base::TimeDelta::FromMilliseconds(
2379 kAudioBlockDuration * 2)));
2380 AppendCluster(GenerateCluster(0, 4));
2383 TEST_F(ChunkDemuxerTest, EndOfStreamTruncateDuration) {
2384 ASSERT_TRUE(InitDemuxer(true, true));
2386 AppendCluster(kDefaultFirstCluster());
2388 EXPECT_CALL(host_, SetDuration(
2389 base::TimeDelta::FromMilliseconds(kDefaultFirstClusterEndTimestamp)));
2390 MarkEndOfStream(PIPELINE_OK);
2394 TEST_F(ChunkDemuxerTest, ZeroLengthAppend) {
2395 ASSERT_TRUE(InitDemuxer(true, true));
2396 AppendData(NULL, 0);
2399 TEST_F(ChunkDemuxerTest, AppendAfterEndOfStream) {
2400 ASSERT_TRUE(InitDemuxer(true, true));
2402 EXPECT_CALL(host_, SetDuration(_))
2403 .Times(AnyNumber());
2405 AppendCluster(kDefaultFirstCluster());
2406 MarkEndOfStream(PIPELINE_OK);
2408 demuxer_->UnmarkEndOfStream();
2410 AppendCluster(kDefaultSecondCluster());
2411 MarkEndOfStream(PIPELINE_OK);
2414 // Test receiving a Shutdown() call before we get an Initialize()
2415 // call. This can happen if video element gets destroyed before
2416 // the pipeline has a chance to initialize the demuxer.
2417 TEST_F(ChunkDemuxerTest, ShutdownBeforeInitialize) {
2418 demuxer_->Shutdown();
2419 demuxer_->Initialize(
2420 &host_, CreateInitDoneCB(DEMUXER_ERROR_COULD_NOT_OPEN));
2421 message_loop_.RunUntilIdle();
2424 TEST_F(ChunkDemuxerTest, ReadAfterAudioDisabled) {
2425 ASSERT_TRUE(InitDemuxer(true, true));
2426 AppendCluster(kDefaultFirstCluster());
2428 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::AUDIO);
2429 ASSERT_TRUE(stream);
2431 // The stream should no longer be present.
2432 demuxer_->OnAudioRendererDisabled();
2433 ASSERT_FALSE(demuxer_->GetStream(DemuxerStream::AUDIO));
2435 // Normally this would return an audio buffer at timestamp zero, but
2436 // all reads should return EOS buffers when disabled.
2437 bool audio_read_done = false;
2438 stream->Read(base::Bind(&OnReadDone_EOSExpected, &audio_read_done));
2439 message_loop_.RunUntilIdle();
2441 EXPECT_TRUE(audio_read_done);
2444 // Verifies that signalling end of stream while stalled at a gap
2445 // boundary does not trigger end of stream buffers to be returned.
2446 TEST_F(ChunkDemuxerTest, EndOfStreamWhileWaitingForGapToBeFilled) {
2447 ASSERT_TRUE(InitDemuxer(true, true));
2449 AppendCluster(0, 10);
2450 AppendCluster(300, 10);
2451 CheckExpectedRanges(kSourceId, "{ [0,132) [300,432) }");
2454 GenerateExpectedReads(0, 10);
2456 bool audio_read_done = false;
2457 bool video_read_done = false;
2458 ReadAudio(base::Bind(&OnReadDone,
2459 base::TimeDelta::FromMilliseconds(138),
2460 &audio_read_done));
2461 ReadVideo(base::Bind(&OnReadDone,
2462 base::TimeDelta::FromMilliseconds(138),
2463 &video_read_done));
2465 // Verify that the reads didn't complete
2466 EXPECT_FALSE(audio_read_done);
2467 EXPECT_FALSE(video_read_done);
2469 EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(438)));
2470 MarkEndOfStream(PIPELINE_OK);
2472 // Verify that the reads still haven't completed.
2473 EXPECT_FALSE(audio_read_done);
2474 EXPECT_FALSE(video_read_done);
2476 demuxer_->UnmarkEndOfStream();
2478 AppendCluster(138, 24);
2480 message_loop_.RunUntilIdle();
2482 CheckExpectedRanges(kSourceId, "{ [0,438) }");
2484 // Verify that the reads have completed.
2485 EXPECT_TRUE(audio_read_done);
2486 EXPECT_TRUE(video_read_done);
2488 // Read the rest of the buffers.
2489 GenerateExpectedReads(161, 171, 22);
2491 // Verify that reads block because the append cleared the end of stream state.
2492 audio_read_done = false;
2493 video_read_done = false;
2494 ReadAudio(base::Bind(&OnReadDone_EOSExpected,
2495 &audio_read_done));
2496 ReadVideo(base::Bind(&OnReadDone_EOSExpected,
2497 &video_read_done));
2499 // Verify that the reads don't complete.
2500 EXPECT_FALSE(audio_read_done);
2501 EXPECT_FALSE(video_read_done);
2503 MarkEndOfStream(PIPELINE_OK);
2505 EXPECT_TRUE(audio_read_done);
2506 EXPECT_TRUE(video_read_done);
2509 TEST_F(ChunkDemuxerTest, CanceledSeekDuringInitialPreroll) {
2510 ASSERT_TRUE(InitDemuxer(true, true));
2512 // Cancel preroll.
2513 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(200);
2514 demuxer_->CancelPendingSeek(seek_time);
2516 // Initiate the seek to the new location.
2517 Seek(seek_time);
2519 // Append data to satisfy the seek.
2520 AppendCluster(seek_time.InMilliseconds(), 10);
2523 TEST_F(ChunkDemuxerTest, GCDuringSeek) {
2524 ASSERT_TRUE(InitDemuxer(true, false));
2526 demuxer_->SetMemoryLimitsForTesting(5 * kBlockSize);
2528 base::TimeDelta seek_time1 = base::TimeDelta::FromMilliseconds(1000);
2529 base::TimeDelta seek_time2 = base::TimeDelta::FromMilliseconds(500);
2531 // Initiate a seek to |seek_time1|.
2532 Seek(seek_time1);
2534 // Append data to satisfy the first seek request.
2535 AppendSingleStreamCluster(kSourceId, kAudioTrackNum,
2536 seek_time1.InMilliseconds(), 5);
2537 CheckExpectedRanges(kSourceId, "{ [1000,1115) }");
2539 // Signal that the second seek is starting.
2540 demuxer_->StartWaitingForSeek(seek_time2);
2542 // Append data to satisfy the second seek. This append triggers
2543 // the garbage collection logic since we set the memory limit to
2544 // 5 blocks.
2545 AppendSingleStreamCluster(kSourceId, kAudioTrackNum,
2546 seek_time2.InMilliseconds(), 5);
2548 // Verify that the buffers that cover |seek_time2| do not get
2549 // garbage collected.
2550 CheckExpectedRanges(kSourceId, "{ [500,615) }");
2552 // Complete the seek.
2553 demuxer_->Seek(seek_time2, NewExpectedStatusCB(PIPELINE_OK));
2556 // Append more data and make sure that the blocks for |seek_time2|
2557 // don't get removed.
2559 // NOTE: The current GC algorithm tries to preserve the GOP at the
2560 // current position as well as the last appended GOP. This is
2561 // why there are 2 ranges in the expectations.
2562 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 700, 5);
2563 CheckExpectedRanges(kSourceId, "{ [500,592) [792,815) }");
2566 TEST_F(ChunkDemuxerTest, RemoveBeforeInitSegment) {
2567 EXPECT_CALL(*this, DemuxerOpened());
2568 demuxer_->Initialize(
2569 &host_, CreateInitDoneCB(kNoTimestamp(), PIPELINE_OK));
2571 EXPECT_EQ(ChunkDemuxer::kOk, AddId(kSourceId, true, true));
2573 demuxer_->Remove(kSourceId, base::TimeDelta::FromMilliseconds(0),
2574 base::TimeDelta::FromMilliseconds(1));
2577 TEST_F(ChunkDemuxerTest, AppendWindow) {
2578 ASSERT_TRUE(InitDemuxer(false, true));
2579 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
2581 // Set the append window to [20,280).
2582 demuxer_->SetAppendWindowStart(kSourceId,
2583 base::TimeDelta::FromMilliseconds(20));
2584 demuxer_->SetAppendWindowEnd(kSourceId,
2585 base::TimeDelta::FromMilliseconds(280));
2587 // Append a cluster that starts before and ends after the append window.
2588 AppendSingleStreamCluster(kSourceId, kVideoTrackNum,
2589 "0K 30 60 90 120K 150 180 210 240K 270 300 330K");
2591 // Verify that GOPs that start outside the window are not included
2592 // in the buffer. Also verify that buffers that extend beyond the
2593 // window are not included.
2594 CheckExpectedRanges(kSourceId, "{ [120,300) }");
2595 CheckExpectedBuffers(stream, "120 150 180 210 240 270");
2597 // Extend the append window to [20,650).
2598 demuxer_->SetAppendWindowEnd(kSourceId,
2599 base::TimeDelta::FromMilliseconds(650));
2601 // Append more data and verify that adding buffers start at the next
2602 // keyframe.
2603 AppendSingleStreamCluster(kSourceId, kVideoTrackNum,
2604 "360 390 420K 450 480 510 540K 570 600 630K");
2605 CheckExpectedRanges(kSourceId, "{ [120,300) [420,660) }");
2608 TEST_F(ChunkDemuxerTest, StartWaitingForSeekAfterParseError) {
2609 ASSERT_TRUE(InitDemuxer(true, true));
2610 EXPECT_CALL(host_, OnDemuxerError(PIPELINE_ERROR_DECODE));
2611 AppendGarbage();
2612 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(50);
2613 demuxer_->StartWaitingForSeek(seek_time);
2616 } // namespace media