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