• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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