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.
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
;
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
+
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
+
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));
88 for (int i
= 7; i
> 0; i
--) {
89 buffer
[i
] = tmp
& 0xff;
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
,
103 DemuxerStream::Status status
,
104 const scoped_refptr
<DecoderBuffer
>& buffer
) {
105 EXPECT_EQ(status
, DemuxerStream::kOk
);
106 EXPECT_EQ(expected_time
, buffer
->timestamp());
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());
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());
126 static void OnSeekDone_OKExpected(bool* called
, PipelineStatus status
) {
127 EXPECT_EQ(status
, PIPELINE_OK
);
131 class ChunkDemuxerTest
: public testing::Test
{
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);
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() {
172 void CreateInitSegment(bool has_audio
, bool has_video
,
173 bool is_audio_encrypted
, bool is_video_encrypted
,
174 scoped_ptr
<uint8
[]>* buffer
,
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;
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();
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.
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();
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
;
268 codecs
.push_back("vorbis");
273 codecs
.push_back("vp8");
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
) {
306 block_duration
= kVideoBlockDuration
;
309 block_duration
= kAudioBlockDuration
;
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
, ' ', ×tamps
);
325 std::vector
<uint8
> data(10);
326 for (size_t i
= 0; i
< timestamps
.size(); ++i
) {
327 std::string timestamp_str
= timestamps
[i
];
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);
335 CHECK(base::StringToInt(timestamp_str
, ×tamp_in_ms
));
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),
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
)
441 AppendInitSegmentWithEncryptedInfo(
442 kSourceId
, has_audio
, has_video
,
443 is_audio_encrypted
, is_video_encrypted
);
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
)
455 if (AddId(video_id
, false, true) != ChunkDemuxer::kOk
)
458 AppendInitSegmentWithSourceId(audio_id
, true, false);
459 AppendInitSegmentWithSourceId(video_id
, false, true);
463 // Initializes the demuxer with data from 2 files with different
464 // decoder configurations. This is used to test the decoder config change
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
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
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),
489 if (AddId(kSourceId
, true, true) != ChunkDemuxer::kOk
)
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)
510 AppendData(bear1
->data(), 4370);
511 AppendData(bear1
->data() + 72737, 28183);
512 CheckExpectedRanges(kSourceId
, "{ [0,2737) }");
514 MarkEndOfStream(PIPELINE_OK
);
518 void ShutdownDemuxer() {
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
) {
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
,
546 CHECK_GT(block_count
, 0);
549 scoped_ptr
<uint8
[]> data(new uint8
[size
]);
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
,
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
,
571 audio_timecode
+= kAudioBlockDuration
;
575 cb
.AddSimpleBlock(kVideoTrackNum
, video_timecode
, video_flag
, data
.get(),
577 video_timecode
+= kVideoBlockDuration
;
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
);
589 AddVideoBlockGroup(&cb
, kVideoTrackNum
, video_timecode
,
590 kVideoBlockDuration
, video_flag
);
591 cb
.AddBlockGroup(kAudioTrackNum
, audio_timecode
, kAudioBlockDuration
,
592 kWebMFlagKeyframe
, data
.get(), size
);
598 scoped_ptr
<Cluster
> GenerateSingleStreamCluster(int timecode
,
601 int block_duration
) {
602 CHECK_GT(end_timecode
, timecode
);
604 std::vector
<uint8
> data(kBlockSize
);
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
,
622 cb
.AddBlockGroup(track_number
, timecode
, block_duration
,
623 kWebMFlagKeyframe
, &data
[0], data
.size());
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
,
648 CHECK_GT(block_count
, 0);
650 if (block_count
== 1) {
651 ExpectRead(DemuxerStream::AUDIO
, start_audio_timecode
);
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
;
665 ExpectRead(DemuxerStream::VIDEO
, video_timecode
);
666 video_timecode
+= kVideoBlockDuration
;
670 void GenerateSingleStreamExpectedReads(int timecode
,
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
) {
695 cb
.SetClusterTimecode(timecode
);
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
;
709 for (size_t i
= 0; i
< r
.size(); ++i
) {
710 ss
<< "[" << r
.start(i
).InMilliseconds() << ","
711 << r
.end(i
).InMilliseconds() << ") ";
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();
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
, ' ', ×tamps
);
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())
782 ss
<< buffer
->timestamp().InMilliseconds();
784 EXPECT_EQ(expected
, ss
.str());
787 MOCK_METHOD1(Checkpoint
, void(int id
));
789 struct BufferTimestamps
{
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
)
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
825 (timestamps
[i
].audio_time_ms
!= kSkip
||
826 timestamps
[i
].video_time_ms
!= kSkip
);
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
),
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
),
844 EXPECT_TRUE(video_read_done
);
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_
;
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
)) {
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
);
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());
933 EXPECT_FALSE(audio_stream
);
936 DemuxerStream
* video_stream
= demuxer_
->GetStream(DemuxerStream::VIDEO
);
938 EXPECT_TRUE(video_stream
);
939 EXPECT_EQ(is_video_encrypted
,
940 video_stream
->video_decoder_config().is_encrypted());
942 EXPECT_FALSE(video_stream
);
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
966 TEST_F(ChunkDemuxerTest
, AppendDataAfterSeek
) {
967 ASSERT_TRUE(InitDemuxer(true, true));
968 AppendCluster(kDefaultFirstCluster());
972 EXPECT_CALL(*this, Checkpoint(1));
974 Seek(base::TimeDelta::FromMilliseconds(46));
976 EXPECT_CALL(*this, Checkpoint(2));
980 AppendCluster(kDefaultSecondCluster());
982 message_loop_
.RunUntilIdle();
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
));
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));
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),
1052 ReadVideo(base::Bind(&OnReadDone
,
1053 base::TimeDelta::FromMilliseconds(0),
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());
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());
1102 // Test timecodes going backwards and including values less than the cluster
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());
1125 // Test monotonic increasing timestamps on a per stream
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
);
1167 CheckExpectedRanges("{ }");
1168 demuxer_
->RemoveId(kSourceId
);
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
1203 class EndOfStreamHelper
{
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_
);
1233 static void OnEndOfStreamReadDone(
1235 DemuxerStream::Status status
,
1236 const scoped_refptr
<DecoderBuffer
>& buffer
) {
1237 EXPECT_EQ(status
, DemuxerStream::kOk
);
1238 EXPECT_TRUE(buffer
->end_of_stream());
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.
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
[] = {
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
[] = {
1411 ASSERT_TRUE(ParseWebMFile("bear-320x240-live.webm", buffer_timestamps
,
1412 kInfiniteDuration()));
1415 TEST_F(ChunkDemuxerTest
, WebMFile_AudioOnly
) {
1416 struct BufferTimestamps buffer_timestamps
[] = {
1425 ASSERT_TRUE(ParseWebMFile("bear-320x240-audio-only.webm", buffer_timestamps
,
1426 base::TimeDelta::FromMilliseconds(2744),
1430 TEST_F(ChunkDemuxerTest
, WebMFile_VideoOnly
) {
1431 struct BufferTimestamps buffer_timestamps
[] = {
1440 ASSERT_TRUE(ParseWebMFile("bear-320x240-video-only.webm", buffer_timestamps
,
1441 base::TimeDelta::FromMilliseconds(2703),
1445 TEST_F(ChunkDemuxerTest
, WebMFile_AltRefFrames
) {
1446 struct BufferTimestamps buffer_timestamps
[] = {
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),
1471 ReadVideo(base::Bind(&OnReadDone
,
1472 base::TimeDelta::FromMilliseconds(0),
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.
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
);
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),
1505 ReadVideo(base::Bind(&OnReadDone
,
1506 base::TimeDelta::FromMilliseconds(33),
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
);
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
),
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);
1557 ASSERT_EQ(demuxer_
->AddId(kSourceId
, "video/webm", codecs
),
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
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.
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.
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
));
1714 GenerateSingleStreamCluster(0, 92, kAudioTrackNum
, kAudioBlockDuration
));
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),
1725 ReadVideo(base::Bind(&OnReadDone
,
1726 base::TimeDelta::FromMilliseconds(0),
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),
1739 ReadVideo(base::Bind(&OnReadDone
,
1740 base::TimeDelta::FromSeconds(3),
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
);
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
);
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.
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.
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));
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
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
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
;
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
;
2036 const char* codec_ids
[] = {
2037 // GPAC places leading zeros on the audio object type.
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
2106 TEST_F(ChunkDemuxerTest
, EndOfStreamDuringSeek
) {
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
) {
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
2174 ReadUntilNotOkOrEndOfStream(DemuxerStream::VIDEO
, &status
, &last_timestamp
);
2175 ASSERT_EQ(status
, DemuxerStream::kOk
);
2178 TEST_F(ChunkDemuxerTest
, ConfigChange_Audio
) {
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
2221 ReadUntilNotOkOrEndOfStream(DemuxerStream::AUDIO
, &status
, &last_timestamp
);
2222 ASSERT_EQ(status
, DemuxerStream::kOk
);
2225 TEST_F(ChunkDemuxerTest
, ConfigChange_Seek
) {
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
,
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
,
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),
2461 ReadVideo(base::Bind(&OnReadDone
,
2462 base::TimeDelta::FromMilliseconds(138),
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
,
2496 ReadVideo(base::Bind(&OnReadDone_EOSExpected
,
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));
2513 base::TimeDelta seek_time
= base::TimeDelta::FromMilliseconds(200);
2514 demuxer_
->CancelPendingSeek(seek_time
);
2516 // Initiate the seek to the new location.
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|.
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
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
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
));
2612 base::TimeDelta seek_time
= base::TimeDelta::FromSeconds(50);
2613 demuxer_
->StartWaitingForSeek(seek_time
);
2616 } // namespace media