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. Duration for the
807 // last block in a cluster is estimated independently for each track in the
808 // cluster. For video tracks we use the maximum seen so far. For audio we use
810 // TODO(chcunningham): Move audio over to use the maximum.
811 const BlockInfo kBlockInfo1
[] = {
812 {kAudioTrackNum
, 0, 23, true, NULL
, 0},
813 {kAudioTrackNum
, 23, 22, true, NULL
, 0},
814 {kVideoTrackNum
, 33, 33, true, NULL
, 0},
815 {kAudioTrackNum
, 45, 23, true, NULL
, 0},
816 {kVideoTrackNum
, 66, 34, true, NULL
, 0},
817 // Estimated from minimum audio dur
818 {kAudioTrackNum
, 68, 22, true, NULL
, 0},
819 // Estimated from maximum video dur
820 {kVideoTrackNum
, 100, 34, true, NULL
, 0},
823 int block_count1
= arraysize(kBlockInfo1
);
824 scoped_ptr
<Cluster
> cluster1(CreateCluster(0, kBlockInfo1
, block_count1
));
826 // Send slightly less than the first full cluster so all but the last video
827 // block is parsed. Verify the last fully parsed audio and video buffer are
828 // both missing from the result (parser should hold them aside for duration
829 // estimation prior to end of cluster detection in the absence of
830 // DefaultDurations.)
831 int result
= parser_
->Parse(cluster1
->data(), cluster1
->size() - 1);
832 EXPECT_GT(result
, 0);
833 EXPECT_LT(result
, cluster1
->size());
834 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo1
, block_count1
- 3));
835 EXPECT_EQ(3UL, parser_
->GetAudioBuffers().size());
836 EXPECT_EQ(1UL, parser_
->GetVideoBuffers().size());
840 // Now parse the full first cluster and verify all the blocks are parsed.
841 result
= parser_
->Parse(cluster1
->data(), cluster1
->size());
842 EXPECT_EQ(cluster1
->size(), result
);
843 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo1
, block_count1
));
845 // Verify that the estimated frame duration is tracked across clusters for
847 const BlockInfo kBlockInfo2
[] = {
848 // Estimate carries over across clusters
849 {kAudioTrackNum
, 200, 22, true, NULL
, 0},
850 // Estimate carries over across clusters
851 {kVideoTrackNum
, 201, 34, true, NULL
, 0},
854 int block_count2
= arraysize(kBlockInfo2
);
855 scoped_ptr
<Cluster
> cluster2(CreateCluster(0, kBlockInfo2
, block_count2
));
856 result
= parser_
->Parse(cluster2
->data(), cluster2
->size());
857 EXPECT_EQ(cluster2
->size(), result
);
858 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo2
, block_count2
));
861 TEST_F(WebMClusterParserTest
, ParseWithoutAnyDurationsBlockGroups
) {
864 // Absent DefaultDuration and BlockDuration information, BlockGroup block
865 // durations are derived from inter-buffer track timestamp delta if within the
866 // cluster. Duration for the last block in a cluster is estimated
867 // independently for each track in the cluster. For video tracks we use the
868 // maximum seen so far. For audio we use the the minimum.
869 // TODO(chcunningham): Move audio over to use the maximum.
870 const BlockInfo kBlockInfo1
[] = {
871 {kAudioTrackNum
, 0, -23, false, NULL
, 0},
872 {kAudioTrackNum
, 23, -22, false, NULL
, 0},
873 {kVideoTrackNum
, 33, -33, false, NULL
, 0},
874 {kAudioTrackNum
, 45, -23, false, NULL
, 0},
875 {kVideoTrackNum
, 66, -34, false, NULL
, 0},
876 // Estimated from minimum audio dur
877 {kAudioTrackNum
, 68, -22, false, NULL
, 0},
878 // Estimated from maximum video dur
879 {kVideoTrackNum
, 100, -34, false, NULL
, 0},
882 int block_count1
= arraysize(kBlockInfo1
);
883 scoped_ptr
<Cluster
> cluster1(CreateCluster(0, kBlockInfo1
, block_count1
));
885 // Send slightly less than the first full cluster so all but the last video
886 // block is parsed. Verify the last fully parsed audio and video buffer are
887 // both missing from the result (parser should hold them aside for duration
888 // estimation prior to end of cluster detection in the absence of
889 // DefaultDurations.)
890 int result
= parser_
->Parse(cluster1
->data(), cluster1
->size() - 1);
891 EXPECT_GT(result
, 0);
892 EXPECT_LT(result
, cluster1
->size());
893 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo1
, block_count1
- 3));
894 EXPECT_EQ(3UL, parser_
->GetAudioBuffers().size());
895 EXPECT_EQ(1UL, parser_
->GetVideoBuffers().size());
899 // Now parse the full first cluster and verify all the blocks are parsed.
900 result
= parser_
->Parse(cluster1
->data(), cluster1
->size());
901 EXPECT_EQ(cluster1
->size(), result
);
902 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo1
, block_count1
));
904 // Verify that the estimated frame duration is tracked across clusters for
906 const BlockInfo kBlockInfo2
[] = {
907 {kAudioTrackNum
, 200, -22, false, NULL
, 0},
908 {kVideoTrackNum
, 201, -34, false, NULL
, 0},
911 int block_count2
= arraysize(kBlockInfo2
);
912 scoped_ptr
<Cluster
> cluster2(CreateCluster(0, kBlockInfo2
, block_count2
));
913 result
= parser_
->Parse(cluster2
->data(), cluster2
->size());
914 EXPECT_EQ(cluster2
->size(), result
);
915 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo2
, block_count2
));
918 // TODO(wolenetz): Is parser behavior correct? See http://crbug.com/363433.
919 TEST_F(WebMClusterParserTest
,
920 ParseWithDefaultDurationsBlockGroupsWithoutDurations
) {
922 ResetParserToHaveDefaultDurations();
924 EXPECT_LT(kTestAudioFrameDefaultDurationInMs
, 23);
925 EXPECT_LT(kTestVideoFrameDefaultDurationInMs
, 33);
927 const BlockInfo kBlockInfo
[] = {
928 {kAudioTrackNum
, 0, -kTestAudioFrameDefaultDurationInMs
, false, NULL
, 0},
929 {kAudioTrackNum
, 23, -kTestAudioFrameDefaultDurationInMs
, false, NULL
, 0},
930 {kVideoTrackNum
, 33, -kTestVideoFrameDefaultDurationInMs
, false, NULL
, 0},
931 {kAudioTrackNum
, 46, -kTestAudioFrameDefaultDurationInMs
, false, NULL
, 0},
932 {kVideoTrackNum
, 67, -kTestVideoFrameDefaultDurationInMs
, false, NULL
, 0},
933 {kAudioTrackNum
, 69, -kTestAudioFrameDefaultDurationInMs
, false, NULL
, 0},
936 -kTestVideoFrameDefaultDurationInMs
,
942 int block_count
= arraysize(kBlockInfo
);
943 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kBlockInfo
, block_count
));
945 // Send slightly less than the full cluster so all but the last block is
946 // parsed. None should be held aside for duration estimation prior to end of
947 // cluster detection because all the tracks have DefaultDurations.
948 int result
= parser_
->Parse(cluster
->data(), cluster
->size() - 1);
949 EXPECT_GT(result
, 0);
950 EXPECT_LT(result
, cluster
->size());
951 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
- 1));
955 // Now parse a whole cluster to verify that all the blocks will get parsed.
956 result
= parser_
->Parse(cluster
->data(), cluster
->size());
957 EXPECT_EQ(cluster
->size(), result
);
958 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
));
961 TEST_F(WebMClusterParserTest
,
962 ParseDegenerateClusterYieldsHardcodedEstimatedDurations
) {
963 const BlockInfo kBlockInfo
[] = {
967 WebMClusterParser::kDefaultAudioBufferDurationInMs
,
972 WebMClusterParser::kDefaultVideoBufferDurationInMs
,
977 int block_count
= arraysize(kBlockInfo
);
978 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kBlockInfo
, block_count
));
979 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
980 EXPECT_EQ(cluster
->size(), result
);
981 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
));
984 TEST_F(WebMClusterParserTest
,
985 ParseDegenerateClusterWithDefaultDurationsYieldsDefaultDurations
) {
986 ResetParserToHaveDefaultDurations();
988 const BlockInfo kBlockInfo
[] = {
989 { kAudioTrackNum
, 0, kTestAudioFrameDefaultDurationInMs
, true },
990 { kVideoTrackNum
, 0, kTestVideoFrameDefaultDurationInMs
, true },
993 int block_count
= arraysize(kBlockInfo
);
994 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kBlockInfo
, block_count
));
995 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
996 EXPECT_EQ(cluster
->size(), result
);
997 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
));
1000 TEST_F(WebMClusterParserTest
, ReadOpusDurationsSimpleBlockAtEndOfCluster
) {
1001 // Reset parser to expect Opus codec audio.
1002 parser_
.reset(new WebMClusterParser(
1003 kTimecodeScale
, kAudioTrackNum
, kNoTimestamp(), kVideoTrackNum
,
1004 kNoTimestamp(), TextTracks(), std::set
<int64
>(), std::string(),
1005 std::string(), kCodecOpus
, LogCB()));
1008 for (const auto* packet_ptr
: BuildAllOpusPackets()) {
1009 const BlockInfo kBlockInfo
[] = {{kAudioTrackNum
,
1011 packet_ptr
->duration_ms(),
1012 true, // Make it a SimpleBlock.
1014 packet_ptr
->size()}};
1016 int block_count
= arraysize(kBlockInfo
);
1017 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kBlockInfo
, block_count
));
1018 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
1019 EXPECT_EQ(cluster
->size(), result
);
1020 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
));
1024 // Test should minimally cover all the combinations of config and frame count.
1025 ASSERT_GE(loop_count
, kNumPossibleOpusConfigs
* kMaxOpusPacketFrameCount
);
1028 TEST_F(WebMClusterParserTest
, PreferOpusDurationsOverBlockDurations
) {
1029 // Reset parser to expect Opus codec audio.
1030 parser_
.reset(new WebMClusterParser(
1031 kTimecodeScale
, kAudioTrackNum
, kNoTimestamp(), kVideoTrackNum
,
1032 kNoTimestamp(), TextTracks(), std::set
<int64
>(), std::string(),
1033 std::string(), kCodecOpus
, LogCB()));
1036 for (const auto* packet_ptr
: BuildAllOpusPackets()) {
1037 // Setting BlockDuration != Opus duration to see which one the parser uses.
1038 int block_duration_ms
= packet_ptr
->duration_ms() + 10;
1040 BlockInfo block_infos
[] = {{kAudioTrackNum
,
1043 false, // Not a SimpleBlock.
1045 packet_ptr
->size()}};
1047 int block_count
= arraysize(block_infos
);
1048 scoped_ptr
<Cluster
> cluster(CreateCluster(0, block_infos
, block_count
));
1049 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
1050 EXPECT_EQ(cluster
->size(), result
);
1052 // BlockInfo duration will be used to verify buffer duration, so changing
1053 // duration to be that of the Opus packet to verify it was preferred.
1054 block_infos
[0].duration
= packet_ptr
->duration_ms();
1056 ASSERT_TRUE(VerifyBuffers(parser_
, block_infos
, block_count
));
1060 // Test should minimally cover all the combinations of config and frame count.
1061 ASSERT_GE(loop_count
, kNumPossibleOpusConfigs
* kMaxOpusPacketFrameCount
);
1064 // Tests that BlockDuration is used to set duration on buffer rather than
1065 // encoded duration in Opus packet (or hard coded duration estimates). Encoded
1066 // Opus duration is usually preferred but cannot be known when encrypted.
1067 TEST_F(WebMClusterParserTest
, DontReadEncodedDurationWhenEncrypted
) {
1068 // Non-empty dummy value signals encryption is active for audio.
1069 std::string
audio_encryption_id("audio_key_id");
1071 // Reset parser to expect Opus codec audio and use audio encryption key id.
1072 parser_
.reset(new WebMClusterParser(
1073 kTimecodeScale
, kAudioTrackNum
, kNoTimestamp(), kVideoTrackNum
,
1074 kNoTimestamp(), TextTracks(), std::set
<int64
>(), audio_encryption_id
,
1075 std::string(), kCodecOpus
, LogCB()));
1077 // Single Block with BlockDuration and encrypted data.
1078 const BlockInfo kBlockInfo
[] = {{kAudioTrackNum
,
1080 kTestAudioFrameDefaultDurationInMs
,
1081 false, // Not a SimpleBlock
1082 kEncryptedFrame
, // Encrypted frame data
1083 arraysize(kEncryptedFrame
)}};
1085 int block_count
= arraysize(kBlockInfo
);
1086 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kBlockInfo
, block_count
));
1087 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
1088 EXPECT_EQ(cluster
->size(), result
);
1090 // Will verify that duration of buffer matches that of BlockDuration.
1091 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
));
1094 } // namespace media