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
;
31 kTimecodeScale
= 1000000, // Timecode scale for millisecond timestamps.
35 kTestAudioFrameDefaultDurationInMs
= 13,
36 kTestVideoFrameDefaultDurationInMs
= 17
39 // Test duration defaults must differ from parser estimation defaults to know
40 // which durations parser used when emitting buffers.
42 static_cast<int>(kTestAudioFrameDefaultDurationInMs
) !=
43 static_cast<int>(WebMClusterParser::kDefaultAudioBufferDurationInMs
),
44 "test default is the same as estimation fallback audio duration");
46 static_cast<int>(kTestVideoFrameDefaultDurationInMs
) !=
47 static_cast<int>(WebMClusterParser::kDefaultVideoBufferDurationInMs
),
48 "test default is the same as estimation fallback video duration");
54 // Negative value is allowed only for block groups (not simple blocks) and
55 // directs CreateCluster() to exclude BlockDuration entry from the cluster for
56 // this BlockGroup. The absolute value is used for parser verification.
57 // For simple blocks, this value must be non-negative, and is used only for
58 // parser verification.
61 bool use_simple_block
;
63 // Default data will be used if no data given.
68 const BlockInfo kDefaultBlockInfo
[] = {
69 {kAudioTrackNum
, 0, 23, true, NULL
, 0},
70 {kAudioTrackNum
, 23, 23, true, NULL
, 0},
71 // Assumes not using DefaultDuration
72 {kVideoTrackNum
, 33, 34, true, NULL
, 0},
73 {kAudioTrackNum
, 46, 23, true, NULL
, 0},
74 {kVideoTrackNum
, 67, 33, false, NULL
, 0},
75 {kAudioTrackNum
, 69, 23, false, NULL
, 0},
76 {kVideoTrackNum
, 100, 33, false, NULL
, 0},
79 const uint8_t kEncryptedFrame
[] = {
84 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
86 // Helper that hard-codes some non-varying constructor parameters.
87 WebMClusterParser
* CreateParserHelper(
88 base::TimeDelta audio_default_duration
,
89 base::TimeDelta video_default_duration
,
90 const WebMTracksParser::TextTracks
& text_tracks
,
91 const std::set
<int64
>& ignored_tracks
,
92 const std::string
& audio_encryption_key_id
,
93 const std::string
& video_encryption_key_id
,
94 const AudioCodec audio_codec
) {
95 return new WebMClusterParser(
96 kTimecodeScale
, kAudioTrackNum
, audio_default_duration
, kVideoTrackNum
,
97 video_default_duration
, text_tracks
, ignored_tracks
,
98 audio_encryption_key_id
, video_encryption_key_id
, audio_codec
,
102 // Create a default version of the parser for test.
103 WebMClusterParser
* CreateDefaultParser() {
104 return CreateParserHelper(kNoTimestamp(), kNoTimestamp(), TextTracks(),
105 std::set
<int64
>(), std::string(), std::string(),
109 // Create a parser for test with custom audio and video default durations, and
110 // optionally custom text tracks.
111 WebMClusterParser
* CreateParserWithDefaultDurationsAndOptionalTextTracks(
112 base::TimeDelta audio_default_duration
,
113 base::TimeDelta video_default_duration
,
114 const WebMTracksParser::TextTracks
& text_tracks
= TextTracks()) {
115 return CreateParserHelper(audio_default_duration
, video_default_duration
,
116 text_tracks
, std::set
<int64
>(), std::string(),
117 std::string(), kUnknownAudioCodec
);
120 // Create a parser for test with custom ignored tracks.
121 WebMClusterParser
* CreateParserWithIgnoredTracks(
122 std::set
<int64
>& ignored_tracks
) {
123 return CreateParserHelper(kNoTimestamp(), kNoTimestamp(), TextTracks(),
124 ignored_tracks
, std::string(), std::string(),
128 // Create a parser for test with custom encryption key ids and audio codec.
129 WebMClusterParser
* CreateParserWithKeyIdsAndAudioCodec(
130 const std::string
& audio_encryption_key_id
,
131 const std::string
& video_encryption_key_id
,
132 const AudioCodec audio_codec
) {
133 return CreateParserHelper(kNoTimestamp(), kNoTimestamp(), TextTracks(),
134 std::set
<int64
>(), audio_encryption_key_id
,
135 video_encryption_key_id
, audio_codec
);
138 scoped_ptr
<Cluster
> CreateCluster(int timecode
,
139 const BlockInfo
* block_info
,
142 cb
.SetClusterTimecode(0);
144 uint8_t kDefaultBlockData
[] = { 0x00 };
146 for (int i
= 0; i
< block_count
; i
++) {
149 if (block_info
[i
].data
!= NULL
) {
150 data
= block_info
[i
].data
;
151 data_length
= block_info
[i
].data_length
;
153 data
= kDefaultBlockData
;
154 data_length
= sizeof(kDefaultBlockData
);
157 if (block_info
[i
].use_simple_block
) {
158 CHECK_GE(block_info
[i
].duration
, 0);
159 cb
.AddSimpleBlock(block_info
[i
].track_num
, block_info
[i
].timestamp
, 0,
164 if (block_info
[i
].duration
< 0) {
165 cb
.AddBlockGroupWithoutBlockDuration(block_info
[i
].track_num
,
166 block_info
[i
].timestamp
, 0, data
,
171 cb
.AddBlockGroup(block_info
[i
].track_num
, block_info
[i
].timestamp
,
172 block_info
[i
].duration
, 0, data
, data_length
);
178 // Creates a Cluster with one encrypted Block. |bytes_to_write| is number of
179 // bytes of the encrypted frame to write.
180 scoped_ptr
<Cluster
> CreateEncryptedCluster(int bytes_to_write
) {
181 CHECK_GT(bytes_to_write
, 0);
182 CHECK_LE(bytes_to_write
, static_cast<int>(sizeof(kEncryptedFrame
)));
185 cb
.SetClusterTimecode(0);
186 cb
.AddSimpleBlock(kVideoTrackNum
, 0, 0, kEncryptedFrame
, bytes_to_write
);
190 bool VerifyBuffers(const WebMClusterParser::BufferQueue
& audio_buffers
,
191 const WebMClusterParser::BufferQueue
& video_buffers
,
192 const WebMClusterParser::BufferQueue
& text_buffers
,
193 const BlockInfo
* block_info
,
195 int buffer_count
= audio_buffers
.size() + video_buffers
.size() +
197 if (block_count
!= buffer_count
) {
198 DVLOG(1) << __FUNCTION__
<< " : block_count (" << block_count
199 << ") mismatches buffer_count (" << buffer_count
<< ")";
203 size_t audio_offset
= 0;
204 size_t video_offset
= 0;
205 size_t text_offset
= 0;
206 for (int i
= 0; i
< block_count
; i
++) {
207 const WebMClusterParser::BufferQueue
* buffers
= NULL
;
209 StreamParserBuffer::Type expected_type
= DemuxerStream::UNKNOWN
;
211 if (block_info
[i
].track_num
== kAudioTrackNum
) {
212 buffers
= &audio_buffers
;
213 offset
= &audio_offset
;
214 expected_type
= DemuxerStream::AUDIO
;
215 } else if (block_info
[i
].track_num
== kVideoTrackNum
) {
216 buffers
= &video_buffers
;
217 offset
= &video_offset
;
218 expected_type
= DemuxerStream::VIDEO
;
219 } else if (block_info
[i
].track_num
== kTextTrackNum
) {
220 buffers
= &text_buffers
;
221 offset
= &text_offset
;
222 expected_type
= DemuxerStream::TEXT
;
224 LOG(ERROR
) << "Unexpected track number " << block_info
[i
].track_num
;
228 if (*offset
>= buffers
->size()) {
229 DVLOG(1) << __FUNCTION__
<< " : Too few buffers (" << buffers
->size()
230 << ") for track_num (" << block_info
[i
].track_num
231 << "), expected at least " << *offset
+ 1 << " buffers";
235 scoped_refptr
<StreamParserBuffer
> buffer
= (*buffers
)[(*offset
)++];
237 EXPECT_EQ(block_info
[i
].timestamp
, buffer
->timestamp().InMilliseconds());
238 EXPECT_EQ(std::abs(block_info
[i
].duration
),
239 buffer
->duration().InMillisecondsF());
240 EXPECT_EQ(expected_type
, buffer
->type());
241 EXPECT_EQ(block_info
[i
].track_num
, buffer
->track_id());
247 bool VerifyBuffers(const scoped_ptr
<WebMClusterParser
>& parser
,
248 const BlockInfo
* block_info
,
250 const WebMClusterParser::TextBufferQueueMap
& text_map
=
251 parser
->GetTextBuffers();
252 const WebMClusterParser::BufferQueue
* text_buffers
;
253 const WebMClusterParser::BufferQueue no_text_buffers
;
254 if (!text_map
.empty())
255 text_buffers
= &(text_map
.rbegin()->second
);
257 text_buffers
= &no_text_buffers
;
259 return VerifyBuffers(parser
->GetAudioBuffers(),
260 parser
->GetVideoBuffers(),
266 bool VerifyTextBuffers(const scoped_ptr
<WebMClusterParser
>& parser
,
267 const BlockInfo
* block_info_ptr
,
270 const WebMClusterParser::BufferQueue
& text_buffers
) {
271 const BlockInfo
* const block_info_end
= block_info_ptr
+ block_count
;
273 typedef WebMClusterParser::BufferQueue::const_iterator TextBufferIter
;
274 TextBufferIter buffer_iter
= text_buffers
.begin();
275 const TextBufferIter buffer_end
= text_buffers
.end();
277 while (block_info_ptr
!= block_info_end
) {
278 const BlockInfo
& block_info
= *block_info_ptr
++;
280 if (block_info
.track_num
!= text_track_num
)
283 EXPECT_FALSE(block_info
.use_simple_block
);
284 EXPECT_FALSE(buffer_iter
== buffer_end
);
286 const scoped_refptr
<StreamParserBuffer
> buffer
= *buffer_iter
++;
287 EXPECT_EQ(block_info
.timestamp
, buffer
->timestamp().InMilliseconds());
288 EXPECT_EQ(std::abs(block_info
.duration
),
289 buffer
->duration().InMillisecondsF());
290 EXPECT_EQ(DemuxerStream::TEXT
, buffer
->type());
291 EXPECT_EQ(text_track_num
, buffer
->track_id());
294 EXPECT_TRUE(buffer_iter
== buffer_end
);
298 void VerifyEncryptedBuffer(scoped_refptr
<StreamParserBuffer
> buffer
) {
299 EXPECT_TRUE(buffer
->decrypt_config());
300 EXPECT_EQ(static_cast<unsigned long>(DecryptConfig::kDecryptionKeySize
),
301 buffer
->decrypt_config()->iv().length());
304 void AppendToEnd(const WebMClusterParser::BufferQueue
& src
,
305 WebMClusterParser::BufferQueue
* dest
) {
306 for (WebMClusterParser::BufferQueue::const_iterator itr
= src
.begin();
307 itr
!= src
.end(); ++itr
) {
308 dest
->push_back(*itr
);
314 class WebMClusterParserTest
: public testing::Test
{
316 WebMClusterParserTest() : parser_(CreateDefaultParser()) {}
319 void ResetParserToHaveDefaultDurations() {
320 base::TimeDelta default_audio_duration
= base::TimeDelta::FromMilliseconds(
321 kTestAudioFrameDefaultDurationInMs
);
322 base::TimeDelta default_video_duration
= base::TimeDelta::FromMilliseconds(
323 kTestVideoFrameDefaultDurationInMs
);
324 ASSERT_GE(default_audio_duration
, base::TimeDelta());
325 ASSERT_GE(default_video_duration
, base::TimeDelta());
326 ASSERT_NE(kNoTimestamp(), default_audio_duration
);
327 ASSERT_NE(kNoTimestamp(), default_video_duration
);
329 parser_
.reset(CreateParserWithDefaultDurationsAndOptionalTextTracks(
330 default_audio_duration
, default_video_duration
));
333 scoped_ptr
<WebMClusterParser
> parser_
;
336 DISALLOW_COPY_AND_ASSIGN(WebMClusterParserTest
);
339 TEST_F(WebMClusterParserTest
, HeldBackBufferHoldsBackAllTracks
) {
340 // If a buffer is missing duration and is being held back, then all other
341 // tracks' buffers that have same or higher (decode) timestamp should be held
342 // back too to keep the timestamps emitted for a cluster monotonically
343 // non-decreasing and in same order as parsed.
346 // Reset the parser to have 3 tracks: text, video (no default frame duration),
347 // and audio (with a default frame duration).
348 TextTracks text_tracks
;
349 text_tracks
.insert(std::make_pair(TextTracks::key_type(kTextTrackNum
),
350 TextTrackConfig(kTextSubtitles
, "", "",
352 base::TimeDelta default_audio_duration
=
353 base::TimeDelta::FromMilliseconds(kTestAudioFrameDefaultDurationInMs
);
354 ASSERT_GE(default_audio_duration
, base::TimeDelta());
355 ASSERT_NE(kNoTimestamp(), default_audio_duration
);
356 parser_
.reset(CreateParserWithDefaultDurationsAndOptionalTextTracks(
357 default_audio_duration
, kNoTimestamp(), text_tracks
));
359 const BlockInfo kBlockInfo
[] = {
360 {kVideoTrackNum
, 0, 33, true, NULL
, 0},
361 {kAudioTrackNum
, 0, 23, false, NULL
, 0},
362 {kTextTrackNum
, 10, 42, false, NULL
, 0},
363 {kAudioTrackNum
, 23, kTestAudioFrameDefaultDurationInMs
, true, NULL
, 0},
364 {kVideoTrackNum
, 33, 33, true, NULL
, 0},
365 {kAudioTrackNum
, 36, kTestAudioFrameDefaultDurationInMs
, true, NULL
, 0},
366 {kVideoTrackNum
, 66, 33, true, NULL
, 0},
367 {kAudioTrackNum
, 70, kTestAudioFrameDefaultDurationInMs
, true, NULL
, 0},
368 {kAudioTrackNum
, 83, kTestAudioFrameDefaultDurationInMs
, true, NULL
, 0},
371 const int kExpectedBuffersOnPartialCluster
[] = {
372 0, // Video simple block without DefaultDuration should be held back
373 0, // Audio buffer ready, but not emitted because its TS >= held back video
374 0, // Text buffer ready, but not emitted because its TS >= held back video
375 0, // 2nd audio buffer ready, also not emitted for same reason as first
376 4, // All previous buffers emitted, 2nd video held back with no duration
377 4, // 2nd video still has no duration, 3rd audio ready but not emitted
378 6, // All previous buffers emitted, 3rd video held back with no duration
379 6, // 3rd video still has no duration, 4th audio ready but not emitted
380 9, // Cluster end emits all buffers and 3rd video's duration is estimated
383 ASSERT_EQ(arraysize(kBlockInfo
), arraysize(kExpectedBuffersOnPartialCluster
));
384 int block_count
= arraysize(kBlockInfo
);
386 // Iteratively create a cluster containing the first N+1 blocks and parse all
387 // but the last byte of the cluster (except when N==|block_count|, just parse
388 // the whole cluster). Verify that the corresponding entry in
389 // |kExpectedBuffersOnPartialCluster| identifies the exact subset of
390 // |kBlockInfo| returned by the parser.
391 for (int i
= 0; i
< block_count
; ++i
) {
394 // Since we don't know exactly the offsets of each block in the full
395 // cluster, build a cluster with exactly one additional block so that
396 // parse of all but one byte should deterministically parse all but the
397 // last full block. Don't |exceed block_count| blocks though.
398 int blocks_in_cluster
= std::min(i
+ 2, block_count
);
399 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kBlockInfo
,
401 // Parse all but the last byte unless we need to parse the full cluster.
402 bool parse_full_cluster
= i
== (block_count
- 1);
403 int result
= parser_
->Parse(cluster
->data(), parse_full_cluster
?
404 cluster
->size() : cluster
->size() - 1);
405 if (parse_full_cluster
) {
406 DVLOG(1) << "Verifying parse result of full cluster of "
407 << blocks_in_cluster
<< " blocks";
408 EXPECT_EQ(cluster
->size(), result
);
410 DVLOG(1) << "Verifying parse result of cluster of "
411 << blocks_in_cluster
<< " blocks with last block incomplete";
412 EXPECT_GT(cluster
->size(), result
);
413 EXPECT_LT(0, result
);
416 EXPECT_TRUE(VerifyBuffers(parser_
, kBlockInfo
,
417 kExpectedBuffersOnPartialCluster
[i
]));
421 TEST_F(WebMClusterParserTest
, Reset
) {
424 int block_count
= arraysize(kDefaultBlockInfo
);
425 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kDefaultBlockInfo
, block_count
));
427 // Send slightly less than the full cluster so all but the last block is
429 int result
= parser_
->Parse(cluster
->data(), cluster
->size() - 1);
430 EXPECT_GT(result
, 0);
431 EXPECT_LT(result
, cluster
->size());
433 ASSERT_TRUE(VerifyBuffers(parser_
, kDefaultBlockInfo
, block_count
- 1));
436 // Now parse a whole cluster to verify that all the blocks will get parsed.
437 result
= parser_
->Parse(cluster
->data(), cluster
->size());
438 EXPECT_EQ(cluster
->size(), result
);
439 ASSERT_TRUE(VerifyBuffers(parser_
, kDefaultBlockInfo
, block_count
));
442 TEST_F(WebMClusterParserTest
, ParseClusterWithSingleCall
) {
443 int block_count
= arraysize(kDefaultBlockInfo
);
444 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kDefaultBlockInfo
, block_count
));
446 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
447 EXPECT_EQ(cluster
->size(), result
);
448 ASSERT_TRUE(VerifyBuffers(parser_
, kDefaultBlockInfo
, block_count
));
451 TEST_F(WebMClusterParserTest
, ParseClusterWithMultipleCalls
) {
452 int block_count
= arraysize(kDefaultBlockInfo
);
453 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kDefaultBlockInfo
, block_count
));
455 WebMClusterParser::BufferQueue audio_buffers
;
456 WebMClusterParser::BufferQueue video_buffers
;
457 const WebMClusterParser::BufferQueue no_text_buffers
;
459 const uint8_t* data
= cluster
->data();
460 int size
= cluster
->size();
461 int default_parse_size
= 3;
462 int parse_size
= std::min(default_parse_size
, size
);
465 int result
= parser_
->Parse(data
, parse_size
);
466 ASSERT_GE(result
, 0);
467 ASSERT_LE(result
, parse_size
);
470 // The parser needs more data so increase the parse_size a little.
471 parse_size
+= default_parse_size
;
472 parse_size
= std::min(parse_size
, size
);
476 AppendToEnd(parser_
->GetAudioBuffers(), &audio_buffers
);
477 AppendToEnd(parser_
->GetVideoBuffers(), &video_buffers
);
479 parse_size
= default_parse_size
;
484 ASSERT_TRUE(VerifyBuffers(audio_buffers
, video_buffers
,
485 no_text_buffers
, kDefaultBlockInfo
,
489 // Verify that both BlockGroups with the BlockDuration before the Block
490 // and BlockGroups with the BlockDuration after the Block are supported
492 // Note: Raw bytes are use here because ClusterBuilder only generates
493 // one of these scenarios.
494 TEST_F(WebMClusterParserTest
, ParseBlockGroup
) {
495 const BlockInfo kBlockInfo
[] = {
496 {kAudioTrackNum
, 0, 23, false, NULL
, 0},
497 {kVideoTrackNum
, 33, 34, false, NULL
, 0},
499 int block_count
= arraysize(kBlockInfo
);
501 const uint8_t kClusterData
[] = {
502 0x1F, 0x43, 0xB6, 0x75, 0x9B, // Cluster(size=27)
503 0xE7, 0x81, 0x00, // Timecode(size=1, value=0)
504 // BlockGroup with BlockDuration before Block.
505 0xA0, 0x8A, // BlockGroup(size=10)
506 0x9B, 0x81, 0x17, // BlockDuration(size=1, value=23)
507 0xA1, 0x85, 0x81, 0x00, 0x00, 0x00, 0xaa, // Block(size=5, track=1, ts=0)
508 // BlockGroup with BlockDuration after Block.
509 0xA0, 0x8A, // BlockGroup(size=10)
510 0xA1, 0x85, 0x82, 0x00, 0x21, 0x00, 0x55, // Block(size=5, track=2, ts=33)
511 0x9B, 0x81, 0x22, // BlockDuration(size=1, value=34)
513 const int kClusterSize
= sizeof(kClusterData
);
515 int result
= parser_
->Parse(kClusterData
, kClusterSize
);
516 EXPECT_EQ(kClusterSize
, result
);
517 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
));
520 TEST_F(WebMClusterParserTest
, ParseSimpleBlockAndBlockGroupMixture
) {
521 const BlockInfo kBlockInfo
[] = {
522 {kAudioTrackNum
, 0, 23, true, NULL
, 0},
523 {kAudioTrackNum
, 23, 23, false, NULL
, 0},
524 {kVideoTrackNum
, 33, 34, true, NULL
, 0},
525 {kAudioTrackNum
, 46, 23, false, NULL
, 0},
526 {kVideoTrackNum
, 67, 33, false, NULL
, 0},
528 int block_count
= arraysize(kBlockInfo
);
529 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kBlockInfo
, block_count
));
531 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
532 EXPECT_EQ(cluster
->size(), result
);
533 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
));
536 TEST_F(WebMClusterParserTest
, IgnoredTracks
) {
537 std::set
<int64
> ignored_tracks
;
538 ignored_tracks
.insert(kTextTrackNum
);
540 parser_
.reset(CreateParserWithIgnoredTracks(ignored_tracks
));
542 const BlockInfo kInputBlockInfo
[] = {
543 {kAudioTrackNum
, 0, 23, true, NULL
, 0},
544 {kAudioTrackNum
, 23, 23, true, NULL
, 0},
545 {kVideoTrackNum
, 33, 34, true, NULL
, 0},
546 {kTextTrackNum
, 33, 99, true, NULL
, 0},
547 {kAudioTrackNum
, 46, 23, true, NULL
, 0},
548 {kVideoTrackNum
, 67, 34, true, NULL
, 0},
550 int input_block_count
= arraysize(kInputBlockInfo
);
552 const BlockInfo kOutputBlockInfo
[] = {
553 {kAudioTrackNum
, 0, 23, true, NULL
, 0},
554 {kAudioTrackNum
, 23, 23, true, NULL
, 0},
555 {kVideoTrackNum
, 33, 34, true, NULL
, 0},
556 {kAudioTrackNum
, 46, 23, true, NULL
, 0},
557 {kVideoTrackNum
, 67, 34, true, NULL
, 0},
559 int output_block_count
= arraysize(kOutputBlockInfo
);
561 scoped_ptr
<Cluster
> cluster(
562 CreateCluster(0, kInputBlockInfo
, input_block_count
));
564 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
565 EXPECT_EQ(cluster
->size(), result
);
566 ASSERT_TRUE(VerifyBuffers(parser_
, kOutputBlockInfo
, output_block_count
));
569 TEST_F(WebMClusterParserTest
, ParseTextTracks
) {
570 TextTracks text_tracks
;
572 text_tracks
.insert(std::make_pair(TextTracks::key_type(kTextTrackNum
),
573 TextTrackConfig(kTextSubtitles
, "", "",
576 parser_
.reset(CreateParserWithDefaultDurationsAndOptionalTextTracks(
577 kNoTimestamp(), kNoTimestamp(), text_tracks
));
579 const BlockInfo kInputBlockInfo
[] = {
580 {kAudioTrackNum
, 0, 23, true, NULL
, 0},
581 {kAudioTrackNum
, 23, 23, true, NULL
, 0},
582 {kVideoTrackNum
, 33, 34, true, NULL
, 0},
583 {kTextTrackNum
, 33, 42, false, NULL
, 0},
584 {kAudioTrackNum
, 46, 23, true, NULL
, 0},
585 {kTextTrackNum
, 55, 44, false, NULL
, 0},
586 {kVideoTrackNum
, 67, 34, true, NULL
, 0},
588 int input_block_count
= arraysize(kInputBlockInfo
);
590 scoped_ptr
<Cluster
> cluster(
591 CreateCluster(0, kInputBlockInfo
, input_block_count
));
593 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
594 EXPECT_EQ(cluster
->size(), result
);
595 ASSERT_TRUE(VerifyBuffers(parser_
, kInputBlockInfo
, input_block_count
));
598 TEST_F(WebMClusterParserTest
, TextTracksSimpleBlock
) {
599 TextTracks text_tracks
;
601 text_tracks
.insert(std::make_pair(TextTracks::key_type(kTextTrackNum
),
602 TextTrackConfig(kTextSubtitles
, "", "",
605 parser_
.reset(CreateParserWithDefaultDurationsAndOptionalTextTracks(
606 kNoTimestamp(), kNoTimestamp(), text_tracks
));
608 const BlockInfo kInputBlockInfo
[] = {
609 { kTextTrackNum
, 33, 42, true },
611 int input_block_count
= arraysize(kInputBlockInfo
);
613 scoped_ptr
<Cluster
> cluster(
614 CreateCluster(0, kInputBlockInfo
, input_block_count
));
616 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
617 EXPECT_LT(result
, 0);
620 TEST_F(WebMClusterParserTest
, ParseMultipleTextTracks
) {
621 TextTracks text_tracks
;
623 const int kSubtitleTextTrackNum
= kTextTrackNum
;
624 const int kCaptionTextTrackNum
= kTextTrackNum
+ 1;
626 text_tracks
.insert(std::make_pair(TextTracks::key_type(kSubtitleTextTrackNum
),
627 TextTrackConfig(kTextSubtitles
, "", "",
630 text_tracks
.insert(std::make_pair(TextTracks::key_type(kCaptionTextTrackNum
),
631 TextTrackConfig(kTextCaptions
, "", "",
634 parser_
.reset(CreateParserWithDefaultDurationsAndOptionalTextTracks(
635 kNoTimestamp(), kNoTimestamp(), text_tracks
));
637 const BlockInfo kInputBlockInfo
[] = {
638 {kAudioTrackNum
, 0, 23, true, NULL
, 0},
639 {kAudioTrackNum
, 23, 23, true, NULL
, 0},
640 {kVideoTrackNum
, 33, 34, true, NULL
, 0},
641 {kSubtitleTextTrackNum
, 33, 42, false, NULL
, 0},
642 {kAudioTrackNum
, 46, 23, true, NULL
, 0},
643 {kCaptionTextTrackNum
, 55, 44, false, NULL
, 0},
644 {kVideoTrackNum
, 67, 34, true, NULL
, 0},
645 {kSubtitleTextTrackNum
, 67, 33, false, NULL
, 0},
647 int input_block_count
= arraysize(kInputBlockInfo
);
649 scoped_ptr
<Cluster
> cluster(
650 CreateCluster(0, kInputBlockInfo
, input_block_count
));
652 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
653 EXPECT_EQ(cluster
->size(), result
);
655 const WebMClusterParser::TextBufferQueueMap
& text_map
=
656 parser_
->GetTextBuffers();
657 for (WebMClusterParser::TextBufferQueueMap::const_iterator itr
=
659 itr
!= text_map
.end();
661 const TextTracks::const_iterator find_result
=
662 text_tracks
.find(itr
->first
);
663 ASSERT_TRUE(find_result
!= text_tracks
.end());
664 ASSERT_TRUE(VerifyTextBuffers(parser_
, kInputBlockInfo
, input_block_count
,
665 itr
->first
, itr
->second
));
669 TEST_F(WebMClusterParserTest
, ParseEncryptedBlock
) {
670 scoped_ptr
<Cluster
> cluster(CreateEncryptedCluster(sizeof(kEncryptedFrame
)));
672 parser_
.reset(CreateParserWithKeyIdsAndAudioCodec(
673 std::string(), "video_key_id", kUnknownAudioCodec
));
674 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
675 EXPECT_EQ(cluster
->size(), result
);
676 ASSERT_EQ(1UL, parser_
->GetVideoBuffers().size());
677 scoped_refptr
<StreamParserBuffer
> buffer
= parser_
->GetVideoBuffers()[0];
678 VerifyEncryptedBuffer(buffer
);
681 TEST_F(WebMClusterParserTest
, ParseBadEncryptedBlock
) {
682 scoped_ptr
<Cluster
> cluster(
683 CreateEncryptedCluster(sizeof(kEncryptedFrame
) - 1));
685 parser_
.reset(CreateParserWithKeyIdsAndAudioCodec(
686 std::string(), "video_key_id", kUnknownAudioCodec
));
687 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
688 EXPECT_EQ(-1, result
);
691 TEST_F(WebMClusterParserTest
, ParseInvalidZeroSizedCluster
) {
692 const uint8_t kBuffer
[] = {
693 0x1F, 0x43, 0xB6, 0x75, 0x80, // CLUSTER (size = 0)
696 EXPECT_EQ(-1, parser_
->Parse(kBuffer
, sizeof(kBuffer
)));
699 TEST_F(WebMClusterParserTest
, ParseInvalidUnknownButActuallyZeroSizedCluster
) {
700 const uint8_t kBuffer
[] = {
701 0x1F, 0x43, 0xB6, 0x75, 0xFF, // CLUSTER (size = "unknown")
702 0x1F, 0x43, 0xB6, 0x75, 0x85, // CLUSTER (size = 5)
705 EXPECT_EQ(-1, parser_
->Parse(kBuffer
, sizeof(kBuffer
)));
708 TEST_F(WebMClusterParserTest
, ParseInvalidTextBlockGroupWithoutDuration
) {
709 // Text track frames must have explicitly specified BlockGroup BlockDurations.
710 TextTracks text_tracks
;
712 text_tracks
.insert(std::make_pair(TextTracks::key_type(kTextTrackNum
),
713 TextTrackConfig(kTextSubtitles
, "", "",
716 parser_
.reset(CreateParserWithDefaultDurationsAndOptionalTextTracks(
717 kNoTimestamp(), kNoTimestamp(), text_tracks
));
719 const BlockInfo kBlockInfo
[] = {
720 { kTextTrackNum
, 33, -42, false },
722 int block_count
= arraysize(kBlockInfo
);
723 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kBlockInfo
, block_count
));
724 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
725 EXPECT_LT(result
, 0);
728 TEST_F(WebMClusterParserTest
, ParseWithDefaultDurationsSimpleBlocks
) {
730 ResetParserToHaveDefaultDurations();
732 EXPECT_LT(kTestAudioFrameDefaultDurationInMs
, 23);
733 EXPECT_LT(kTestVideoFrameDefaultDurationInMs
, 33);
735 const BlockInfo kBlockInfo
[] = {
736 {kAudioTrackNum
, 0, kTestAudioFrameDefaultDurationInMs
, true, NULL
, 0},
737 {kAudioTrackNum
, 23, kTestAudioFrameDefaultDurationInMs
, true, NULL
, 0},
738 {kVideoTrackNum
, 33, kTestVideoFrameDefaultDurationInMs
, true, NULL
, 0},
739 {kAudioTrackNum
, 46, kTestAudioFrameDefaultDurationInMs
, true, NULL
, 0},
740 {kVideoTrackNum
, 67, kTestVideoFrameDefaultDurationInMs
, true, NULL
, 0},
741 {kAudioTrackNum
, 69, kTestAudioFrameDefaultDurationInMs
, true, NULL
, 0},
742 {kVideoTrackNum
, 100, kTestVideoFrameDefaultDurationInMs
, true, NULL
, 0},
745 int block_count
= arraysize(kBlockInfo
);
746 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kBlockInfo
, block_count
));
748 // Send slightly less than the full cluster so all but the last block is
749 // parsed. Though all the blocks are simple blocks, none should be held aside
750 // for duration estimation prior to end of cluster detection because all the
751 // tracks have DefaultDurations.
752 int result
= parser_
->Parse(cluster
->data(), cluster
->size() - 1);
753 EXPECT_GT(result
, 0);
754 EXPECT_LT(result
, cluster
->size());
755 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
- 1));
759 // Now parse a whole cluster to verify that all the blocks will get parsed.
760 result
= parser_
->Parse(cluster
->data(), cluster
->size());
761 EXPECT_EQ(cluster
->size(), result
);
762 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
));
765 TEST_F(WebMClusterParserTest
, ParseWithoutAnyDurationsSimpleBlocks
) {
768 // Absent DefaultDuration information, SimpleBlock durations are derived from
769 // inter-buffer track timestamp delta if within the cluster. Duration for the
770 // last block in a cluster is estimated independently for each track in the
771 // cluster. For video tracks we use the maximum seen so far. For audio we use
773 // TODO(chcunningham): Move audio over to use the maximum.
774 const BlockInfo kBlockInfo1
[] = {
775 {kAudioTrackNum
, 0, 23, true, NULL
, 0},
776 {kAudioTrackNum
, 23, 22, true, NULL
, 0},
777 {kVideoTrackNum
, 33, 33, true, NULL
, 0},
778 {kAudioTrackNum
, 45, 23, true, NULL
, 0},
779 {kVideoTrackNum
, 66, 34, true, NULL
, 0},
780 // Estimated from minimum audio dur
781 {kAudioTrackNum
, 68, 22, true, NULL
, 0},
782 // Estimated from maximum video dur
783 {kVideoTrackNum
, 100, 34, true, NULL
, 0},
786 int block_count1
= arraysize(kBlockInfo1
);
787 scoped_ptr
<Cluster
> cluster1(CreateCluster(0, kBlockInfo1
, block_count1
));
789 // Send slightly less than the first full cluster so all but the last video
790 // block is parsed. Verify the last fully parsed audio and video buffer are
791 // both missing from the result (parser should hold them aside for duration
792 // estimation prior to end of cluster detection in the absence of
793 // DefaultDurations.)
794 int result
= parser_
->Parse(cluster1
->data(), cluster1
->size() - 1);
795 EXPECT_GT(result
, 0);
796 EXPECT_LT(result
, cluster1
->size());
797 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo1
, block_count1
- 3));
798 EXPECT_EQ(3UL, parser_
->GetAudioBuffers().size());
799 EXPECT_EQ(1UL, parser_
->GetVideoBuffers().size());
803 // Now parse the full first cluster and verify all the blocks are parsed.
804 result
= parser_
->Parse(cluster1
->data(), cluster1
->size());
805 EXPECT_EQ(cluster1
->size(), result
);
806 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo1
, block_count1
));
808 // Verify that the estimated frame duration is tracked across clusters for
810 const BlockInfo kBlockInfo2
[] = {
811 // Estimate carries over across clusters
812 {kAudioTrackNum
, 200, 22, true, NULL
, 0},
813 // Estimate carries over across clusters
814 {kVideoTrackNum
, 201, 34, true, NULL
, 0},
817 int block_count2
= arraysize(kBlockInfo2
);
818 scoped_ptr
<Cluster
> cluster2(CreateCluster(0, kBlockInfo2
, block_count2
));
819 result
= parser_
->Parse(cluster2
->data(), cluster2
->size());
820 EXPECT_EQ(cluster2
->size(), result
);
821 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo2
, block_count2
));
824 TEST_F(WebMClusterParserTest
, ParseWithoutAnyDurationsBlockGroups
) {
827 // Absent DefaultDuration and BlockDuration information, BlockGroup block
828 // durations are derived from inter-buffer track timestamp delta if within the
829 // cluster. Duration for the last block in a cluster is estimated
830 // independently for each track in the cluster. For video tracks we use the
831 // maximum seen so far. For audio we use the the minimum.
832 // TODO(chcunningham): Move audio over to use the maximum.
833 const BlockInfo kBlockInfo1
[] = {
834 {kAudioTrackNum
, 0, -23, false, NULL
, 0},
835 {kAudioTrackNum
, 23, -22, false, NULL
, 0},
836 {kVideoTrackNum
, 33, -33, false, NULL
, 0},
837 {kAudioTrackNum
, 45, -23, false, NULL
, 0},
838 {kVideoTrackNum
, 66, -34, false, NULL
, 0},
839 // Estimated from minimum audio dur
840 {kAudioTrackNum
, 68, -22, false, NULL
, 0},
841 // Estimated from maximum video dur
842 {kVideoTrackNum
, 100, -34, false, NULL
, 0},
845 int block_count1
= arraysize(kBlockInfo1
);
846 scoped_ptr
<Cluster
> cluster1(CreateCluster(0, kBlockInfo1
, block_count1
));
848 // Send slightly less than the first full cluster so all but the last video
849 // block is parsed. Verify the last fully parsed audio and video buffer are
850 // both missing from the result (parser should hold them aside for duration
851 // estimation prior to end of cluster detection in the absence of
852 // DefaultDurations.)
853 int result
= parser_
->Parse(cluster1
->data(), cluster1
->size() - 1);
854 EXPECT_GT(result
, 0);
855 EXPECT_LT(result
, cluster1
->size());
856 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo1
, block_count1
- 3));
857 EXPECT_EQ(3UL, parser_
->GetAudioBuffers().size());
858 EXPECT_EQ(1UL, parser_
->GetVideoBuffers().size());
862 // Now parse the full first cluster and verify all the blocks are parsed.
863 result
= parser_
->Parse(cluster1
->data(), cluster1
->size());
864 EXPECT_EQ(cluster1
->size(), result
);
865 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo1
, block_count1
));
867 // Verify that the estimated frame duration is tracked across clusters for
869 const BlockInfo kBlockInfo2
[] = {
870 {kAudioTrackNum
, 200, -22, false, NULL
, 0},
871 {kVideoTrackNum
, 201, -34, false, NULL
, 0},
874 int block_count2
= arraysize(kBlockInfo2
);
875 scoped_ptr
<Cluster
> cluster2(CreateCluster(0, kBlockInfo2
, block_count2
));
876 result
= parser_
->Parse(cluster2
->data(), cluster2
->size());
877 EXPECT_EQ(cluster2
->size(), result
);
878 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo2
, block_count2
));
881 // TODO(wolenetz): Is parser behavior correct? See http://crbug.com/363433.
882 TEST_F(WebMClusterParserTest
,
883 ParseWithDefaultDurationsBlockGroupsWithoutDurations
) {
885 ResetParserToHaveDefaultDurations();
887 EXPECT_LT(kTestAudioFrameDefaultDurationInMs
, 23);
888 EXPECT_LT(kTestVideoFrameDefaultDurationInMs
, 33);
890 const BlockInfo kBlockInfo
[] = {
891 {kAudioTrackNum
, 0, -kTestAudioFrameDefaultDurationInMs
, false, NULL
, 0},
892 {kAudioTrackNum
, 23, -kTestAudioFrameDefaultDurationInMs
, false, NULL
, 0},
893 {kVideoTrackNum
, 33, -kTestVideoFrameDefaultDurationInMs
, false, NULL
, 0},
894 {kAudioTrackNum
, 46, -kTestAudioFrameDefaultDurationInMs
, false, NULL
, 0},
895 {kVideoTrackNum
, 67, -kTestVideoFrameDefaultDurationInMs
, false, NULL
, 0},
896 {kAudioTrackNum
, 69, -kTestAudioFrameDefaultDurationInMs
, false, NULL
, 0},
899 -kTestVideoFrameDefaultDurationInMs
,
905 int block_count
= arraysize(kBlockInfo
);
906 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kBlockInfo
, block_count
));
908 // Send slightly less than the full cluster so all but the last block is
909 // parsed. None should be held aside for duration estimation prior to end of
910 // cluster detection because all the tracks have DefaultDurations.
911 int result
= parser_
->Parse(cluster
->data(), cluster
->size() - 1);
912 EXPECT_GT(result
, 0);
913 EXPECT_LT(result
, cluster
->size());
914 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
- 1));
918 // Now parse a whole cluster to verify that all the blocks will get parsed.
919 result
= parser_
->Parse(cluster
->data(), cluster
->size());
920 EXPECT_EQ(cluster
->size(), result
);
921 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
));
924 TEST_F(WebMClusterParserTest
,
925 ParseDegenerateClusterYieldsHardcodedEstimatedDurations
) {
926 const BlockInfo kBlockInfo
[] = {
930 WebMClusterParser::kDefaultAudioBufferDurationInMs
,
935 WebMClusterParser::kDefaultVideoBufferDurationInMs
,
940 int block_count
= arraysize(kBlockInfo
);
941 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kBlockInfo
, block_count
));
942 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
943 EXPECT_EQ(cluster
->size(), result
);
944 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
));
947 TEST_F(WebMClusterParserTest
,
948 ParseDegenerateClusterWithDefaultDurationsYieldsDefaultDurations
) {
949 ResetParserToHaveDefaultDurations();
951 const BlockInfo kBlockInfo
[] = {
952 { kAudioTrackNum
, 0, kTestAudioFrameDefaultDurationInMs
, true },
953 { kVideoTrackNum
, 0, kTestVideoFrameDefaultDurationInMs
, true },
956 int block_count
= arraysize(kBlockInfo
);
957 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kBlockInfo
, block_count
));
958 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
959 EXPECT_EQ(cluster
->size(), result
);
960 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
));
963 TEST_F(WebMClusterParserTest
, ReadOpusDurationsSimpleBlockAtEndOfCluster
) {
964 // Reset parser to expect Opus codec audio.
965 parser_
.reset(CreateParserWithKeyIdsAndAudioCodec(std::string(),
966 std::string(), kCodecOpus
));
969 for (const auto* packet_ptr
: BuildAllOpusPackets()) {
970 const BlockInfo kBlockInfo
[] = {{kAudioTrackNum
,
972 packet_ptr
->duration_ms(),
973 true, // Make it a SimpleBlock.
975 packet_ptr
->size()}};
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
));
985 // Test should minimally cover all the combinations of config and frame count.
986 ASSERT_GE(loop_count
, kNumPossibleOpusConfigs
* kMaxOpusPacketFrameCount
);
989 TEST_F(WebMClusterParserTest
, PreferOpusDurationsOverBlockDurations
) {
990 // Reset parser to expect Opus codec audio.
991 parser_
.reset(CreateParserWithKeyIdsAndAudioCodec(std::string(),
992 std::string(), kCodecOpus
));
995 for (const auto* packet_ptr
: BuildAllOpusPackets()) {
996 // Setting BlockDuration != Opus duration to see which one the parser uses.
997 int block_duration_ms
= packet_ptr
->duration_ms() + 10;
999 BlockInfo block_infos
[] = {{kAudioTrackNum
,
1002 false, // Not a SimpleBlock.
1004 packet_ptr
->size()}};
1006 int block_count
= arraysize(block_infos
);
1007 scoped_ptr
<Cluster
> cluster(CreateCluster(0, block_infos
, block_count
));
1008 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
1009 EXPECT_EQ(cluster
->size(), result
);
1011 // BlockInfo duration will be used to verify buffer duration, so changing
1012 // duration to be that of the Opus packet to verify it was preferred.
1013 block_infos
[0].duration
= packet_ptr
->duration_ms();
1015 ASSERT_TRUE(VerifyBuffers(parser_
, block_infos
, block_count
));
1019 // Test should minimally cover all the combinations of config and frame count.
1020 ASSERT_GE(loop_count
, kNumPossibleOpusConfigs
* kMaxOpusPacketFrameCount
);
1023 // Tests that BlockDuration is used to set duration on buffer rather than
1024 // encoded duration in Opus packet (or hard coded duration estimates). Encoded
1025 // Opus duration is usually preferred but cannot be known when encrypted.
1026 TEST_F(WebMClusterParserTest
, DontReadEncodedDurationWhenEncrypted
) {
1027 // Non-empty dummy value signals encryption is active for audio.
1028 std::string
audio_encryption_id("audio_key_id");
1030 // Reset parser to expect Opus codec audio and use audio encryption key id.
1031 parser_
.reset(CreateParserWithKeyIdsAndAudioCodec(audio_encryption_id
,
1032 std::string(), kCodecOpus
));
1034 // Single Block with BlockDuration and encrypted data.
1035 const BlockInfo kBlockInfo
[] = {{kAudioTrackNum
,
1037 kTestAudioFrameDefaultDurationInMs
,
1038 false, // Not a SimpleBlock
1039 kEncryptedFrame
, // Encrypted frame data
1040 arraysize(kEncryptedFrame
)}};
1042 int block_count
= arraysize(kBlockInfo
);
1043 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kBlockInfo
, block_count
));
1044 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
1045 EXPECT_EQ(cluster
->size(), result
);
1047 // Will verify that duration of buffer matches that of BlockDuration.
1048 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
));
1051 } // namespace media