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/bind.h"
11 #include "base/logging.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "media/base/audio_decoder_config.h"
14 #include "media/base/decrypt_config.h"
15 #include "media/base/mock_media_log.h"
16 #include "media/base/timestamp_constants.h"
17 #include "media/formats/webm/cluster_builder.h"
18 #include "media/formats/webm/opus_packet_builder.h"
19 #include "media/formats/webm/webm_cluster_parser.h"
20 #include "media/formats/webm/webm_constants.h"
21 #include "testing/gmock/include/gmock/gmock.h"
22 #include "testing/gtest/include/gtest/gtest.h"
24 using ::testing::HasSubstr
;
25 using ::testing::InSequence
;
26 using ::testing::Return
;
27 using ::testing::StrictMock
;
28 using ::testing::Mock
;
33 typedef WebMTracksParser::TextTracks TextTracks
;
35 // Matchers for verifying common media log entry strings.
36 MATCHER_P(OpusPacketDurationTooHigh
, actual_duration_ms
, "") {
37 return CONTAINS_STRING(
38 arg
, "Warning, demuxed Opus packet with encoded duration: " +
39 base::IntToString(actual_duration_ms
) +
40 "ms. Should be no greater than 120ms.");
43 MATCHER_P(WebMSimpleBlockDurationEstimated
, estimated_duration_ms
, "") {
44 return CONTAINS_STRING(arg
, "Estimating WebM block duration to be " +
45 base::IntToString(estimated_duration_ms
) +
46 "ms for the last (Simple)Block in the "
47 "Cluster for this Track. Use BlockGroups "
48 "with BlockDurations at the end of each "
49 "Track in a Cluster to avoid estimation.");
52 MATCHER_P2(WebMBlockDurationMismatchesOpusDuration
,
56 return CONTAINS_STRING(
57 arg
, "BlockDuration (" + base::IntToString(block_duration_ms
) +
58 "ms) differs significantly from encoded duration (" +
59 base::IntToString(opus_duration_ms
) + "ms).");
64 // Timecode scale for millisecond timestamps.
65 const int kTimecodeScale
= 1000000;
67 const int kAudioTrackNum
= 1;
68 const int kVideoTrackNum
= 2;
69 const int kTextTrackNum
= 3;
70 const int kTestAudioFrameDefaultDurationInMs
= 13;
71 const int kTestVideoFrameDefaultDurationInMs
= 17;
73 // Test duration defaults must differ from parser estimation defaults to know
74 // which durations parser used when emitting buffers.
76 static_cast<int>(kTestAudioFrameDefaultDurationInMs
) !=
77 static_cast<int>(WebMClusterParser::kDefaultAudioBufferDurationInMs
),
78 "test default is the same as estimation fallback audio duration");
80 static_cast<int>(kTestVideoFrameDefaultDurationInMs
) !=
81 static_cast<int>(WebMClusterParser::kDefaultVideoBufferDurationInMs
),
82 "test default is the same as estimation fallback video duration");
88 // Negative value is allowed only for block groups (not simple blocks) and
89 // directs CreateCluster() to exclude BlockDuration entry from the cluster for
90 // this BlockGroup. The absolute value is used for parser verification.
91 // For simple blocks, this value must be non-negative, and is used only for
92 // parser verification.
95 bool use_simple_block
;
97 // Default data will be used if no data given.
102 const BlockInfo kDefaultBlockInfo
[] = {
103 {kAudioTrackNum
, 0, 23, true, NULL
, 0},
104 {kAudioTrackNum
, 23, 23, true, NULL
, 0},
105 // Assumes not using DefaultDuration
106 {kVideoTrackNum
, 33, 34, true, NULL
, 0},
107 {kAudioTrackNum
, 46, 23, true, NULL
, 0},
108 {kVideoTrackNum
, 67, 33, false, NULL
, 0},
109 {kAudioTrackNum
, 69, 23, false, NULL
, 0},
110 {kVideoTrackNum
, 100, 33, false, NULL
, 0},
113 const uint8_t kEncryptedFrame
[] = {
114 // Block is encrypted
118 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
120 scoped_ptr
<Cluster
> CreateCluster(int timecode
,
121 const BlockInfo
* block_info
,
124 cb
.SetClusterTimecode(0);
126 uint8_t kDefaultBlockData
[] = { 0x00 };
128 for (int i
= 0; i
< block_count
; i
++) {
131 if (block_info
[i
].data
!= NULL
) {
132 data
= block_info
[i
].data
;
133 data_length
= block_info
[i
].data_length
;
135 data
= kDefaultBlockData
;
136 data_length
= sizeof(kDefaultBlockData
);
139 if (block_info
[i
].use_simple_block
) {
140 CHECK_GE(block_info
[i
].duration
, 0);
141 cb
.AddSimpleBlock(block_info
[i
].track_num
, block_info
[i
].timestamp
, 0,
146 if (block_info
[i
].duration
< 0) {
147 cb
.AddBlockGroupWithoutBlockDuration(block_info
[i
].track_num
,
148 block_info
[i
].timestamp
, 0, data
,
153 cb
.AddBlockGroup(block_info
[i
].track_num
, block_info
[i
].timestamp
,
154 block_info
[i
].duration
, 0, data
, data_length
);
160 // Creates a Cluster with one encrypted Block. |bytes_to_write| is number of
161 // bytes of the encrypted frame to write.
162 scoped_ptr
<Cluster
> CreateEncryptedCluster(int bytes_to_write
) {
163 CHECK_GT(bytes_to_write
, 0);
164 CHECK_LE(bytes_to_write
, static_cast<int>(sizeof(kEncryptedFrame
)));
167 cb
.SetClusterTimecode(0);
168 cb
.AddSimpleBlock(kVideoTrackNum
, 0, 0, kEncryptedFrame
, bytes_to_write
);
172 bool VerifyBuffers(const WebMClusterParser::BufferQueue
& audio_buffers
,
173 const WebMClusterParser::BufferQueue
& video_buffers
,
174 const WebMClusterParser::BufferQueue
& text_buffers
,
175 const BlockInfo
* block_info
,
177 int buffer_count
= audio_buffers
.size() + video_buffers
.size() +
179 if (block_count
!= buffer_count
) {
180 DVLOG(1) << __FUNCTION__
<< " : block_count (" << block_count
181 << ") mismatches buffer_count (" << buffer_count
<< ")";
185 size_t audio_offset
= 0;
186 size_t video_offset
= 0;
187 size_t text_offset
= 0;
188 for (int i
= 0; i
< block_count
; i
++) {
189 const WebMClusterParser::BufferQueue
* buffers
= NULL
;
191 StreamParserBuffer::Type expected_type
= DemuxerStream::UNKNOWN
;
193 if (block_info
[i
].track_num
== kAudioTrackNum
) {
194 buffers
= &audio_buffers
;
195 offset
= &audio_offset
;
196 expected_type
= DemuxerStream::AUDIO
;
197 } else if (block_info
[i
].track_num
== kVideoTrackNum
) {
198 buffers
= &video_buffers
;
199 offset
= &video_offset
;
200 expected_type
= DemuxerStream::VIDEO
;
201 } else if (block_info
[i
].track_num
== kTextTrackNum
) {
202 buffers
= &text_buffers
;
203 offset
= &text_offset
;
204 expected_type
= DemuxerStream::TEXT
;
206 LOG(ERROR
) << "Unexpected track number " << block_info
[i
].track_num
;
210 if (*offset
>= buffers
->size()) {
211 DVLOG(1) << __FUNCTION__
<< " : Too few buffers (" << buffers
->size()
212 << ") for track_num (" << block_info
[i
].track_num
213 << "), expected at least " << *offset
+ 1 << " buffers";
217 scoped_refptr
<StreamParserBuffer
> buffer
= (*buffers
)[(*offset
)++];
219 EXPECT_EQ(block_info
[i
].timestamp
, buffer
->timestamp().InMilliseconds());
220 EXPECT_EQ(std::abs(block_info
[i
].duration
),
221 buffer
->duration().InMillisecondsF());
222 EXPECT_EQ(expected_type
, buffer
->type());
223 EXPECT_EQ(block_info
[i
].track_num
, buffer
->track_id());
229 bool VerifyBuffers(const scoped_ptr
<WebMClusterParser
>& parser
,
230 const BlockInfo
* block_info
,
232 const WebMClusterParser::TextBufferQueueMap
& text_map
=
233 parser
->GetTextBuffers();
234 const WebMClusterParser::BufferQueue
* text_buffers
;
235 const WebMClusterParser::BufferQueue no_text_buffers
;
236 if (!text_map
.empty())
237 text_buffers
= &(text_map
.rbegin()->second
);
239 text_buffers
= &no_text_buffers
;
241 return VerifyBuffers(parser
->GetAudioBuffers(),
242 parser
->GetVideoBuffers(),
248 bool VerifyTextBuffers(const scoped_ptr
<WebMClusterParser
>& parser
,
249 const BlockInfo
* block_info_ptr
,
252 const WebMClusterParser::BufferQueue
& text_buffers
) {
253 const BlockInfo
* const block_info_end
= block_info_ptr
+ block_count
;
255 typedef WebMClusterParser::BufferQueue::const_iterator TextBufferIter
;
256 TextBufferIter buffer_iter
= text_buffers
.begin();
257 const TextBufferIter buffer_end
= text_buffers
.end();
259 while (block_info_ptr
!= block_info_end
) {
260 const BlockInfo
& block_info
= *block_info_ptr
++;
262 if (block_info
.track_num
!= text_track_num
)
265 EXPECT_FALSE(block_info
.use_simple_block
);
266 EXPECT_FALSE(buffer_iter
== buffer_end
);
268 const scoped_refptr
<StreamParserBuffer
> buffer
= *buffer_iter
++;
269 EXPECT_EQ(block_info
.timestamp
, buffer
->timestamp().InMilliseconds());
270 EXPECT_EQ(std::abs(block_info
.duration
),
271 buffer
->duration().InMillisecondsF());
272 EXPECT_EQ(DemuxerStream::TEXT
, buffer
->type());
273 EXPECT_EQ(text_track_num
, buffer
->track_id());
276 EXPECT_TRUE(buffer_iter
== buffer_end
);
280 void VerifyEncryptedBuffer(scoped_refptr
<StreamParserBuffer
> buffer
) {
281 EXPECT_TRUE(buffer
->decrypt_config());
282 EXPECT_EQ(static_cast<unsigned long>(DecryptConfig::kDecryptionKeySize
),
283 buffer
->decrypt_config()->iv().length());
286 void AppendToEnd(const WebMClusterParser::BufferQueue
& src
,
287 WebMClusterParser::BufferQueue
* dest
) {
288 for (WebMClusterParser::BufferQueue::const_iterator itr
= src
.begin();
289 itr
!= src
.end(); ++itr
) {
290 dest
->push_back(*itr
);
296 class WebMClusterParserTest
: public testing::Test
{
298 WebMClusterParserTest()
299 : media_log_(new StrictMock
<MockMediaLog
>()),
300 parser_(CreateDefaultParser()) {}
303 void ResetParserToHaveDefaultDurations() {
304 base::TimeDelta default_audio_duration
= base::TimeDelta::FromMilliseconds(
305 kTestAudioFrameDefaultDurationInMs
);
306 base::TimeDelta default_video_duration
= base::TimeDelta::FromMilliseconds(
307 kTestVideoFrameDefaultDurationInMs
);
308 ASSERT_GE(default_audio_duration
, base::TimeDelta());
309 ASSERT_GE(default_video_duration
, base::TimeDelta());
310 ASSERT_NE(kNoTimestamp(), default_audio_duration
);
311 ASSERT_NE(kNoTimestamp(), default_video_duration
);
313 parser_
.reset(CreateParserWithDefaultDurationsAndOptionalTextTracks(
314 default_audio_duration
, default_video_duration
));
317 // Helper that hard-codes some non-varying constructor parameters.
318 WebMClusterParser
* CreateParserHelper(
319 base::TimeDelta audio_default_duration
,
320 base::TimeDelta video_default_duration
,
321 const WebMTracksParser::TextTracks
& text_tracks
,
322 const std::set
<int64
>& ignored_tracks
,
323 const std::string
& audio_encryption_key_id
,
324 const std::string
& video_encryption_key_id
,
325 const AudioCodec audio_codec
) {
326 return new WebMClusterParser(
327 kTimecodeScale
, kAudioTrackNum
, audio_default_duration
, kVideoTrackNum
,
328 video_default_duration
, text_tracks
, ignored_tracks
,
329 audio_encryption_key_id
, video_encryption_key_id
, audio_codec
,
333 // Create a default version of the parser for test.
334 WebMClusterParser
* CreateDefaultParser() {
335 return CreateParserHelper(kNoTimestamp(), kNoTimestamp(), TextTracks(),
336 std::set
<int64
>(), std::string(), std::string(),
340 // Create a parser for test with custom audio and video default durations, and
341 // optionally custom text tracks.
342 WebMClusterParser
* CreateParserWithDefaultDurationsAndOptionalTextTracks(
343 base::TimeDelta audio_default_duration
,
344 base::TimeDelta video_default_duration
,
345 const WebMTracksParser::TextTracks
& text_tracks
= TextTracks()) {
346 return CreateParserHelper(audio_default_duration
, video_default_duration
,
347 text_tracks
, std::set
<int64
>(), std::string(),
348 std::string(), kUnknownAudioCodec
);
351 // Create a parser for test with custom ignored tracks.
352 WebMClusterParser
* CreateParserWithIgnoredTracks(
353 std::set
<int64
>& ignored_tracks
) {
354 return CreateParserHelper(kNoTimestamp(), kNoTimestamp(), TextTracks(),
355 ignored_tracks
, std::string(), std::string(),
359 // Create a parser for test with custom encryption key ids and audio codec.
360 WebMClusterParser
* CreateParserWithKeyIdsAndAudioCodec(
361 const std::string
& audio_encryption_key_id
,
362 const std::string
& video_encryption_key_id
,
363 const AudioCodec audio_codec
) {
364 return CreateParserHelper(kNoTimestamp(), kNoTimestamp(), TextTracks(),
365 std::set
<int64
>(), audio_encryption_key_id
,
366 video_encryption_key_id
, audio_codec
);
369 scoped_refptr
<StrictMock
<MockMediaLog
>> media_log_
;
370 scoped_ptr
<WebMClusterParser
> parser_
;
373 DISALLOW_COPY_AND_ASSIGN(WebMClusterParserTest
);
376 TEST_F(WebMClusterParserTest
, HeldBackBufferHoldsBackAllTracks
) {
377 // If a buffer is missing duration and is being held back, then all other
378 // tracks' buffers that have same or higher (decode) timestamp should be held
379 // back too to keep the timestamps emitted for a cluster monotonically
380 // non-decreasing and in same order as parsed.
383 // Reset the parser to have 3 tracks: text, video (no default frame duration),
384 // and audio (with a default frame duration).
385 TextTracks text_tracks
;
386 text_tracks
.insert(std::make_pair(TextTracks::key_type(kTextTrackNum
),
387 TextTrackConfig(kTextSubtitles
, "", "",
389 base::TimeDelta default_audio_duration
=
390 base::TimeDelta::FromMilliseconds(kTestAudioFrameDefaultDurationInMs
);
391 ASSERT_GE(default_audio_duration
, base::TimeDelta());
392 ASSERT_NE(kNoTimestamp(), default_audio_duration
);
393 parser_
.reset(CreateParserWithDefaultDurationsAndOptionalTextTracks(
394 default_audio_duration
, kNoTimestamp(), text_tracks
));
396 const int kExpectedVideoEstimationInMs
= 33;
398 const BlockInfo kBlockInfo
[] = {
399 {kVideoTrackNum
, 0, 33, true, NULL
, 0},
400 {kAudioTrackNum
, 0, 23, false, NULL
, 0},
401 {kTextTrackNum
, 10, 42, false, NULL
, 0},
402 {kAudioTrackNum
, 23, kTestAudioFrameDefaultDurationInMs
, true, NULL
, 0},
403 {kVideoTrackNum
, 33, 33, true, NULL
, 0},
404 {kAudioTrackNum
, 36, kTestAudioFrameDefaultDurationInMs
, true, NULL
, 0},
405 {kVideoTrackNum
, 66, kExpectedVideoEstimationInMs
, true, NULL
, 0},
406 {kAudioTrackNum
, 70, kTestAudioFrameDefaultDurationInMs
, true, NULL
, 0},
407 {kAudioTrackNum
, 83, kTestAudioFrameDefaultDurationInMs
, true, NULL
, 0},
410 const int kExpectedBuffersOnPartialCluster
[] = {
411 0, // Video simple block without DefaultDuration should be held back
412 0, // Audio buffer ready, but not emitted because its TS >= held back video
413 0, // Text buffer ready, but not emitted because its TS >= held back video
414 0, // 2nd audio buffer ready, also not emitted for same reason as first
415 4, // All previous buffers emitted, 2nd video held back with no duration
416 4, // 2nd video still has no duration, 3rd audio ready but not emitted
417 6, // All previous buffers emitted, 3rd video held back with no duration
418 6, // 3rd video still has no duration, 4th audio ready but not emitted
419 9, // Cluster end emits all buffers and 3rd video's duration is estimated
422 ASSERT_EQ(arraysize(kBlockInfo
), arraysize(kExpectedBuffersOnPartialCluster
));
423 int block_count
= arraysize(kBlockInfo
);
425 // Iteratively create a cluster containing the first N+1 blocks and parse all
426 // but the last byte of the cluster (except when N==|block_count|, just parse
427 // the whole cluster). Verify that the corresponding entry in
428 // |kExpectedBuffersOnPartialCluster| identifies the exact subset of
429 // |kBlockInfo| returned by the parser.
430 for (int i
= 0; i
< block_count
; ++i
) {
433 // Since we don't know exactly the offsets of each block in the full
434 // cluster, build a cluster with exactly one additional block so that
435 // parse of all but one byte should deterministically parse all but the
436 // last full block. Don't |exceed block_count| blocks though.
437 int blocks_in_cluster
= std::min(i
+ 2, block_count
);
438 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kBlockInfo
,
440 // Parse all but the last byte unless we need to parse the full cluster.
441 bool parse_full_cluster
= i
== (block_count
- 1);
443 if (parse_full_cluster
) {
445 WebMSimpleBlockDurationEstimated(kExpectedVideoEstimationInMs
));
448 int result
= parser_
->Parse(cluster
->data(), parse_full_cluster
?
449 cluster
->size() : cluster
->size() - 1);
450 if (parse_full_cluster
) {
451 DVLOG(1) << "Verifying parse result of full cluster of "
452 << blocks_in_cluster
<< " blocks";
453 EXPECT_EQ(cluster
->size(), result
);
455 DVLOG(1) << "Verifying parse result of cluster of "
456 << blocks_in_cluster
<< " blocks with last block incomplete";
457 EXPECT_GT(cluster
->size(), result
);
458 EXPECT_LT(0, result
);
461 EXPECT_TRUE(VerifyBuffers(parser_
, kBlockInfo
,
462 kExpectedBuffersOnPartialCluster
[i
]));
466 TEST_F(WebMClusterParserTest
, Reset
) {
469 int block_count
= arraysize(kDefaultBlockInfo
);
470 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kDefaultBlockInfo
, block_count
));
472 // Send slightly less than the full cluster so all but the last block is
474 int result
= parser_
->Parse(cluster
->data(), cluster
->size() - 1);
475 EXPECT_GT(result
, 0);
476 EXPECT_LT(result
, cluster
->size());
478 ASSERT_TRUE(VerifyBuffers(parser_
, kDefaultBlockInfo
, block_count
- 1));
481 // Now parse a whole cluster to verify that all the blocks will get parsed.
482 result
= parser_
->Parse(cluster
->data(), cluster
->size());
483 EXPECT_EQ(cluster
->size(), result
);
484 ASSERT_TRUE(VerifyBuffers(parser_
, kDefaultBlockInfo
, block_count
));
487 TEST_F(WebMClusterParserTest
, ParseClusterWithSingleCall
) {
488 int block_count
= arraysize(kDefaultBlockInfo
);
489 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kDefaultBlockInfo
, block_count
));
491 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
492 EXPECT_EQ(cluster
->size(), result
);
493 ASSERT_TRUE(VerifyBuffers(parser_
, kDefaultBlockInfo
, block_count
));
496 TEST_F(WebMClusterParserTest
, ParseClusterWithMultipleCalls
) {
497 int block_count
= arraysize(kDefaultBlockInfo
);
498 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kDefaultBlockInfo
, block_count
));
500 WebMClusterParser::BufferQueue audio_buffers
;
501 WebMClusterParser::BufferQueue video_buffers
;
502 const WebMClusterParser::BufferQueue no_text_buffers
;
504 const uint8_t* data
= cluster
->data();
505 int size
= cluster
->size();
506 int default_parse_size
= 3;
507 int parse_size
= std::min(default_parse_size
, size
);
510 int result
= parser_
->Parse(data
, parse_size
);
511 ASSERT_GE(result
, 0);
512 ASSERT_LE(result
, parse_size
);
515 // The parser needs more data so increase the parse_size a little.
516 parse_size
+= default_parse_size
;
517 parse_size
= std::min(parse_size
, size
);
521 AppendToEnd(parser_
->GetAudioBuffers(), &audio_buffers
);
522 AppendToEnd(parser_
->GetVideoBuffers(), &video_buffers
);
524 parse_size
= default_parse_size
;
529 ASSERT_TRUE(VerifyBuffers(audio_buffers
, video_buffers
,
530 no_text_buffers
, kDefaultBlockInfo
,
534 // Verify that both BlockGroups with the BlockDuration before the Block
535 // and BlockGroups with the BlockDuration after the Block are supported
537 // Note: Raw bytes are use here because ClusterBuilder only generates
538 // one of these scenarios.
539 TEST_F(WebMClusterParserTest
, ParseBlockGroup
) {
540 const BlockInfo kBlockInfo
[] = {
541 {kAudioTrackNum
, 0, 23, false, NULL
, 0},
542 {kVideoTrackNum
, 33, 34, false, NULL
, 0},
544 int block_count
= arraysize(kBlockInfo
);
546 const uint8_t kClusterData
[] = {
547 0x1F, 0x43, 0xB6, 0x75, 0x9B, // Cluster(size=27)
548 0xE7, 0x81, 0x00, // Timecode(size=1, value=0)
549 // BlockGroup with BlockDuration before Block.
550 0xA0, 0x8A, // BlockGroup(size=10)
551 0x9B, 0x81, 0x17, // BlockDuration(size=1, value=23)
552 0xA1, 0x85, 0x81, 0x00, 0x00, 0x00, 0xaa, // Block(size=5, track=1, ts=0)
553 // BlockGroup with BlockDuration after Block.
554 0xA0, 0x8A, // BlockGroup(size=10)
555 0xA1, 0x85, 0x82, 0x00, 0x21, 0x00, 0x55, // Block(size=5, track=2, ts=33)
556 0x9B, 0x81, 0x22, // BlockDuration(size=1, value=34)
558 const int kClusterSize
= sizeof(kClusterData
);
560 int result
= parser_
->Parse(kClusterData
, kClusterSize
);
561 EXPECT_EQ(kClusterSize
, result
);
562 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
));
565 TEST_F(WebMClusterParserTest
, ParseSimpleBlockAndBlockGroupMixture
) {
566 const BlockInfo kBlockInfo
[] = {
567 {kAudioTrackNum
, 0, 23, true, NULL
, 0},
568 {kAudioTrackNum
, 23, 23, false, NULL
, 0},
569 {kVideoTrackNum
, 33, 34, true, NULL
, 0},
570 {kAudioTrackNum
, 46, 23, false, NULL
, 0},
571 {kVideoTrackNum
, 67, 33, false, NULL
, 0},
573 int block_count
= arraysize(kBlockInfo
);
574 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kBlockInfo
, block_count
));
576 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
577 EXPECT_EQ(cluster
->size(), result
);
578 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
));
581 TEST_F(WebMClusterParserTest
, IgnoredTracks
) {
582 std::set
<int64
> ignored_tracks
;
583 ignored_tracks
.insert(kTextTrackNum
);
585 parser_
.reset(CreateParserWithIgnoredTracks(ignored_tracks
));
587 const BlockInfo kInputBlockInfo
[] = {
588 {kAudioTrackNum
, 0, 23, true, NULL
, 0},
589 {kAudioTrackNum
, 23, 23, true, NULL
, 0},
590 {kVideoTrackNum
, 33, 34, true, NULL
, 0},
591 {kTextTrackNum
, 33, 99, true, NULL
, 0},
592 {kAudioTrackNum
, 46, 23, true, NULL
, 0},
593 {kVideoTrackNum
, 67, 34, true, NULL
, 0},
595 int input_block_count
= arraysize(kInputBlockInfo
);
597 const BlockInfo kOutputBlockInfo
[] = {
598 {kAudioTrackNum
, 0, 23, true, NULL
, 0},
599 {kAudioTrackNum
, 23, 23, true, NULL
, 0},
600 {kVideoTrackNum
, 33, 34, true, NULL
, 0},
601 {kAudioTrackNum
, 46, 23, true, NULL
, 0},
602 {kVideoTrackNum
, 67, 34, true, NULL
, 0},
604 int output_block_count
= arraysize(kOutputBlockInfo
);
606 scoped_ptr
<Cluster
> cluster(
607 CreateCluster(0, kInputBlockInfo
, input_block_count
));
609 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(23));
610 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(34));
611 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
612 EXPECT_EQ(cluster
->size(), result
);
613 ASSERT_TRUE(VerifyBuffers(parser_
, kOutputBlockInfo
, output_block_count
));
616 TEST_F(WebMClusterParserTest
, ParseTextTracks
) {
617 TextTracks text_tracks
;
619 text_tracks
.insert(std::make_pair(TextTracks::key_type(kTextTrackNum
),
620 TextTrackConfig(kTextSubtitles
, "", "",
623 parser_
.reset(CreateParserWithDefaultDurationsAndOptionalTextTracks(
624 kNoTimestamp(), kNoTimestamp(), text_tracks
));
626 const BlockInfo kInputBlockInfo
[] = {
627 {kAudioTrackNum
, 0, 23, true, NULL
, 0},
628 {kAudioTrackNum
, 23, 23, true, NULL
, 0},
629 {kVideoTrackNum
, 33, 34, true, NULL
, 0},
630 {kTextTrackNum
, 33, 42, false, NULL
, 0},
631 {kAudioTrackNum
, 46, 23, true, NULL
, 0},
632 {kTextTrackNum
, 55, 44, false, NULL
, 0},
633 {kVideoTrackNum
, 67, 34, true, NULL
, 0},
635 int input_block_count
= arraysize(kInputBlockInfo
);
637 scoped_ptr
<Cluster
> cluster(
638 CreateCluster(0, kInputBlockInfo
, input_block_count
));
640 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(23));
641 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(34));
642 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
643 EXPECT_EQ(cluster
->size(), result
);
644 ASSERT_TRUE(VerifyBuffers(parser_
, kInputBlockInfo
, input_block_count
));
647 TEST_F(WebMClusterParserTest
, TextTracksSimpleBlock
) {
648 TextTracks text_tracks
;
650 text_tracks
.insert(std::make_pair(TextTracks::key_type(kTextTrackNum
),
651 TextTrackConfig(kTextSubtitles
, "", "",
654 parser_
.reset(CreateParserWithDefaultDurationsAndOptionalTextTracks(
655 kNoTimestamp(), kNoTimestamp(), text_tracks
));
657 const BlockInfo kInputBlockInfo
[] = {
658 { kTextTrackNum
, 33, 42, true },
660 int input_block_count
= arraysize(kInputBlockInfo
);
662 scoped_ptr
<Cluster
> cluster(
663 CreateCluster(0, kInputBlockInfo
, input_block_count
));
665 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
666 EXPECT_LT(result
, 0);
669 TEST_F(WebMClusterParserTest
, ParseMultipleTextTracks
) {
670 TextTracks text_tracks
;
672 const int kSubtitleTextTrackNum
= kTextTrackNum
;
673 const int kCaptionTextTrackNum
= kTextTrackNum
+ 1;
675 text_tracks
.insert(std::make_pair(TextTracks::key_type(kSubtitleTextTrackNum
),
676 TextTrackConfig(kTextSubtitles
, "", "",
679 text_tracks
.insert(std::make_pair(TextTracks::key_type(kCaptionTextTrackNum
),
680 TextTrackConfig(kTextCaptions
, "", "",
683 parser_
.reset(CreateParserWithDefaultDurationsAndOptionalTextTracks(
684 kNoTimestamp(), kNoTimestamp(), text_tracks
));
686 const BlockInfo kInputBlockInfo
[] = {
687 {kAudioTrackNum
, 0, 23, true, NULL
, 0},
688 {kAudioTrackNum
, 23, 23, true, NULL
, 0},
689 {kVideoTrackNum
, 33, 34, true, NULL
, 0},
690 {kSubtitleTextTrackNum
, 33, 42, false, NULL
, 0},
691 {kAudioTrackNum
, 46, 23, true, NULL
, 0},
692 {kCaptionTextTrackNum
, 55, 44, false, NULL
, 0},
693 {kVideoTrackNum
, 67, 34, true, NULL
, 0},
694 {kSubtitleTextTrackNum
, 67, 33, false, NULL
, 0},
696 int input_block_count
= arraysize(kInputBlockInfo
);
698 scoped_ptr
<Cluster
> cluster(
699 CreateCluster(0, kInputBlockInfo
, input_block_count
));
701 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(23));
702 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(34));
703 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
704 EXPECT_EQ(cluster
->size(), result
);
706 const WebMClusterParser::TextBufferQueueMap
& text_map
=
707 parser_
->GetTextBuffers();
708 for (WebMClusterParser::TextBufferQueueMap::const_iterator itr
=
710 itr
!= text_map
.end();
712 const TextTracks::const_iterator find_result
=
713 text_tracks
.find(itr
->first
);
714 ASSERT_TRUE(find_result
!= text_tracks
.end());
715 ASSERT_TRUE(VerifyTextBuffers(parser_
, kInputBlockInfo
, input_block_count
,
716 itr
->first
, itr
->second
));
720 TEST_F(WebMClusterParserTest
, ParseEncryptedBlock
) {
721 scoped_ptr
<Cluster
> cluster(CreateEncryptedCluster(sizeof(kEncryptedFrame
)));
723 parser_
.reset(CreateParserWithKeyIdsAndAudioCodec(
724 std::string(), "video_key_id", kUnknownAudioCodec
));
726 // The encrypted cluster contains just one block, video.
727 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(
728 WebMClusterParser::kDefaultVideoBufferDurationInMs
));
730 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
731 EXPECT_EQ(cluster
->size(), result
);
732 ASSERT_EQ(1UL, parser_
->GetVideoBuffers().size());
733 scoped_refptr
<StreamParserBuffer
> buffer
= parser_
->GetVideoBuffers()[0];
734 VerifyEncryptedBuffer(buffer
);
737 TEST_F(WebMClusterParserTest
, ParseBadEncryptedBlock
) {
738 scoped_ptr
<Cluster
> cluster(
739 CreateEncryptedCluster(sizeof(kEncryptedFrame
) - 1));
741 parser_
.reset(CreateParserWithKeyIdsAndAudioCodec(
742 std::string(), "video_key_id", kUnknownAudioCodec
));
743 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
744 EXPECT_EQ(-1, result
);
747 TEST_F(WebMClusterParserTest
, ParseInvalidZeroSizedCluster
) {
748 const uint8_t kBuffer
[] = {
749 0x1F, 0x43, 0xB6, 0x75, 0x80, // CLUSTER (size = 0)
752 EXPECT_EQ(-1, parser_
->Parse(kBuffer
, sizeof(kBuffer
)));
755 TEST_F(WebMClusterParserTest
, ParseInvalidUnknownButActuallyZeroSizedCluster
) {
756 const uint8_t kBuffer
[] = {
757 0x1F, 0x43, 0xB6, 0x75, 0xFF, // CLUSTER (size = "unknown")
758 0x1F, 0x43, 0xB6, 0x75, 0x85, // CLUSTER (size = 5)
761 EXPECT_EQ(-1, parser_
->Parse(kBuffer
, sizeof(kBuffer
)));
764 TEST_F(WebMClusterParserTest
, ParseInvalidTextBlockGroupWithoutDuration
) {
765 // Text track frames must have explicitly specified BlockGroup BlockDurations.
766 TextTracks text_tracks
;
768 text_tracks
.insert(std::make_pair(TextTracks::key_type(kTextTrackNum
),
769 TextTrackConfig(kTextSubtitles
, "", "",
772 parser_
.reset(CreateParserWithDefaultDurationsAndOptionalTextTracks(
773 kNoTimestamp(), kNoTimestamp(), text_tracks
));
775 const BlockInfo kBlockInfo
[] = {
776 { kTextTrackNum
, 33, -42, false },
778 int block_count
= arraysize(kBlockInfo
);
779 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kBlockInfo
, block_count
));
780 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
781 EXPECT_LT(result
, 0);
784 TEST_F(WebMClusterParserTest
, ParseWithDefaultDurationsSimpleBlocks
) {
786 ResetParserToHaveDefaultDurations();
788 EXPECT_LT(kTestAudioFrameDefaultDurationInMs
, 23);
789 EXPECT_LT(kTestVideoFrameDefaultDurationInMs
, 33);
791 const BlockInfo kBlockInfo
[] = {
792 {kAudioTrackNum
, 0, kTestAudioFrameDefaultDurationInMs
, true, NULL
, 0},
793 {kAudioTrackNum
, 23, kTestAudioFrameDefaultDurationInMs
, true, NULL
, 0},
794 {kVideoTrackNum
, 33, kTestVideoFrameDefaultDurationInMs
, true, NULL
, 0},
795 {kAudioTrackNum
, 46, kTestAudioFrameDefaultDurationInMs
, true, NULL
, 0},
796 {kVideoTrackNum
, 67, kTestVideoFrameDefaultDurationInMs
, true, NULL
, 0},
797 {kAudioTrackNum
, 69, kTestAudioFrameDefaultDurationInMs
, true, NULL
, 0},
798 {kVideoTrackNum
, 100, kTestVideoFrameDefaultDurationInMs
, true, NULL
, 0},
801 int block_count
= arraysize(kBlockInfo
);
802 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kBlockInfo
, block_count
));
804 // Send slightly less than the full cluster so all but the last block is
805 // parsed. Though all the blocks are simple blocks, none should be held aside
806 // for duration estimation prior to end of cluster detection because all the
807 // tracks have DefaultDurations.
808 int result
= parser_
->Parse(cluster
->data(), cluster
->size() - 1);
809 EXPECT_GT(result
, 0);
810 EXPECT_LT(result
, cluster
->size());
811 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
- 1));
815 // Now parse a whole cluster to verify that all the blocks will get parsed.
816 result
= parser_
->Parse(cluster
->data(), cluster
->size());
817 EXPECT_EQ(cluster
->size(), result
);
818 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
));
821 TEST_F(WebMClusterParserTest
, ParseWithoutAnyDurationsSimpleBlocks
) {
824 // Absent DefaultDuration information, SimpleBlock durations are derived from
825 // inter-buffer track timestamp delta if within the cluster. Duration for the
826 // last block in a cluster is estimated independently for each track in the
827 // cluster. For video tracks we use the maximum seen so far. For audio we use
829 // TODO(chcunningham): Move audio over to use the maximum.
831 const int kExpectedAudioEstimationInMs
= 22;
832 const int kExpectedVideoEstimationInMs
= 34;
833 const BlockInfo kBlockInfo1
[] = {
834 {kAudioTrackNum
, 0, 23, true, NULL
, 0},
835 {kAudioTrackNum
, 23, 22, true, NULL
, 0},
836 {kVideoTrackNum
, 33, 33, true, NULL
, 0},
837 {kAudioTrackNum
, 45, 23, true, NULL
, 0},
838 {kVideoTrackNum
, 66, 34, true, NULL
, 0},
839 {kAudioTrackNum
, 68, kExpectedAudioEstimationInMs
, true, NULL
, 0},
840 {kVideoTrackNum
, 100, kExpectedVideoEstimationInMs
, true, NULL
, 0},
843 int block_count1
= arraysize(kBlockInfo1
);
844 scoped_ptr
<Cluster
> cluster1(CreateCluster(0, kBlockInfo1
, block_count1
));
846 // Send slightly less than the first full cluster so all but the last video
847 // block is parsed. Verify the last fully parsed audio and video buffer are
848 // both missing from the result (parser should hold them aside for duration
849 // estimation prior to end of cluster detection in the absence of
850 // DefaultDurations.)
851 int result
= parser_
->Parse(cluster1
->data(), cluster1
->size() - 1);
852 EXPECT_GT(result
, 0);
853 EXPECT_LT(result
, cluster1
->size());
854 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo1
, block_count1
- 3));
855 EXPECT_EQ(3UL, parser_
->GetAudioBuffers().size());
856 EXPECT_EQ(1UL, parser_
->GetVideoBuffers().size());
860 // Now parse the full first cluster and verify all the blocks are parsed.
862 WebMSimpleBlockDurationEstimated(kExpectedAudioEstimationInMs
));
864 WebMSimpleBlockDurationEstimated(kExpectedVideoEstimationInMs
));
865 result
= parser_
->Parse(cluster1
->data(), cluster1
->size());
866 EXPECT_EQ(cluster1
->size(), result
);
867 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo1
, block_count1
));
869 // Verify that the estimated frame duration is tracked across clusters for
871 const BlockInfo kBlockInfo2
[] = {
872 // Estimate carries over across clusters
873 {kAudioTrackNum
, 200, kExpectedAudioEstimationInMs
, true, NULL
, 0},
874 // Estimate carries over across clusters
875 {kVideoTrackNum
, 201, kExpectedVideoEstimationInMs
, true, NULL
, 0},
878 int block_count2
= arraysize(kBlockInfo2
);
879 scoped_ptr
<Cluster
> cluster2(CreateCluster(0, kBlockInfo2
, block_count2
));
881 WebMSimpleBlockDurationEstimated(kExpectedAudioEstimationInMs
));
883 WebMSimpleBlockDurationEstimated(kExpectedVideoEstimationInMs
));
884 result
= parser_
->Parse(cluster2
->data(), cluster2
->size());
885 EXPECT_EQ(cluster2
->size(), result
);
886 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo2
, block_count2
));
889 TEST_F(WebMClusterParserTest
, ParseWithoutAnyDurationsBlockGroups
) {
892 // Absent DefaultDuration and BlockDuration information, BlockGroup block
893 // durations are derived from inter-buffer track timestamp delta if within the
894 // cluster. Duration for the last block in a cluster is estimated
895 // independently for each track in the cluster. For video tracks we use the
896 // maximum seen so far. For audio we use the the minimum.
897 // TODO(chcunningham): Move audio over to use the maximum.
899 const int kExpectedAudioEstimationInMs
= 22;
900 const int kExpectedVideoEstimationInMs
= 34;
901 const BlockInfo kBlockInfo1
[] = {
902 {kAudioTrackNum
, 0, -23, false, NULL
, 0},
903 {kAudioTrackNum
, 23, -22, false, NULL
, 0},
904 {kVideoTrackNum
, 33, -33, false, NULL
, 0},
905 {kAudioTrackNum
, 45, -23, false, NULL
, 0},
906 {kVideoTrackNum
, 66, -34, false, NULL
, 0},
907 {kAudioTrackNum
, 68, -kExpectedAudioEstimationInMs
, false, NULL
, 0},
908 {kVideoTrackNum
, 100, -kExpectedVideoEstimationInMs
, false, NULL
, 0},
911 int block_count1
= arraysize(kBlockInfo1
);
912 scoped_ptr
<Cluster
> cluster1(CreateCluster(0, kBlockInfo1
, block_count1
));
914 // Send slightly less than the first full cluster so all but the last video
915 // block is parsed. Verify the last fully parsed audio and video buffer are
916 // both missing from the result (parser should hold them aside for duration
917 // estimation prior to end of cluster detection in the absence of
918 // DefaultDurations.)
919 int result
= parser_
->Parse(cluster1
->data(), cluster1
->size() - 1);
920 EXPECT_GT(result
, 0);
921 EXPECT_LT(result
, cluster1
->size());
922 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo1
, block_count1
- 3));
923 EXPECT_EQ(3UL, parser_
->GetAudioBuffers().size());
924 EXPECT_EQ(1UL, parser_
->GetVideoBuffers().size());
928 // Now parse the full first cluster and verify all the blocks are parsed.
930 WebMSimpleBlockDurationEstimated(kExpectedAudioEstimationInMs
));
932 WebMSimpleBlockDurationEstimated(kExpectedVideoEstimationInMs
));
933 result
= parser_
->Parse(cluster1
->data(), cluster1
->size());
934 EXPECT_EQ(cluster1
->size(), result
);
935 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo1
, block_count1
));
937 // Verify that the estimated frame duration is tracked across clusters for
939 const BlockInfo kBlockInfo2
[] = {
940 {kAudioTrackNum
, 200, -kExpectedAudioEstimationInMs
, false, NULL
, 0},
941 {kVideoTrackNum
, 201, -kExpectedVideoEstimationInMs
, false, NULL
, 0},
944 int block_count2
= arraysize(kBlockInfo2
);
945 scoped_ptr
<Cluster
> cluster2(CreateCluster(0, kBlockInfo2
, block_count2
));
947 WebMSimpleBlockDurationEstimated(kExpectedAudioEstimationInMs
));
949 WebMSimpleBlockDurationEstimated(kExpectedVideoEstimationInMs
));
950 result
= parser_
->Parse(cluster2
->data(), cluster2
->size());
951 EXPECT_EQ(cluster2
->size(), result
);
952 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo2
, block_count2
));
955 // TODO(wolenetz): Is parser behavior correct? See http://crbug.com/363433.
956 TEST_F(WebMClusterParserTest
,
957 ParseWithDefaultDurationsBlockGroupsWithoutDurations
) {
959 ResetParserToHaveDefaultDurations();
961 EXPECT_LT(kTestAudioFrameDefaultDurationInMs
, 23);
962 EXPECT_LT(kTestVideoFrameDefaultDurationInMs
, 33);
964 const BlockInfo kBlockInfo
[] = {
965 {kAudioTrackNum
, 0, -kTestAudioFrameDefaultDurationInMs
, false, NULL
, 0},
966 {kAudioTrackNum
, 23, -kTestAudioFrameDefaultDurationInMs
, false, NULL
, 0},
967 {kVideoTrackNum
, 33, -kTestVideoFrameDefaultDurationInMs
, false, NULL
, 0},
968 {kAudioTrackNum
, 46, -kTestAudioFrameDefaultDurationInMs
, false, NULL
, 0},
969 {kVideoTrackNum
, 67, -kTestVideoFrameDefaultDurationInMs
, false, NULL
, 0},
970 {kAudioTrackNum
, 69, -kTestAudioFrameDefaultDurationInMs
, false, NULL
, 0},
973 -kTestVideoFrameDefaultDurationInMs
,
979 int block_count
= arraysize(kBlockInfo
);
980 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kBlockInfo
, block_count
));
982 // Send slightly less than the full cluster so all but the last block is
983 // parsed. None should be held aside for duration estimation prior to end of
984 // cluster detection because all the tracks have DefaultDurations.
985 int result
= parser_
->Parse(cluster
->data(), cluster
->size() - 1);
986 EXPECT_GT(result
, 0);
987 EXPECT_LT(result
, cluster
->size());
988 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
- 1));
992 // Now parse a whole cluster to verify that all the blocks will get parsed.
993 result
= parser_
->Parse(cluster
->data(), cluster
->size());
994 EXPECT_EQ(cluster
->size(), result
);
995 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
));
998 TEST_F(WebMClusterParserTest
,
999 ParseDegenerateClusterYieldsHardcodedEstimatedDurations
) {
1000 const BlockInfo kBlockInfo
[] = {
1004 WebMClusterParser::kDefaultAudioBufferDurationInMs
,
1009 WebMClusterParser::kDefaultVideoBufferDurationInMs
,
1014 int block_count
= arraysize(kBlockInfo
);
1015 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kBlockInfo
, block_count
));
1016 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(
1017 WebMClusterParser::kDefaultAudioBufferDurationInMs
));
1018 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(
1019 WebMClusterParser::kDefaultVideoBufferDurationInMs
));
1020 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
1021 EXPECT_EQ(cluster
->size(), result
);
1022 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
));
1025 TEST_F(WebMClusterParserTest
,
1026 ParseDegenerateClusterWithDefaultDurationsYieldsDefaultDurations
) {
1027 ResetParserToHaveDefaultDurations();
1029 const BlockInfo kBlockInfo
[] = {
1030 { kAudioTrackNum
, 0, kTestAudioFrameDefaultDurationInMs
, true },
1031 { kVideoTrackNum
, 0, kTestVideoFrameDefaultDurationInMs
, true },
1034 int block_count
= arraysize(kBlockInfo
);
1035 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kBlockInfo
, block_count
));
1036 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
1037 EXPECT_EQ(cluster
->size(), result
);
1038 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
));
1041 TEST_F(WebMClusterParserTest
, ReadOpusDurationsSimpleBlockAtEndOfCluster
) {
1043 for (const auto* packet_ptr
: BuildAllOpusPackets()) {
1046 // Get a new parser each iteration to prevent exceeding the media log cap.
1047 parser_
.reset(CreateParserWithKeyIdsAndAudioCodec(
1048 std::string(), std::string(), kCodecOpus
));
1050 const BlockInfo kBlockInfo
[] = {{kAudioTrackNum
,
1052 packet_ptr
->duration_ms(),
1053 true, // Make it a SimpleBlock.
1055 packet_ptr
->size()}};
1057 int block_count
= arraysize(kBlockInfo
);
1058 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kBlockInfo
, block_count
));
1059 int duration_ms
= packet_ptr
->duration_ms(); // Casts from double.
1060 if (duration_ms
> 120) {
1061 EXPECT_MEDIA_LOG(OpusPacketDurationTooHigh(duration_ms
));
1064 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
1065 EXPECT_EQ(cluster
->size(), result
);
1066 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
));
1068 // Fail early if any iteration fails to meet the logging expectations.
1069 ASSERT_TRUE(Mock::VerifyAndClearExpectations(media_log_
.get()));
1074 // Test should minimally cover all the combinations of config and frame count.
1075 ASSERT_GE(loop_count
, kNumPossibleOpusConfigs
* kMaxOpusPacketFrameCount
);
1078 TEST_F(WebMClusterParserTest
, PreferOpusDurationsOverBlockDurations
) {
1080 for (const auto* packet_ptr
: BuildAllOpusPackets()) {
1083 // Get a new parser each iteration to prevent exceeding the media log cap.
1084 parser_
.reset(CreateParserWithKeyIdsAndAudioCodec(
1085 std::string(), std::string(), kCodecOpus
));
1087 // Setting BlockDuration != Opus duration to see which one the parser uses.
1088 int block_duration_ms
= packet_ptr
->duration_ms() + 10;
1089 if (packet_ptr
->duration_ms() > 120) {
1090 EXPECT_MEDIA_LOG(OpusPacketDurationTooHigh(packet_ptr
->duration_ms()));
1093 EXPECT_MEDIA_LOG(WebMBlockDurationMismatchesOpusDuration(
1094 block_duration_ms
, packet_ptr
->duration_ms()));
1096 BlockInfo block_infos
[] = {{kAudioTrackNum
,
1099 false, // Not a SimpleBlock.
1101 packet_ptr
->size()}};
1103 int block_count
= arraysize(block_infos
);
1104 scoped_ptr
<Cluster
> cluster(CreateCluster(0, block_infos
, block_count
));
1105 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
1106 EXPECT_EQ(cluster
->size(), result
);
1108 // BlockInfo duration will be used to verify buffer duration, so changing
1109 // duration to be that of the Opus packet to verify it was preferred.
1110 block_infos
[0].duration
= packet_ptr
->duration_ms();
1112 ASSERT_TRUE(VerifyBuffers(parser_
, block_infos
, block_count
));
1114 // Fail early if any iteration fails to meet the logging expectations.
1115 ASSERT_TRUE(Mock::VerifyAndClearExpectations(media_log_
.get()));
1120 // Test should minimally cover all the combinations of config and frame count.
1121 ASSERT_GE(loop_count
, kNumPossibleOpusConfigs
* kMaxOpusPacketFrameCount
);
1124 // Tests that BlockDuration is used to set duration on buffer rather than
1125 // encoded duration in Opus packet (or hard coded duration estimates). Encoded
1126 // Opus duration is usually preferred but cannot be known when encrypted.
1127 TEST_F(WebMClusterParserTest
, DontReadEncodedDurationWhenEncrypted
) {
1128 // Non-empty dummy value signals encryption is active for audio.
1129 std::string
audio_encryption_id("audio_key_id");
1131 // Reset parser to expect Opus codec audio and use audio encryption key id.
1132 parser_
.reset(CreateParserWithKeyIdsAndAudioCodec(audio_encryption_id
,
1133 std::string(), kCodecOpus
));
1135 // Single Block with BlockDuration and encrypted data.
1136 const BlockInfo kBlockInfo
[] = {{kAudioTrackNum
,
1138 kTestAudioFrameDefaultDurationInMs
,
1139 false, // Not a SimpleBlock
1140 kEncryptedFrame
, // Encrypted frame data
1141 arraysize(kEncryptedFrame
)}};
1143 int block_count
= arraysize(kBlockInfo
);
1144 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kBlockInfo
, block_count
));
1145 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
1146 EXPECT_EQ(cluster
->size(), result
);
1148 // Will verify that duration of buffer matches that of BlockDuration.
1149 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
));
1152 } // namespace media