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