Roll ANGLE e754fb8..6ffeb74
[chromium-blink-merge.git] / media / formats / webm / webm_cluster_parser_unittest.cc
blob4020df458bd2044ef2cea50731281ac3ed8b66e4
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 <vector>
9 #include "base/bind.h"
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;
22 using ::testing::_;
24 namespace media {
26 typedef WebMTracksParser::TextTracks TextTracks;
28 enum {
29 kTimecodeScale = 1000000, // Timecode scale for millisecond timestamps.
30 kAudioTrackNum = 1,
31 kVideoTrackNum = 2,
32 kTextTrackNum = 3,
33 kTestAudioFrameDefaultDurationInMs = 13,
34 kTestVideoFrameDefaultDurationInMs = 17
37 // Test duration defaults must differ from parser estimation defaults to know
38 // which durations parser used when emitting buffers.
39 static_assert(
40 static_cast<int>(kTestAudioFrameDefaultDurationInMs) !=
41 static_cast<int>(WebMClusterParser::kDefaultAudioBufferDurationInMs),
42 "test default is the same as estimation fallback audio duration");
43 static_assert(
44 static_cast<int>(kTestVideoFrameDefaultDurationInMs) !=
45 static_cast<int>(WebMClusterParser::kDefaultVideoBufferDurationInMs),
46 "test default is the same as estimation fallback video duration");
48 struct BlockInfo {
49 int track_num;
50 int timestamp;
52 // Negative value is allowed only for block groups (not simple blocks) and
53 // directs CreateCluster() to exclude BlockDuration entry from the cluster for
54 // this BlockGroup. The absolute value is used for parser verification.
55 // For simple blocks, this value must be non-negative, and is used only for
56 // parser verification.
57 double duration;
59 bool use_simple_block;
61 // Default data will be used if no data given.
62 const uint8_t* data;
63 int data_length;
66 static const BlockInfo kDefaultBlockInfo[] = {
67 {kAudioTrackNum, 0, 23, true, NULL, 0},
68 {kAudioTrackNum, 23, 23, true, NULL, 0},
69 // Assumes not using DefaultDuration
70 {kVideoTrackNum, 33, 34, true, NULL, 0},
71 {kAudioTrackNum, 46, 23, true, NULL, 0},
72 {kVideoTrackNum, 67, 33, false, NULL, 0},
73 {kAudioTrackNum, 69, 23, false, NULL, 0},
74 {kVideoTrackNum, 100, 33, false, NULL, 0},
77 static const uint8_t kEncryptedFrame[] = {
78 0x01, // Block is encrypted
79 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 // IV
82 static scoped_ptr<Cluster> CreateCluster(int timecode,
83 const BlockInfo* block_info,
84 int block_count) {
85 ClusterBuilder cb;
86 cb.SetClusterTimecode(0);
88 uint8_t kDefaultBlockData[] = { 0x00 };
90 for (int i = 0; i < block_count; i++) {
91 const uint8_t* data;
92 int data_length;
93 if (block_info[i].data != NULL) {
94 data = block_info[i].data;
95 data_length = block_info[i].data_length;
96 } else {
97 data = kDefaultBlockData;
98 data_length = sizeof(kDefaultBlockData);
101 if (block_info[i].use_simple_block) {
102 CHECK_GE(block_info[i].duration, 0);
103 cb.AddSimpleBlock(block_info[i].track_num, block_info[i].timestamp, 0,
104 data, data_length);
105 continue;
108 if (block_info[i].duration < 0) {
109 cb.AddBlockGroupWithoutBlockDuration(block_info[i].track_num,
110 block_info[i].timestamp, 0, data,
111 data_length);
112 continue;
115 cb.AddBlockGroup(block_info[i].track_num, block_info[i].timestamp,
116 block_info[i].duration, 0, data, data_length);
119 return cb.Finish();
122 // Creates a Cluster with one encrypted Block. |bytes_to_write| is number of
123 // bytes of the encrypted frame to write.
124 static scoped_ptr<Cluster> CreateEncryptedCluster(int bytes_to_write) {
125 CHECK_GT(bytes_to_write, 0);
126 CHECK_LE(bytes_to_write, static_cast<int>(sizeof(kEncryptedFrame)));
128 ClusterBuilder cb;
129 cb.SetClusterTimecode(0);
130 cb.AddSimpleBlock(kVideoTrackNum, 0, 0, kEncryptedFrame, bytes_to_write);
131 return cb.Finish();
134 static bool VerifyBuffers(const WebMClusterParser::BufferQueue& audio_buffers,
135 const WebMClusterParser::BufferQueue& video_buffers,
136 const WebMClusterParser::BufferQueue& text_buffers,
137 const BlockInfo* block_info,
138 int block_count) {
139 int buffer_count = audio_buffers.size() + video_buffers.size() +
140 text_buffers.size();
141 if (block_count != buffer_count) {
142 DVLOG(1) << __FUNCTION__ << " : block_count (" << block_count
143 << ") mismatches buffer_count (" << buffer_count << ")";
144 return false;
147 size_t audio_offset = 0;
148 size_t video_offset = 0;
149 size_t text_offset = 0;
150 for (int i = 0; i < block_count; i++) {
151 const WebMClusterParser::BufferQueue* buffers = NULL;
152 size_t* offset;
153 StreamParserBuffer::Type expected_type = DemuxerStream::UNKNOWN;
155 if (block_info[i].track_num == kAudioTrackNum) {
156 buffers = &audio_buffers;
157 offset = &audio_offset;
158 expected_type = DemuxerStream::AUDIO;
159 } else if (block_info[i].track_num == kVideoTrackNum) {
160 buffers = &video_buffers;
161 offset = &video_offset;
162 expected_type = DemuxerStream::VIDEO;
163 } else if (block_info[i].track_num == kTextTrackNum) {
164 buffers = &text_buffers;
165 offset = &text_offset;
166 expected_type = DemuxerStream::TEXT;
167 } else {
168 LOG(ERROR) << "Unexpected track number " << block_info[i].track_num;
169 return false;
172 if (*offset >= buffers->size()) {
173 DVLOG(1) << __FUNCTION__ << " : Too few buffers (" << buffers->size()
174 << ") for track_num (" << block_info[i].track_num
175 << "), expected at least " << *offset + 1 << " buffers";
176 return false;
179 scoped_refptr<StreamParserBuffer> buffer = (*buffers)[(*offset)++];
181 EXPECT_EQ(block_info[i].timestamp, buffer->timestamp().InMilliseconds());
182 EXPECT_EQ(std::abs(block_info[i].duration),
183 buffer->duration().InMillisecondsF());
184 EXPECT_EQ(expected_type, buffer->type());
185 EXPECT_EQ(block_info[i].track_num, buffer->track_id());
188 return true;
191 static bool VerifyBuffers(const scoped_ptr<WebMClusterParser>& parser,
192 const BlockInfo* block_info,
193 int block_count) {
194 const WebMClusterParser::TextBufferQueueMap& text_map =
195 parser->GetTextBuffers();
196 const WebMClusterParser::BufferQueue* text_buffers;
197 const WebMClusterParser::BufferQueue no_text_buffers;
198 if (!text_map.empty())
199 text_buffers = &(text_map.rbegin()->second);
200 else
201 text_buffers = &no_text_buffers;
203 return VerifyBuffers(parser->GetAudioBuffers(),
204 parser->GetVideoBuffers(),
205 *text_buffers,
206 block_info,
207 block_count);
210 static bool VerifyTextBuffers(
211 const scoped_ptr<WebMClusterParser>& parser,
212 const BlockInfo* block_info_ptr,
213 int block_count,
214 int text_track_num,
215 const WebMClusterParser::BufferQueue& text_buffers) {
216 const BlockInfo* const block_info_end = block_info_ptr + block_count;
218 typedef WebMClusterParser::BufferQueue::const_iterator TextBufferIter;
219 TextBufferIter buffer_iter = text_buffers.begin();
220 const TextBufferIter buffer_end = text_buffers.end();
222 while (block_info_ptr != block_info_end) {
223 const BlockInfo& block_info = *block_info_ptr++;
225 if (block_info.track_num != text_track_num)
226 continue;
228 EXPECT_FALSE(block_info.use_simple_block);
229 EXPECT_FALSE(buffer_iter == buffer_end);
231 const scoped_refptr<StreamParserBuffer> buffer = *buffer_iter++;
232 EXPECT_EQ(block_info.timestamp, buffer->timestamp().InMilliseconds());
233 EXPECT_EQ(std::abs(block_info.duration),
234 buffer->duration().InMillisecondsF());
235 EXPECT_EQ(DemuxerStream::TEXT, buffer->type());
236 EXPECT_EQ(text_track_num, buffer->track_id());
239 EXPECT_TRUE(buffer_iter == buffer_end);
240 return true;
243 static void VerifyEncryptedBuffer(
244 scoped_refptr<StreamParserBuffer> buffer) {
245 EXPECT_TRUE(buffer->decrypt_config());
246 EXPECT_EQ(static_cast<unsigned long>(DecryptConfig::kDecryptionKeySize),
247 buffer->decrypt_config()->iv().length());
250 static void AppendToEnd(const WebMClusterParser::BufferQueue& src,
251 WebMClusterParser::BufferQueue* dest) {
252 for (WebMClusterParser::BufferQueue::const_iterator itr = src.begin();
253 itr != src.end(); ++itr) {
254 dest->push_back(*itr);
258 class WebMClusterParserTest : public testing::Test {
259 public:
260 WebMClusterParserTest()
261 : parser_(new WebMClusterParser(kTimecodeScale,
262 kAudioTrackNum,
263 kNoTimestamp(),
264 kVideoTrackNum,
265 kNoTimestamp(),
266 TextTracks(),
267 std::set<int64>(),
268 std::string(),
269 std::string(),
270 kUnknownAudioCodec,
271 LogCB())) {}
273 protected:
274 void ResetParserToHaveDefaultDurations() {
275 base::TimeDelta default_audio_duration = base::TimeDelta::FromMilliseconds(
276 kTestAudioFrameDefaultDurationInMs);
277 base::TimeDelta default_video_duration = base::TimeDelta::FromMilliseconds(
278 kTestVideoFrameDefaultDurationInMs);
279 ASSERT_GE(default_audio_duration, base::TimeDelta());
280 ASSERT_GE(default_video_duration, base::TimeDelta());
281 ASSERT_NE(kNoTimestamp(), default_audio_duration);
282 ASSERT_NE(kNoTimestamp(), default_video_duration);
284 parser_.reset(new WebMClusterParser(kTimecodeScale,
285 kAudioTrackNum,
286 default_audio_duration,
287 kVideoTrackNum,
288 default_video_duration,
289 TextTracks(),
290 std::set<int64>(),
291 std::string(),
292 std::string(),
293 kUnknownAudioCodec,
294 LogCB()));
297 scoped_ptr<WebMClusterParser> parser_;
299 private:
300 DISALLOW_COPY_AND_ASSIGN(WebMClusterParserTest);
303 TEST_F(WebMClusterParserTest, HeldBackBufferHoldsBackAllTracks) {
304 // If a buffer is missing duration and is being held back, then all other
305 // tracks' buffers that have same or higher (decode) timestamp should be held
306 // back too to keep the timestamps emitted for a cluster monotonically
307 // non-decreasing and in same order as parsed.
308 InSequence s;
310 // Reset the parser to have 3 tracks: text, video (no default frame duration),
311 // and audio (with a default frame duration).
312 TextTracks text_tracks;
313 text_tracks.insert(std::make_pair(TextTracks::key_type(kTextTrackNum),
314 TextTrackConfig(kTextSubtitles, "", "",
315 "")));
316 base::TimeDelta default_audio_duration =
317 base::TimeDelta::FromMilliseconds(kTestAudioFrameDefaultDurationInMs);
318 ASSERT_GE(default_audio_duration, base::TimeDelta());
319 ASSERT_NE(kNoTimestamp(), default_audio_duration);
320 parser_.reset(new WebMClusterParser(kTimecodeScale,
321 kAudioTrackNum,
322 default_audio_duration,
323 kVideoTrackNum,
324 kNoTimestamp(),
325 text_tracks,
326 std::set<int64>(),
327 std::string(),
328 std::string(),
329 kUnknownAudioCodec,
330 LogCB()));
332 const BlockInfo kBlockInfo[] = {
333 {kVideoTrackNum, 0, 33, true, NULL, 0},
334 {kAudioTrackNum, 0, 23, false, NULL, 0},
335 {kTextTrackNum, 10, 42, false, NULL, 0},
336 {kAudioTrackNum, 23, kTestAudioFrameDefaultDurationInMs, true, NULL, 0},
337 {kVideoTrackNum, 33, 33, true, NULL, 0},
338 {kAudioTrackNum, 36, kTestAudioFrameDefaultDurationInMs, true, NULL, 0},
339 {kVideoTrackNum, 66, 33, true, NULL, 0},
340 {kAudioTrackNum, 70, kTestAudioFrameDefaultDurationInMs, true, NULL, 0},
341 {kAudioTrackNum, 83, kTestAudioFrameDefaultDurationInMs, true, NULL, 0},
344 const int kExpectedBuffersOnPartialCluster[] = {
345 0, // Video simple block without DefaultDuration should be held back
346 0, // Audio buffer ready, but not emitted because its TS >= held back video
347 0, // Text buffer ready, but not emitted because its TS >= held back video
348 0, // 2nd audio buffer ready, also not emitted for same reason as first
349 4, // All previous buffers emitted, 2nd video held back with no duration
350 4, // 2nd video still has no duration, 3rd audio ready but not emitted
351 6, // All previous buffers emitted, 3rd video held back with no duration
352 6, // 3rd video still has no duration, 4th audio ready but not emitted
353 9, // Cluster end emits all buffers and 3rd video's duration is estimated
356 ASSERT_EQ(arraysize(kBlockInfo), arraysize(kExpectedBuffersOnPartialCluster));
357 int block_count = arraysize(kBlockInfo);
359 // Iteratively create a cluster containing the first N+1 blocks and parse all
360 // but the last byte of the cluster (except when N==|block_count|, just parse
361 // the whole cluster). Verify that the corresponding entry in
362 // |kExpectedBuffersOnPartialCluster| identifies the exact subset of
363 // |kBlockInfo| returned by the parser.
364 for (int i = 0; i < block_count; ++i) {
365 if (i > 0)
366 parser_->Reset();
367 // Since we don't know exactly the offsets of each block in the full
368 // cluster, build a cluster with exactly one additional block so that
369 // parse of all but one byte should deterministically parse all but the
370 // last full block. Don't |exceed block_count| blocks though.
371 int blocks_in_cluster = std::min(i + 2, block_count);
372 scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo,
373 blocks_in_cluster));
374 // Parse all but the last byte unless we need to parse the full cluster.
375 bool parse_full_cluster = i == (block_count - 1);
376 int result = parser_->Parse(cluster->data(), parse_full_cluster ?
377 cluster->size() : cluster->size() - 1);
378 if (parse_full_cluster) {
379 DVLOG(1) << "Verifying parse result of full cluster of "
380 << blocks_in_cluster << " blocks";
381 EXPECT_EQ(cluster->size(), result);
382 } else {
383 DVLOG(1) << "Verifying parse result of cluster of "
384 << blocks_in_cluster << " blocks with last block incomplete";
385 EXPECT_GT(cluster->size(), result);
386 EXPECT_LT(0, result);
389 EXPECT_TRUE(VerifyBuffers(parser_, kBlockInfo,
390 kExpectedBuffersOnPartialCluster[i]));
394 TEST_F(WebMClusterParserTest, Reset) {
395 InSequence s;
397 int block_count = arraysize(kDefaultBlockInfo);
398 scoped_ptr<Cluster> cluster(CreateCluster(0, kDefaultBlockInfo, block_count));
400 // Send slightly less than the full cluster so all but the last block is
401 // parsed.
402 int result = parser_->Parse(cluster->data(), cluster->size() - 1);
403 EXPECT_GT(result, 0);
404 EXPECT_LT(result, cluster->size());
406 ASSERT_TRUE(VerifyBuffers(parser_, kDefaultBlockInfo, block_count - 1));
407 parser_->Reset();
409 // Now parse a whole cluster to verify that all the blocks will get parsed.
410 result = parser_->Parse(cluster->data(), cluster->size());
411 EXPECT_EQ(cluster->size(), result);
412 ASSERT_TRUE(VerifyBuffers(parser_, kDefaultBlockInfo, block_count));
415 TEST_F(WebMClusterParserTest, ParseClusterWithSingleCall) {
416 int block_count = arraysize(kDefaultBlockInfo);
417 scoped_ptr<Cluster> cluster(CreateCluster(0, kDefaultBlockInfo, block_count));
419 int result = parser_->Parse(cluster->data(), cluster->size());
420 EXPECT_EQ(cluster->size(), result);
421 ASSERT_TRUE(VerifyBuffers(parser_, kDefaultBlockInfo, block_count));
424 TEST_F(WebMClusterParserTest, ParseClusterWithMultipleCalls) {
425 int block_count = arraysize(kDefaultBlockInfo);
426 scoped_ptr<Cluster> cluster(CreateCluster(0, kDefaultBlockInfo, block_count));
428 WebMClusterParser::BufferQueue audio_buffers;
429 WebMClusterParser::BufferQueue video_buffers;
430 const WebMClusterParser::BufferQueue no_text_buffers;
432 const uint8_t* data = cluster->data();
433 int size = cluster->size();
434 int default_parse_size = 3;
435 int parse_size = std::min(default_parse_size, size);
437 while (size > 0) {
438 int result = parser_->Parse(data, parse_size);
439 ASSERT_GE(result, 0);
440 ASSERT_LE(result, parse_size);
442 if (result == 0) {
443 // The parser needs more data so increase the parse_size a little.
444 parse_size += default_parse_size;
445 parse_size = std::min(parse_size, size);
446 continue;
449 AppendToEnd(parser_->GetAudioBuffers(), &audio_buffers);
450 AppendToEnd(parser_->GetVideoBuffers(), &video_buffers);
452 parse_size = default_parse_size;
454 data += result;
455 size -= result;
457 ASSERT_TRUE(VerifyBuffers(audio_buffers, video_buffers,
458 no_text_buffers, kDefaultBlockInfo,
459 block_count));
462 // Verify that both BlockGroups with the BlockDuration before the Block
463 // and BlockGroups with the BlockDuration after the Block are supported
464 // correctly.
465 // Note: Raw bytes are use here because ClusterBuilder only generates
466 // one of these scenarios.
467 TEST_F(WebMClusterParserTest, ParseBlockGroup) {
468 const BlockInfo kBlockInfo[] = {
469 {kAudioTrackNum, 0, 23, false, NULL, 0},
470 {kVideoTrackNum, 33, 34, false, NULL, 0},
472 int block_count = arraysize(kBlockInfo);
474 const uint8_t kClusterData[] = {
475 0x1F, 0x43, 0xB6, 0x75, 0x9B, // Cluster(size=27)
476 0xE7, 0x81, 0x00, // Timecode(size=1, value=0)
477 // BlockGroup with BlockDuration before Block.
478 0xA0, 0x8A, // BlockGroup(size=10)
479 0x9B, 0x81, 0x17, // BlockDuration(size=1, value=23)
480 0xA1, 0x85, 0x81, 0x00, 0x00, 0x00, 0xaa, // Block(size=5, track=1, ts=0)
481 // BlockGroup with BlockDuration after Block.
482 0xA0, 0x8A, // BlockGroup(size=10)
483 0xA1, 0x85, 0x82, 0x00, 0x21, 0x00, 0x55, // Block(size=5, track=2, ts=33)
484 0x9B, 0x81, 0x22, // BlockDuration(size=1, value=34)
486 const int kClusterSize = sizeof(kClusterData);
488 int result = parser_->Parse(kClusterData, kClusterSize);
489 EXPECT_EQ(kClusterSize, result);
490 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count));
493 TEST_F(WebMClusterParserTest, ParseSimpleBlockAndBlockGroupMixture) {
494 const BlockInfo kBlockInfo[] = {
495 {kAudioTrackNum, 0, 23, true, NULL, 0},
496 {kAudioTrackNum, 23, 23, false, NULL, 0},
497 {kVideoTrackNum, 33, 34, true, NULL, 0},
498 {kAudioTrackNum, 46, 23, false, NULL, 0},
499 {kVideoTrackNum, 67, 33, false, NULL, 0},
501 int block_count = arraysize(kBlockInfo);
502 scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count));
504 int result = parser_->Parse(cluster->data(), cluster->size());
505 EXPECT_EQ(cluster->size(), result);
506 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count));
509 TEST_F(WebMClusterParserTest, IgnoredTracks) {
510 std::set<int64> ignored_tracks;
511 ignored_tracks.insert(kTextTrackNum);
513 parser_.reset(new WebMClusterParser(kTimecodeScale,
514 kAudioTrackNum,
515 kNoTimestamp(),
516 kVideoTrackNum,
517 kNoTimestamp(),
518 TextTracks(),
519 ignored_tracks,
520 std::string(),
521 std::string(),
522 kUnknownAudioCodec,
523 LogCB()));
525 const BlockInfo kInputBlockInfo[] = {
526 {kAudioTrackNum, 0, 23, true, NULL, 0},
527 {kAudioTrackNum, 23, 23, true, NULL, 0},
528 {kVideoTrackNum, 33, 34, true, NULL, 0},
529 {kTextTrackNum, 33, 99, true, NULL, 0},
530 {kAudioTrackNum, 46, 23, true, NULL, 0},
531 {kVideoTrackNum, 67, 34, true, NULL, 0},
533 int input_block_count = arraysize(kInputBlockInfo);
535 const BlockInfo kOutputBlockInfo[] = {
536 {kAudioTrackNum, 0, 23, true, NULL, 0},
537 {kAudioTrackNum, 23, 23, true, NULL, 0},
538 {kVideoTrackNum, 33, 34, true, NULL, 0},
539 {kAudioTrackNum, 46, 23, true, NULL, 0},
540 {kVideoTrackNum, 67, 34, true, NULL, 0},
542 int output_block_count = arraysize(kOutputBlockInfo);
544 scoped_ptr<Cluster> cluster(
545 CreateCluster(0, kInputBlockInfo, input_block_count));
547 int result = parser_->Parse(cluster->data(), cluster->size());
548 EXPECT_EQ(cluster->size(), result);
549 ASSERT_TRUE(VerifyBuffers(parser_, kOutputBlockInfo, output_block_count));
552 TEST_F(WebMClusterParserTest, ParseTextTracks) {
553 TextTracks text_tracks;
555 text_tracks.insert(std::make_pair(TextTracks::key_type(kTextTrackNum),
556 TextTrackConfig(kTextSubtitles, "", "",
557 "")));
559 parser_.reset(new WebMClusterParser(kTimecodeScale,
560 kAudioTrackNum,
561 kNoTimestamp(),
562 kVideoTrackNum,
563 kNoTimestamp(),
564 text_tracks,
565 std::set<int64>(),
566 std::string(),
567 std::string(),
568 kUnknownAudioCodec,
569 LogCB()));
571 const BlockInfo kInputBlockInfo[] = {
572 {kAudioTrackNum, 0, 23, true, NULL, 0},
573 {kAudioTrackNum, 23, 23, true, NULL, 0},
574 {kVideoTrackNum, 33, 34, true, NULL, 0},
575 {kTextTrackNum, 33, 42, false, NULL, 0},
576 {kAudioTrackNum, 46, 23, true, NULL, 0},
577 {kTextTrackNum, 55, 44, false, NULL, 0},
578 {kVideoTrackNum, 67, 34, true, NULL, 0},
580 int input_block_count = arraysize(kInputBlockInfo);
582 scoped_ptr<Cluster> cluster(
583 CreateCluster(0, kInputBlockInfo, input_block_count));
585 int result = parser_->Parse(cluster->data(), cluster->size());
586 EXPECT_EQ(cluster->size(), result);
587 ASSERT_TRUE(VerifyBuffers(parser_, kInputBlockInfo, input_block_count));
590 TEST_F(WebMClusterParserTest, TextTracksSimpleBlock) {
591 TextTracks text_tracks;
593 text_tracks.insert(std::make_pair(TextTracks::key_type(kTextTrackNum),
594 TextTrackConfig(kTextSubtitles, "", "",
595 "")));
597 parser_.reset(new WebMClusterParser(kTimecodeScale,
598 kAudioTrackNum,
599 kNoTimestamp(),
600 kVideoTrackNum,
601 kNoTimestamp(),
602 text_tracks,
603 std::set<int64>(),
604 std::string(),
605 std::string(),
606 kUnknownAudioCodec,
607 LogCB()));
609 const BlockInfo kInputBlockInfo[] = {
610 { kTextTrackNum, 33, 42, true },
612 int input_block_count = arraysize(kInputBlockInfo);
614 scoped_ptr<Cluster> cluster(
615 CreateCluster(0, kInputBlockInfo, input_block_count));
617 int result = parser_->Parse(cluster->data(), cluster->size());
618 EXPECT_LT(result, 0);
621 TEST_F(WebMClusterParserTest, ParseMultipleTextTracks) {
622 TextTracks text_tracks;
624 const int kSubtitleTextTrackNum = kTextTrackNum;
625 const int kCaptionTextTrackNum = kTextTrackNum + 1;
627 text_tracks.insert(std::make_pair(TextTracks::key_type(kSubtitleTextTrackNum),
628 TextTrackConfig(kTextSubtitles, "", "",
629 "")));
631 text_tracks.insert(std::make_pair(TextTracks::key_type(kCaptionTextTrackNum),
632 TextTrackConfig(kTextCaptions, "", "",
633 "")));
635 parser_.reset(new WebMClusterParser(kTimecodeScale,
636 kAudioTrackNum,
637 kNoTimestamp(),
638 kVideoTrackNum,
639 kNoTimestamp(),
640 text_tracks,
641 std::set<int64>(),
642 std::string(),
643 std::string(),
644 kUnknownAudioCodec,
645 LogCB()));
647 const BlockInfo kInputBlockInfo[] = {
648 {kAudioTrackNum, 0, 23, true, NULL, 0},
649 {kAudioTrackNum, 23, 23, true, NULL, 0},
650 {kVideoTrackNum, 33, 34, true, NULL, 0},
651 {kSubtitleTextTrackNum, 33, 42, false, NULL, 0},
652 {kAudioTrackNum, 46, 23, true, NULL, 0},
653 {kCaptionTextTrackNum, 55, 44, false, NULL, 0},
654 {kVideoTrackNum, 67, 34, true, NULL, 0},
655 {kSubtitleTextTrackNum, 67, 33, false, NULL, 0},
657 int input_block_count = arraysize(kInputBlockInfo);
659 scoped_ptr<Cluster> cluster(
660 CreateCluster(0, kInputBlockInfo, input_block_count));
662 int result = parser_->Parse(cluster->data(), cluster->size());
663 EXPECT_EQ(cluster->size(), result);
665 const WebMClusterParser::TextBufferQueueMap& text_map =
666 parser_->GetTextBuffers();
667 for (WebMClusterParser::TextBufferQueueMap::const_iterator itr =
668 text_map.begin();
669 itr != text_map.end();
670 ++itr) {
671 const TextTracks::const_iterator find_result =
672 text_tracks.find(itr->first);
673 ASSERT_TRUE(find_result != text_tracks.end());
674 ASSERT_TRUE(VerifyTextBuffers(parser_, kInputBlockInfo, input_block_count,
675 itr->first, itr->second));
679 TEST_F(WebMClusterParserTest, ParseEncryptedBlock) {
680 scoped_ptr<Cluster> cluster(CreateEncryptedCluster(sizeof(kEncryptedFrame)));
682 parser_.reset(new WebMClusterParser(kTimecodeScale,
683 kAudioTrackNum,
684 kNoTimestamp(),
685 kVideoTrackNum,
686 kNoTimestamp(),
687 TextTracks(),
688 std::set<int64>(),
689 std::string(),
690 "video_key_id",
691 kUnknownAudioCodec,
692 LogCB()));
693 int result = parser_->Parse(cluster->data(), cluster->size());
694 EXPECT_EQ(cluster->size(), result);
695 ASSERT_EQ(1UL, parser_->GetVideoBuffers().size());
696 scoped_refptr<StreamParserBuffer> buffer = parser_->GetVideoBuffers()[0];
697 VerifyEncryptedBuffer(buffer);
700 TEST_F(WebMClusterParserTest, ParseBadEncryptedBlock) {
701 scoped_ptr<Cluster> cluster(
702 CreateEncryptedCluster(sizeof(kEncryptedFrame) - 1));
704 parser_.reset(new WebMClusterParser(kTimecodeScale,
705 kAudioTrackNum,
706 kNoTimestamp(),
707 kVideoTrackNum,
708 kNoTimestamp(),
709 TextTracks(),
710 std::set<int64>(),
711 std::string(),
712 "video_key_id",
713 kUnknownAudioCodec,
714 LogCB()));
715 int result = parser_->Parse(cluster->data(), cluster->size());
716 EXPECT_EQ(-1, result);
719 TEST_F(WebMClusterParserTest, ParseInvalidZeroSizedCluster) {
720 const uint8_t kBuffer[] = {
721 0x1F, 0x43, 0xB6, 0x75, 0x80, // CLUSTER (size = 0)
724 EXPECT_EQ(-1, parser_->Parse(kBuffer, sizeof(kBuffer)));
727 TEST_F(WebMClusterParserTest, ParseInvalidUnknownButActuallyZeroSizedCluster) {
728 const uint8_t kBuffer[] = {
729 0x1F, 0x43, 0xB6, 0x75, 0xFF, // CLUSTER (size = "unknown")
730 0x1F, 0x43, 0xB6, 0x75, 0x85, // CLUSTER (size = 5)
733 EXPECT_EQ(-1, parser_->Parse(kBuffer, sizeof(kBuffer)));
736 TEST_F(WebMClusterParserTest, ParseInvalidTextBlockGroupWithoutDuration) {
737 // Text track frames must have explicitly specified BlockGroup BlockDurations.
738 TextTracks text_tracks;
740 text_tracks.insert(std::make_pair(TextTracks::key_type(kTextTrackNum),
741 TextTrackConfig(kTextSubtitles, "", "",
742 "")));
744 parser_.reset(new WebMClusterParser(kTimecodeScale,
745 kAudioTrackNum,
746 kNoTimestamp(),
747 kVideoTrackNum,
748 kNoTimestamp(),
749 text_tracks,
750 std::set<int64>(),
751 std::string(),
752 std::string(),
753 kUnknownAudioCodec,
754 LogCB()));
756 const BlockInfo kBlockInfo[] = {
757 { kTextTrackNum, 33, -42, false },
759 int block_count = arraysize(kBlockInfo);
760 scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count));
761 int result = parser_->Parse(cluster->data(), cluster->size());
762 EXPECT_LT(result, 0);
765 TEST_F(WebMClusterParserTest, ParseWithDefaultDurationsSimpleBlocks) {
766 InSequence s;
767 ResetParserToHaveDefaultDurations();
769 EXPECT_LT(kTestAudioFrameDefaultDurationInMs, 23);
770 EXPECT_LT(kTestVideoFrameDefaultDurationInMs, 33);
772 const BlockInfo kBlockInfo[] = {
773 {kAudioTrackNum, 0, kTestAudioFrameDefaultDurationInMs, true, NULL, 0},
774 {kAudioTrackNum, 23, kTestAudioFrameDefaultDurationInMs, true, NULL, 0},
775 {kVideoTrackNum, 33, kTestVideoFrameDefaultDurationInMs, true, NULL, 0},
776 {kAudioTrackNum, 46, kTestAudioFrameDefaultDurationInMs, true, NULL, 0},
777 {kVideoTrackNum, 67, kTestVideoFrameDefaultDurationInMs, true, NULL, 0},
778 {kAudioTrackNum, 69, kTestAudioFrameDefaultDurationInMs, true, NULL, 0},
779 {kVideoTrackNum, 100, kTestVideoFrameDefaultDurationInMs, true, NULL, 0},
782 int block_count = arraysize(kBlockInfo);
783 scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count));
785 // Send slightly less than the full cluster so all but the last block is
786 // parsed. Though all the blocks are simple blocks, none should be held aside
787 // for duration estimation prior to end of cluster detection because all the
788 // tracks have DefaultDurations.
789 int result = parser_->Parse(cluster->data(), cluster->size() - 1);
790 EXPECT_GT(result, 0);
791 EXPECT_LT(result, cluster->size());
792 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count - 1));
794 parser_->Reset();
796 // Now parse a whole cluster to verify that all the blocks will get parsed.
797 result = parser_->Parse(cluster->data(), cluster->size());
798 EXPECT_EQ(cluster->size(), result);
799 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count));
802 TEST_F(WebMClusterParserTest, ParseWithoutAnyDurationsSimpleBlocks) {
803 InSequence s;
805 // Absent DefaultDuration information, SimpleBlock durations are derived from
806 // inter-buffer track timestamp delta if within the cluster. Duration for the
807 // last block in a cluster is estimated independently for each track in the
808 // cluster. For video tracks we use the maximum seen so far. For audio we use
809 // the the minimum.
810 // TODO(chcunningham): Move audio over to use the maximum.
811 const BlockInfo kBlockInfo1[] = {
812 {kAudioTrackNum, 0, 23, true, NULL, 0},
813 {kAudioTrackNum, 23, 22, true, NULL, 0},
814 {kVideoTrackNum, 33, 33, true, NULL, 0},
815 {kAudioTrackNum, 45, 23, true, NULL, 0},
816 {kVideoTrackNum, 66, 34, true, NULL, 0},
817 // Estimated from minimum audio dur
818 {kAudioTrackNum, 68, 22, true, NULL, 0},
819 // Estimated from maximum video dur
820 {kVideoTrackNum, 100, 34, true, NULL, 0},
823 int block_count1 = arraysize(kBlockInfo1);
824 scoped_ptr<Cluster> cluster1(CreateCluster(0, kBlockInfo1, block_count1));
826 // Send slightly less than the first full cluster so all but the last video
827 // block is parsed. Verify the last fully parsed audio and video buffer are
828 // both missing from the result (parser should hold them aside for duration
829 // estimation prior to end of cluster detection in the absence of
830 // DefaultDurations.)
831 int result = parser_->Parse(cluster1->data(), cluster1->size() - 1);
832 EXPECT_GT(result, 0);
833 EXPECT_LT(result, cluster1->size());
834 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo1, block_count1 - 3));
835 EXPECT_EQ(3UL, parser_->GetAudioBuffers().size());
836 EXPECT_EQ(1UL, parser_->GetVideoBuffers().size());
838 parser_->Reset();
840 // Now parse the full first cluster and verify all the blocks are parsed.
841 result = parser_->Parse(cluster1->data(), cluster1->size());
842 EXPECT_EQ(cluster1->size(), result);
843 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo1, block_count1));
845 // Verify that the estimated frame duration is tracked across clusters for
846 // each track.
847 const BlockInfo kBlockInfo2[] = {
848 // Estimate carries over across clusters
849 {kAudioTrackNum, 200, 22, true, NULL, 0},
850 // Estimate carries over across clusters
851 {kVideoTrackNum, 201, 34, true, NULL, 0},
854 int block_count2 = arraysize(kBlockInfo2);
855 scoped_ptr<Cluster> cluster2(CreateCluster(0, kBlockInfo2, block_count2));
856 result = parser_->Parse(cluster2->data(), cluster2->size());
857 EXPECT_EQ(cluster2->size(), result);
858 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo2, block_count2));
861 TEST_F(WebMClusterParserTest, ParseWithoutAnyDurationsBlockGroups) {
862 InSequence s;
864 // Absent DefaultDuration and BlockDuration information, BlockGroup block
865 // durations are derived from inter-buffer track timestamp delta if within the
866 // cluster. Duration for the last block in a cluster is estimated
867 // independently for each track in the cluster. For video tracks we use the
868 // maximum seen so far. For audio we use the the minimum.
869 // TODO(chcunningham): Move audio over to use the maximum.
870 const BlockInfo kBlockInfo1[] = {
871 {kAudioTrackNum, 0, -23, false, NULL, 0},
872 {kAudioTrackNum, 23, -22, false, NULL, 0},
873 {kVideoTrackNum, 33, -33, false, NULL, 0},
874 {kAudioTrackNum, 45, -23, false, NULL, 0},
875 {kVideoTrackNum, 66, -34, false, NULL, 0},
876 // Estimated from minimum audio dur
877 {kAudioTrackNum, 68, -22, false, NULL, 0},
878 // Estimated from maximum video dur
879 {kVideoTrackNum, 100, -34, false, NULL, 0},
882 int block_count1 = arraysize(kBlockInfo1);
883 scoped_ptr<Cluster> cluster1(CreateCluster(0, kBlockInfo1, block_count1));
885 // Send slightly less than the first full cluster so all but the last video
886 // block is parsed. Verify the last fully parsed audio and video buffer are
887 // both missing from the result (parser should hold them aside for duration
888 // estimation prior to end of cluster detection in the absence of
889 // DefaultDurations.)
890 int result = parser_->Parse(cluster1->data(), cluster1->size() - 1);
891 EXPECT_GT(result, 0);
892 EXPECT_LT(result, cluster1->size());
893 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo1, block_count1 - 3));
894 EXPECT_EQ(3UL, parser_->GetAudioBuffers().size());
895 EXPECT_EQ(1UL, parser_->GetVideoBuffers().size());
897 parser_->Reset();
899 // Now parse the full first cluster and verify all the blocks are parsed.
900 result = parser_->Parse(cluster1->data(), cluster1->size());
901 EXPECT_EQ(cluster1->size(), result);
902 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo1, block_count1));
904 // Verify that the estimated frame duration is tracked across clusters for
905 // each track.
906 const BlockInfo kBlockInfo2[] = {
907 {kAudioTrackNum, 200, -22, false, NULL, 0},
908 {kVideoTrackNum, 201, -34, false, NULL, 0},
911 int block_count2 = arraysize(kBlockInfo2);
912 scoped_ptr<Cluster> cluster2(CreateCluster(0, kBlockInfo2, block_count2));
913 result = parser_->Parse(cluster2->data(), cluster2->size());
914 EXPECT_EQ(cluster2->size(), result);
915 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo2, block_count2));
918 // TODO(wolenetz): Is parser behavior correct? See http://crbug.com/363433.
919 TEST_F(WebMClusterParserTest,
920 ParseWithDefaultDurationsBlockGroupsWithoutDurations) {
921 InSequence s;
922 ResetParserToHaveDefaultDurations();
924 EXPECT_LT(kTestAudioFrameDefaultDurationInMs, 23);
925 EXPECT_LT(kTestVideoFrameDefaultDurationInMs, 33);
927 const BlockInfo kBlockInfo[] = {
928 {kAudioTrackNum, 0, -kTestAudioFrameDefaultDurationInMs, false, NULL, 0},
929 {kAudioTrackNum, 23, -kTestAudioFrameDefaultDurationInMs, false, NULL, 0},
930 {kVideoTrackNum, 33, -kTestVideoFrameDefaultDurationInMs, false, NULL, 0},
931 {kAudioTrackNum, 46, -kTestAudioFrameDefaultDurationInMs, false, NULL, 0},
932 {kVideoTrackNum, 67, -kTestVideoFrameDefaultDurationInMs, false, NULL, 0},
933 {kAudioTrackNum, 69, -kTestAudioFrameDefaultDurationInMs, false, NULL, 0},
934 {kVideoTrackNum,
935 100,
936 -kTestVideoFrameDefaultDurationInMs,
937 false,
938 NULL,
942 int block_count = arraysize(kBlockInfo);
943 scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count));
945 // Send slightly less than the full cluster so all but the last block is
946 // parsed. None should be held aside for duration estimation prior to end of
947 // cluster detection because all the tracks have DefaultDurations.
948 int result = parser_->Parse(cluster->data(), cluster->size() - 1);
949 EXPECT_GT(result, 0);
950 EXPECT_LT(result, cluster->size());
951 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count - 1));
953 parser_->Reset();
955 // Now parse a whole cluster to verify that all the blocks will get parsed.
956 result = parser_->Parse(cluster->data(), cluster->size());
957 EXPECT_EQ(cluster->size(), result);
958 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count));
961 TEST_F(WebMClusterParserTest,
962 ParseDegenerateClusterYieldsHardcodedEstimatedDurations) {
963 const BlockInfo kBlockInfo[] = {
965 kAudioTrackNum,
967 WebMClusterParser::kDefaultAudioBufferDurationInMs,
968 true
969 }, {
970 kVideoTrackNum,
972 WebMClusterParser::kDefaultVideoBufferDurationInMs,
973 true
977 int block_count = arraysize(kBlockInfo);
978 scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count));
979 int result = parser_->Parse(cluster->data(), cluster->size());
980 EXPECT_EQ(cluster->size(), result);
981 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count));
984 TEST_F(WebMClusterParserTest,
985 ParseDegenerateClusterWithDefaultDurationsYieldsDefaultDurations) {
986 ResetParserToHaveDefaultDurations();
988 const BlockInfo kBlockInfo[] = {
989 { kAudioTrackNum, 0, kTestAudioFrameDefaultDurationInMs, true },
990 { kVideoTrackNum, 0, kTestVideoFrameDefaultDurationInMs, true },
993 int block_count = arraysize(kBlockInfo);
994 scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count));
995 int result = parser_->Parse(cluster->data(), cluster->size());
996 EXPECT_EQ(cluster->size(), result);
997 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count));
1000 TEST_F(WebMClusterParserTest, ReadOpusDurationsSimpleBlockAtEndOfCluster) {
1001 // Reset parser to expect Opus codec audio.
1002 parser_.reset(new WebMClusterParser(
1003 kTimecodeScale, kAudioTrackNum, kNoTimestamp(), kVideoTrackNum,
1004 kNoTimestamp(), TextTracks(), std::set<int64>(), std::string(),
1005 std::string(), kCodecOpus, LogCB()));
1007 int loop_count = 0;
1008 for (const auto* packet_ptr : BuildAllOpusPackets()) {
1009 const BlockInfo kBlockInfo[] = {{kAudioTrackNum,
1011 packet_ptr->duration_ms(),
1012 true, // Make it a SimpleBlock.
1013 packet_ptr->data(),
1014 packet_ptr->size()}};
1016 int block_count = arraysize(kBlockInfo);
1017 scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count));
1018 int result = parser_->Parse(cluster->data(), cluster->size());
1019 EXPECT_EQ(cluster->size(), result);
1020 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count));
1021 loop_count++;
1024 // Test should minimally cover all the combinations of config and frame count.
1025 ASSERT_GE(loop_count, kNumPossibleOpusConfigs * kMaxOpusPacketFrameCount);
1028 TEST_F(WebMClusterParserTest, PreferOpusDurationsOverBlockDurations) {
1029 // Reset parser to expect Opus codec audio.
1030 parser_.reset(new WebMClusterParser(
1031 kTimecodeScale, kAudioTrackNum, kNoTimestamp(), kVideoTrackNum,
1032 kNoTimestamp(), TextTracks(), std::set<int64>(), std::string(),
1033 std::string(), kCodecOpus, LogCB()));
1035 int loop_count = 0;
1036 for (const auto* packet_ptr : BuildAllOpusPackets()) {
1037 // Setting BlockDuration != Opus duration to see which one the parser uses.
1038 int block_duration_ms = packet_ptr->duration_ms() + 10;
1040 BlockInfo block_infos[] = {{kAudioTrackNum,
1042 block_duration_ms,
1043 false, // Not a SimpleBlock.
1044 packet_ptr->data(),
1045 packet_ptr->size()}};
1047 int block_count = arraysize(block_infos);
1048 scoped_ptr<Cluster> cluster(CreateCluster(0, block_infos, block_count));
1049 int result = parser_->Parse(cluster->data(), cluster->size());
1050 EXPECT_EQ(cluster->size(), result);
1052 // BlockInfo duration will be used to verify buffer duration, so changing
1053 // duration to be that of the Opus packet to verify it was preferred.
1054 block_infos[0].duration = packet_ptr->duration_ms();
1056 ASSERT_TRUE(VerifyBuffers(parser_, block_infos, block_count));
1057 loop_count++;
1060 // Test should minimally cover all the combinations of config and frame count.
1061 ASSERT_GE(loop_count, kNumPossibleOpusConfigs * kMaxOpusPacketFrameCount);
1064 // Tests that BlockDuration is used to set duration on buffer rather than
1065 // encoded duration in Opus packet (or hard coded duration estimates). Encoded
1066 // Opus duration is usually preferred but cannot be known when encrypted.
1067 TEST_F(WebMClusterParserTest, DontReadEncodedDurationWhenEncrypted) {
1068 // Non-empty dummy value signals encryption is active for audio.
1069 std::string audio_encryption_id("audio_key_id");
1071 // Reset parser to expect Opus codec audio and use audio encryption key id.
1072 parser_.reset(new WebMClusterParser(
1073 kTimecodeScale, kAudioTrackNum, kNoTimestamp(), kVideoTrackNum,
1074 kNoTimestamp(), TextTracks(), std::set<int64>(), audio_encryption_id,
1075 std::string(), kCodecOpus, LogCB()));
1077 // Single Block with BlockDuration and encrypted data.
1078 const BlockInfo kBlockInfo[] = {{kAudioTrackNum,
1080 kTestAudioFrameDefaultDurationInMs,
1081 false, // Not a SimpleBlock
1082 kEncryptedFrame, // Encrypted frame data
1083 arraysize(kEncryptedFrame)}};
1085 int block_count = arraysize(kBlockInfo);
1086 scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count));
1087 int result = parser_->Parse(cluster->data(), cluster->size());
1088 EXPECT_EQ(cluster->size(), result);
1090 // Will verify that duration of buffer matches that of BlockDuration.
1091 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count));
1094 } // namespace media