1 /*
2 * Copyright (c) 2019, 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 "gtest/gtest.h"
13
14 #include "aom/aom_codec.h"
15 #include "aom/aom_image.h"
16 #include "aom/internal/aom_image_internal.h"
17 #include "aom_scale/yv12config.h"
18 #include "test/codec_factory.h"
19 #include "test/encode_test_driver.h"
20 #include "test/i420_video_source.h"
21 #include "test/util.h"
22 #include "test/video_source.h"
23
24 namespace {
25 const size_t kMetadataPayloadSizeT35 = 24;
26 // 0xB5 stands for the itut t35 metadata country code for the Unites States
27 const uint8_t kMetadataPayloadT35[kMetadataPayloadSizeT35] = {
28 0xB5, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
29 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17
30 };
31
32 #if !CONFIG_REALTIME_ONLY
33 const size_t kMetadataPayloadSizeCll = 4;
34 const uint8_t kMetadataPayloadCll[kMetadataPayloadSizeCll] = { 0xB5, 0x01, 0x02,
35 0x03 };
36
37 const size_t kMetadataObuSizeT35 = 28;
38 const uint8_t kMetadataObuT35[kMetadataObuSizeT35] = {
39 0x2A, 0x1A, 0x02, 0xB5, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
40 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
41 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x80
42 };
43 const size_t kMetadataObuSizeMdcv = 28;
44 const uint8_t kMetadataObuMdcv[kMetadataObuSizeMdcv] = {
45 0x2A, 0x1A, 0x02, 0xB5, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
46 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
47 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x80
48 };
49 const size_t kMetadataObuSizeCll = 8;
50 const uint8_t kMetadataObuCll[kMetadataObuSizeCll] = { 0x2A, 0x06, 0x01, 0xB5,
51 0x01, 0x02, 0x03, 0x80 };
52
53 class MetadataEncodeTest
54 : public ::libaom_test::CodecTestWithParam<libaom_test::TestMode>,
55 public ::libaom_test::EncoderTest {
56 protected:
MetadataEncodeTest()57 MetadataEncodeTest() : EncoderTest(GET_PARAM(0)) {}
58
59 ~MetadataEncodeTest() override = default;
60
SetUp()61 void SetUp() override { InitializeConfig(GET_PARAM(1)); }
62
PreEncodeFrameHook(::libaom_test::VideoSource * video,::libaom_test::Encoder *)63 void PreEncodeFrameHook(::libaom_test::VideoSource *video,
64 ::libaom_test::Encoder * /*encoder*/) override {
65 aom_image_t *current_frame = video->img();
66 if (current_frame) {
67 if (current_frame->metadata) aom_img_remove_metadata(current_frame);
68 ASSERT_EQ(aom_img_add_metadata(current_frame, OBU_METADATA_TYPE_ITUT_T35,
69 kMetadataPayloadT35, 0, AOM_MIF_ANY_FRAME),
70 -1);
71 ASSERT_EQ(aom_img_add_metadata(current_frame, OBU_METADATA_TYPE_ITUT_T35,
72 nullptr, kMetadataPayloadSizeT35,
73 AOM_MIF_ANY_FRAME),
74 -1);
75 ASSERT_EQ(aom_img_add_metadata(current_frame, OBU_METADATA_TYPE_ITUT_T35,
76 nullptr, 0, AOM_MIF_ANY_FRAME),
77 -1);
78 ASSERT_EQ(
79 aom_img_add_metadata(current_frame, OBU_METADATA_TYPE_ITUT_T35,
80 kMetadataPayloadT35, kMetadataPayloadSizeT35,
81 AOM_MIF_ANY_FRAME),
82 0);
83
84 ASSERT_EQ(
85 aom_img_add_metadata(current_frame, OBU_METADATA_TYPE_HDR_MDCV,
86 kMetadataPayloadT35, kMetadataPayloadSizeT35,
87 AOM_MIF_KEY_FRAME),
88 0);
89
90 ASSERT_EQ(
91 aom_img_add_metadata(current_frame, OBU_METADATA_TYPE_HDR_CLL,
92 kMetadataPayloadCll, kMetadataPayloadSizeCll,
93 AOM_MIF_KEY_FRAME),
94 0);
95 }
96 }
97
FramePktHook(const aom_codec_cx_pkt_t * pkt)98 void FramePktHook(const aom_codec_cx_pkt_t *pkt) override {
99 if (pkt->kind == AOM_CODEC_CX_FRAME_PKT) {
100 const size_t bitstream_size = pkt->data.frame.sz;
101 const uint8_t *bitstream =
102 static_cast<const uint8_t *>(pkt->data.frame.buf);
103 // look for valid metadatas in bitstream
104 bool itut_t35_metadata_found = false;
105 if (bitstream_size >= kMetadataObuSizeT35) {
106 for (size_t i = 0; i <= bitstream_size - kMetadataObuSizeT35; ++i) {
107 if (memcmp(bitstream + i, kMetadataObuT35, kMetadataObuSizeT35) ==
108 0) {
109 itut_t35_metadata_found = true;
110 }
111 }
112 }
113 ASSERT_EQ(itut_t35_metadata_found, 1u);
114
115 // Testing for HDR MDCV metadata
116 bool hdr_mdcv_metadata_found = false;
117 if (bitstream_size >= kMetadataObuSizeMdcv) {
118 for (size_t i = 0; i <= bitstream_size - kMetadataObuSizeMdcv; ++i) {
119 if (memcmp(bitstream + i, kMetadataObuMdcv, kMetadataObuSizeMdcv) ==
120 0) {
121 hdr_mdcv_metadata_found = true;
122 }
123 }
124 }
125 ASSERT_TRUE(hdr_mdcv_metadata_found);
126
127 // Testing for HDR CLL metadata
128 bool hdr_cll_metadata_found = false;
129 if (bitstream_size >= kMetadataObuSizeCll) {
130 for (size_t i = 0; i <= bitstream_size - kMetadataObuSizeCll; ++i) {
131 if (memcmp(bitstream + i, kMetadataObuCll, kMetadataObuSizeCll) ==
132 0) {
133 hdr_cll_metadata_found = true;
134 }
135 }
136 }
137 ASSERT_TRUE(hdr_cll_metadata_found);
138 }
139 }
140
DecompressedFrameHook(const aom_image_t & img,aom_codec_pts_t)141 void DecompressedFrameHook(const aom_image_t &img,
142 aom_codec_pts_t /*pts*/) override {
143 ASSERT_NE(img.metadata, nullptr);
144
145 ASSERT_EQ(img.metadata->sz, 3u);
146
147 for (size_t i = 0; i < img.metadata->sz - 1; ++i) {
148 ASSERT_EQ(kMetadataPayloadSizeT35, img.metadata->metadata_array[i]->sz);
149 EXPECT_EQ(
150 memcmp(kMetadataPayloadT35, img.metadata->metadata_array[i]->payload,
151 kMetadataPayloadSizeT35),
152 0);
153 }
154
155 ASSERT_EQ(kMetadataPayloadSizeCll, img.metadata->metadata_array[2]->sz);
156 EXPECT_EQ(
157 memcmp(kMetadataPayloadCll, img.metadata->metadata_array[2]->payload,
158 kMetadataPayloadSizeCll),
159 0);
160 }
161 };
162
TEST_P(MetadataEncodeTest,TestMetadataEncoding)163 TEST_P(MetadataEncodeTest, TestMetadataEncoding) {
164 ::libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
165 30, 1, 0, 5);
166 init_flags_ = AOM_CODEC_USE_PSNR;
167
168 cfg_.g_w = 352;
169 cfg_.g_h = 288;
170
171 cfg_.rc_buf_initial_sz = 500;
172 cfg_.rc_buf_optimal_sz = 600;
173 cfg_.rc_buf_sz = 1000;
174 cfg_.rc_min_quantizer = 2;
175 cfg_.rc_max_quantizer = 56;
176 cfg_.rc_undershoot_pct = 50;
177 cfg_.rc_overshoot_pct = 50;
178 cfg_.rc_end_usage = AOM_CBR;
179 cfg_.kf_mode = AOM_KF_AUTO;
180 cfg_.g_lag_in_frames = 1;
181 cfg_.kf_min_dist = cfg_.kf_max_dist = 3000;
182 // Enable dropped frames.
183 cfg_.rc_dropframe_thresh = 1;
184 // Disable error_resilience mode.
185 cfg_.g_error_resilient = 0;
186 // Run at low bitrate.
187 cfg_.rc_target_bitrate = 40;
188
189 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
190 }
191
192 AV1_INSTANTIATE_TEST_SUITE(MetadataEncodeTest,
193 ::testing::Values(::libaom_test::kOnePassGood));
194 #endif // !CONFIG_REALTIME_ONLY
195 } // namespace
196
TEST(MetadataTest,MetadataAllocation)197 TEST(MetadataTest, MetadataAllocation) {
198 aom_metadata_t *metadata =
199 aom_img_metadata_alloc(OBU_METADATA_TYPE_ITUT_T35, kMetadataPayloadT35,
200 kMetadataPayloadSizeT35, AOM_MIF_ANY_FRAME);
201 ASSERT_NE(metadata, nullptr);
202 aom_img_metadata_free(metadata);
203 }
204
TEST(MetadataTest,MetadataArrayAllocation)205 TEST(MetadataTest, MetadataArrayAllocation) {
206 aom_metadata_array_t *metadata_array = aom_img_metadata_array_alloc(2);
207 ASSERT_NE(metadata_array, nullptr);
208
209 metadata_array->metadata_array[0] =
210 aom_img_metadata_alloc(OBU_METADATA_TYPE_ITUT_T35, kMetadataPayloadT35,
211 kMetadataPayloadSizeT35, AOM_MIF_ANY_FRAME);
212 metadata_array->metadata_array[1] =
213 aom_img_metadata_alloc(OBU_METADATA_TYPE_ITUT_T35, kMetadataPayloadT35,
214 kMetadataPayloadSizeT35, AOM_MIF_ANY_FRAME);
215
216 aom_img_metadata_array_free(metadata_array);
217 }
218
TEST(MetadataTest,AddMetadataToImage)219 TEST(MetadataTest, AddMetadataToImage) {
220 aom_image_t image;
221 image.metadata = nullptr;
222
223 ASSERT_EQ(aom_img_add_metadata(&image, OBU_METADATA_TYPE_ITUT_T35,
224 kMetadataPayloadT35, kMetadataPayloadSizeT35,
225 AOM_MIF_ANY_FRAME),
226 0);
227 aom_img_metadata_array_free(image.metadata);
228 EXPECT_EQ(aom_img_add_metadata(nullptr, OBU_METADATA_TYPE_ITUT_T35,
229 kMetadataPayloadT35, kMetadataPayloadSizeT35,
230 AOM_MIF_ANY_FRAME),
231 -1);
232 }
233
TEST(MetadataTest,RemoveMetadataFromImage)234 TEST(MetadataTest, RemoveMetadataFromImage) {
235 aom_image_t image;
236 image.metadata = nullptr;
237
238 ASSERT_EQ(aom_img_add_metadata(&image, OBU_METADATA_TYPE_ITUT_T35,
239 kMetadataPayloadT35, kMetadataPayloadSizeT35,
240 AOM_MIF_ANY_FRAME),
241 0);
242 aom_img_remove_metadata(&image);
243 aom_img_remove_metadata(nullptr);
244 }
245
TEST(MetadataTest,CopyMetadataToFrameBuffer)246 TEST(MetadataTest, CopyMetadataToFrameBuffer) {
247 YV12_BUFFER_CONFIG yvBuf;
248 yvBuf.metadata = nullptr;
249
250 aom_metadata_array_t *metadata_array = aom_img_metadata_array_alloc(1);
251 ASSERT_NE(metadata_array, nullptr);
252
253 metadata_array->metadata_array[0] =
254 aom_img_metadata_alloc(OBU_METADATA_TYPE_ITUT_T35, kMetadataPayloadT35,
255 kMetadataPayloadSizeT35, AOM_MIF_ANY_FRAME);
256
257 // Metadata_array
258 int status = aom_copy_metadata_to_frame_buffer(&yvBuf, metadata_array);
259 EXPECT_EQ(status, 0);
260 status = aom_copy_metadata_to_frame_buffer(nullptr, metadata_array);
261 EXPECT_EQ(status, -1);
262 aom_img_metadata_array_free(metadata_array);
263
264 // Metadata_array_2
265 aom_metadata_array_t *metadata_array_2 = aom_img_metadata_array_alloc(0);
266 ASSERT_NE(metadata_array_2, nullptr);
267 status = aom_copy_metadata_to_frame_buffer(&yvBuf, metadata_array_2);
268 EXPECT_EQ(status, -1);
269 aom_img_metadata_array_free(metadata_array_2);
270
271 // YV12_BUFFER_CONFIG
272 status = aom_copy_metadata_to_frame_buffer(&yvBuf, nullptr);
273 EXPECT_EQ(status, -1);
274 aom_remove_metadata_from_frame_buffer(&yvBuf);
275 aom_remove_metadata_from_frame_buffer(nullptr);
276 }
277
TEST(MetadataTest,GetMetadataFromImage)278 TEST(MetadataTest, GetMetadataFromImage) {
279 aom_image_t image;
280 image.metadata = nullptr;
281
282 ASSERT_EQ(aom_img_add_metadata(&image, OBU_METADATA_TYPE_ITUT_T35,
283 kMetadataPayloadT35, kMetadataPayloadSizeT35,
284 AOM_MIF_ANY_FRAME),
285 0);
286
287 EXPECT_EQ(aom_img_get_metadata(nullptr, 0), nullptr);
288 EXPECT_EQ(aom_img_get_metadata(&image, 1u), nullptr);
289 EXPECT_EQ(aom_img_get_metadata(&image, 10u), nullptr);
290
291 const aom_metadata_t *metadata = aom_img_get_metadata(&image, 0);
292 ASSERT_NE(metadata, nullptr);
293 ASSERT_EQ(metadata->sz, kMetadataPayloadSizeT35);
294 EXPECT_EQ(
295 memcmp(kMetadataPayloadT35, metadata->payload, kMetadataPayloadSizeT35),
296 0);
297
298 aom_img_metadata_array_free(image.metadata);
299 }
300
TEST(MetadataTest,ReadMetadatasFromImage)301 TEST(MetadataTest, ReadMetadatasFromImage) {
302 aom_image_t image;
303 image.metadata = nullptr;
304
305 uint32_t types[3];
306 types[0] = OBU_METADATA_TYPE_ITUT_T35;
307 types[1] = OBU_METADATA_TYPE_HDR_CLL;
308 types[2] = OBU_METADATA_TYPE_HDR_MDCV;
309
310 ASSERT_EQ(aom_img_add_metadata(&image, types[0], kMetadataPayloadT35,
311 kMetadataPayloadSizeT35, AOM_MIF_ANY_FRAME),
312 0);
313 ASSERT_EQ(aom_img_add_metadata(&image, types[1], kMetadataPayloadT35,
314 kMetadataPayloadSizeT35, AOM_MIF_KEY_FRAME),
315 0);
316 ASSERT_EQ(aom_img_add_metadata(&image, types[2], kMetadataPayloadT35,
317 kMetadataPayloadSizeT35, AOM_MIF_KEY_FRAME),
318 0);
319
320 size_t number_metadata = aom_img_num_metadata(&image);
321 ASSERT_EQ(number_metadata, 3u);
322 for (size_t i = 0; i < number_metadata; ++i) {
323 const aom_metadata_t *metadata = aom_img_get_metadata(&image, i);
324 ASSERT_NE(metadata, nullptr);
325 ASSERT_EQ(metadata->type, types[i]);
326 ASSERT_EQ(metadata->sz, kMetadataPayloadSizeT35);
327 EXPECT_EQ(
328 memcmp(kMetadataPayloadT35, metadata->payload, kMetadataPayloadSizeT35),
329 0);
330 }
331 aom_img_metadata_array_free(image.metadata);
332 }
333