xref: /aosp_15_r20/external/libwebm/common/vp9_header_parser_tests.cc (revision 103e46e4cd4b6efcf6001f23fa8665fb110abf8d)
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 "common/vp9_header_parser.h"
9 
10 #include <string>
11 
12 #include "gtest/gtest.h"
13 
14 #include "common/hdr_util.h"
15 #include "mkvparser/mkvparser.h"
16 #include "mkvparser/mkvreader.h"
17 #include "testing/test_util.h"
18 
19 namespace {
20 
21 class Vp9HeaderParserTests : public ::testing::Test {
22  public:
Vp9HeaderParserTests()23   Vp9HeaderParserTests() : is_reader_open_(false), segment_(NULL) {}
24 
~Vp9HeaderParserTests()25   ~Vp9HeaderParserTests() override {
26     CloseReader();
27     if (segment_ != NULL) {
28       delete segment_;
29       segment_ = NULL;
30     }
31   }
32 
CloseReader()33   void CloseReader() {
34     if (is_reader_open_) {
35       reader_.Close();
36     }
37     is_reader_open_ = false;
38   }
39 
CreateAndLoadSegment(const std::string & filename,int expected_doc_type_ver)40   void CreateAndLoadSegment(const std::string& filename,
41                             int expected_doc_type_ver) {
42     filename_ = test::GetTestFilePath(filename);
43     ASSERT_EQ(0, reader_.Open(filename_.c_str()));
44     is_reader_open_ = true;
45     pos_ = 0;
46     mkvparser::EBMLHeader ebml_header;
47     ebml_header.Parse(&reader_, pos_);
48     ASSERT_EQ(1, ebml_header.m_version);
49     ASSERT_EQ(1, ebml_header.m_readVersion);
50     ASSERT_STREQ("webm", ebml_header.m_docType);
51     ASSERT_EQ(expected_doc_type_ver, ebml_header.m_docTypeVersion);
52     ASSERT_EQ(2, ebml_header.m_docTypeReadVersion);
53     ASSERT_EQ(0, mkvparser::Segment::CreateInstance(&reader_, pos_, segment_));
54     ASSERT_FALSE(HasFailure());
55     ASSERT_GE(0, segment_->Load());
56   }
57 
CreateAndLoadSegment(const std::string & filename)58   void CreateAndLoadSegment(const std::string& filename) {
59     CreateAndLoadSegment(filename, 4);
60   }
61 
62   // Load a corrupted segment with no expectation of correctness.
CreateAndLoadInvalidSegment(const std::string & filename)63   void CreateAndLoadInvalidSegment(const std::string& filename) {
64     filename_ = test::GetTestFilePath(filename);
65     ASSERT_EQ(0, reader_.Open(filename_.c_str()));
66     is_reader_open_ = true;
67     pos_ = 0;
68     mkvparser::EBMLHeader ebml_header;
69     ebml_header.Parse(&reader_, pos_);
70     ASSERT_EQ(0, mkvparser::Segment::CreateInstance(&reader_, pos_, segment_));
71     ASSERT_GE(0, segment_->Load());
72   }
73 
ProcessTheFrames(bool invalid_bitstream)74   void ProcessTheFrames(bool invalid_bitstream) {
75     unsigned char* data = NULL;
76     size_t data_len = 0;
77     const mkvparser::Tracks* const parser_tracks = segment_->GetTracks();
78     ASSERT_TRUE(parser_tracks != NULL);
79     const mkvparser::Cluster* cluster = segment_->GetFirst();
80     ASSERT_TRUE(cluster != NULL);
81 
82     while ((cluster != NULL) && !cluster->EOS()) {
83       const mkvparser::BlockEntry* block_entry;
84       long status = cluster->GetFirst(block_entry);  // NOLINT
85       ASSERT_EQ(0, status);
86 
87       while ((block_entry != NULL) && !block_entry->EOS()) {
88         const mkvparser::Block* const block = block_entry->GetBlock();
89         ASSERT_TRUE(block != NULL);
90         const long long trackNum = block->GetTrackNumber();  // NOLINT
91         const mkvparser::Track* const parser_track =
92             parser_tracks->GetTrackByNumber(
93                 static_cast<unsigned long>(trackNum));  // NOLINT
94         ASSERT_TRUE(parser_track != NULL);
95         const long long track_type = parser_track->GetType();  // NOLINT
96 
97         if (track_type == mkvparser::Track::kVideo) {
98           const int frame_count = block->GetFrameCount();
99 
100           for (int i = 0; i < frame_count; ++i) {
101             const mkvparser::Block::Frame& frame = block->GetFrame(i);
102 
103             if (static_cast<size_t>(frame.len) > data_len) {
104               delete[] data;
105               data = new unsigned char[frame.len];
106               ASSERT_TRUE(data != NULL);
107               data_len = static_cast<size_t>(frame.len);
108             }
109             ASSERT_FALSE(frame.Read(&reader_, data));
110             ASSERT_EQ(parser_.ParseUncompressedHeader(data, data_len),
111                       !invalid_bitstream);
112           }
113         }
114 
115         status = cluster->GetNext(block_entry, block_entry);
116         ASSERT_EQ(0, status);
117       }
118 
119       cluster = segment_->GetNext(cluster);
120     }
121     delete[] data;
122   }
123 
124  protected:
125   mkvparser::MkvReader reader_;
126   bool is_reader_open_;
127   mkvparser::Segment* segment_;
128   std::string filename_;
129   long long pos_;  // NOLINT
130   vp9_parser::Vp9HeaderParser parser_;
131 };
132 
TEST_F(Vp9HeaderParserTests,VideoOnlyFile)133 TEST_F(Vp9HeaderParserTests, VideoOnlyFile) {
134   ASSERT_NO_FATAL_FAILURE(CreateAndLoadSegment("test_stereo_left_right.webm"));
135   ProcessTheFrames(false);
136   EXPECT_EQ(256, parser_.width());
137   EXPECT_EQ(144, parser_.height());
138   EXPECT_EQ(1, parser_.column_tiles());
139   EXPECT_EQ(0, parser_.frame_parallel_mode());
140 }
141 
TEST_F(Vp9HeaderParserTests,Muxed)142 TEST_F(Vp9HeaderParserTests, Muxed) {
143   ASSERT_NO_FATAL_FAILURE(
144       CreateAndLoadSegment("bbb_480p_vp9_opus_1second.webm", 4));
145   ProcessTheFrames(false);
146   EXPECT_EQ(854, parser_.width());
147   EXPECT_EQ(480, parser_.height());
148   EXPECT_EQ(2, parser_.column_tiles());
149   EXPECT_EQ(1, parser_.frame_parallel_mode());
150 }
151 
TEST_F(Vp9HeaderParserTests,Invalid)152 TEST_F(Vp9HeaderParserTests, Invalid) {
153   const char* files[] = {
154       "invalid/invalid_vp9_bitstream-bug_1416.webm",
155       "invalid/invalid_vp9_bitstream-bug_1417.webm",
156   };
157 
158   for (int i = 0; i < static_cast<int>(sizeof(files) / sizeof(files[0])); ++i) {
159     SCOPED_TRACE(files[i]);
160     ASSERT_NO_FATAL_FAILURE(CreateAndLoadInvalidSegment(files[i]));
161     ProcessTheFrames(true);
162     CloseReader();
163     delete segment_;
164     segment_ = NULL;
165   }
166 }
167 
TEST_F(Vp9HeaderParserTests,API)168 TEST_F(Vp9HeaderParserTests, API) {
169   vp9_parser::Vp9HeaderParser parser;
170   uint8_t data;
171   EXPECT_FALSE(parser.ParseUncompressedHeader(NULL, 0));
172   EXPECT_FALSE(parser.ParseUncompressedHeader(NULL, 10));
173   EXPECT_FALSE(parser.ParseUncompressedHeader(&data, 0));
174 }
175 
176 }  // namespace
177 
main(int argc,char * argv[])178 int main(int argc, char* argv[]) {
179   ::testing::InitGoogleTest(&argc, argv);
180   return RUN_ALL_TESTS();
181 }
182