1 // Copyright 2014 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.
10 #include "base/logging.h"
11 #include "media/base/audio_decoder_config.h"
12 #include "media/base/decrypt_config.h"
13 #include "media/formats/webm/cluster_builder.h"
14 #include "media/formats/webm/opus_packet_builder.h"
15 #include "media/formats/webm/webm_cluster_parser.h"
16 #include "media/formats/webm/webm_constants.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
20 using ::testing::InSequence
;
21 using ::testing::Return
;
26 typedef WebMTracksParser::TextTracks TextTracks
;
29 kTimecodeScale
= 1000000, // Timecode scale for millisecond timestamps.
33 kTestAudioFrameDefaultDurationInMs
= 13,
34 kTestVideoFrameDefaultDurationInMs
= 17
37 // Test duration defaults must differ from parser estimation defaults to know
38 // which durations parser used when emitting buffers.
40 static_cast<int>(kTestAudioFrameDefaultDurationInMs
) !=
41 static_cast<int>(WebMClusterParser::kDefaultAudioBufferDurationInMs
),
42 "test default is the same as estimation fallback audio duration");
44 static_cast<int>(kTestVideoFrameDefaultDurationInMs
) !=
45 static_cast<int>(WebMClusterParser::kDefaultVideoBufferDurationInMs
),
46 "test default is the same as estimation fallback video duration");
52 // Negative value is allowed only for block groups (not simple blocks) and
53 // directs CreateCluster() to exclude BlockDuration entry from the cluster for
54 // this BlockGroup. The absolute value is used for parser verification.
55 // For simple blocks, this value must be non-negative, and is used only for
56 // parser verification.
59 bool use_simple_block
;
61 // Default data will be used if no data given.
66 static const BlockInfo kDefaultBlockInfo
[] = {
67 {kAudioTrackNum
, 0, 23, true, NULL
, 0},
68 {kAudioTrackNum
, 23, 23, true, NULL
, 0},
69 // Assumes not using DefaultDuration
70 {kVideoTrackNum
, 33, 34, true, NULL
, 0},
71 {kAudioTrackNum
, 46, 23, true, NULL
, 0},
72 {kVideoTrackNum
, 67, 33, false, NULL
, 0},
73 {kAudioTrackNum
, 69, 23, false, NULL
, 0},
74 {kVideoTrackNum
, 100, 33, false, NULL
, 0},
77 static const uint8_t kEncryptedFrame
[] = {
78 0x01, // Block is encrypted
79 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 // IV
82 static scoped_ptr
<Cluster
> CreateCluster(int timecode
,
83 const BlockInfo
* block_info
,
86 cb
.SetClusterTimecode(0);
88 uint8_t kDefaultBlockData
[] = { 0x00 };
90 for (int i
= 0; i
< block_count
; i
++) {
93 if (block_info
[i
].data
!= NULL
) {
94 data
= block_info
[i
].data
;
95 data_length
= block_info
[i
].data_length
;
97 data
= kDefaultBlockData
;
98 data_length
= sizeof(kDefaultBlockData
);
101 if (block_info
[i
].use_simple_block
) {
102 CHECK_GE(block_info
[i
].duration
, 0);
103 cb
.AddSimpleBlock(block_info
[i
].track_num
, block_info
[i
].timestamp
, 0,
108 if (block_info
[i
].duration
< 0) {
109 cb
.AddBlockGroupWithoutBlockDuration(block_info
[i
].track_num
,
110 block_info
[i
].timestamp
, 0, data
,
115 cb
.AddBlockGroup(block_info
[i
].track_num
, block_info
[i
].timestamp
,
116 block_info
[i
].duration
, 0, data
, data_length
);
122 // Creates a Cluster with one encrypted Block. |bytes_to_write| is number of
123 // bytes of the encrypted frame to write.
124 static scoped_ptr
<Cluster
> CreateEncryptedCluster(int bytes_to_write
) {
125 CHECK_GT(bytes_to_write
, 0);
126 CHECK_LE(bytes_to_write
, static_cast<int>(sizeof(kEncryptedFrame
)));
129 cb
.SetClusterTimecode(0);
130 cb
.AddSimpleBlock(kVideoTrackNum
, 0, 0, kEncryptedFrame
, bytes_to_write
);
134 static bool VerifyBuffers(const WebMClusterParser::BufferQueue
& audio_buffers
,
135 const WebMClusterParser::BufferQueue
& video_buffers
,
136 const WebMClusterParser::BufferQueue
& text_buffers
,
137 const BlockInfo
* block_info
,
139 int buffer_count
= audio_buffers
.size() + video_buffers
.size() +
141 if (block_count
!= buffer_count
) {
142 DVLOG(1) << __FUNCTION__
<< " : block_count (" << block_count
143 << ") mismatches buffer_count (" << buffer_count
<< ")";
147 size_t audio_offset
= 0;
148 size_t video_offset
= 0;
149 size_t text_offset
= 0;
150 for (int i
= 0; i
< block_count
; i
++) {
151 const WebMClusterParser::BufferQueue
* buffers
= NULL
;
153 StreamParserBuffer::Type expected_type
= DemuxerStream::UNKNOWN
;
155 if (block_info
[i
].track_num
== kAudioTrackNum
) {
156 buffers
= &audio_buffers
;
157 offset
= &audio_offset
;
158 expected_type
= DemuxerStream::AUDIO
;
159 } else if (block_info
[i
].track_num
== kVideoTrackNum
) {
160 buffers
= &video_buffers
;
161 offset
= &video_offset
;
162 expected_type
= DemuxerStream::VIDEO
;
163 } else if (block_info
[i
].track_num
== kTextTrackNum
) {
164 buffers
= &text_buffers
;
165 offset
= &text_offset
;
166 expected_type
= DemuxerStream::TEXT
;
168 LOG(ERROR
) << "Unexpected track number " << block_info
[i
].track_num
;
172 if (*offset
>= buffers
->size()) {
173 DVLOG(1) << __FUNCTION__
<< " : Too few buffers (" << buffers
->size()
174 << ") for track_num (" << block_info
[i
].track_num
175 << "), expected at least " << *offset
+ 1 << " buffers";
179 scoped_refptr
<StreamParserBuffer
> buffer
= (*buffers
)[(*offset
)++];
181 EXPECT_EQ(block_info
[i
].timestamp
, buffer
->timestamp().InMilliseconds());
182 EXPECT_EQ(std::abs(block_info
[i
].duration
),
183 buffer
->duration().InMillisecondsF());
184 EXPECT_EQ(expected_type
, buffer
->type());
185 EXPECT_EQ(block_info
[i
].track_num
, buffer
->track_id());
191 static bool VerifyBuffers(const scoped_ptr
<WebMClusterParser
>& parser
,
192 const BlockInfo
* block_info
,
194 const WebMClusterParser::TextBufferQueueMap
& text_map
=
195 parser
->GetTextBuffers();
196 const WebMClusterParser::BufferQueue
* text_buffers
;
197 const WebMClusterParser::BufferQueue no_text_buffers
;
198 if (!text_map
.empty())
199 text_buffers
= &(text_map
.rbegin()->second
);
201 text_buffers
= &no_text_buffers
;
203 return VerifyBuffers(parser
->GetAudioBuffers(),
204 parser
->GetVideoBuffers(),
210 static bool VerifyTextBuffers(
211 const scoped_ptr
<WebMClusterParser
>& parser
,
212 const BlockInfo
* block_info_ptr
,
215 const WebMClusterParser::BufferQueue
& text_buffers
) {
216 const BlockInfo
* const block_info_end
= block_info_ptr
+ block_count
;
218 typedef WebMClusterParser::BufferQueue::const_iterator TextBufferIter
;
219 TextBufferIter buffer_iter
= text_buffers
.begin();
220 const TextBufferIter buffer_end
= text_buffers
.end();
222 while (block_info_ptr
!= block_info_end
) {
223 const BlockInfo
& block_info
= *block_info_ptr
++;
225 if (block_info
.track_num
!= text_track_num
)
228 EXPECT_FALSE(block_info
.use_simple_block
);
229 EXPECT_FALSE(buffer_iter
== buffer_end
);
231 const scoped_refptr
<StreamParserBuffer
> buffer
= *buffer_iter
++;
232 EXPECT_EQ(block_info
.timestamp
, buffer
->timestamp().InMilliseconds());
233 EXPECT_EQ(std::abs(block_info
.duration
),
234 buffer
->duration().InMillisecondsF());
235 EXPECT_EQ(DemuxerStream::TEXT
, buffer
->type());
236 EXPECT_EQ(text_track_num
, buffer
->track_id());
239 EXPECT_TRUE(buffer_iter
== buffer_end
);
243 static void VerifyEncryptedBuffer(
244 scoped_refptr
<StreamParserBuffer
> buffer
) {
245 EXPECT_TRUE(buffer
->decrypt_config());
246 EXPECT_EQ(static_cast<unsigned long>(DecryptConfig::kDecryptionKeySize
),
247 buffer
->decrypt_config()->iv().length());
250 static void AppendToEnd(const WebMClusterParser::BufferQueue
& src
,
251 WebMClusterParser::BufferQueue
* dest
) {
252 for (WebMClusterParser::BufferQueue::const_iterator itr
= src
.begin();
253 itr
!= src
.end(); ++itr
) {
254 dest
->push_back(*itr
);
258 class WebMClusterParserTest
: public testing::Test
{
260 WebMClusterParserTest()
261 : parser_(new WebMClusterParser(kTimecodeScale
,
274 void ResetParserToHaveDefaultDurations() {
275 base::TimeDelta default_audio_duration
= base::TimeDelta::FromMilliseconds(
276 kTestAudioFrameDefaultDurationInMs
);
277 base::TimeDelta default_video_duration
= base::TimeDelta::FromMilliseconds(
278 kTestVideoFrameDefaultDurationInMs
);
279 ASSERT_GE(default_audio_duration
, base::TimeDelta());
280 ASSERT_GE(default_video_duration
, base::TimeDelta());
281 ASSERT_NE(kNoTimestamp(), default_audio_duration
);
282 ASSERT_NE(kNoTimestamp(), default_video_duration
);
284 parser_
.reset(new WebMClusterParser(kTimecodeScale
,
286 default_audio_duration
,
288 default_video_duration
,
297 scoped_ptr
<WebMClusterParser
> parser_
;
300 DISALLOW_COPY_AND_ASSIGN(WebMClusterParserTest
);
303 TEST_F(WebMClusterParserTest
, HeldBackBufferHoldsBackAllTracks
) {
304 // If a buffer is missing duration and is being held back, then all other
305 // tracks' buffers that have same or higher (decode) timestamp should be held
306 // back too to keep the timestamps emitted for a cluster monotonically
307 // non-decreasing and in same order as parsed.
310 // Reset the parser to have 3 tracks: text, video (no default frame duration),
311 // and audio (with a default frame duration).
312 TextTracks text_tracks
;
313 text_tracks
.insert(std::make_pair(TextTracks::key_type(kTextTrackNum
),
314 TextTrackConfig(kTextSubtitles
, "", "",
316 base::TimeDelta default_audio_duration
=
317 base::TimeDelta::FromMilliseconds(kTestAudioFrameDefaultDurationInMs
);
318 ASSERT_GE(default_audio_duration
, base::TimeDelta());
319 ASSERT_NE(kNoTimestamp(), default_audio_duration
);
320 parser_
.reset(new WebMClusterParser(kTimecodeScale
,
322 default_audio_duration
,
332 const BlockInfo kBlockInfo
[] = {
333 {kVideoTrackNum
, 0, 33, true, NULL
, 0},
334 {kAudioTrackNum
, 0, 23, false, NULL
, 0},
335 {kTextTrackNum
, 10, 42, false, NULL
, 0},
336 {kAudioTrackNum
, 23, kTestAudioFrameDefaultDurationInMs
, true, NULL
, 0},
337 {kVideoTrackNum
, 33, 33, true, NULL
, 0},
338 {kAudioTrackNum
, 36, kTestAudioFrameDefaultDurationInMs
, true, NULL
, 0},
339 {kVideoTrackNum
, 66, 33, true, NULL
, 0},
340 {kAudioTrackNum
, 70, kTestAudioFrameDefaultDurationInMs
, true, NULL
, 0},
341 {kAudioTrackNum
, 83, kTestAudioFrameDefaultDurationInMs
, true, NULL
, 0},
344 const int kExpectedBuffersOnPartialCluster
[] = {
345 0, // Video simple block without DefaultDuration should be held back
346 0, // Audio buffer ready, but not emitted because its TS >= held back video
347 0, // Text buffer ready, but not emitted because its TS >= held back video
348 0, // 2nd audio buffer ready, also not emitted for same reason as first
349 4, // All previous buffers emitted, 2nd video held back with no duration
350 4, // 2nd video still has no duration, 3rd audio ready but not emitted
351 6, // All previous buffers emitted, 3rd video held back with no duration
352 6, // 3rd video still has no duration, 4th audio ready but not emitted
353 9, // Cluster end emits all buffers and 3rd video's duration is estimated
356 ASSERT_EQ(arraysize(kBlockInfo
), arraysize(kExpectedBuffersOnPartialCluster
));
357 int block_count
= arraysize(kBlockInfo
);
359 // Iteratively create a cluster containing the first N+1 blocks and parse all
360 // but the last byte of the cluster (except when N==|block_count|, just parse
361 // the whole cluster). Verify that the corresponding entry in
362 // |kExpectedBuffersOnPartialCluster| identifies the exact subset of
363 // |kBlockInfo| returned by the parser.
364 for (int i
= 0; i
< block_count
; ++i
) {
367 // Since we don't know exactly the offsets of each block in the full
368 // cluster, build a cluster with exactly one additional block so that
369 // parse of all but one byte should deterministically parse all but the
370 // last full block. Don't |exceed block_count| blocks though.
371 int blocks_in_cluster
= std::min(i
+ 2, block_count
);
372 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kBlockInfo
,
374 // Parse all but the last byte unless we need to parse the full cluster.
375 bool parse_full_cluster
= i
== (block_count
- 1);
376 int result
= parser_
->Parse(cluster
->data(), parse_full_cluster
?
377 cluster
->size() : cluster
->size() - 1);
378 if (parse_full_cluster
) {
379 DVLOG(1) << "Verifying parse result of full cluster of "
380 << blocks_in_cluster
<< " blocks";
381 EXPECT_EQ(cluster
->size(), result
);
383 DVLOG(1) << "Verifying parse result of cluster of "
384 << blocks_in_cluster
<< " blocks with last block incomplete";
385 EXPECT_GT(cluster
->size(), result
);
386 EXPECT_LT(0, result
);
389 EXPECT_TRUE(VerifyBuffers(parser_
, kBlockInfo
,
390 kExpectedBuffersOnPartialCluster
[i
]));
394 TEST_F(WebMClusterParserTest
, Reset
) {
397 int block_count
= arraysize(kDefaultBlockInfo
);
398 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kDefaultBlockInfo
, block_count
));
400 // Send slightly less than the full cluster so all but the last block is
402 int result
= parser_
->Parse(cluster
->data(), cluster
->size() - 1);
403 EXPECT_GT(result
, 0);
404 EXPECT_LT(result
, cluster
->size());
406 ASSERT_TRUE(VerifyBuffers(parser_
, kDefaultBlockInfo
, block_count
- 1));
409 // Now parse a whole cluster to verify that all the blocks will get parsed.
410 result
= parser_
->Parse(cluster
->data(), cluster
->size());
411 EXPECT_EQ(cluster
->size(), result
);
412 ASSERT_TRUE(VerifyBuffers(parser_
, kDefaultBlockInfo
, block_count
));
415 TEST_F(WebMClusterParserTest
, ParseClusterWithSingleCall
) {
416 int block_count
= arraysize(kDefaultBlockInfo
);
417 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kDefaultBlockInfo
, block_count
));
419 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
420 EXPECT_EQ(cluster
->size(), result
);
421 ASSERT_TRUE(VerifyBuffers(parser_
, kDefaultBlockInfo
, block_count
));
424 TEST_F(WebMClusterParserTest
, ParseClusterWithMultipleCalls
) {
425 int block_count
= arraysize(kDefaultBlockInfo
);
426 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kDefaultBlockInfo
, block_count
));
428 WebMClusterParser::BufferQueue audio_buffers
;
429 WebMClusterParser::BufferQueue video_buffers
;
430 const WebMClusterParser::BufferQueue no_text_buffers
;
432 const uint8_t* data
= cluster
->data();
433 int size
= cluster
->size();
434 int default_parse_size
= 3;
435 int parse_size
= std::min(default_parse_size
, size
);
438 int result
= parser_
->Parse(data
, parse_size
);
439 ASSERT_GE(result
, 0);
440 ASSERT_LE(result
, parse_size
);
443 // The parser needs more data so increase the parse_size a little.
444 parse_size
+= default_parse_size
;
445 parse_size
= std::min(parse_size
, size
);
449 AppendToEnd(parser_
->GetAudioBuffers(), &audio_buffers
);
450 AppendToEnd(parser_
->GetVideoBuffers(), &video_buffers
);
452 parse_size
= default_parse_size
;
457 ASSERT_TRUE(VerifyBuffers(audio_buffers
, video_buffers
,
458 no_text_buffers
, kDefaultBlockInfo
,
462 // Verify that both BlockGroups with the BlockDuration before the Block
463 // and BlockGroups with the BlockDuration after the Block are supported
465 // Note: Raw bytes are use here because ClusterBuilder only generates
466 // one of these scenarios.
467 TEST_F(WebMClusterParserTest
, ParseBlockGroup
) {
468 const BlockInfo kBlockInfo
[] = {
469 {kAudioTrackNum
, 0, 23, false, NULL
, 0},
470 {kVideoTrackNum
, 33, 34, false, NULL
, 0},
472 int block_count
= arraysize(kBlockInfo
);
474 const uint8_t kClusterData
[] = {
475 0x1F, 0x43, 0xB6, 0x75, 0x9B, // Cluster(size=27)
476 0xE7, 0x81, 0x00, // Timecode(size=1, value=0)
477 // BlockGroup with BlockDuration before Block.
478 0xA0, 0x8A, // BlockGroup(size=10)
479 0x9B, 0x81, 0x17, // BlockDuration(size=1, value=23)
480 0xA1, 0x85, 0x81, 0x00, 0x00, 0x00, 0xaa, // Block(size=5, track=1, ts=0)
481 // BlockGroup with BlockDuration after Block.
482 0xA0, 0x8A, // BlockGroup(size=10)
483 0xA1, 0x85, 0x82, 0x00, 0x21, 0x00, 0x55, // Block(size=5, track=2, ts=33)
484 0x9B, 0x81, 0x22, // BlockDuration(size=1, value=34)
486 const int kClusterSize
= sizeof(kClusterData
);
488 int result
= parser_
->Parse(kClusterData
, kClusterSize
);
489 EXPECT_EQ(kClusterSize
, result
);
490 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
));
493 TEST_F(WebMClusterParserTest
, ParseSimpleBlockAndBlockGroupMixture
) {
494 const BlockInfo kBlockInfo
[] = {
495 {kAudioTrackNum
, 0, 23, true, NULL
, 0},
496 {kAudioTrackNum
, 23, 23, false, NULL
, 0},
497 {kVideoTrackNum
, 33, 34, true, NULL
, 0},
498 {kAudioTrackNum
, 46, 23, false, NULL
, 0},
499 {kVideoTrackNum
, 67, 33, false, NULL
, 0},
501 int block_count
= arraysize(kBlockInfo
);
502 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kBlockInfo
, block_count
));
504 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
505 EXPECT_EQ(cluster
->size(), result
);
506 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
));
509 TEST_F(WebMClusterParserTest
, IgnoredTracks
) {
510 std::set
<int64
> ignored_tracks
;
511 ignored_tracks
.insert(kTextTrackNum
);
513 parser_
.reset(new WebMClusterParser(kTimecodeScale
,
525 const BlockInfo kInputBlockInfo
[] = {
526 {kAudioTrackNum
, 0, 23, true, NULL
, 0},
527 {kAudioTrackNum
, 23, 23, true, NULL
, 0},
528 {kVideoTrackNum
, 33, 34, true, NULL
, 0},
529 {kTextTrackNum
, 33, 99, true, NULL
, 0},
530 {kAudioTrackNum
, 46, 23, true, NULL
, 0},
531 {kVideoTrackNum
, 67, 34, true, NULL
, 0},
533 int input_block_count
= arraysize(kInputBlockInfo
);
535 const BlockInfo kOutputBlockInfo
[] = {
536 {kAudioTrackNum
, 0, 23, true, NULL
, 0},
537 {kAudioTrackNum
, 23, 23, true, NULL
, 0},
538 {kVideoTrackNum
, 33, 34, true, NULL
, 0},
539 {kAudioTrackNum
, 46, 23, true, NULL
, 0},
540 {kVideoTrackNum
, 67, 34, true, NULL
, 0},
542 int output_block_count
= arraysize(kOutputBlockInfo
);
544 scoped_ptr
<Cluster
> cluster(
545 CreateCluster(0, kInputBlockInfo
, input_block_count
));
547 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
548 EXPECT_EQ(cluster
->size(), result
);
549 ASSERT_TRUE(VerifyBuffers(parser_
, kOutputBlockInfo
, output_block_count
));
552 TEST_F(WebMClusterParserTest
, ParseTextTracks
) {
553 TextTracks text_tracks
;
555 text_tracks
.insert(std::make_pair(TextTracks::key_type(kTextTrackNum
),
556 TextTrackConfig(kTextSubtitles
, "", "",
559 parser_
.reset(new WebMClusterParser(kTimecodeScale
,
571 const BlockInfo kInputBlockInfo
[] = {
572 {kAudioTrackNum
, 0, 23, true, NULL
, 0},
573 {kAudioTrackNum
, 23, 23, true, NULL
, 0},
574 {kVideoTrackNum
, 33, 34, true, NULL
, 0},
575 {kTextTrackNum
, 33, 42, false, NULL
, 0},
576 {kAudioTrackNum
, 46, 23, true, NULL
, 0},
577 {kTextTrackNum
, 55, 44, false, NULL
, 0},
578 {kVideoTrackNum
, 67, 34, true, NULL
, 0},
580 int input_block_count
= arraysize(kInputBlockInfo
);
582 scoped_ptr
<Cluster
> cluster(
583 CreateCluster(0, kInputBlockInfo
, input_block_count
));
585 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
586 EXPECT_EQ(cluster
->size(), result
);
587 ASSERT_TRUE(VerifyBuffers(parser_
, kInputBlockInfo
, input_block_count
));
590 TEST_F(WebMClusterParserTest
, TextTracksSimpleBlock
) {
591 TextTracks text_tracks
;
593 text_tracks
.insert(std::make_pair(TextTracks::key_type(kTextTrackNum
),
594 TextTrackConfig(kTextSubtitles
, "", "",
597 parser_
.reset(new WebMClusterParser(kTimecodeScale
,
609 const BlockInfo kInputBlockInfo
[] = {
610 { kTextTrackNum
, 33, 42, true },
612 int input_block_count
= arraysize(kInputBlockInfo
);
614 scoped_ptr
<Cluster
> cluster(
615 CreateCluster(0, kInputBlockInfo
, input_block_count
));
617 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
618 EXPECT_LT(result
, 0);
621 TEST_F(WebMClusterParserTest
, ParseMultipleTextTracks
) {
622 TextTracks text_tracks
;
624 const int kSubtitleTextTrackNum
= kTextTrackNum
;
625 const int kCaptionTextTrackNum
= kTextTrackNum
+ 1;
627 text_tracks
.insert(std::make_pair(TextTracks::key_type(kSubtitleTextTrackNum
),
628 TextTrackConfig(kTextSubtitles
, "", "",
631 text_tracks
.insert(std::make_pair(TextTracks::key_type(kCaptionTextTrackNum
),
632 TextTrackConfig(kTextCaptions
, "", "",
635 parser_
.reset(new WebMClusterParser(kTimecodeScale
,
647 const BlockInfo kInputBlockInfo
[] = {
648 {kAudioTrackNum
, 0, 23, true, NULL
, 0},
649 {kAudioTrackNum
, 23, 23, true, NULL
, 0},
650 {kVideoTrackNum
, 33, 34, true, NULL
, 0},
651 {kSubtitleTextTrackNum
, 33, 42, false, NULL
, 0},
652 {kAudioTrackNum
, 46, 23, true, NULL
, 0},
653 {kCaptionTextTrackNum
, 55, 44, false, NULL
, 0},
654 {kVideoTrackNum
, 67, 34, true, NULL
, 0},
655 {kSubtitleTextTrackNum
, 67, 33, false, NULL
, 0},
657 int input_block_count
= arraysize(kInputBlockInfo
);
659 scoped_ptr
<Cluster
> cluster(
660 CreateCluster(0, kInputBlockInfo
, input_block_count
));
662 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
663 EXPECT_EQ(cluster
->size(), result
);
665 const WebMClusterParser::TextBufferQueueMap
& text_map
=
666 parser_
->GetTextBuffers();
667 for (WebMClusterParser::TextBufferQueueMap::const_iterator itr
=
669 itr
!= text_map
.end();
671 const TextTracks::const_iterator find_result
=
672 text_tracks
.find(itr
->first
);
673 ASSERT_TRUE(find_result
!= text_tracks
.end());
674 ASSERT_TRUE(VerifyTextBuffers(parser_
, kInputBlockInfo
, input_block_count
,
675 itr
->first
, itr
->second
));
679 TEST_F(WebMClusterParserTest
, ParseEncryptedBlock
) {
680 scoped_ptr
<Cluster
> cluster(CreateEncryptedCluster(sizeof(kEncryptedFrame
)));
682 parser_
.reset(new WebMClusterParser(kTimecodeScale
,
693 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
694 EXPECT_EQ(cluster
->size(), result
);
695 ASSERT_EQ(1UL, parser_
->GetVideoBuffers().size());
696 scoped_refptr
<StreamParserBuffer
> buffer
= parser_
->GetVideoBuffers()[0];
697 VerifyEncryptedBuffer(buffer
);
700 TEST_F(WebMClusterParserTest
, ParseBadEncryptedBlock
) {
701 scoped_ptr
<Cluster
> cluster(
702 CreateEncryptedCluster(sizeof(kEncryptedFrame
) - 1));
704 parser_
.reset(new WebMClusterParser(kTimecodeScale
,
715 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
716 EXPECT_EQ(-1, result
);
719 TEST_F(WebMClusterParserTest
, ParseInvalidZeroSizedCluster
) {
720 const uint8_t kBuffer
[] = {
721 0x1F, 0x43, 0xB6, 0x75, 0x80, // CLUSTER (size = 0)
724 EXPECT_EQ(-1, parser_
->Parse(kBuffer
, sizeof(kBuffer
)));
727 TEST_F(WebMClusterParserTest
, ParseInvalidUnknownButActuallyZeroSizedCluster
) {
728 const uint8_t kBuffer
[] = {
729 0x1F, 0x43, 0xB6, 0x75, 0xFF, // CLUSTER (size = "unknown")
730 0x1F, 0x43, 0xB6, 0x75, 0x85, // CLUSTER (size = 5)
733 EXPECT_EQ(-1, parser_
->Parse(kBuffer
, sizeof(kBuffer
)));
736 TEST_F(WebMClusterParserTest
, ParseInvalidTextBlockGroupWithoutDuration
) {
737 // Text track frames must have explicitly specified BlockGroup BlockDurations.
738 TextTracks text_tracks
;
740 text_tracks
.insert(std::make_pair(TextTracks::key_type(kTextTrackNum
),
741 TextTrackConfig(kTextSubtitles
, "", "",
744 parser_
.reset(new WebMClusterParser(kTimecodeScale
,
756 const BlockInfo kBlockInfo
[] = {
757 { kTextTrackNum
, 33, -42, false },
759 int block_count
= arraysize(kBlockInfo
);
760 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kBlockInfo
, block_count
));
761 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
762 EXPECT_LT(result
, 0);
765 TEST_F(WebMClusterParserTest
, ParseWithDefaultDurationsSimpleBlocks
) {
767 ResetParserToHaveDefaultDurations();
769 EXPECT_LT(kTestAudioFrameDefaultDurationInMs
, 23);
770 EXPECT_LT(kTestVideoFrameDefaultDurationInMs
, 33);
772 const BlockInfo kBlockInfo
[] = {
773 {kAudioTrackNum
, 0, kTestAudioFrameDefaultDurationInMs
, true, NULL
, 0},
774 {kAudioTrackNum
, 23, kTestAudioFrameDefaultDurationInMs
, true, NULL
, 0},
775 {kVideoTrackNum
, 33, kTestVideoFrameDefaultDurationInMs
, true, NULL
, 0},
776 {kAudioTrackNum
, 46, kTestAudioFrameDefaultDurationInMs
, true, NULL
, 0},
777 {kVideoTrackNum
, 67, kTestVideoFrameDefaultDurationInMs
, true, NULL
, 0},
778 {kAudioTrackNum
, 69, kTestAudioFrameDefaultDurationInMs
, true, NULL
, 0},
779 {kVideoTrackNum
, 100, kTestVideoFrameDefaultDurationInMs
, true, NULL
, 0},
782 int block_count
= arraysize(kBlockInfo
);
783 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kBlockInfo
, block_count
));
785 // Send slightly less than the full cluster so all but the last block is
786 // parsed. Though all the blocks are simple blocks, none should be held aside
787 // for duration estimation prior to end of cluster detection because all the
788 // tracks have DefaultDurations.
789 int result
= parser_
->Parse(cluster
->data(), cluster
->size() - 1);
790 EXPECT_GT(result
, 0);
791 EXPECT_LT(result
, cluster
->size());
792 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
- 1));
796 // Now parse a whole cluster to verify that all the blocks will get parsed.
797 result
= parser_
->Parse(cluster
->data(), cluster
->size());
798 EXPECT_EQ(cluster
->size(), result
);
799 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
));
802 TEST_F(WebMClusterParserTest
, ParseWithoutAnyDurationsSimpleBlocks
) {
805 // Absent DefaultDuration information, SimpleBlock durations are derived from
806 // inter-buffer track timestamp delta if within the cluster, and are estimated
807 // as the lowest non-zero duration seen so far if the last buffer in the track
808 // in the cluster (independently for each track in the cluster).
809 const BlockInfo kBlockInfo1
[] = {
810 {kAudioTrackNum
, 0, 23, true, NULL
, 0},
811 {kAudioTrackNum
, 23, 22, true, NULL
, 0},
812 {kVideoTrackNum
, 33, 33, true, NULL
, 0},
813 {kAudioTrackNum
, 45, 23, true, NULL
, 0},
814 {kVideoTrackNum
, 66, 34, true, NULL
, 0},
815 // Estimated from minimum audio dur
816 {kAudioTrackNum
, 68, 22, true, NULL
, 0},
817 // Estimated from minimum video dur
818 {kVideoTrackNum
, 100, 33, true, NULL
, 0},
821 int block_count1
= arraysize(kBlockInfo1
);
822 scoped_ptr
<Cluster
> cluster1(CreateCluster(0, kBlockInfo1
, block_count1
));
824 // Send slightly less than the first full cluster so all but the last video
825 // block is parsed. Verify the last fully parsed audio and video buffer are
826 // both missing from the result (parser should hold them aside for duration
827 // estimation prior to end of cluster detection in the absence of
828 // DefaultDurations.)
829 int result
= parser_
->Parse(cluster1
->data(), cluster1
->size() - 1);
830 EXPECT_GT(result
, 0);
831 EXPECT_LT(result
, cluster1
->size());
832 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo1
, block_count1
- 3));
833 EXPECT_EQ(3UL, parser_
->GetAudioBuffers().size());
834 EXPECT_EQ(1UL, parser_
->GetVideoBuffers().size());
838 // Now parse the full first cluster and verify all the blocks are parsed.
839 result
= parser_
->Parse(cluster1
->data(), cluster1
->size());
840 EXPECT_EQ(cluster1
->size(), result
);
841 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo1
, block_count1
));
843 // Verify that the estimated frame duration is tracked across clusters for
845 const BlockInfo kBlockInfo2
[] = {
846 // Estimate carries over across clusters
847 {kAudioTrackNum
, 200, 22, true, NULL
, 0},
848 // Estimate carries over across clusters
849 {kVideoTrackNum
, 201, 33, true, NULL
, 0},
852 int block_count2
= arraysize(kBlockInfo2
);
853 scoped_ptr
<Cluster
> cluster2(CreateCluster(0, kBlockInfo2
, block_count2
));
854 result
= parser_
->Parse(cluster2
->data(), cluster2
->size());
855 EXPECT_EQ(cluster2
->size(), result
);
856 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo2
, block_count2
));
859 TEST_F(WebMClusterParserTest
, ParseWithoutAnyDurationsBlockGroups
) {
862 // Absent DefaultDuration and BlockDuration information, BlockGroup block
863 // durations are derived from inter-buffer track timestamp delta if within the
864 // cluster, and are estimated as the lowest non-zero duration seen so far if
865 // the last buffer in the track in the cluster (independently for each track
867 const BlockInfo kBlockInfo1
[] = {
868 {kAudioTrackNum
, 0, -23, false, NULL
, 0},
869 {kAudioTrackNum
, 23, -22, false, NULL
, 0},
870 {kVideoTrackNum
, 33, -33, false, NULL
, 0},
871 {kAudioTrackNum
, 45, -23, false, NULL
, 0},
872 {kVideoTrackNum
, 66, -34, false, NULL
, 0},
873 // Estimated from minimum audio dur
874 {kAudioTrackNum
, 68, -22, false, NULL
, 0},
875 // Estimated from minimum video dur
876 {kVideoTrackNum
, 100, -33, false, NULL
, 0},
879 int block_count1
= arraysize(kBlockInfo1
);
880 scoped_ptr
<Cluster
> cluster1(CreateCluster(0, kBlockInfo1
, block_count1
));
882 // Send slightly less than the first full cluster so all but the last video
883 // block is parsed. Verify the last fully parsed audio and video buffer are
884 // both missing from the result (parser should hold them aside for duration
885 // estimation prior to end of cluster detection in the absence of
886 // DefaultDurations.)
887 int result
= parser_
->Parse(cluster1
->data(), cluster1
->size() - 1);
888 EXPECT_GT(result
, 0);
889 EXPECT_LT(result
, cluster1
->size());
890 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo1
, block_count1
- 3));
891 EXPECT_EQ(3UL, parser_
->GetAudioBuffers().size());
892 EXPECT_EQ(1UL, parser_
->GetVideoBuffers().size());
896 // Now parse the full first cluster and verify all the blocks are parsed.
897 result
= parser_
->Parse(cluster1
->data(), cluster1
->size());
898 EXPECT_EQ(cluster1
->size(), result
);
899 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo1
, block_count1
));
901 // Verify that the estimated frame duration is tracked across clusters for
903 const BlockInfo kBlockInfo2
[] = {
904 {kAudioTrackNum
, 200, -22, false, NULL
, 0},
905 {kVideoTrackNum
, 201, -33, false, NULL
, 0},
908 int block_count2
= arraysize(kBlockInfo2
);
909 scoped_ptr
<Cluster
> cluster2(CreateCluster(0, kBlockInfo2
, block_count2
));
910 result
= parser_
->Parse(cluster2
->data(), cluster2
->size());
911 EXPECT_EQ(cluster2
->size(), result
);
912 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo2
, block_count2
));
915 // TODO(wolenetz): Is parser behavior correct? See http://crbug.com/363433.
916 TEST_F(WebMClusterParserTest
,
917 ParseWithDefaultDurationsBlockGroupsWithoutDurations
) {
919 ResetParserToHaveDefaultDurations();
921 EXPECT_LT(kTestAudioFrameDefaultDurationInMs
, 23);
922 EXPECT_LT(kTestVideoFrameDefaultDurationInMs
, 33);
924 const BlockInfo kBlockInfo
[] = {
925 {kAudioTrackNum
, 0, -kTestAudioFrameDefaultDurationInMs
, false, NULL
, 0},
926 {kAudioTrackNum
, 23, -kTestAudioFrameDefaultDurationInMs
, false, NULL
, 0},
927 {kVideoTrackNum
, 33, -kTestVideoFrameDefaultDurationInMs
, false, NULL
, 0},
928 {kAudioTrackNum
, 46, -kTestAudioFrameDefaultDurationInMs
, false, NULL
, 0},
929 {kVideoTrackNum
, 67, -kTestVideoFrameDefaultDurationInMs
, false, NULL
, 0},
930 {kAudioTrackNum
, 69, -kTestAudioFrameDefaultDurationInMs
, false, NULL
, 0},
933 -kTestVideoFrameDefaultDurationInMs
,
939 int block_count
= arraysize(kBlockInfo
);
940 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kBlockInfo
, block_count
));
942 // Send slightly less than the full cluster so all but the last block is
943 // parsed. None should be held aside for duration estimation prior to end of
944 // cluster detection because all the tracks have DefaultDurations.
945 int result
= parser_
->Parse(cluster
->data(), cluster
->size() - 1);
946 EXPECT_GT(result
, 0);
947 EXPECT_LT(result
, cluster
->size());
948 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
- 1));
952 // Now parse a whole cluster to verify that all the blocks will get parsed.
953 result
= parser_
->Parse(cluster
->data(), cluster
->size());
954 EXPECT_EQ(cluster
->size(), result
);
955 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
));
958 TEST_F(WebMClusterParserTest
,
959 ParseDegenerateClusterYieldsHardcodedEstimatedDurations
) {
960 const BlockInfo kBlockInfo
[] = {
964 WebMClusterParser::kDefaultAudioBufferDurationInMs
,
969 WebMClusterParser::kDefaultVideoBufferDurationInMs
,
974 int block_count
= arraysize(kBlockInfo
);
975 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kBlockInfo
, block_count
));
976 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
977 EXPECT_EQ(cluster
->size(), result
);
978 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
));
981 TEST_F(WebMClusterParserTest
,
982 ParseDegenerateClusterWithDefaultDurationsYieldsDefaultDurations
) {
983 ResetParserToHaveDefaultDurations();
985 const BlockInfo kBlockInfo
[] = {
986 { kAudioTrackNum
, 0, kTestAudioFrameDefaultDurationInMs
, true },
987 { kVideoTrackNum
, 0, kTestVideoFrameDefaultDurationInMs
, true },
990 int block_count
= arraysize(kBlockInfo
);
991 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kBlockInfo
, block_count
));
992 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
993 EXPECT_EQ(cluster
->size(), result
);
994 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
));
997 TEST_F(WebMClusterParserTest
, ReadOpusDurationsSimpleBlockAtEndOfCluster
) {
998 // Reset parser to expect Opus codec audio.
999 parser_
.reset(new WebMClusterParser(
1000 kTimecodeScale
, kAudioTrackNum
, kNoTimestamp(), kVideoTrackNum
,
1001 kNoTimestamp(), TextTracks(), std::set
<int64
>(), std::string(),
1002 std::string(), kCodecOpus
, LogCB()));
1005 for (const auto* packet_ptr
: BuildAllOpusPackets()) {
1006 const BlockInfo kBlockInfo
[] = {{kAudioTrackNum
,
1008 packet_ptr
->duration_ms(),
1009 true, // Make it a SimpleBlock.
1011 packet_ptr
->size()}};
1013 int block_count
= arraysize(kBlockInfo
);
1014 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kBlockInfo
, block_count
));
1015 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
1016 EXPECT_EQ(cluster
->size(), result
);
1017 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
));
1021 // Test should minimally cover all the combinations of config and frame count.
1022 ASSERT_GE(loop_count
, kNumPossibleOpusConfigs
* kMaxOpusPacketFrameCount
);
1025 TEST_F(WebMClusterParserTest
, PreferOpusDurationsOverBlockDurations
) {
1026 // Reset parser to expect Opus codec audio.
1027 parser_
.reset(new WebMClusterParser(
1028 kTimecodeScale
, kAudioTrackNum
, kNoTimestamp(), kVideoTrackNum
,
1029 kNoTimestamp(), TextTracks(), std::set
<int64
>(), std::string(),
1030 std::string(), kCodecOpus
, LogCB()));
1033 for (const auto* packet_ptr
: BuildAllOpusPackets()) {
1034 // Setting BlockDuration != Opus duration to see which one the parser uses.
1035 int block_duration_ms
= packet_ptr
->duration_ms() + 10;
1037 BlockInfo block_infos
[] = {{kAudioTrackNum
,
1040 false, // Not a SimpleBlock.
1042 packet_ptr
->size()}};
1044 int block_count
= arraysize(block_infos
);
1045 scoped_ptr
<Cluster
> cluster(CreateCluster(0, block_infos
, block_count
));
1046 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
1047 EXPECT_EQ(cluster
->size(), result
);
1049 // BlockInfo duration will be used to verify buffer duration, so changing
1050 // duration to be that of the Opus packet to verify it was preferred.
1051 block_infos
[0].duration
= packet_ptr
->duration_ms();
1053 ASSERT_TRUE(VerifyBuffers(parser_
, block_infos
, block_count
));
1057 // Test should minimally cover all the combinations of config and frame count.
1058 ASSERT_GE(loop_count
, kNumPossibleOpusConfigs
* kMaxOpusPacketFrameCount
);
1061 // Tests that BlockDuration is used to set duration on buffer rather than
1062 // encoded duration in Opus packet (or hard coded duration estimates). Encoded
1063 // Opus duration is usually preferred but cannot be known when encrypted.
1064 TEST_F(WebMClusterParserTest
, DontReadEncodedDurationWhenEncrypted
) {
1065 // Non-empty dummy value signals encryption is active for audio.
1066 std::string
audio_encryption_id("audio_key_id");
1068 // Reset parser to expect Opus codec audio and use audio encryption key id.
1069 parser_
.reset(new WebMClusterParser(
1070 kTimecodeScale
, kAudioTrackNum
, kNoTimestamp(), kVideoTrackNum
,
1071 kNoTimestamp(), TextTracks(), std::set
<int64
>(), audio_encryption_id
,
1072 std::string(), kCodecOpus
, LogCB()));
1074 // Single Block with BlockDuration and encrypted data.
1075 const BlockInfo kBlockInfo
[] = {{kAudioTrackNum
,
1077 kTestAudioFrameDefaultDurationInMs
,
1078 false, // Not a SimpleBlock
1079 kEncryptedFrame
, // Encrypted frame data
1080 arraysize(kEncryptedFrame
)}};
1082 int block_count
= arraysize(kBlockInfo
);
1083 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kBlockInfo
, block_count
));
1084 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
1085 EXPECT_EQ(cluster
->size(), result
);
1087 // Will verify that duration of buffer matches that of BlockDuration.
1088 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
));
1091 } // namespace media