Update V8 to version 4.7.56.
[chromium-blink-merge.git] / media / formats / webm / webm_cluster_parser_unittest.cc
blob7581bbf86659f8022f93aa78d85d0714685cf784
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.
5 #include <algorithm>
6 #include <cstdlib>
7 #include <string>
8 #include <vector>
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;
29 using ::testing::_;
31 namespace media {
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,
53 block_duration_ms,
54 opus_duration_ms,
55 "") {
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).");
62 namespace {
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.
75 static_assert(
76 static_cast<int>(kTestAudioFrameDefaultDurationInMs) !=
77 static_cast<int>(WebMClusterParser::kDefaultAudioBufferDurationInMs),
78 "test default is the same as estimation fallback audio duration");
79 static_assert(
80 static_cast<int>(kTestVideoFrameDefaultDurationInMs) !=
81 static_cast<int>(WebMClusterParser::kDefaultVideoBufferDurationInMs),
82 "test default is the same as estimation fallback video duration");
84 struct BlockInfo {
85 int track_num;
86 int timestamp;
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.
93 double duration;
95 bool use_simple_block;
97 // Default data will be used if no data given.
98 const uint8_t* data;
99 int data_length;
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
115 0x01,
117 // IV
118 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
120 scoped_ptr<Cluster> CreateCluster(int timecode,
121 const BlockInfo* block_info,
122 int block_count) {
123 ClusterBuilder cb;
124 cb.SetClusterTimecode(0);
126 uint8_t kDefaultBlockData[] = { 0x00 };
128 for (int i = 0; i < block_count; i++) {
129 const uint8_t* data;
130 int data_length;
131 if (block_info[i].data != NULL) {
132 data = block_info[i].data;
133 data_length = block_info[i].data_length;
134 } else {
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,
142 data, data_length);
143 continue;
146 if (block_info[i].duration < 0) {
147 cb.AddBlockGroupWithoutBlockDuration(block_info[i].track_num,
148 block_info[i].timestamp, 0, data,
149 data_length);
150 continue;
153 cb.AddBlockGroup(block_info[i].track_num, block_info[i].timestamp,
154 block_info[i].duration, 0, data, data_length);
157 return cb.Finish();
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)));
166 ClusterBuilder cb;
167 cb.SetClusterTimecode(0);
168 cb.AddSimpleBlock(kVideoTrackNum, 0, 0, kEncryptedFrame, bytes_to_write);
169 return cb.Finish();
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,
176 int block_count) {
177 int buffer_count = audio_buffers.size() + video_buffers.size() +
178 text_buffers.size();
179 if (block_count != buffer_count) {
180 DVLOG(1) << __FUNCTION__ << " : block_count (" << block_count
181 << ") mismatches buffer_count (" << buffer_count << ")";
182 return false;
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;
190 size_t* offset;
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;
205 } else {
206 LOG(ERROR) << "Unexpected track number " << block_info[i].track_num;
207 return false;
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";
214 return false;
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());
226 return true;
229 bool VerifyBuffers(const scoped_ptr<WebMClusterParser>& parser,
230 const BlockInfo* block_info,
231 int block_count) {
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);
238 else
239 text_buffers = &no_text_buffers;
241 return VerifyBuffers(parser->GetAudioBuffers(),
242 parser->GetVideoBuffers(),
243 *text_buffers,
244 block_info,
245 block_count);
248 bool VerifyTextBuffers(const scoped_ptr<WebMClusterParser>& parser,
249 const BlockInfo* block_info_ptr,
250 int block_count,
251 int text_track_num,
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)
263 continue;
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);
277 return true;
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);
294 } // namespace
296 class WebMClusterParserTest : public testing::Test {
297 public:
298 WebMClusterParserTest()
299 : media_log_(new StrictMock<MockMediaLog>()),
300 parser_(CreateDefaultParser()) {}
302 protected:
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,
330 media_log_);
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(),
337 kUnknownAudioCodec);
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(),
356 kUnknownAudioCodec);
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_;
372 private:
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.
381 InSequence s;
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, "", "",
388 "")));
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) {
431 if (i > 0)
432 parser_->Reset();
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,
439 blocks_in_cluster));
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) {
444 EXPECT_MEDIA_LOG(
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);
454 } else {
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) {
467 InSequence s;
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
473 // parsed.
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));
479 parser_->Reset();
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);
509 while (size > 0) {
510 int result = parser_->Parse(data, parse_size);
511 ASSERT_GE(result, 0);
512 ASSERT_LE(result, parse_size);
514 if (result == 0) {
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);
518 continue;
521 AppendToEnd(parser_->GetAudioBuffers(), &audio_buffers);
522 AppendToEnd(parser_->GetVideoBuffers(), &video_buffers);
524 parse_size = default_parse_size;
526 data += result;
527 size -= result;
529 ASSERT_TRUE(VerifyBuffers(audio_buffers, video_buffers,
530 no_text_buffers, kDefaultBlockInfo,
531 block_count));
534 // Verify that both BlockGroups with the BlockDuration before the Block
535 // and BlockGroups with the BlockDuration after the Block are supported
536 // correctly.
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, "", "",
621 "")));
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, "", "",
652 "")));
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, "", "",
677 "")));
679 text_tracks.insert(std::make_pair(TextTracks::key_type(kCaptionTextTrackNum),
680 TextTrackConfig(kTextCaptions, "", "",
681 "")));
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 =
709 text_map.begin();
710 itr != text_map.end();
711 ++itr) {
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, "", "",
770 "")));
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) {
785 InSequence s;
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));
813 parser_->Reset();
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) {
822 InSequence s;
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
828 // the the minimum.
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());
858 parser_->Reset();
860 // Now parse the full first cluster and verify all the blocks are parsed.
861 EXPECT_MEDIA_LOG(
862 WebMSimpleBlockDurationEstimated(kExpectedAudioEstimationInMs));
863 EXPECT_MEDIA_LOG(
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
870 // each track.
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));
880 EXPECT_MEDIA_LOG(
881 WebMSimpleBlockDurationEstimated(kExpectedAudioEstimationInMs));
882 EXPECT_MEDIA_LOG(
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) {
890 InSequence s;
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());
926 parser_->Reset();
928 // Now parse the full first cluster and verify all the blocks are parsed.
929 EXPECT_MEDIA_LOG(
930 WebMSimpleBlockDurationEstimated(kExpectedAudioEstimationInMs));
931 EXPECT_MEDIA_LOG(
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
938 // each track.
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));
946 EXPECT_MEDIA_LOG(
947 WebMSimpleBlockDurationEstimated(kExpectedAudioEstimationInMs));
948 EXPECT_MEDIA_LOG(
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) {
958 InSequence s;
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},
971 {kVideoTrackNum,
972 100,
973 -kTestVideoFrameDefaultDurationInMs,
974 false,
975 NULL,
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));
990 parser_->Reset();
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[] = {
1002 kAudioTrackNum,
1004 WebMClusterParser::kDefaultAudioBufferDurationInMs,
1005 true
1006 }, {
1007 kVideoTrackNum,
1009 WebMClusterParser::kDefaultVideoBufferDurationInMs,
1010 true
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) {
1042 int loop_count = 0;
1043 for (const auto* packet_ptr : BuildAllOpusPackets()) {
1044 InSequence s;
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.
1054 packet_ptr->data(),
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()));
1071 loop_count++;
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) {
1079 int loop_count = 0;
1080 for (const auto* packet_ptr : BuildAllOpusPackets()) {
1081 InSequence s;
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,
1098 block_duration_ms,
1099 false, // Not a SimpleBlock.
1100 packet_ptr->data(),
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()));
1117 loop_count++;
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