1 // Copyright (c) 2016 The WebM project authors. All Rights Reserved.
2 //
3 // Use of this source code is governed by a BSD-style license
4 // that can be found in the LICENSE file in the root of the source
5 // tree. An additional intellectual property rights grant can be found
6 // in the file PATENTS. All contributing project authors may
7 // be found in the AUTHORS file in the root of the source tree.
8 #include "gtest/gtest.h"
9
10 #include <array>
11 #include <cstdint>
12 #include <cstdio>
13 #include <cstring>
14 #include <iomanip>
15 #include <string>
16
17 #include "common/hdr_util.h"
18 #include "mkvparser/mkvparser.h"
19 #include "mkvparser/mkvreader.h"
20 #include "testing/test_util.h"
21
22 using mkvparser::AudioTrack;
23 using mkvparser::Block;
24 using mkvparser::BlockEntry;
25 using mkvparser::BlockGroup;
26 using mkvparser::Cluster;
27 using mkvparser::CuePoint;
28 using mkvparser::Cues;
29 using mkvparser::MkvReader;
30 using mkvparser::Segment;
31 using mkvparser::SegmentInfo;
32 using mkvparser::Track;
33 using mkvparser::Tracks;
34 using mkvparser::VideoTrack;
35
36 namespace test {
37
38 // Base class containing boiler plate stuff.
39 class ParserTest : public testing::Test {
40 public:
ParserTest()41 ParserTest() : is_reader_open_(false), segment_(NULL) {
42 memset(dummy_data_, -1, kFrameLength);
43 memset(gold_frame_, 0, kFrameLength);
44 }
45
~ParserTest()46 virtual ~ParserTest() {
47 CloseReader();
48 if (segment_ != NULL) {
49 delete segment_;
50 segment_ = NULL;
51 }
52 }
53
CloseReader()54 void CloseReader() {
55 if (is_reader_open_) {
56 reader_.Close();
57 }
58 is_reader_open_ = false;
59 }
60
CreateAndLoadSegment(const std::string & filename,int expected_doc_type_ver)61 bool CreateAndLoadSegment(const std::string& filename,
62 int expected_doc_type_ver) {
63 filename_ = GetTestFilePath(filename);
64 if (reader_.Open(filename_.c_str())) {
65 return false;
66 }
67 is_reader_open_ = true;
68 pos_ = 0;
69 mkvparser::EBMLHeader ebml_header;
70 ebml_header.Parse(&reader_, pos_);
71 EXPECT_EQ(1, ebml_header.m_version);
72 EXPECT_EQ(1, ebml_header.m_readVersion);
73 EXPECT_STREQ("webm", ebml_header.m_docType);
74 EXPECT_EQ(expected_doc_type_ver, ebml_header.m_docTypeVersion);
75 EXPECT_EQ(2, ebml_header.m_docTypeReadVersion);
76
77 if (mkvparser::Segment::CreateInstance(&reader_, pos_, segment_)) {
78 return false;
79 }
80 return !HasFailure() && segment_->Load() >= 0;
81 }
82
CreateAndLoadSegment(const std::string & filename)83 bool CreateAndLoadSegment(const std::string& filename) {
84 return CreateAndLoadSegment(filename, 4);
85 }
86
CreateSegmentNoHeaderChecks(const std::string & filename)87 void CreateSegmentNoHeaderChecks(const std::string& filename) {
88 filename_ = GetTestFilePath(filename);
89 ASSERT_NE(0u, filename_.length());
90 ASSERT_EQ(0, reader_.Open(filename_.c_str()));
91 mkvparser::EBMLHeader ebml_header;
92 ASSERT_EQ(0, ebml_header.Parse(&reader_, pos_));
93 ASSERT_EQ(0, mkvparser::Segment::CreateInstance(&reader_, pos_, segment_));
94 }
95
CompareBlockContents(const Cluster * const cluster,const Block * const block,std::uint64_t timestamp,int track_number,bool is_key,int frame_count)96 void CompareBlockContents(const Cluster* const cluster,
97 const Block* const block, std::uint64_t timestamp,
98 int track_number, bool is_key, int frame_count) {
99 ASSERT_TRUE(block != NULL);
100 EXPECT_EQ(track_number, block->GetTrackNumber());
101 EXPECT_EQ(static_cast<long long>(timestamp), block->GetTime(cluster));
102 EXPECT_EQ(is_key, block->IsKey());
103 EXPECT_EQ(frame_count, block->GetFrameCount());
104 const Block::Frame& frame = block->GetFrame(0);
105 EXPECT_EQ(kFrameLength, frame.len);
106 std::memset(dummy_data_, -1, kFrameLength);
107 frame.Read(&reader_, dummy_data_);
108 EXPECT_EQ(0, std::memcmp(gold_frame_, dummy_data_, kFrameLength));
109 }
110
CompareCuePointContents(const Track * const track,const CuePoint * const cue_point,std::uint64_t timestamp,int track_number,std::uint64_t pos)111 void CompareCuePointContents(const Track* const track,
112 const CuePoint* const cue_point,
113 std::uint64_t timestamp, int track_number,
114 std::uint64_t pos) {
115 ASSERT_TRUE(cue_point != NULL);
116 EXPECT_EQ(static_cast<long long>(timestamp), cue_point->GetTime(segment_));
117 const CuePoint::TrackPosition* const track_position =
118 cue_point->Find(track);
119 EXPECT_EQ(track_number, track_position->m_track);
120 EXPECT_EQ(static_cast<long long>(pos), track_position->m_pos);
121 }
122
123 protected:
124 MkvReader reader_;
125 bool is_reader_open_;
126 Segment* segment_;
127 std::string filename_;
128 long long pos_;
129 std::uint8_t dummy_data_[kFrameLength];
130 std::uint8_t gold_frame_[kFrameLength];
131 };
132
TEST_F(ParserTest,SegmentInfo)133 TEST_F(ParserTest, SegmentInfo) {
134 ASSERT_TRUE(CreateAndLoadSegment("segment_info.webm"));
135 const SegmentInfo* const info = segment_->GetInfo();
136 EXPECT_EQ(kTimeCodeScale, info->GetTimeCodeScale());
137 EXPECT_STREQ(kAppString, info->GetMuxingAppAsUTF8());
138 EXPECT_STREQ(kAppString, info->GetWritingAppAsUTF8());
139 }
140
TEST_F(ParserTest,TrackEntries)141 TEST_F(ParserTest, TrackEntries) {
142 ASSERT_TRUE(CreateAndLoadSegment("tracks.webm"));
143 const Tracks* const tracks = segment_->GetTracks();
144 const unsigned int kTracksCount = 2;
145 EXPECT_EQ(kTracksCount, tracks->GetTracksCount());
146 for (int i = 0; i < 2; ++i) {
147 const Track* const track = tracks->GetTrackByIndex(i);
148 ASSERT_TRUE(track != NULL);
149 EXPECT_STREQ(kTrackName, track->GetNameAsUTF8());
150 if (track->GetType() == Track::kVideo) {
151 const VideoTrack* const video_track =
152 dynamic_cast<const VideoTrack*>(track);
153 EXPECT_EQ(kWidth, static_cast<int>(video_track->GetWidth()));
154 EXPECT_EQ(kHeight, static_cast<int>(video_track->GetHeight()));
155 EXPECT_STREQ(kVP8CodecId, video_track->GetCodecId());
156 EXPECT_DOUBLE_EQ(kVideoFrameRate, video_track->GetFrameRate());
157 const unsigned int kTrackUid = 1;
158 EXPECT_EQ(kTrackUid, video_track->GetUid());
159 } else if (track->GetType() == Track::kAudio) {
160 const AudioTrack* const audio_track =
161 dynamic_cast<const AudioTrack*>(track);
162 EXPECT_EQ(kSampleRate, audio_track->GetSamplingRate());
163 EXPECT_EQ(kChannels, audio_track->GetChannels());
164 EXPECT_EQ(kBitDepth, audio_track->GetBitDepth());
165 EXPECT_STREQ(kVorbisCodecId, audio_track->GetCodecId());
166 const unsigned int kTrackUid = 2;
167 EXPECT_EQ(kTrackUid, audio_track->GetUid());
168 }
169 }
170 }
171
TEST_F(ParserTest,SimpleBlock)172 TEST_F(ParserTest, SimpleBlock) {
173 ASSERT_TRUE(CreateAndLoadSegment("simple_block.webm"));
174 const unsigned int kTracksCount = 1;
175 EXPECT_EQ(kTracksCount, segment_->GetTracks()->GetTracksCount());
176
177 // Get the cluster
178 const Cluster* cluster = segment_->GetFirst();
179 ASSERT_TRUE(cluster != NULL);
180 EXPECT_FALSE(cluster->EOS());
181
182 // Get the first block
183 const BlockEntry* block_entry;
184 EXPECT_EQ(0, cluster->GetFirst(block_entry));
185 ASSERT_TRUE(block_entry != NULL);
186 EXPECT_FALSE(block_entry->EOS());
187 CompareBlockContents(cluster, block_entry->GetBlock(), 0, kVideoTrackNumber,
188 false, 1);
189
190 // Get the second block
191 EXPECT_EQ(0, cluster->GetNext(block_entry, block_entry));
192 ASSERT_TRUE(block_entry != NULL);
193 EXPECT_FALSE(block_entry->EOS());
194 CompareBlockContents(cluster, block_entry->GetBlock(), 2000000,
195 kVideoTrackNumber, false, 1);
196
197 // End of Stream
198 EXPECT_EQ(0, cluster->GetNext(block_entry, block_entry));
199 ASSERT_EQ(NULL, block_entry);
200 cluster = segment_->GetNext(cluster);
201 EXPECT_TRUE(cluster->EOS());
202 }
203
TEST_F(ParserTest,MultipleClusters)204 TEST_F(ParserTest, MultipleClusters) {
205 ASSERT_TRUE(CreateAndLoadSegment("force_new_cluster.webm"));
206 const unsigned int kTracksCount = 1;
207 EXPECT_EQ(kTracksCount, segment_->GetTracks()->GetTracksCount());
208
209 // Get the first cluster
210 const Cluster* cluster = segment_->GetFirst();
211 ASSERT_TRUE(cluster != NULL);
212 EXPECT_FALSE(cluster->EOS());
213
214 // Get the first block
215 const BlockEntry* block_entry;
216 EXPECT_EQ(0, cluster->GetFirst(block_entry));
217 ASSERT_TRUE(block_entry != NULL);
218 EXPECT_FALSE(block_entry->EOS());
219 CompareBlockContents(cluster, block_entry->GetBlock(), 0, kVideoTrackNumber,
220 false, 1);
221
222 // Get the second cluster
223 EXPECT_EQ(0, cluster->GetNext(block_entry, block_entry));
224 EXPECT_EQ(NULL, block_entry);
225 cluster = segment_->GetNext(cluster);
226 ASSERT_TRUE(cluster != NULL);
227 EXPECT_FALSE(cluster->EOS());
228
229 // Get the second block
230 EXPECT_EQ(0, cluster->GetFirst(block_entry));
231 ASSERT_TRUE(block_entry != NULL);
232 EXPECT_FALSE(block_entry->EOS());
233 CompareBlockContents(cluster, block_entry->GetBlock(), 2000000,
234 kVideoTrackNumber, false, 1);
235
236 // Get the third block
237 EXPECT_EQ(0, cluster->GetNext(block_entry, block_entry));
238 ASSERT_TRUE(block_entry != NULL);
239 EXPECT_FALSE(block_entry->EOS());
240 CompareBlockContents(cluster, block_entry->GetBlock(), 4000000,
241 kVideoTrackNumber, false, 1);
242
243 // Get the third cluster
244 EXPECT_EQ(0, cluster->GetNext(block_entry, block_entry));
245 EXPECT_EQ(NULL, block_entry);
246 cluster = segment_->GetNext(cluster);
247 ASSERT_TRUE(cluster != NULL);
248 EXPECT_FALSE(cluster->EOS());
249
250 // Get the fourth block
251 EXPECT_EQ(0, cluster->GetFirst(block_entry));
252 ASSERT_TRUE(block_entry != NULL);
253 EXPECT_FALSE(block_entry->EOS());
254 CompareBlockContents(cluster, block_entry->GetBlock(), 6000000,
255 kVideoTrackNumber, false, 1);
256
257 // End of Stream
258 EXPECT_EQ(0, cluster->GetNext(block_entry, block_entry));
259 EXPECT_EQ(NULL, block_entry);
260 cluster = segment_->GetNext(cluster);
261 EXPECT_TRUE(cluster->EOS());
262 }
263
TEST_F(ParserTest,BlockGroup)264 TEST_F(ParserTest, BlockGroup) {
265 ASSERT_TRUE(CreateAndLoadSegment("metadata_block.webm"));
266 const unsigned int kTracksCount = 1;
267 EXPECT_EQ(kTracksCount, segment_->GetTracks()->GetTracksCount());
268
269 // Get the cluster
270 const Cluster* cluster = segment_->GetFirst();
271 ASSERT_TRUE(cluster != NULL);
272 EXPECT_FALSE(cluster->EOS());
273
274 // Get the first block
275 const BlockEntry* block_entry;
276 EXPECT_EQ(0, cluster->GetFirst(block_entry));
277 ASSERT_TRUE(block_entry != NULL);
278 EXPECT_FALSE(block_entry->EOS());
279 EXPECT_EQ(BlockEntry::Kind::kBlockGroup, block_entry->GetKind());
280 const BlockGroup* block_group = static_cast<const BlockGroup*>(block_entry);
281 EXPECT_EQ(2, block_group->GetDurationTimeCode());
282 CompareBlockContents(cluster, block_group->GetBlock(), 0,
283 kMetadataTrackNumber, true, 1);
284
285 // Get the second block
286 EXPECT_EQ(0, cluster->GetNext(block_entry, block_entry));
287 ASSERT_TRUE(block_entry != NULL);
288 EXPECT_FALSE(block_entry->EOS());
289 EXPECT_EQ(BlockEntry::Kind::kBlockGroup, block_entry->GetKind());
290 block_group = static_cast<const BlockGroup*>(block_entry);
291 EXPECT_EQ(6, block_group->GetDurationTimeCode());
292 CompareBlockContents(cluster, block_group->GetBlock(), 2000000,
293 kMetadataTrackNumber, true, 1);
294
295 // End of Stream
296 EXPECT_EQ(0, cluster->GetNext(block_entry, block_entry));
297 EXPECT_EQ(NULL, block_entry);
298 cluster = segment_->GetNext(cluster);
299 EXPECT_TRUE(cluster->EOS());
300 }
301
TEST_F(ParserTest,Cues)302 TEST_F(ParserTest, Cues) {
303 ASSERT_TRUE(CreateAndLoadSegment("output_cues.webm"));
304 const unsigned int kTracksCount = 1;
305 EXPECT_EQ(kTracksCount, segment_->GetTracks()->GetTracksCount());
306
307 const Track* const track = segment_->GetTracks()->GetTrackByIndex(0);
308 const Cues* const cues = segment_->GetCues();
309 ASSERT_TRUE(cues != NULL);
310 while (!cues->DoneParsing()) {
311 cues->LoadCuePoint();
312 }
313 EXPECT_EQ(3, cues->GetCount());
314
315 // Get first Cue Point
316 const CuePoint* cue_point = cues->GetFirst();
317 CompareCuePointContents(track, cue_point, 0, kVideoTrackNumber, 206);
318
319 // Get second Cue Point
320 cue_point = cues->GetNext(cue_point);
321 CompareCuePointContents(track, cue_point, 6000000, kVideoTrackNumber, 269);
322
323 // Get third (also last) Cue Point
324 cue_point = cues->GetNext(cue_point);
325 const CuePoint* last_cue_point = cues->GetLast();
326 EXPECT_TRUE(cue_point == last_cue_point);
327 CompareCuePointContents(track, cue_point, 4000000, kVideoTrackNumber, 269);
328
329 EXPECT_TRUE(ValidateCues(segment_, &reader_));
330 }
331
TEST_F(ParserTest,CuesBeforeClusters)332 TEST_F(ParserTest, CuesBeforeClusters) {
333 ASSERT_TRUE(CreateAndLoadSegment("cues_before_clusters.webm"));
334 const unsigned int kTracksCount = 1;
335 EXPECT_EQ(kTracksCount, segment_->GetTracks()->GetTracksCount());
336
337 const Track* const track = segment_->GetTracks()->GetTrackByIndex(0);
338 const Cues* const cues = segment_->GetCues();
339 ASSERT_TRUE(cues != NULL);
340 while (!cues->DoneParsing()) {
341 cues->LoadCuePoint();
342 }
343 EXPECT_EQ(2, cues->GetCount());
344
345 // Get first Cue Point
346 const CuePoint* cue_point = cues->GetFirst();
347 CompareCuePointContents(track, cue_point, 0, kVideoTrackNumber, 238);
348
349 // Get second (also last) Cue Point
350 cue_point = cues->GetNext(cue_point);
351 const CuePoint* last_cue_point = cues->GetLast();
352 EXPECT_TRUE(cue_point == last_cue_point);
353 CompareCuePointContents(track, cue_point, 6000000, kVideoTrackNumber, 301);
354
355 EXPECT_TRUE(ValidateCues(segment_, &reader_));
356 }
357
TEST_F(ParserTest,CuesTrackNumber)358 TEST_F(ParserTest, CuesTrackNumber) {
359 ASSERT_TRUE(CreateAndLoadSegment("set_cues_track_number.webm"));
360 const unsigned int kTracksCount = 1;
361 EXPECT_EQ(kTracksCount, segment_->GetTracks()->GetTracksCount());
362
363 const Track* const track = segment_->GetTracks()->GetTrackByIndex(0);
364 const Cues* const cues = segment_->GetCues();
365 ASSERT_TRUE(cues != NULL);
366 while (!cues->DoneParsing()) {
367 cues->LoadCuePoint();
368 }
369 EXPECT_EQ(2, cues->GetCount());
370
371 // Get first Cue Point
372 const CuePoint* cue_point = cues->GetFirst();
373 CompareCuePointContents(track, cue_point, 0, 10, 206);
374
375 // Get second (also last) Cue Point
376 cue_point = cues->GetNext(cue_point);
377 const CuePoint* last_cue_point = cues->GetLast();
378 EXPECT_TRUE(cue_point == last_cue_point);
379 CompareCuePointContents(track, cue_point, 6000000, 10, 269);
380
381 EXPECT_TRUE(ValidateCues(segment_, &reader_));
382 }
383
TEST_F(ParserTest,Opus)384 TEST_F(ParserTest, Opus) {
385 ASSERT_TRUE(CreateAndLoadSegment("bbb_480p_vp9_opus_1second.webm", 4));
386 const unsigned int kTracksCount = 2;
387 EXPECT_EQ(kTracksCount, segment_->GetTracks()->GetTracksCount());
388
389 // --------------------------------------------------------------------------
390 // Track Header validation.
391 const Tracks* const tracks = segment_->GetTracks();
392 EXPECT_EQ(kTracksCount, tracks->GetTracksCount());
393 for (int i = 0; i < 2; ++i) {
394 const Track* const track = tracks->GetTrackByIndex(i);
395 ASSERT_TRUE(track != NULL);
396
397 EXPECT_EQ(NULL, track->GetNameAsUTF8());
398 EXPECT_STREQ("und", track->GetLanguage());
399 EXPECT_EQ(i + 1, track->GetNumber());
400 EXPECT_FALSE(track->GetLacing());
401
402 if (track->GetType() == Track::kVideo) {
403 const VideoTrack* const video_track =
404 dynamic_cast<const VideoTrack*>(track);
405 EXPECT_EQ(854, static_cast<int>(video_track->GetWidth()));
406 EXPECT_EQ(480, static_cast<int>(video_track->GetHeight()));
407 EXPECT_STREQ(kVP9CodecId, video_track->GetCodecId());
408 EXPECT_DOUBLE_EQ(0., video_track->GetFrameRate());
409 EXPECT_EQ(41666666,
410 static_cast<int>(video_track->GetDefaultDuration())); // 24.000
411 const unsigned int kVideoUid = kVideoTrackNumber;
412 EXPECT_EQ(kVideoUid, video_track->GetUid());
413 const unsigned int kCodecDelay = 0;
414 EXPECT_EQ(kCodecDelay, video_track->GetCodecDelay());
415 const unsigned int kSeekPreRoll = 0;
416 EXPECT_EQ(kSeekPreRoll, video_track->GetSeekPreRoll());
417
418 size_t video_codec_private_size;
419 EXPECT_EQ(NULL, video_track->GetCodecPrivate(video_codec_private_size));
420 const unsigned int kPrivateSize = 0;
421 EXPECT_EQ(kPrivateSize, video_codec_private_size);
422 } else if (track->GetType() == Track::kAudio) {
423 const AudioTrack* const audio_track =
424 dynamic_cast<const AudioTrack*>(track);
425 EXPECT_EQ(48000, audio_track->GetSamplingRate());
426 EXPECT_EQ(6, audio_track->GetChannels());
427 EXPECT_EQ(32, audio_track->GetBitDepth());
428 EXPECT_STREQ(kOpusCodecId, audio_track->GetCodecId());
429 EXPECT_EQ(kAudioTrackNumber, static_cast<int>(audio_track->GetUid()));
430 const unsigned int kDefaultDuration = 0;
431 EXPECT_EQ(kDefaultDuration, audio_track->GetDefaultDuration());
432 EXPECT_EQ(kOpusCodecDelay, audio_track->GetCodecDelay());
433 EXPECT_EQ(kOpusSeekPreroll, audio_track->GetSeekPreRoll());
434
435 size_t audio_codec_private_size;
436 EXPECT_TRUE(audio_track->GetCodecPrivate(audio_codec_private_size) !=
437 NULL);
438 EXPECT_GE(audio_codec_private_size, kOpusPrivateDataSizeMinimum);
439 }
440 }
441
442 // --------------------------------------------------------------------------
443 // Parse the file to do block-level validation.
444 const Cluster* cluster = segment_->GetFirst();
445 ASSERT_TRUE(cluster != NULL);
446 EXPECT_FALSE(cluster->EOS());
447
448 for (; cluster != NULL && !cluster->EOS();
449 cluster = segment_->GetNext(cluster)) {
450 // Get the first block
451 const BlockEntry* block_entry;
452 EXPECT_EQ(0, cluster->GetFirst(block_entry));
453 ASSERT_TRUE(block_entry != NULL);
454 EXPECT_FALSE(block_entry->EOS());
455
456 while (block_entry != NULL && !block_entry->EOS()) {
457 const Block* const block = block_entry->GetBlock();
458 ASSERT_TRUE(block != NULL);
459 EXPECT_FALSE(block->IsInvisible());
460 EXPECT_EQ(Block::kLacingNone, block->GetLacing());
461
462 const std::uint32_t track_number =
463 static_cast<std::uint32_t>(block->GetTrackNumber());
464 const Track* const track = tracks->GetTrackByNumber(track_number);
465 ASSERT_TRUE(track != NULL);
466 EXPECT_EQ(track->GetNumber(), block->GetTrackNumber());
467 const unsigned int kContentEncodingCount = 0;
468 EXPECT_EQ(kContentEncodingCount,
469 track->GetContentEncodingCount()); // no encryption
470
471 const std::int64_t track_type = track->GetType();
472 EXPECT_TRUE(track_type == Track::kVideo || track_type == Track::kAudio);
473 if (track_type == Track::kVideo) {
474 EXPECT_EQ(BlockEntry::kBlockSimple, block_entry->GetKind());
475 EXPECT_EQ(0, block->GetDiscardPadding());
476 } else {
477 EXPECT_TRUE(block->IsKey());
478 const std::int64_t kLastAudioTimecode = 1001;
479 const std::int64_t timecode = block->GetTimeCode(cluster);
480 // Only the final Opus block should have discard padding.
481 if (timecode == kLastAudioTimecode) {
482 EXPECT_EQ(BlockEntry::kBlockGroup, block_entry->GetKind());
483 EXPECT_EQ(13500000, block->GetDiscardPadding());
484 } else {
485 EXPECT_EQ(BlockEntry::kBlockSimple, block_entry->GetKind());
486 EXPECT_EQ(0, block->GetDiscardPadding());
487 }
488 }
489
490 const int frame_count = block->GetFrameCount();
491 const Block::Frame& frame = block->GetFrame(0);
492 EXPECT_EQ(1, frame_count);
493 EXPECT_GT(frame.len, 0);
494
495 EXPECT_EQ(0, cluster->GetNext(block_entry, block_entry));
496 }
497 }
498
499 ASSERT_TRUE(cluster != NULL);
500 EXPECT_TRUE(cluster->EOS());
501 }
502
TEST_F(ParserTest,DiscardPadding)503 TEST_F(ParserTest, DiscardPadding) {
504 // Test an artificial file with some extreme DiscardPadding values.
505 const std::string file = "discard_padding.webm";
506 ASSERT_TRUE(CreateAndLoadSegment(file, 4));
507 const unsigned int kTracksCount = 1;
508 EXPECT_EQ(kTracksCount, segment_->GetTracks()->GetTracksCount());
509
510 // --------------------------------------------------------------------------
511 // Track Header validation.
512 const Tracks* const tracks = segment_->GetTracks();
513 EXPECT_EQ(kTracksCount, tracks->GetTracksCount());
514 const Track* const track = tracks->GetTrackByIndex(0);
515 ASSERT_TRUE(track != NULL);
516
517 EXPECT_STREQ(NULL, track->GetNameAsUTF8());
518 EXPECT_EQ(NULL, track->GetLanguage());
519 EXPECT_EQ(kAudioTrackNumber, track->GetNumber());
520 EXPECT_TRUE(track->GetLacing());
521
522 EXPECT_EQ(Track::kAudio, track->GetType());
523 const AudioTrack* const audio_track = dynamic_cast<const AudioTrack*>(track);
524 EXPECT_EQ(30, audio_track->GetSamplingRate());
525 EXPECT_EQ(2, audio_track->GetChannels());
526 EXPECT_STREQ(kOpusCodecId, audio_track->GetCodecId());
527 EXPECT_EQ(kAudioTrackNumber, static_cast<int>(audio_track->GetUid()));
528 const unsigned int kDefaultDuration = 0;
529 EXPECT_EQ(kDefaultDuration, audio_track->GetDefaultDuration());
530 const unsigned int kCodecDelay = 0;
531 EXPECT_EQ(kCodecDelay, audio_track->GetCodecDelay());
532 const unsigned int kSeekPreRoll = 0;
533 EXPECT_EQ(kSeekPreRoll, audio_track->GetSeekPreRoll());
534
535 size_t audio_codec_private_size;
536 EXPECT_EQ(NULL, audio_track->GetCodecPrivate(audio_codec_private_size));
537 const unsigned int kPrivateSize = 0;
538 EXPECT_EQ(kPrivateSize, audio_codec_private_size);
539
540 // --------------------------------------------------------------------------
541 // Parse the file to do block-level validation.
542 const Cluster* cluster = segment_->GetFirst();
543 ASSERT_TRUE(cluster != NULL);
544 EXPECT_FALSE(cluster->EOS());
545 const unsigned int kSegmentCount = 1;
546 EXPECT_EQ(kSegmentCount, segment_->GetCount());
547
548 // Get the first block
549 const BlockEntry* block_entry;
550 EXPECT_EQ(0, cluster->GetFirst(block_entry));
551 ASSERT_TRUE(block_entry != NULL);
552 EXPECT_FALSE(block_entry->EOS());
553
554 const std::array<int, 3> discard_padding = {{12810000, 127, -128}};
555 int index = 0;
556 while (block_entry != NULL && !block_entry->EOS()) {
557 const Block* const block = block_entry->GetBlock();
558 ASSERT_TRUE(block != NULL);
559 EXPECT_FALSE(block->IsInvisible());
560 EXPECT_EQ(Block::kLacingNone, block->GetLacing());
561
562 const std::uint32_t track_number =
563 static_cast<std::uint32_t>(block->GetTrackNumber());
564 const Track* const track = tracks->GetTrackByNumber(track_number);
565 ASSERT_TRUE(track != NULL);
566 EXPECT_EQ(track->GetNumber(), block->GetTrackNumber());
567 const unsigned int kContentEncodingCount = 0;
568 EXPECT_EQ(kContentEncodingCount,
569 track->GetContentEncodingCount()); // no encryption
570
571 const std::int64_t track_type = track->GetType();
572 EXPECT_EQ(Track::kAudio, track_type);
573 EXPECT_TRUE(block->IsKey());
574
575 // All blocks have DiscardPadding.
576 EXPECT_EQ(BlockEntry::kBlockGroup, block_entry->GetKind());
577 ASSERT_LT(index, static_cast<int>(discard_padding.size()));
578 EXPECT_EQ(discard_padding[index], block->GetDiscardPadding());
579 ++index;
580
581 const int frame_count = block->GetFrameCount();
582 const Block::Frame& frame = block->GetFrame(0);
583 EXPECT_EQ(1, frame_count);
584 EXPECT_GT(frame.len, 0);
585
586 EXPECT_EQ(0, cluster->GetNext(block_entry, block_entry));
587 }
588
589 cluster = segment_->GetNext(cluster);
590 ASSERT_TRUE(cluster != NULL);
591 EXPECT_TRUE(cluster->EOS());
592 }
593
TEST_F(ParserTest,StereoModeParsedCorrectly)594 TEST_F(ParserTest, StereoModeParsedCorrectly) {
595 ASSERT_TRUE(CreateAndLoadSegment("test_stereo_left_right.webm"));
596 const unsigned int kTracksCount = 1;
597 EXPECT_EQ(kTracksCount, segment_->GetTracks()->GetTracksCount());
598
599 const VideoTrack* const video_track = dynamic_cast<const VideoTrack*>(
600 segment_->GetTracks()->GetTrackByIndex(0));
601
602 EXPECT_EQ(1, video_track->GetStereoMode());
603 EXPECT_EQ(256, video_track->GetWidth());
604 EXPECT_EQ(144, video_track->GetHeight());
605 EXPECT_EQ(128, video_track->GetDisplayWidth());
606 EXPECT_EQ(144, video_track->GetDisplayHeight());
607 }
608
TEST_F(ParserTest,CanParseColour)609 TEST_F(ParserTest, CanParseColour) {
610 ASSERT_TRUE(CreateAndLoadSegment("colour.webm"));
611 const unsigned int kTracksCount = 1;
612 EXPECT_EQ(kTracksCount, segment_->GetTracks()->GetTracksCount());
613 const VideoTrack* const video_track = dynamic_cast<const VideoTrack*>(
614 segment_->GetTracks()->GetTrackByIndex(0));
615
616 const mkvparser::Colour* const colour = video_track->GetColour();
617 ASSERT_TRUE(colour != nullptr);
618 EXPECT_EQ(0u, colour->matrix_coefficients);
619 EXPECT_EQ(1u, colour->bits_per_channel);
620 EXPECT_EQ(2u, colour->chroma_subsampling_horz);
621 EXPECT_EQ(3u, colour->chroma_subsampling_vert);
622 EXPECT_EQ(4u, colour->cb_subsampling_horz);
623 EXPECT_EQ(5u, colour->cb_subsampling_vert);
624 EXPECT_EQ(1u, colour->chroma_siting_horz);
625 EXPECT_EQ(1u, colour->chroma_siting_vert);
626 EXPECT_EQ(2u, colour->range);
627 EXPECT_EQ(9u, colour->transfer_characteristics);
628 EXPECT_EQ(10u, colour->primaries);
629 EXPECT_EQ(11u, colour->max_cll);
630 EXPECT_EQ(12u, colour->max_fall);
631
632 const mkvparser::MasteringMetadata* const mm =
633 video_track->GetColour()->mastering_metadata;
634 ASSERT_TRUE(mm != nullptr);
635 ASSERT_TRUE(mm->r != nullptr);
636 ASSERT_TRUE(mm->g != nullptr);
637 ASSERT_TRUE(mm->b != nullptr);
638 ASSERT_TRUE(mm->white_point != nullptr);
639 EXPECT_FLOAT_EQ(.1, mm->r->x);
640 EXPECT_FLOAT_EQ(.2, mm->r->y);
641 EXPECT_FLOAT_EQ(.1, mm->g->x);
642 EXPECT_FLOAT_EQ(.2, mm->g->y);
643 EXPECT_FLOAT_EQ(.1, mm->b->x);
644 EXPECT_FLOAT_EQ(.2, mm->b->y);
645 EXPECT_FLOAT_EQ(.1, mm->white_point->x);
646 EXPECT_FLOAT_EQ(.2, mm->white_point->y);
647 EXPECT_FLOAT_EQ(30.0, mm->luminance_min);
648 EXPECT_FLOAT_EQ(40.0, mm->luminance_max);
649 }
650
TEST_F(ParserTest,CanParseProjection)651 TEST_F(ParserTest, CanParseProjection) {
652 ASSERT_TRUE(CreateAndLoadSegment("projection.webm"));
653 const unsigned int kTracksCount = 1;
654 EXPECT_EQ(kTracksCount, segment_->GetTracks()->GetTracksCount());
655 const VideoTrack* const video_track =
656 static_cast<const VideoTrack*>(segment_->GetTracks()->GetTrackByIndex(0));
657
658 const mkvparser::Projection* const projection = video_track->GetProjection();
659 ASSERT_TRUE(projection != nullptr);
660 EXPECT_EQ(mkvparser::Projection::kRectangular, projection->type);
661 EXPECT_FLOAT_EQ(1, projection->pose_yaw);
662 EXPECT_FLOAT_EQ(2, projection->pose_pitch);
663 EXPECT_FLOAT_EQ(3, projection->pose_roll);
664 EXPECT_EQ(1u, projection->private_data_length);
665 ASSERT_TRUE(projection->private_data != nullptr);
666 EXPECT_EQ(4u, projection->private_data[0]);
667 }
668
TEST_F(ParserTest,Vp9CodecLevelTest)669 TEST_F(ParserTest, Vp9CodecLevelTest) {
670 const int kCodecPrivateLength = 3;
671 const uint8_t good_codec_private_level[kCodecPrivateLength] = {2, 1, 11};
672 libwebm::Vp9CodecFeatures features;
673 EXPECT_TRUE(libwebm::ParseVpxCodecPrivate(&good_codec_private_level[0],
674 kCodecPrivateLength, &features));
675 EXPECT_EQ(libwebm::Vp9CodecFeatures::kValueNotPresent, features.profile);
676 EXPECT_EQ(11, features.level);
677 EXPECT_EQ(libwebm::Vp9CodecFeatures::kValueNotPresent, features.bit_depth);
678 EXPECT_EQ(libwebm::Vp9CodecFeatures::kValueNotPresent,
679 features.chroma_subsampling);
680 }
681
TEST_F(ParserTest,Vp9CodecProfileTest)682 TEST_F(ParserTest, Vp9CodecProfileTest) {
683 const int kCodecPrivateLength = 3;
684 const uint8_t good_codec_private_profile[kCodecPrivateLength] = {1, 1, 1};
685 libwebm::Vp9CodecFeatures features;
686 EXPECT_TRUE(libwebm::ParseVpxCodecPrivate(&good_codec_private_profile[0],
687 kCodecPrivateLength, &features));
688 EXPECT_EQ(1, features.profile);
689 EXPECT_EQ(libwebm::Vp9CodecFeatures::kValueNotPresent, features.level);
690 EXPECT_EQ(libwebm::Vp9CodecFeatures::kValueNotPresent, features.bit_depth);
691 EXPECT_EQ(libwebm::Vp9CodecFeatures::kValueNotPresent,
692 features.chroma_subsampling);
693 }
694
TEST_F(ParserTest,Vp9CodecBitDepthTest)695 TEST_F(ParserTest, Vp9CodecBitDepthTest) {
696 const int kCodecPrivateLength = 3;
697 const uint8_t good_codec_private_profile[kCodecPrivateLength] = {3, 1, 8};
698 libwebm::Vp9CodecFeatures features;
699 EXPECT_TRUE(libwebm::ParseVpxCodecPrivate(&good_codec_private_profile[0],
700 kCodecPrivateLength, &features));
701 EXPECT_EQ(libwebm::Vp9CodecFeatures::kValueNotPresent, features.profile);
702 EXPECT_EQ(libwebm::Vp9CodecFeatures::kValueNotPresent, features.level);
703 EXPECT_EQ(8, features.bit_depth);
704 EXPECT_EQ(libwebm::Vp9CodecFeatures::kValueNotPresent,
705 features.chroma_subsampling);
706 }
707
TEST_F(ParserTest,Vp9CodecChromaSubsamplingTest)708 TEST_F(ParserTest, Vp9CodecChromaSubsamplingTest) {
709 const int kCodecPrivateLength = 3;
710 const uint8_t good_codec_private_profile[kCodecPrivateLength] = {4, 1, 0};
711 libwebm::Vp9CodecFeatures features;
712 EXPECT_TRUE(libwebm::ParseVpxCodecPrivate(&good_codec_private_profile[0],
713 kCodecPrivateLength, &features));
714 EXPECT_EQ(libwebm::Vp9CodecFeatures::kValueNotPresent, features.profile);
715 EXPECT_EQ(libwebm::Vp9CodecFeatures::kValueNotPresent, features.level);
716 EXPECT_EQ(libwebm::Vp9CodecFeatures::kValueNotPresent, features.bit_depth);
717 EXPECT_EQ(0, features.chroma_subsampling);
718 }
719
TEST_F(ParserTest,Vp9CodecProfileLevelTest)720 TEST_F(ParserTest, Vp9CodecProfileLevelTest) {
721 const int kCodecPrivateLength = 6;
722 const uint8_t codec_private[kCodecPrivateLength] = {1, 1, 1, 2, 1, 11};
723 libwebm::Vp9CodecFeatures features;
724 EXPECT_TRUE(libwebm::ParseVpxCodecPrivate(&codec_private[0],
725 kCodecPrivateLength, &features));
726 EXPECT_EQ(1, features.profile);
727 EXPECT_EQ(11, features.level);
728 }
729
TEST_F(ParserTest,Vp9CodecAllTest)730 TEST_F(ParserTest, Vp9CodecAllTest) {
731 const int kCodecPrivateLength = 12;
732 const uint8_t codec_private[kCodecPrivateLength] = {1, 1, 1, 2, 1, 11,
733 3, 1, 8, 4, 1, 0};
734 libwebm::Vp9CodecFeatures features;
735 EXPECT_TRUE(libwebm::ParseVpxCodecPrivate(&codec_private[0],
736 kCodecPrivateLength, &features));
737 EXPECT_EQ(1, features.profile);
738 EXPECT_EQ(11, features.level);
739 EXPECT_EQ(8, features.bit_depth);
740 EXPECT_EQ(0, features.chroma_subsampling);
741 }
742
TEST_F(ParserTest,Vp9CodecPrivateBadTest)743 TEST_F(ParserTest, Vp9CodecPrivateBadTest) {
744 const int kCodecPrivateLength = 3;
745 libwebm::Vp9CodecFeatures features;
746 // Test invalid codec private data; all of these should return false.
747 const uint8_t bad_codec_private[kCodecPrivateLength] = {0, 0, 0};
748 EXPECT_FALSE(
749 libwebm::ParseVpxCodecPrivate(NULL, kCodecPrivateLength, &features));
750 EXPECT_FALSE(
751 libwebm::ParseVpxCodecPrivate(&bad_codec_private[0], 0, &features));
752 EXPECT_FALSE(libwebm::ParseVpxCodecPrivate(&bad_codec_private[0],
753 kCodecPrivateLength, &features));
754 const uint8_t good_codec_private_level[kCodecPrivateLength] = {2, 1, 11};
755
756 // Test parse of codec private chunks, but lie about length.
757 EXPECT_FALSE(
758 libwebm::ParseVpxCodecPrivate(&bad_codec_private[0], 0, &features));
759 EXPECT_FALSE(libwebm::ParseVpxCodecPrivate(&good_codec_private_level[0], 0,
760 &features));
761 EXPECT_FALSE(libwebm::ParseVpxCodecPrivate(&good_codec_private_level[0],
762 kCodecPrivateLength, NULL));
763 }
764
TEST_F(ParserTest,InvalidTruncatedChapterString)765 TEST_F(ParserTest, InvalidTruncatedChapterString) {
766 ASSERT_NO_FATAL_FAILURE(CreateSegmentNoHeaderChecks(
767 "invalid/chapters_truncated_chapter_string.mkv"));
768 EXPECT_EQ(mkvparser::E_PARSE_FAILED, segment_->Load());
769 }
770
TEST_F(ParserTest,InvalidTruncatedChapterString2)771 TEST_F(ParserTest, InvalidTruncatedChapterString2) {
772 ASSERT_NO_FATAL_FAILURE(CreateSegmentNoHeaderChecks(
773 "invalid/chapters_truncated_chapter_string_2.mkv"));
774 EXPECT_EQ(mkvparser::E_FILE_FORMAT_INVALID, segment_->Load());
775 }
776
TEST_F(ParserTest,InvalidFixedLacingSize)777 TEST_F(ParserTest, InvalidFixedLacingSize) {
778 ASSERT_NO_FATAL_FAILURE(
779 CreateSegmentNoHeaderChecks("invalid/fixed_lacing_bad_lace_size.mkv"));
780 ASSERT_EQ(0, segment_->Load());
781 const mkvparser::BlockEntry* block_entry = NULL;
782 EXPECT_EQ(mkvparser::E_FILE_FORMAT_INVALID,
783 segment_->GetFirst()->GetFirst(block_entry));
784 }
785
TEST_F(ParserTest,InvalidBlockEndsBeyondCluster)786 TEST_F(ParserTest, InvalidBlockEndsBeyondCluster) {
787 ASSERT_NO_FATAL_FAILURE(
788 CreateSegmentNoHeaderChecks("invalid/block_ends_beyond_cluster.mkv"));
789 ASSERT_EQ(0, segment_->Load());
790 const mkvparser::BlockEntry* block_entry = NULL;
791 EXPECT_EQ(0, segment_->GetFirst()->GetFirst(block_entry));
792 EXPECT_EQ(mkvparser::E_FILE_FORMAT_INVALID,
793 segment_->GetFirst()->GetNext(block_entry, block_entry));
794 }
795
TEST_F(ParserTest,InvalidBlockGroupBlockEndsBlockGroup)796 TEST_F(ParserTest, InvalidBlockGroupBlockEndsBlockGroup) {
797 ASSERT_NO_FATAL_FAILURE(CreateSegmentNoHeaderChecks(
798 "invalid/blockgroup_block_ends_beyond_blockgroup.mkv"));
799 ASSERT_EQ(0, segment_->Load());
800 const mkvparser::BlockEntry* block_entry = NULL;
801 EXPECT_EQ(0, segment_->GetFirst()->GetFirst(block_entry));
802 EXPECT_EQ(mkvparser::E_FILE_FORMAT_INVALID,
803 segment_->GetFirst()->GetNext(block_entry, block_entry));
804 }
805
TEST_F(ParserTest,InvalidProjectionFloatOverflow)806 TEST_F(ParserTest, InvalidProjectionFloatOverflow) {
807 ASSERT_NO_FATAL_FAILURE(
808 CreateSegmentNoHeaderChecks("invalid/projection_float_overflow.webm"));
809 EXPECT_EQ(mkvparser::E_FILE_FORMAT_INVALID, segment_->Load());
810 }
811
TEST_F(ParserTest,InvalidPrimaryChromaticityParseFail)812 TEST_F(ParserTest, InvalidPrimaryChromaticityParseFail) {
813 ASSERT_NO_FATAL_FAILURE(CreateSegmentNoHeaderChecks(
814 "invalid/primarychromaticity_fieldtoolarge.webm"));
815 EXPECT_EQ(mkvparser::E_FILE_FORMAT_INVALID, segment_->Load());
816 }
817
818 } // namespace test
819
main(int argc,char * argv[])820 int main(int argc, char* argv[]) {
821 ::testing::InitGoogleTest(&argc, argv);
822 return RUN_ALL_TESTS();
823 }
824