1 /*
2 * Copyright (c) 2024, Alliance for Open Media. All rights reserved.
3 *
4 * This source code is subject to the terms of the BSD 2 Clause License and
5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6 * was not distributed with this source code in the LICENSE file, you can
7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8 * Media Patent License 1.0 was not distributed with this source code in the
9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10 */
11
12 #include <cmath>
13
14 #include "gtest/gtest.h"
15
16 #include "examples/multilayer_metadata.h"
17 #include "test/video_source.h"
18
19 namespace libaom_examples {
20 namespace {
21
TEST(MultilayerMetadataTest,ParseAlpha)22 TEST(MultilayerMetadataTest, ParseAlpha) {
23 const std::string metadata = R"(
24
25 use_case: 1 # global alpha
26 layers:
27 - layer_type: 5 # alpha
28 luma_plane_only_flag: 1
29 layer_metadata_scope: 2 # global
30 alpha:
31 alpha_use_idc: 2 # segmentation
32 alpha_bit_depth: 8
33 alpha_transparent_value: 0
34 alpha_opaque_value: 4
35 label_type_id:
36 - 5
37 - 3
38 - 9
39 - 128
40 - 42
41
42 - layer_type: 1 # texture
43 luma_plane_only_flag: 0
44 layer_metadata_scope: 2 # global
45 layer_color_description:
46 color_range: 1
47 color_primaries: 1
48 transfer_characteristics: 13
49 matrix_coefficients: 6
50
51 )";
52 libaom_test::TempOutFile tmp_file(/*text_mode=*/true);
53 fprintf(tmp_file.file(), "%s", metadata.c_str());
54 fflush(tmp_file.file());
55
56 MultilayerMetadata multilayer;
57 EXPECT_TRUE(parse_multilayer_file(tmp_file.file_name().c_str(), &multilayer));
58
59 EXPECT_EQ(multilayer.use_case, 1);
60 ASSERT_EQ(multilayer.layers.size(), 2);
61 EXPECT_EQ(multilayer.layers[0].layer_type, 5);
62 EXPECT_EQ(multilayer.layers[0].luma_plane_only_flag, 1);
63 EXPECT_EQ(multilayer.layers[0].layer_metadata_scope, 2);
64 EXPECT_EQ(multilayer.layers[0].global_alpha_info.alpha_use_idc, 2);
65 EXPECT_EQ(multilayer.layers[0].global_alpha_info.alpha_bit_depth, 8);
66 EXPECT_EQ(multilayer.layers[0].global_alpha_info.alpha_transparent_value, 0);
67 EXPECT_EQ(multilayer.layers[0].global_alpha_info.alpha_opaque_value, 4);
68 ASSERT_EQ(multilayer.layers[0].global_alpha_info.label_type_id.size(), 5);
69 EXPECT_EQ(multilayer.layers[0].global_alpha_info.label_type_id[0], 5);
70 EXPECT_EQ(multilayer.layers[0].global_alpha_info.label_type_id[1], 3);
71 EXPECT_EQ(multilayer.layers[0].global_alpha_info.label_type_id[2], 9);
72 EXPECT_EQ(multilayer.layers[0].global_alpha_info.label_type_id[3], 128);
73 EXPECT_EQ(multilayer.layers[0].global_alpha_info.label_type_id[4], 42);
74 EXPECT_EQ(multilayer.layers[1].layer_type, 1);
75 EXPECT_EQ(multilayer.layers[1].luma_plane_only_flag, 0);
76 EXPECT_EQ(multilayer.layers[1].layer_metadata_scope, 2);
77 EXPECT_TRUE(multilayer.layers[1].layer_color_description.second);
78 EXPECT_EQ(multilayer.layers[1].layer_color_description.first.color_range, 1);
79 EXPECT_EQ(multilayer.layers[1].layer_color_description.first.color_primaries,
80 1);
81 EXPECT_EQ(multilayer.layers[1]
82 .layer_color_description.first.transfer_characteristics,
83 13);
84 EXPECT_EQ(
85 multilayer.layers[1].layer_color_description.first.matrix_coefficients,
86 6);
87 }
88
TEST(MultilayerMetadataTest,ParseDepth)89 TEST(MultilayerMetadataTest, ParseDepth) {
90 const std::string metadata = R"(
91 use_case: 2 # global depth
92 layers:
93 - layer_type: 6 # depth
94 luma_plane_only_flag: 1
95 layer_metadata_scope: 2 # global
96 depth:
97 z_near: 1.456
98 z_far: 9.786
99 depth_representation_type: 3
100 depth_nonlinear_precision: 8
101 depth_nonlinear_representation_model:
102 - 12
103 - 23
104 - 5
105
106 - layer_type: 1 # texture
107 luma_plane_only_flag: 0
108 layer_metadata_scope: 2 # global
109 layer_color_description:
110 color_range: 1
111 color_primaries: 1
112 transfer_characteristics: 13
113 matrix_coefficients: 6
114
115 )";
116 libaom_test::TempOutFile tmp_file(/*text_mode=*/true);
117 fprintf(tmp_file.file(), "%s", metadata.c_str());
118 fflush(tmp_file.file());
119
120 MultilayerMetadata multilayer;
121 EXPECT_TRUE(parse_multilayer_file(tmp_file.file_name().c_str(), &multilayer));
122 EXPECT_EQ(multilayer.use_case, 2);
123 ASSERT_EQ(multilayer.layers.size(), 2);
124 EXPECT_EQ(multilayer.layers[0].layer_type, 6);
125 EXPECT_EQ(multilayer.layers[0].luma_plane_only_flag, 1);
126 EXPECT_EQ(multilayer.layers[0].layer_metadata_scope, 2);
127 EXPECT_TRUE(multilayer.layers[0].global_depth_info.z_near.second);
128 EXPECT_NEAR(depth_representation_element_to_double(
129 multilayer.layers[0].global_depth_info.z_near.first),
130 1.456, 0.00001);
131 EXPECT_TRUE(multilayer.layers[0].global_depth_info.z_far.second);
132 EXPECT_NEAR(depth_representation_element_to_double(
133 multilayer.layers[0].global_depth_info.z_far.first),
134 9.786, 0.00001);
135 EXPECT_EQ(multilayer.layers[0].global_depth_info.depth_representation_type,
136 3);
137 EXPECT_EQ(multilayer.layers[0].global_depth_info.depth_nonlinear_precision,
138 8);
139 ASSERT_EQ(multilayer.layers[0]
140 .global_depth_info.depth_nonlinear_representation_model.size(),
141 3);
142 EXPECT_EQ(multilayer.layers[0]
143 .global_depth_info.depth_nonlinear_representation_model[0],
144 12);
145 EXPECT_EQ(multilayer.layers[0]
146 .global_depth_info.depth_nonlinear_representation_model[1],
147 23);
148 EXPECT_EQ(multilayer.layers[0]
149 .global_depth_info.depth_nonlinear_representation_model[2],
150 5);
151 EXPECT_EQ(multilayer.layers[1].layer_type, 1);
152 EXPECT_EQ(multilayer.layers[1].luma_plane_only_flag, 0);
153 EXPECT_EQ(multilayer.layers[1].layer_metadata_scope, 2);
154 EXPECT_TRUE(multilayer.layers[1].layer_color_description.second);
155 EXPECT_EQ(multilayer.layers[1].layer_color_description.first.color_range, 1);
156 EXPECT_EQ(multilayer.layers[1].layer_color_description.first.color_primaries,
157 1);
158 EXPECT_EQ(multilayer.layers[1]
159 .layer_color_description.first.transfer_characteristics,
160 13);
161 EXPECT_EQ(
162 multilayer.layers[1].layer_color_description.first.matrix_coefficients,
163 6);
164 }
165
TEST(MultilayerMetadataTest,ParseInvalid)166 TEST(MultilayerMetadataTest, ParseInvalid) {
167 const std::string metadata = R"(
168
169 use_case: 1 # global alpha
170 layers:
171 - layer_type: 5 # alpha
172 luma_plane_only_flag: 1
173 layer_metadata_scope: 2 # global
174
175 - layer_type: 1 # texture
176 luma_plane_only_flag: 0
177 layer_metadata_scope: 2 # global
178
179 - layer_type: 6 # depth => bad layer type
180 luma_plane_only_flag: 1
181 layer_metadata_scope: 2 # global
182 )";
183 libaom_test::TempOutFile tmp_file(/*text_mode=*/true);
184 fprintf(tmp_file.file(), "%s", metadata.c_str());
185 fflush(tmp_file.file());
186
187 MultilayerMetadata multilayer;
188 // Invalid: has a depth layer even though use_case is alpha
189 EXPECT_FALSE(
190 parse_multilayer_file(tmp_file.file_name().c_str(), &multilayer));
191 }
192
TEST(MultilayerMetadataTest,ParseBadIndent)193 TEST(MultilayerMetadataTest, ParseBadIndent) {
194 const std::string metadata = R"(
195
196 use_case: 1 # global alpha
197 layers:
198 - layer_type: 5 # alpha
199 luma_plane_only_flag: 1
200 layer_metadata_scope: 2 # global
201
202 - layer_type: 1 # texture
203 luma_plane_only_flag: 0
204 layer_metadata_scope: 2 # global
205 )";
206 libaom_test::TempOutFile tmp_file(/*text_mode=*/true);
207 fprintf(tmp_file.file(), "%s", metadata.c_str());
208 fflush(tmp_file.file());
209
210 MultilayerMetadata multilayer;
211 // Invalid indentation.
212 EXPECT_FALSE(
213 parse_multilayer_file(tmp_file.file_name().c_str(), &multilayer));
214 }
215
TEST(MultilayerMetadataTest,ParseUnknownField)216 TEST(MultilayerMetadataTest, ParseUnknownField) {
217 const std::string metadata = R"(
218
219 use_case: 1 # global alpha
220 layers:
221 - layer_type: 5 # alpha
222 luma_plane_only_flag: 1
223 layer_metadata_scope: 2 # global
224 foobar: 42
225
226 - layer_type: 1 # texture
227 luma_plane_only_flag: 0
228 layer_metadata_scope: 2 # global
229 )";
230 libaom_test::TempOutFile tmp_file(/*text_mode=*/true);
231 fprintf(tmp_file.file(), "%s", metadata.c_str());
232 fflush(tmp_file.file());
233
234 MultilayerMetadata multilayer;
235 // Unkonwn field 'foobar'.
236 EXPECT_FALSE(
237 parse_multilayer_file(tmp_file.file_name().c_str(), &multilayer));
238 }
239
TestConversion(double v)240 void TestConversion(double v) {
241 DepthRepresentationElement e;
242 ASSERT_TRUE(double_to_depth_representation_element(v, &e)) << v;
243 EXPECT_NEAR(depth_representation_element_to_double(e), v, 0.000000001);
244 }
245
TEST(MultilayerMetadataTest,DoubleConversion)246 TEST(MultilayerMetadataTest, DoubleConversion) {
247 TestConversion(0.0);
248 TestConversion(1.789456e-5);
249 TestConversion(-1.789456e-5);
250 TestConversion(42);
251 TestConversion(6.7894564456);
252 TestConversion(6.7894564456e10);
253 TestConversion(-6.7894564456e10);
254
255 DepthRepresentationElement e;
256 // Too small.
257 ASSERT_FALSE(double_to_depth_representation_element(1e-10, &e));
258 // Too big.
259 ASSERT_FALSE(double_to_depth_representation_element(1e+30, &e));
260 }
261
262 } // namespace
263 } // namespace libaom_examples
264