blob: 41d55ec4979e5fd6122d9d3ccf02d4deccc92efb [file] [log] [blame]
Dichen Zhang85b37562022-10-11 11:08:28 -07001/*
2 * Copyright 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Dichen Zhangdbceb0e2023-04-14 19:03:18 +000017#include <ultrahdr/jpegr.h>
18#include <ultrahdr/jpegrutils.h>
19#include <ultrahdr/gainmapmath.h>
Dichen Zhang36c1e732022-11-23 01:25:34 +000020#include <fcntl.h>
21#include <fstream>
22#include <gtest/gtest.h>
Nick Deakind19e5762023-02-10 15:39:08 -050023#include <sys/time.h>
Dichen Zhang36c1e732022-11-23 01:25:34 +000024#include <utils/Log.h>
25
26#define RAW_P010_IMAGE "/sdcard/Documents/raw_p010_image.p010"
Dichen Zhang66ca6e32023-04-05 12:22:54 -070027#define RAW_P010_IMAGE_WITH_STRIDE "/sdcard/Documents/raw_p010_image_with_stride.p010"
Dichen Zhang7e3ed122022-12-14 22:05:01 +000028#define RAW_YUV420_IMAGE "/sdcard/Documents/raw_yuv420_image.yuv420"
Dichen Zhang36c1e732022-11-23 01:25:34 +000029#define JPEG_IMAGE "/sdcard/Documents/jpeg_image.jpg"
Dichen Zhang7e3ed122022-12-14 22:05:01 +000030#define TEST_IMAGE_WIDTH 1280
31#define TEST_IMAGE_HEIGHT 720
Dichen Zhang66ca6e32023-04-05 12:22:54 -070032#define TEST_IMAGE_STRIDE 1288
Dichen Zhang7e3ed122022-12-14 22:05:01 +000033#define DEFAULT_JPEG_QUALITY 90
Dichen Zhang36c1e732022-11-23 01:25:34 +000034
35#define SAVE_ENCODING_RESULT true
36#define SAVE_DECODING_RESULT true
Harish Mahendrakar1e057282022-12-04 12:47:53 -080037#define SAVE_INPUT_RGBA true
Dichen Zhang85b37562022-10-11 11:08:28 -070038
Dichen Zhangdbceb0e2023-04-14 19:03:18 +000039namespace android::ultrahdr {
Dichen Zhang85b37562022-10-11 11:08:28 -070040
Nick Deakind19e5762023-02-10 15:39:08 -050041struct Timer {
42 struct timeval StartingTime;
43 struct timeval EndingTime;
44 struct timeval ElapsedMicroseconds;
Nick Deakin594a4ca2022-11-16 20:57:42 -050045};
46
Nick Deakind19e5762023-02-10 15:39:08 -050047void timerStart(Timer *t) {
48 gettimeofday(&t->StartingTime, nullptr);
49}
Nick Deakin594a4ca2022-11-16 20:57:42 -050050
Nick Deakind19e5762023-02-10 15:39:08 -050051void timerStop(Timer *t) {
52 gettimeofday(&t->EndingTime, nullptr);
53}
54
55int64_t elapsedTime(Timer *t) {
56 t->ElapsedMicroseconds.tv_sec = t->EndingTime.tv_sec - t->StartingTime.tv_sec;
57 t->ElapsedMicroseconds.tv_usec = t->EndingTime.tv_usec - t->StartingTime.tv_usec;
58 return t->ElapsedMicroseconds.tv_sec * 1000000 + t->ElapsedMicroseconds.tv_usec;
Dichen Zhang36c1e732022-11-23 01:25:34 +000059}
60
61static size_t getFileSize(int fd) {
62 struct stat st;
63 if (fstat(fd, &st) < 0) {
64 ALOGW("%s : fstat failed", __func__);
65 return 0;
66 }
67 return st.st_size; // bytes
68}
69
70static bool loadFile(const char filename[], void*& result, int* fileLength) {
71 int fd = open(filename, O_CLOEXEC);
72 if (fd < 0) {
73 return false;
74 }
75 int length = getFileSize(fd);
76 if (length == 0) {
77 close(fd);
78 return false;
79 }
80 if (fileLength != nullptr) {
81 *fileLength = length;
82 }
83 result = malloc(length);
84 if (read(fd, result, length) != static_cast<ssize_t>(length)) {
85 close(fd);
86 return false;
87 }
88 close(fd);
89 return true;
90}
Nick Deakin594a4ca2022-11-16 20:57:42 -050091
Ram Mohanfd7bb542023-05-20 00:55:56 +053092static bool loadP010Image(const char *filename, jr_uncompressed_ptr img,
93 bool isUVContiguous) {
94 int fd = open(filename, O_CLOEXEC);
95 if (fd < 0) {
96 return false;
97 }
98 const int bpp = 2;
99 int lumaStride = img->luma_stride == 0 ? img->width : img->luma_stride;
100 int lumaSize = bpp * lumaStride * img->height;
101 int chromaSize = bpp * (img->height / 2) *
102 (isUVContiguous ? lumaStride : img->chroma_stride);
103 img->data = malloc(lumaSize + (isUVContiguous ? chromaSize : 0));
104 if (img->data == nullptr) {
105 ALOGE("loadP010Image(): failed to allocate memory for luma data.");
106 return false;
107 }
108 uint8_t *mem = static_cast<uint8_t *>(img->data);
109 for (int i = 0; i < img->height; i++) {
110 if (read(fd, mem, img->width * bpp) != img->width * bpp) {
111 close(fd);
112 return false;
113 }
114 mem += lumaStride * bpp;
115 }
116 int chromaStride = lumaStride;
117 if (!isUVContiguous) {
118 img->chroma_data = malloc(chromaSize);
119 if (img->chroma_data == nullptr) {
120 ALOGE("loadP010Image(): failed to allocate memory for chroma data.");
121 return false;
122 }
123 mem = static_cast<uint8_t *>(img->chroma_data);
124 chromaStride = img->chroma_stride;
125 }
126 for (int i = 0; i < img->height / 2; i++) {
127 if (read(fd, mem, img->width * bpp) != img->width * bpp) {
128 close(fd);
129 return false;
130 }
131 mem += chromaStride * bpp;
132 }
133 close(fd);
134 return true;
135}
136
Dichen Zhang761b52d2023-02-10 22:38:38 +0000137class JpegRTest : public testing::Test {
Nick Deakind19e5762023-02-10 15:39:08 -0500138public:
Dichen Zhang761b52d2023-02-10 22:38:38 +0000139 JpegRTest();
140 ~JpegRTest();
Nick Deakind19e5762023-02-10 15:39:08 -0500141
142protected:
143 virtual void SetUp();
144 virtual void TearDown();
145
Ram Mohanfd7bb542023-05-20 00:55:56 +0530146 struct jpegr_uncompressed_struct mRawP010Image{};
147 struct jpegr_uncompressed_struct mRawP010ImageWithStride{};
148 struct jpegr_uncompressed_struct mRawP010ImageWithChromaData{};
149 struct jpegr_uncompressed_struct mRawYuv420Image{};
150 struct jpegr_compressed_struct mJpegImage{};
Nick Deakind19e5762023-02-10 15:39:08 -0500151};
152
Dichen Zhang761b52d2023-02-10 22:38:38 +0000153JpegRTest::JpegRTest() {}
154JpegRTest::~JpegRTest() {}
Nick Deakind19e5762023-02-10 15:39:08 -0500155
Dichen Zhang761b52d2023-02-10 22:38:38 +0000156void JpegRTest::SetUp() {}
157void JpegRTest::TearDown() {
Nick Deakind19e5762023-02-10 15:39:08 -0500158 free(mRawP010Image.data);
Ram Mohanfd7bb542023-05-20 00:55:56 +0530159 free(mRawP010Image.chroma_data);
Dichen Zhang66ca6e32023-04-05 12:22:54 -0700160 free(mRawP010ImageWithStride.data);
Ram Mohanfd7bb542023-05-20 00:55:56 +0530161 free(mRawP010ImageWithStride.chroma_data);
162 free(mRawP010ImageWithChromaData.data);
163 free(mRawP010ImageWithChromaData.chroma_data);
Nick Deakind19e5762023-02-10 15:39:08 -0500164 free(mRawYuv420Image.data);
165 free(mJpegImage.data);
166}
167
Dichen Zhang761b52d2023-02-10 22:38:38 +0000168class JpegRBenchmark : public JpegR {
Nick Deakind19e5762023-02-10 15:39:08 -0500169public:
Dichen Zhang10959a42023-04-10 16:28:16 -0700170 void BenchmarkGenerateGainMap(jr_uncompressed_ptr yuv420Image, jr_uncompressed_ptr p010Image,
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000171 ultrahdr_metadata_ptr metadata, jr_uncompressed_ptr map);
Dichen Zhang10959a42023-04-10 16:28:16 -0700172 void BenchmarkApplyGainMap(jr_uncompressed_ptr yuv420Image, jr_uncompressed_ptr map,
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000173 ultrahdr_metadata_ptr metadata, jr_uncompressed_ptr dest);
Nick Deakind19e5762023-02-10 15:39:08 -0500174private:
175 const int kProfileCount = 10;
176};
177
Dichen Zhang10959a42023-04-10 16:28:16 -0700178void JpegRBenchmark::BenchmarkGenerateGainMap(jr_uncompressed_ptr yuv420Image,
179 jr_uncompressed_ptr p010Image,
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000180 ultrahdr_metadata_ptr metadata,
Dichen Zhang10959a42023-04-10 16:28:16 -0700181 jr_uncompressed_ptr map) {
Nick Deakind19e5762023-02-10 15:39:08 -0500182 ASSERT_EQ(yuv420Image->width, p010Image->width);
183 ASSERT_EQ(yuv420Image->height, p010Image->height);
184
185 Timer genRecMapTime;
186
187 timerStart(&genRecMapTime);
188 for (auto i = 0; i < kProfileCount; i++) {
Dichen Zhang10959a42023-04-10 16:28:16 -0700189 ASSERT_EQ(OK, generateGainMap(
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000190 yuv420Image, p010Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, metadata, map));
Nick Deakind19e5762023-02-10 15:39:08 -0500191 if (i != kProfileCount - 1) delete[] static_cast<uint8_t *>(map->data);
192 }
193 timerStop(&genRecMapTime);
194
Dichen Zhang10959a42023-04-10 16:28:16 -0700195 ALOGE("Generate Gain Map:- Res = %i x %i, time = %f ms",
Nick Deakind19e5762023-02-10 15:39:08 -0500196 yuv420Image->width, yuv420Image->height,
197 elapsedTime(&genRecMapTime) / (kProfileCount * 1000.f));
198
199}
200
Dichen Zhang10959a42023-04-10 16:28:16 -0700201void JpegRBenchmark::BenchmarkApplyGainMap(jr_uncompressed_ptr yuv420Image,
202 jr_uncompressed_ptr map,
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000203 ultrahdr_metadata_ptr metadata,
Dichen Zhang10959a42023-04-10 16:28:16 -0700204 jr_uncompressed_ptr dest) {
Nick Deakind19e5762023-02-10 15:39:08 -0500205 Timer applyRecMapTime;
206
207 timerStart(&applyRecMapTime);
208 for (auto i = 0; i < kProfileCount; i++) {
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000209 ASSERT_EQ(OK, applyGainMap(yuv420Image, map, metadata, ULTRAHDR_OUTPUT_HDR_HLG,
Dichen Zhang10959a42023-04-10 16:28:16 -0700210 metadata->maxContentBoost /* displayBoost */, dest));
Nick Deakind19e5762023-02-10 15:39:08 -0500211 }
212 timerStop(&applyRecMapTime);
213
Dichen Zhang10959a42023-04-10 16:28:16 -0700214 ALOGE("Apply Gain Map:- Res = %i x %i, time = %f ms",
Nick Deakind19e5762023-02-10 15:39:08 -0500215 yuv420Image->width, yuv420Image->height,
216 elapsedTime(&applyRecMapTime) / (kProfileCount * 1000.f));
217}
218
Dichen Zhang761b52d2023-02-10 22:38:38 +0000219TEST_F(JpegRTest, build) {
Dichen Zhang10959a42023-04-10 16:28:16 -0700220 // Force all of the gain map lib to be linked by calling all public functions.
Dichen Zhang761b52d2023-02-10 22:38:38 +0000221 JpegR jpegRCodec;
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000222 jpegRCodec.encodeJPEGR(nullptr, static_cast<ultrahdr_transfer_function>(0), nullptr, 0, nullptr);
223 jpegRCodec.encodeJPEGR(nullptr, nullptr, static_cast<ultrahdr_transfer_function>(0),
Dichen Zhang761b52d2023-02-10 22:38:38 +0000224 nullptr, 0, nullptr);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000225 jpegRCodec.encodeJPEGR(nullptr, nullptr, nullptr, static_cast<ultrahdr_transfer_function>(0),
Dichen Zhang761b52d2023-02-10 22:38:38 +0000226 nullptr);
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000227 jpegRCodec.encodeJPEGR(nullptr, nullptr, static_cast<ultrahdr_transfer_function>(0), nullptr);
Dichen Zhangc6605702023-03-15 18:40:55 -0700228 jpegRCodec.decodeJPEGR(nullptr, nullptr);
Nick Deakin594a4ca2022-11-16 20:57:42 -0500229}
230
Ram Mohan35ab3a82023-05-18 18:38:16 +0530231/* Test Encode API-0 invalid arguments */
232TEST_F(JpegRTest, encodeAPI0ForInvalidArgs) {
233 int ret;
234
235 // we are not really compressing anything so lets keep allocs to a minimum
236 jpegr_compressed_struct jpegR;
237 jpegR.maxLength = 16 * sizeof(uint8_t);
238 jpegR.data = malloc(jpegR.maxLength);
239
240 JpegR jpegRCodec;
241
242 // we are not really compressing anything so lets keep allocs to a minimum
243 mRawP010ImageWithStride.data = malloc(16);
244 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
245 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
246 mRawP010ImageWithStride.luma_stride = TEST_IMAGE_STRIDE;
247 mRawP010ImageWithStride.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
248
249 // test quality factor
250 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
251 &mRawP010ImageWithStride, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR,
252 -1, nullptr)) << "fail, API allows bad jpeg quality factor";
253
254 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
255 &mRawP010ImageWithStride, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR,
256 101, nullptr)) << "fail, API allows bad jpeg quality factor";
257
258 // test hdr transfer function
259 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
260 &mRawP010ImageWithStride, ultrahdr_transfer_function::ULTRAHDR_TF_UNSPECIFIED, &jpegR,
261 DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows bad hdr transfer function";
262
263 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
264 &mRawP010ImageWithStride,
265 static_cast<ultrahdr_transfer_function>(ultrahdr_transfer_function::ULTRAHDR_TF_MAX + 1),
266 &jpegR, DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows bad hdr transfer function";
267
268 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
269 &mRawP010ImageWithStride,
270 static_cast<ultrahdr_transfer_function>(-10),
271 &jpegR, DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows bad hdr transfer function";
272
273 // test dest
274 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
275 &mRawP010ImageWithStride, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, nullptr,
276 DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows nullptr dest";
277
278 // test p010 input
279 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
280 nullptr, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR,
281 DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows nullptr p010 image";
282
283 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
284 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
285 mRawP010ImageWithStride.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_UNSPECIFIED;
286 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
287 &mRawP010ImageWithStride, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR,
288 DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows bad p010 color gamut";
289
290 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
291 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
292 mRawP010ImageWithStride.colorGamut = static_cast<ultrahdr_color_gamut>(
293 ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_MAX + 1);
294 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
295 &mRawP010ImageWithStride, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR,
296 DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows bad p010 color gamut";
297
298 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH - 1;
299 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
300 mRawP010ImageWithStride.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
301 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
302 &mRawP010ImageWithStride, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR,
303 DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows bad image width";
304
305 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
306 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT - 1;
307 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
308 &mRawP010ImageWithStride, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR,
309 DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows bad image height";
310
311 mRawP010ImageWithStride.width = 0;
312 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
313 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
314 &mRawP010ImageWithStride, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR,
315 DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows bad image width";
316
317 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
318 mRawP010ImageWithStride.height = 0;
319 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
320 &mRawP010ImageWithStride, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR,
321 DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows bad image height";
322
323 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
324 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
325 mRawP010ImageWithStride.luma_stride = TEST_IMAGE_WIDTH - 2;
326 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
327 &mRawP010ImageWithStride, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR,
328 DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows bad luma stride";
329
330 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
331 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
332 mRawP010ImageWithStride.luma_stride = TEST_IMAGE_STRIDE;
333 mRawP010ImageWithStride.chroma_data = mRawP010ImageWithStride.data;
334 mRawP010ImageWithStride.chroma_stride = TEST_IMAGE_WIDTH - 2;
335 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
336 &mRawP010ImageWithStride, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR,
337 DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows bad chroma stride";
338
Ram Mohanfd7bb542023-05-20 00:55:56 +0530339 mRawP010ImageWithStride.chroma_data = nullptr;
340
Ram Mohan35ab3a82023-05-18 18:38:16 +0530341 free(jpegR.data);
342}
343
344/* Test Encode API-1 invalid arguments */
345TEST_F(JpegRTest, encodeAPI1ForInvalidArgs) {
346 int ret;
347
348 // we are not really compressing anything so lets keep allocs to a minimum
349 jpegr_compressed_struct jpegR;
350 jpegR.maxLength = 16 * sizeof(uint8_t);
351 jpegR.data = malloc(jpegR.maxLength);
352
353 JpegR jpegRCodec;
354
355 // we are not really compressing anything so lets keep allocs to a minimum
356 mRawP010ImageWithStride.data = malloc(16);
357 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
358 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
359 mRawP010ImageWithStride.luma_stride = TEST_IMAGE_STRIDE;
360 mRawP010ImageWithStride.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
361
362 // we are not really compressing anything so lets keep allocs to a minimum
363 mRawYuv420Image.data = malloc(16);
364 mRawYuv420Image.width = TEST_IMAGE_WIDTH;
365 mRawYuv420Image.height = TEST_IMAGE_HEIGHT;
366 mRawYuv420Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709;
367
368 // test quality factor
369 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
370 &mRawP010ImageWithStride, &mRawYuv420Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
371 &jpegR, -1, nullptr)) << "fail, API allows bad jpeg quality factor";
372
373 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
374 &mRawP010ImageWithStride, &mRawYuv420Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
375 &jpegR, 101, nullptr)) << "fail, API allows bad jpeg quality factor";
376
377 // test hdr transfer function
378 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
379 &mRawP010ImageWithStride, &mRawYuv420Image,
380 ultrahdr_transfer_function::ULTRAHDR_TF_UNSPECIFIED, &jpegR, DEFAULT_JPEG_QUALITY,
381 nullptr)) << "fail, API allows bad hdr transfer function";
382
383 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
384 &mRawP010ImageWithStride, &mRawYuv420Image,
385 static_cast<ultrahdr_transfer_function>(ultrahdr_transfer_function::ULTRAHDR_TF_MAX + 1),
386 &jpegR, DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows bad hdr transfer function";
387
388 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
389 &mRawP010ImageWithStride, &mRawYuv420Image,
390 static_cast<ultrahdr_transfer_function>(-10),
391 &jpegR, DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows bad hdr transfer function";
392
393 // test dest
394 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
395 &mRawP010ImageWithStride, &mRawYuv420Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
396 nullptr, DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows nullptr dest";
397
398 // test p010 input
399 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
400 nullptr, &mRawYuv420Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR,
401 DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows nullptr p010 image";
402
403 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
404 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
405 mRawP010ImageWithStride.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_UNSPECIFIED;
406 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
407 &mRawP010ImageWithStride, &mRawYuv420Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
408 &jpegR, DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows bad p010 color gamut";
409
410 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
411 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
412 mRawP010ImageWithStride.colorGamut = static_cast<ultrahdr_color_gamut>(
413 ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_MAX + 1);
414 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
415 &mRawP010ImageWithStride, &mRawYuv420Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
416 &jpegR, DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows bad p010 color gamut";
417
418 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH - 1;
419 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
420 mRawP010ImageWithStride.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
421 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
422 &mRawP010ImageWithStride, &mRawYuv420Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
423 &jpegR, DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows bad image width";
424
425 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
426 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT - 1;
427 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
428 &mRawP010ImageWithStride, &mRawYuv420Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
429 &jpegR, DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows bad image height";
430
431 mRawP010ImageWithStride.width = 0;
432 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
433 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
434 &mRawP010ImageWithStride, &mRawYuv420Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
435 &jpegR, DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows bad image width";
436
437 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
438 mRawP010ImageWithStride.height = 0;
439 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
440 &mRawP010ImageWithStride, &mRawYuv420Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
441 &jpegR, DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows bad image height";
442
443 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
444 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
445 mRawP010ImageWithStride.luma_stride = TEST_IMAGE_WIDTH - 2;
446 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
447 &mRawP010ImageWithStride, &mRawYuv420Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
448 &jpegR, DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows bad luma stride";
449
450 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
451 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
452 mRawP010ImageWithStride.luma_stride = TEST_IMAGE_STRIDE;
453 mRawP010ImageWithStride.chroma_data = mRawP010ImageWithStride.data;
454 mRawP010ImageWithStride.chroma_stride = TEST_IMAGE_WIDTH - 2;
455 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
456 &mRawP010ImageWithStride, &mRawYuv420Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
457 &jpegR, DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows bad chroma stride";
458
459 // test 420 input
460 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
461 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
462 mRawP010ImageWithStride.luma_stride = TEST_IMAGE_STRIDE;
463 mRawP010ImageWithStride.chroma_data = nullptr;
464 mRawP010ImageWithStride.chroma_stride = 0;
465 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
466 &mRawP010ImageWithStride, nullptr, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR,
467 DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows nullptr for 420 image";
468
469 mRawYuv420Image.width = TEST_IMAGE_WIDTH;
470 mRawYuv420Image.height = TEST_IMAGE_HEIGHT - 2;
471 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
472 &mRawP010ImageWithStride, &mRawYuv420Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
473 &jpegR, DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows bad 420 image width";
474
475 mRawYuv420Image.width = TEST_IMAGE_WIDTH - 2;
476 mRawYuv420Image.height = TEST_IMAGE_HEIGHT;
477 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
478 &mRawP010ImageWithStride, &mRawYuv420Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
479 &jpegR, DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows bad 420 image height";
480
481 mRawYuv420Image.width = TEST_IMAGE_WIDTH;
482 mRawYuv420Image.height = TEST_IMAGE_HEIGHT;
483 mRawYuv420Image.luma_stride = TEST_IMAGE_STRIDE;
484 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
485 &mRawP010ImageWithStride, &mRawYuv420Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
486 &jpegR, DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows bad luma stride for 420";
487
488 mRawYuv420Image.width = TEST_IMAGE_WIDTH;
489 mRawYuv420Image.height = TEST_IMAGE_HEIGHT;
490 mRawYuv420Image.luma_stride = 0;
491 mRawYuv420Image.chroma_data = mRawYuv420Image.data;
492 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
493 &mRawP010ImageWithStride, &mRawYuv420Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
494 &jpegR, DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows chroma pointer for 420";
495
496 mRawYuv420Image.width = TEST_IMAGE_WIDTH;
497 mRawYuv420Image.height = TEST_IMAGE_HEIGHT;
498 mRawYuv420Image.luma_stride = 0;
499 mRawYuv420Image.chroma_data = nullptr;
500 mRawYuv420Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_UNSPECIFIED;
501 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
502 &mRawP010ImageWithStride, &mRawYuv420Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
503 &jpegR, DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows bad 420 color gamut";
504
505 mRawYuv420Image.colorGamut = static_cast<ultrahdr_color_gamut>(
506 ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_MAX + 1);
507 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
508 &mRawP010ImageWithStride, &mRawYuv420Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
509 &jpegR, DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows bad 420 color gamut";
510
511 free(jpegR.data);
512}
513
514/* Test Encode API-2 invalid arguments */
515TEST_F(JpegRTest, encodeAPI2ForInvalidArgs) {
516 int ret;
517
518 // we are not really compressing anything so lets keep allocs to a minimum
519 jpegr_compressed_struct jpegR;
520 jpegR.maxLength = 16 * sizeof(uint8_t);
521 jpegR.data = malloc(jpegR.maxLength);
522
523 JpegR jpegRCodec;
524
525 // we are not really compressing anything so lets keep allocs to a minimum
526 mRawP010ImageWithStride.data = malloc(16);
527 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
528 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
529 mRawP010ImageWithStride.luma_stride = TEST_IMAGE_STRIDE;
530 mRawP010ImageWithStride.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
531
532 // we are not really compressing anything so lets keep allocs to a minimum
533 mRawYuv420Image.data = malloc(16);
534 mRawYuv420Image.width = TEST_IMAGE_WIDTH;
535 mRawYuv420Image.height = TEST_IMAGE_HEIGHT;
536 mRawYuv420Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709;
537
538 // test hdr transfer function
539 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
540 &mRawP010ImageWithStride, &mRawYuv420Image, &jpegR,
541 ultrahdr_transfer_function::ULTRAHDR_TF_UNSPECIFIED,
542 &jpegR)) << "fail, API allows bad hdr transfer function";
543
544 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
545 &mRawP010ImageWithStride, &mRawYuv420Image, &jpegR,
546 static_cast<ultrahdr_transfer_function>(ultrahdr_transfer_function::ULTRAHDR_TF_MAX + 1),
547 &jpegR)) << "fail, API allows bad hdr transfer function";
548
549 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
550 &mRawP010ImageWithStride, &mRawYuv420Image, &jpegR,
551 static_cast<ultrahdr_transfer_function>(-10),
552 &jpegR)) << "fail, API allows bad hdr transfer function";
553
554 // test dest
555 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
556 &mRawP010ImageWithStride, &mRawYuv420Image, &jpegR,
557 ultrahdr_transfer_function::ULTRAHDR_TF_HLG, nullptr)) << "fail, API allows nullptr dest";
558
559 // test p010 input
560 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
561 nullptr, &mRawYuv420Image, &jpegR, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
562 &jpegR)) << "fail, API allows nullptr p010 image";
563
564 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
565 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
566 mRawP010ImageWithStride.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_UNSPECIFIED;
567 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
568 &mRawP010ImageWithStride, &mRawYuv420Image, &jpegR,
569 ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
570 &jpegR)) << "fail, API allows bad p010 color gamut";
571
572 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
573 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
574 mRawP010ImageWithStride.colorGamut = static_cast<ultrahdr_color_gamut>(
575 ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_MAX + 1);
576 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
577 &mRawP010ImageWithStride, &mRawYuv420Image, &jpegR,
578 ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
579 &jpegR)) << "fail, API allows bad p010 color gamut";
580
581 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH - 1;
582 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
583 mRawP010ImageWithStride.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
584 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
585 &mRawP010ImageWithStride, &mRawYuv420Image, &jpegR,
586 ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR)) << "fail, API allows bad image width";
587
588 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
589 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT - 1;
590 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
591 &mRawP010ImageWithStride, &mRawYuv420Image, &jpegR,
592 ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR)) << "fail, API allows bad image height";
593
594 mRawP010ImageWithStride.width = 0;
595 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
596 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
597 &mRawP010ImageWithStride, &mRawYuv420Image, &jpegR,
598 ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR)) << "fail, API allows bad image width";
599
600 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
601 mRawP010ImageWithStride.height = 0;
602 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
603 &mRawP010ImageWithStride, &mRawYuv420Image, &jpegR,
604 ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR)) << "fail, API allows bad image height";
605
606 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
607 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
608 mRawP010ImageWithStride.luma_stride = TEST_IMAGE_WIDTH - 2;
609 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
610 &mRawP010ImageWithStride, &mRawYuv420Image, &jpegR,
611 ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR)) << "fail, API allows bad luma stride";
612
613 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
614 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
615 mRawP010ImageWithStride.luma_stride = TEST_IMAGE_STRIDE;
616 mRawP010ImageWithStride.chroma_data = mRawP010ImageWithStride.data;
617 mRawP010ImageWithStride.chroma_stride = TEST_IMAGE_WIDTH - 2;
618 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
619 &mRawP010ImageWithStride, &mRawYuv420Image, &jpegR,
620 ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
621 &jpegR)) << "fail, API allows bad chroma stride";
622
623 // test 420 input
624 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
625 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
626 mRawP010ImageWithStride.luma_stride = TEST_IMAGE_STRIDE;
627 mRawP010ImageWithStride.chroma_data = nullptr;
628 mRawP010ImageWithStride.chroma_stride = 0;
629 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
630 &mRawP010ImageWithStride, nullptr, &jpegR,
631 ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
632 &jpegR)) << "fail, API allows nullptr for 420 image";
633
634 mRawYuv420Image.width = TEST_IMAGE_WIDTH;
635 mRawYuv420Image.height = TEST_IMAGE_HEIGHT - 2;
636 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
637 &mRawP010ImageWithStride, &mRawYuv420Image, &jpegR,
638 ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
639 &jpegR)) << "fail, API allows bad 420 image width";
640
641 mRawYuv420Image.width = TEST_IMAGE_WIDTH - 2;
642 mRawYuv420Image.height = TEST_IMAGE_HEIGHT;
643 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
644 &mRawP010ImageWithStride, &mRawYuv420Image, &jpegR,
645 ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
646 &jpegR)) << "fail, API allows bad 420 image height";
647
648 mRawYuv420Image.width = TEST_IMAGE_WIDTH;
649 mRawYuv420Image.height = TEST_IMAGE_HEIGHT;
650 mRawYuv420Image.luma_stride = TEST_IMAGE_STRIDE;
651 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
652 &mRawP010ImageWithStride, &mRawYuv420Image, &jpegR,
653 ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
654 &jpegR)) << "fail, API allows bad luma stride for 420";
655
656 mRawYuv420Image.width = TEST_IMAGE_WIDTH;
657 mRawYuv420Image.height = TEST_IMAGE_HEIGHT;
658 mRawYuv420Image.luma_stride = 0;
659 mRawYuv420Image.chroma_data = mRawYuv420Image.data;
660 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
661 &mRawP010ImageWithStride, &mRawYuv420Image, &jpegR,
662 ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
663 &jpegR)) << "fail, API allows chroma pointer for 420";
664
665 mRawYuv420Image.width = TEST_IMAGE_WIDTH;
666 mRawYuv420Image.height = TEST_IMAGE_HEIGHT;
667 mRawYuv420Image.luma_stride = 0;
668 mRawYuv420Image.chroma_data = nullptr;
669 mRawYuv420Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_UNSPECIFIED;
670 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
671 &mRawP010ImageWithStride, &mRawYuv420Image, &jpegR,
672 ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
673 &jpegR)) << "fail, API allows bad 420 color gamut";
674
675 mRawYuv420Image.colorGamut = static_cast<ultrahdr_color_gamut>(
676 ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_MAX + 1);
677 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
678 &mRawP010ImageWithStride, &mRawYuv420Image, &jpegR,
679 ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
680 &jpegR)) << "fail, API allows bad 420 color gamut";
681
682 // bad compressed image
683 mRawYuv420Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709;
684 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
685 &mRawP010ImageWithStride, &mRawYuv420Image, nullptr,
686 ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
687 &jpegR)) << "fail, API allows bad 420 color gamut";
688
689 free(jpegR.data);
690}
691
692/* Test Encode API-3 invalid arguments */
693TEST_F(JpegRTest, encodeAPI3ForInvalidArgs) {
694 int ret;
695
696 // we are not really compressing anything so lets keep allocs to a minimum
697 jpegr_compressed_struct jpegR;
698 jpegR.maxLength = 16 * sizeof(uint8_t);
699 jpegR.data = malloc(jpegR.maxLength);
700
701 JpegR jpegRCodec;
702
703 // we are not really compressing anything so lets keep allocs to a minimum
704 mRawP010ImageWithStride.data = malloc(16);
705 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
706 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
707 mRawP010ImageWithStride.luma_stride = TEST_IMAGE_STRIDE;
708 mRawP010ImageWithStride.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
709
710 // test hdr transfer function
711 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
712 &mRawP010ImageWithStride, &jpegR, ultrahdr_transfer_function::ULTRAHDR_TF_UNSPECIFIED,
713 &jpegR)) << "fail, API allows bad hdr transfer function";
714
715 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
716 &mRawP010ImageWithStride, &jpegR,
717 static_cast<ultrahdr_transfer_function>(ultrahdr_transfer_function::ULTRAHDR_TF_MAX + 1),
718 &jpegR)) << "fail, API allows bad hdr transfer function";
719
720 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
721 &mRawP010ImageWithStride, &jpegR, static_cast<ultrahdr_transfer_function>(-10),
722 &jpegR)) << "fail, API allows bad hdr transfer function";
723
724 // test dest
725 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
726 &mRawP010ImageWithStride, &jpegR, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
727 nullptr)) << "fail, API allows nullptr dest";
728
729 // test p010 input
730 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
731 nullptr, &jpegR, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
732 &jpegR)) << "fail, API allows nullptr p010 image";
733
734 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
735 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
736 mRawP010ImageWithStride.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_UNSPECIFIED;
737 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
738 &mRawP010ImageWithStride, &jpegR, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
739 &jpegR)) << "fail, API allows bad p010 color gamut";
740
741 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
742 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
743 mRawP010ImageWithStride.colorGamut = static_cast<ultrahdr_color_gamut>(
744 ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_MAX + 1);
745 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
746 &mRawP010ImageWithStride, &jpegR, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
747 &jpegR)) << "fail, API allows bad p010 color gamut";
748
749 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH - 1;
750 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
751 mRawP010ImageWithStride.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
752 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
753 &mRawP010ImageWithStride, &jpegR, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
754 &jpegR)) << "fail, API allows bad image width";
755
756 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
757 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT - 1;
758 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
759 &mRawP010ImageWithStride, &jpegR, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
760 &jpegR)) << "fail, API allows bad image height";
761
762 mRawP010ImageWithStride.width = 0;
763 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
764 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
765 &mRawP010ImageWithStride, &jpegR, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
766 &jpegR)) << "fail, API allows bad image width";
767
768 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
769 mRawP010ImageWithStride.height = 0;
770 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
771 &mRawP010ImageWithStride, &jpegR, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
772 &jpegR)) << "fail, API allows bad image height";
773
774 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
775 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
776 mRawP010ImageWithStride.luma_stride = TEST_IMAGE_WIDTH - 2;
777 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
778 &mRawP010ImageWithStride, &jpegR, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
779 &jpegR)) << "fail, API allows bad luma stride";
780
781 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
782 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
783 mRawP010ImageWithStride.luma_stride = TEST_IMAGE_STRIDE;
784 mRawP010ImageWithStride.chroma_data = mRawP010ImageWithStride.data;
785 mRawP010ImageWithStride.chroma_stride = TEST_IMAGE_WIDTH - 2;
786 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
787 &mRawP010ImageWithStride, &jpegR, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
788 &jpegR)) << "fail, API allows bad chroma stride";
Ram Mohanfd7bb542023-05-20 00:55:56 +0530789 mRawP010ImageWithStride.chroma_data = nullptr;
Ram Mohan35ab3a82023-05-18 18:38:16 +0530790
791 // bad compressed image
792 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
793 &mRawP010ImageWithStride, nullptr, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
794 &jpegR)) << "fail, API allows bad 420 color gamut";
795
796 free(jpegR.data);
797}
798
799/* Test Encode API-4 invalid arguments */
800TEST_F(JpegRTest, encodeAPI4ForInvalidArgs) {
801 int ret;
802
803 // we are not really compressing anything so lets keep allocs to a minimum
804 jpegr_compressed_struct jpegR;
805 jpegR.maxLength = 16 * sizeof(uint8_t);
806 jpegR.data = malloc(jpegR.maxLength);
807
808 JpegR jpegRCodec;
809
810 // test dest
811 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
812 &jpegR, &jpegR, nullptr, nullptr)) << "fail, API allows nullptr dest";
813
814 // test primary image
815 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
816 nullptr, &jpegR, nullptr, &jpegR)) << "fail, API allows nullptr primary image";
817
818 // test gain map
819 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
820 &jpegR, nullptr, nullptr, &jpegR)) << "fail, API allows nullptr gainmap image";
821
Nick Deakin094946b2023-06-09 11:58:41 -0400822 // test metadata
823 ultrahdr_metadata_struct good_metadata;
824 good_metadata.version = "1.0";
825 good_metadata.minContentBoost = 1.0f;
826 good_metadata.maxContentBoost = 2.0f;
827 good_metadata.gamma = 1.0f;
828 good_metadata.offsetSdr = 0.0f;
829 good_metadata.offsetHdr = 0.0f;
830 good_metadata.hdrCapacityMin = 1.0f;
831 good_metadata.hdrCapacityMax = 2.0f;
832
833 ultrahdr_metadata_struct metadata = good_metadata;
834 metadata.version = "1.1";
835 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
836 &jpegR, nullptr, &metadata, &jpegR)) << "fail, API allows bad metadata version";
837
838 metadata = good_metadata;
839 metadata.minContentBoost = 3.0f;
840 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
841 &jpegR, nullptr, &metadata, &jpegR)) << "fail, API allows bad metadata content boost";
842
843 metadata = good_metadata;
844 metadata.gamma = -0.1f;
845 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
846 &jpegR, nullptr, &metadata, &jpegR)) << "fail, API allows bad metadata gamma";
847
848 metadata = good_metadata;
849 metadata.offsetSdr = -0.1f;
850 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
851 &jpegR, nullptr, &metadata, &jpegR)) << "fail, API allows bad metadata offset sdr";
852
853 metadata = good_metadata;
854 metadata.offsetHdr = -0.1f;
855 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
856 &jpegR, nullptr, &metadata, &jpegR)) << "fail, API allows bad metadata offset hdr";
857
858 metadata = good_metadata;
859 metadata.hdrCapacityMax = 0.5f;
860 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
861 &jpegR, nullptr, &metadata, &jpegR)) << "fail, API allows bad metadata hdr capacity max";
862
863 metadata = good_metadata;
864 metadata.hdrCapacityMin = 0.5f;
865 EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
866 &jpegR, nullptr, &metadata, &jpegR)) << "fail, API allows bad metadata hdr capacity min";
867
Ram Mohan35ab3a82023-05-18 18:38:16 +0530868 free(jpegR.data);
869}
870
Ram Mohanb0375052023-05-20 04:03:48 +0530871/* Test Decode API invalid arguments */
872TEST_F(JpegRTest, decodeAPIForInvalidArgs) {
873 int ret;
874
875 // we are not really compressing anything so lets keep allocs to a minimum
876 jpegr_compressed_struct jpegR;
877 jpegR.maxLength = 16 * sizeof(uint8_t);
878 jpegR.data = malloc(jpegR.maxLength);
879
880 // we are not really decoding anything so lets keep allocs to a minimum
881 mRawP010Image.data = malloc(16);
882
883 JpegR jpegRCodec;
884
885 // test jpegr image
886 EXPECT_NE(OK, jpegRCodec.decodeJPEGR(
887 nullptr, &mRawP010Image)) << "fail, API allows nullptr for jpegr img";
888
889 // test dest image
890 EXPECT_NE(OK, jpegRCodec.decodeJPEGR(
891 &jpegR, nullptr)) << "fail, API allows nullptr for dest";
892
893 // test max display boost
894 EXPECT_NE(OK, jpegRCodec.decodeJPEGR(
895 &jpegR, &mRawP010Image, 0.5)) << "fail, API allows invalid max display boost";
896
897 // test output format
898 EXPECT_NE(OK, jpegRCodec.decodeJPEGR(
899 &jpegR, &mRawP010Image, 0.5, nullptr,
900 static_cast<ultrahdr_output_format>(-1))) << "fail, API allows invalid output format";
901
902 EXPECT_NE(OK, jpegRCodec.decodeJPEGR(
903 &jpegR, &mRawP010Image, 0.5, nullptr,
904 static_cast<ultrahdr_output_format>(ULTRAHDR_OUTPUT_MAX + 1)))
905 << "fail, API allows invalid output format";
906
907 free(jpegR.data);
908}
909
Dichen Zhang761b52d2023-02-10 22:38:38 +0000910TEST_F(JpegRTest, writeXmpThenRead) {
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000911 ultrahdr_metadata_struct metadata_expected;
Nick Deakin05ceebf2023-04-19 15:27:13 -0400912 metadata_expected.version = "1.0";
Nick Deakin094946b2023-06-09 11:58:41 -0400913 metadata_expected.maxContentBoost = 1.25f;
914 metadata_expected.minContentBoost = 0.75f;
915 metadata_expected.gamma = 1.0f;
916 metadata_expected.offsetSdr = 0.0f;
917 metadata_expected.offsetHdr = 0.0f;
918 metadata_expected.hdrCapacityMin = 1.0f;
919 metadata_expected.hdrCapacityMax = metadata_expected.maxContentBoost;
Fyodor Kyslov8f46e2a2023-01-20 04:21:56 +0000920 const std::string nameSpace = "http://ns.adobe.com/xap/1.0/\0";
921 const int nameSpaceLength = nameSpace.size() + 1; // need to count the null terminator
922
Dichen Zhang61ede362023-02-22 18:50:13 +0000923 std::string xmp = generateXmpForSecondaryImage(metadata_expected);
Dichen Zhangdc8452b2022-11-23 17:17:56 +0000924
Fyodor Kyslov8f46e2a2023-01-20 04:21:56 +0000925 std::vector<uint8_t> xmpData;
926 xmpData.reserve(nameSpaceLength + xmp.size());
927 xmpData.insert(xmpData.end(), reinterpret_cast<const uint8_t*>(nameSpace.c_str()),
928 reinterpret_cast<const uint8_t*>(nameSpace.c_str()) + nameSpaceLength);
929 xmpData.insert(xmpData.end(), reinterpret_cast<const uint8_t*>(xmp.c_str()),
930 reinterpret_cast<const uint8_t*>(xmp.c_str()) + xmp.size());
931
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000932 ultrahdr_metadata_struct metadata_read;
Fyodor Kyslov8f46e2a2023-01-20 04:21:56 +0000933 EXPECT_TRUE(getMetadataFromXMP(xmpData.data(), xmpData.size(), &metadata_read));
Nick Deakin31f03e32023-03-31 16:00:13 -0400934 EXPECT_FLOAT_EQ(metadata_expected.maxContentBoost, metadata_read.maxContentBoost);
935 EXPECT_FLOAT_EQ(metadata_expected.minContentBoost, metadata_read.minContentBoost);
Nick Deakin094946b2023-06-09 11:58:41 -0400936 EXPECT_FLOAT_EQ(metadata_expected.gamma, metadata_read.gamma);
937 EXPECT_FLOAT_EQ(metadata_expected.offsetSdr, metadata_read.offsetSdr);
938 EXPECT_FLOAT_EQ(metadata_expected.offsetHdr, metadata_read.offsetHdr);
939 EXPECT_FLOAT_EQ(metadata_expected.hdrCapacityMin, metadata_read.hdrCapacityMin);
940 EXPECT_FLOAT_EQ(metadata_expected.hdrCapacityMax, metadata_read.hdrCapacityMax);
Dichen Zhangdc8452b2022-11-23 17:17:56 +0000941}
Dichen Zhang7e3ed122022-12-14 22:05:01 +0000942
Ram Mohanfd7bb542023-05-20 00:55:56 +0530943/* Test Encode API-0 */
944TEST_F(JpegRTest, encodeFromP010) {
945 int ret;
946
947 mRawP010Image.width = TEST_IMAGE_WIDTH;
948 mRawP010Image.height = TEST_IMAGE_HEIGHT;
949 mRawP010Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
950 // Load input files.
951 if (!loadP010Image(RAW_P010_IMAGE, &mRawP010Image, true)) {
952 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
953 }
954
955 JpegR jpegRCodec;
956
957 jpegr_compressed_struct jpegR;
958 jpegR.maxLength = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * sizeof(uint8_t);
959 jpegR.data = malloc(jpegR.maxLength);
960 ret = jpegRCodec.encodeJPEGR(
961 &mRawP010Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR, DEFAULT_JPEG_QUALITY,
962 nullptr);
963 if (ret != OK) {
964 FAIL() << "Error code is " << ret;
965 }
966
967 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
968 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
969 mRawP010ImageWithStride.luma_stride = TEST_IMAGE_WIDTH + 128;
970 mRawP010ImageWithStride.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
971 // Load input files.
972 if (!loadP010Image(RAW_P010_IMAGE, &mRawP010ImageWithStride, true)) {
973 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
974 }
975
976 jpegr_compressed_struct jpegRWithStride;
977 jpegRWithStride.maxLength = jpegR.length;
978 jpegRWithStride.data = malloc(jpegRWithStride.maxLength);
979 ret = jpegRCodec.encodeJPEGR(
980 &mRawP010ImageWithStride, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegRWithStride,
981 DEFAULT_JPEG_QUALITY, nullptr);
982 if (ret != OK) {
983 FAIL() << "Error code is " << ret;
984 }
985 ASSERT_EQ(jpegR.length, jpegRWithStride.length)
986 << "Same input is yielding different output";
987 ASSERT_EQ(0, memcmp(jpegR.data, jpegRWithStride.data, jpegR.length))
988 << "Same input is yielding different output";
989
990 mRawP010ImageWithChromaData.width = TEST_IMAGE_WIDTH;
991 mRawP010ImageWithChromaData.height = TEST_IMAGE_HEIGHT;
992 mRawP010ImageWithChromaData.luma_stride = TEST_IMAGE_WIDTH + 64;
993 mRawP010ImageWithChromaData.chroma_stride = TEST_IMAGE_WIDTH + 256;
994 mRawP010ImageWithChromaData.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
995 // Load input files.
996 if (!loadP010Image(RAW_P010_IMAGE, &mRawP010ImageWithChromaData, false)) {
997 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
998 }
999 jpegr_compressed_struct jpegRWithChromaData;
1000 jpegRWithChromaData.maxLength = jpegR.length;
1001 jpegRWithChromaData.data = malloc(jpegRWithChromaData.maxLength);
1002 ret = jpegRCodec.encodeJPEGR(
1003 &mRawP010ImageWithChromaData, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
1004 &jpegRWithChromaData, DEFAULT_JPEG_QUALITY, nullptr);
1005 if (ret != OK) {
1006 FAIL() << "Error code is " << ret;
1007 }
1008 ASSERT_EQ(jpegR.length, jpegRWithChromaData.length)
1009 << "Same input is yielding different output";
1010 ASSERT_EQ(0, memcmp(jpegR.data, jpegRWithChromaData.data, jpegR.length))
1011 << "Same input is yielding different output";
1012
1013 free(jpegR.data);
1014 free(jpegRWithStride.data);
1015 free(jpegRWithChromaData.data);
1016}
1017
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001018/* Test Encode API-0 and decode */
Dichen Zhang761b52d2023-02-10 22:38:38 +00001019TEST_F(JpegRTest, encodeFromP010ThenDecode) {
Dichen Zhangc3437ca2023-01-04 14:00:08 -08001020 int ret;
1021
1022 // Load input files.
1023 if (!loadFile(RAW_P010_IMAGE, mRawP010Image.data, nullptr)) {
1024 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
1025 }
1026 mRawP010Image.width = TEST_IMAGE_WIDTH;
1027 mRawP010Image.height = TEST_IMAGE_HEIGHT;
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001028 mRawP010Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
Dichen Zhangc3437ca2023-01-04 14:00:08 -08001029
Dichen Zhang761b52d2023-02-10 22:38:38 +00001030 JpegR jpegRCodec;
Dichen Zhangc3437ca2023-01-04 14:00:08 -08001031
1032 jpegr_compressed_struct jpegR;
1033 jpegR.maxLength = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * sizeof(uint8_t);
1034 jpegR.data = malloc(jpegR.maxLength);
Dichen Zhang761b52d2023-02-10 22:38:38 +00001035 ret = jpegRCodec.encodeJPEGR(
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001036 &mRawP010Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR, DEFAULT_JPEG_QUALITY,
1037 nullptr);
Dichen Zhangc3437ca2023-01-04 14:00:08 -08001038 if (ret != OK) {
1039 FAIL() << "Error code is " << ret;
1040 }
1041 if (SAVE_ENCODING_RESULT) {
1042 // Output image data to file
Dichen Zhang61ede362023-02-22 18:50:13 +00001043 std::string filePath = "/sdcard/Documents/encoded_from_p010_input.jpgr";
Dichen Zhangc3437ca2023-01-04 14:00:08 -08001044 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
1045 if (!imageFile.is_open()) {
1046 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
1047 }
1048 imageFile.write((const char*)jpegR.data, jpegR.length);
1049 }
1050
1051 jpegr_uncompressed_struct decodedJpegR;
Dichen Zhang3e5798c2023-03-01 22:30:43 +00001052 int decodedJpegRSize = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * 8;
Dichen Zhangc3437ca2023-01-04 14:00:08 -08001053 decodedJpegR.data = malloc(decodedJpegRSize);
Dichen Zhang761b52d2023-02-10 22:38:38 +00001054 ret = jpegRCodec.decodeJPEGR(&jpegR, &decodedJpegR);
Dichen Zhangc3437ca2023-01-04 14:00:08 -08001055 if (ret != OK) {
1056 FAIL() << "Error code is " << ret;
1057 }
1058 if (SAVE_DECODING_RESULT) {
1059 // Output image data to file
Dichen Zhang3e5798c2023-03-01 22:30:43 +00001060 std::string filePath = "/sdcard/Documents/decoded_from_p010_input.rgb";
Dichen Zhangc3437ca2023-01-04 14:00:08 -08001061 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
1062 if (!imageFile.is_open()) {
1063 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
1064 }
1065 imageFile.write((const char*)decodedJpegR.data, decodedJpegRSize);
1066 }
1067
1068 free(jpegR.data);
1069 free(decodedJpegR.data);
1070}
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001071
Dichen Zhang66ca6e32023-04-05 12:22:54 -07001072/* Test Encode API-0 (with stride) and decode */
1073TEST_F(JpegRTest, encodeFromP010WithStrideThenDecode) {
1074 int ret;
1075
1076 // Load input files.
1077 if (!loadFile(RAW_P010_IMAGE_WITH_STRIDE, mRawP010ImageWithStride.data, nullptr)) {
1078 FAIL() << "Load file " << RAW_P010_IMAGE_WITH_STRIDE << " failed";
1079 }
1080 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
1081 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
1082 mRawP010ImageWithStride.luma_stride = TEST_IMAGE_STRIDE;
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001083 mRawP010ImageWithStride.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
Dichen Zhang66ca6e32023-04-05 12:22:54 -07001084
1085 JpegR jpegRCodec;
1086
1087 jpegr_compressed_struct jpegR;
1088 jpegR.maxLength = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * sizeof(uint8_t);
1089 jpegR.data = malloc(jpegR.maxLength);
1090 ret = jpegRCodec.encodeJPEGR(
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001091 &mRawP010ImageWithStride, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR,
Dichen Zhang66ca6e32023-04-05 12:22:54 -07001092 DEFAULT_JPEG_QUALITY, nullptr);
1093 if (ret != OK) {
1094 FAIL() << "Error code is " << ret;
1095 }
1096 if (SAVE_ENCODING_RESULT) {
1097 // Output image data to file
1098 std::string filePath = "/sdcard/Documents/encoded_from_p010_input.jpgr";
1099 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
1100 if (!imageFile.is_open()) {
1101 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
1102 }
1103 imageFile.write((const char*)jpegR.data, jpegR.length);
1104 }
1105
1106 jpegr_uncompressed_struct decodedJpegR;
1107 int decodedJpegRSize = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * 8;
1108 decodedJpegR.data = malloc(decodedJpegRSize);
1109 ret = jpegRCodec.decodeJPEGR(&jpegR, &decodedJpegR);
1110 if (ret != OK) {
1111 FAIL() << "Error code is " << ret;
1112 }
1113 if (SAVE_DECODING_RESULT) {
1114 // Output image data to file
1115 std::string filePath = "/sdcard/Documents/decoded_from_p010_input.rgb";
1116 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
1117 if (!imageFile.is_open()) {
1118 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
1119 }
1120 imageFile.write((const char*)decodedJpegR.data, decodedJpegRSize);
1121 }
1122
1123 free(jpegR.data);
1124 free(decodedJpegR.data);
1125}
1126
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001127/* Test Encode API-1 and decode */
Dichen Zhang761b52d2023-02-10 22:38:38 +00001128TEST_F(JpegRTest, encodeFromRawHdrAndSdrThenDecode) {
Dichen Zhang54444382022-12-07 20:57:49 +00001129 int ret;
1130
1131 // Load input files.
1132 if (!loadFile(RAW_P010_IMAGE, mRawP010Image.data, nullptr)) {
1133 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
1134 }
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001135 mRawP010Image.width = TEST_IMAGE_WIDTH;
1136 mRawP010Image.height = TEST_IMAGE_HEIGHT;
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001137 mRawP010Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
Dichen Zhang54444382022-12-07 20:57:49 +00001138
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001139 if (!loadFile(RAW_YUV420_IMAGE, mRawYuv420Image.data, nullptr)) {
1140 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
1141 }
1142 mRawYuv420Image.width = TEST_IMAGE_WIDTH;
1143 mRawYuv420Image.height = TEST_IMAGE_HEIGHT;
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001144 mRawYuv420Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709;
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001145
Dichen Zhang761b52d2023-02-10 22:38:38 +00001146 JpegR jpegRCodec;
Dichen Zhang54444382022-12-07 20:57:49 +00001147
1148 jpegr_compressed_struct jpegR;
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001149 jpegR.maxLength = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * sizeof(uint8_t);
Dichen Zhang54444382022-12-07 20:57:49 +00001150 jpegR.data = malloc(jpegR.maxLength);
Dichen Zhang761b52d2023-02-10 22:38:38 +00001151 ret = jpegRCodec.encodeJPEGR(
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001152 &mRawP010Image, &mRawYuv420Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR,
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001153 DEFAULT_JPEG_QUALITY, nullptr);
Dichen Zhang54444382022-12-07 20:57:49 +00001154 if (ret != OK) {
1155 FAIL() << "Error code is " << ret;
1156 }
1157 if (SAVE_ENCODING_RESULT) {
1158 // Output image data to file
Dichen Zhang61ede362023-02-22 18:50:13 +00001159 std::string filePath = "/sdcard/Documents/encoded_from_p010_yuv420p_input.jpgr";
Dichen Zhang54444382022-12-07 20:57:49 +00001160 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
1161 if (!imageFile.is_open()) {
1162 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
1163 }
1164 imageFile.write((const char*)jpegR.data, jpegR.length);
1165 }
1166
1167 jpegr_uncompressed_struct decodedJpegR;
Dichen Zhang3e5798c2023-03-01 22:30:43 +00001168 int decodedJpegRSize = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * 8;
Dichen Zhang54444382022-12-07 20:57:49 +00001169 decodedJpegR.data = malloc(decodedJpegRSize);
Dichen Zhang761b52d2023-02-10 22:38:38 +00001170 ret = jpegRCodec.decodeJPEGR(&jpegR, &decodedJpegR);
Dichen Zhang54444382022-12-07 20:57:49 +00001171 if (ret != OK) {
1172 FAIL() << "Error code is " << ret;
1173 }
1174 if (SAVE_DECODING_RESULT) {
1175 // Output image data to file
Dichen Zhang3e5798c2023-03-01 22:30:43 +00001176 std::string filePath = "/sdcard/Documents/decoded_from_p010_yuv420p_input.rgb";
Dichen Zhang54444382022-12-07 20:57:49 +00001177 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
1178 if (!imageFile.is_open()) {
1179 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
1180 }
1181 imageFile.write((const char*)decodedJpegR.data, decodedJpegRSize);
1182 }
1183
1184 free(jpegR.data);
1185 free(decodedJpegR.data);
1186}
1187
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001188/* Test Encode API-2 and decode */
Dichen Zhang761b52d2023-02-10 22:38:38 +00001189TEST_F(JpegRTest, encodeFromRawHdrAndSdrAndJpegThenDecode) {
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001190 int ret;
1191
1192 // Load input files.
1193 if (!loadFile(RAW_P010_IMAGE, mRawP010Image.data, nullptr)) {
1194 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
1195 }
1196 mRawP010Image.width = TEST_IMAGE_WIDTH;
1197 mRawP010Image.height = TEST_IMAGE_HEIGHT;
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001198 mRawP010Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001199
1200 if (!loadFile(RAW_YUV420_IMAGE, mRawYuv420Image.data, nullptr)) {
1201 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
1202 }
1203 mRawYuv420Image.width = TEST_IMAGE_WIDTH;
1204 mRawYuv420Image.height = TEST_IMAGE_HEIGHT;
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001205 mRawYuv420Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709;
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001206
1207 if (!loadFile(JPEG_IMAGE, mJpegImage.data, &mJpegImage.length)) {
1208 FAIL() << "Load file " << JPEG_IMAGE << " failed";
1209 }
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001210 mJpegImage.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709;
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001211
Dichen Zhang761b52d2023-02-10 22:38:38 +00001212 JpegR jpegRCodec;
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001213
1214 jpegr_compressed_struct jpegR;
1215 jpegR.maxLength = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * sizeof(uint8_t);
1216 jpegR.data = malloc(jpegR.maxLength);
Dichen Zhang761b52d2023-02-10 22:38:38 +00001217 ret = jpegRCodec.encodeJPEGR(
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001218 &mRawP010Image, &mRawYuv420Image, &mJpegImage, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
1219 &jpegR);
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001220 if (ret != OK) {
1221 FAIL() << "Error code is " << ret;
1222 }
1223 if (SAVE_ENCODING_RESULT) {
1224 // Output image data to file
Dichen Zhang61ede362023-02-22 18:50:13 +00001225 std::string filePath = "/sdcard/Documents/encoded_from_p010_yuv420p_jpeg_input.jpgr";
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001226 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
1227 if (!imageFile.is_open()) {
1228 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
1229 }
1230 imageFile.write((const char*)jpegR.data, jpegR.length);
1231 }
1232
1233 jpegr_uncompressed_struct decodedJpegR;
Dichen Zhang3e5798c2023-03-01 22:30:43 +00001234 int decodedJpegRSize = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * 8;
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001235 decodedJpegR.data = malloc(decodedJpegRSize);
Dichen Zhang761b52d2023-02-10 22:38:38 +00001236 ret = jpegRCodec.decodeJPEGR(&jpegR, &decodedJpegR);
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001237 if (ret != OK) {
1238 FAIL() << "Error code is " << ret;
1239 }
1240 if (SAVE_DECODING_RESULT) {
1241 // Output image data to file
Dichen Zhang3e5798c2023-03-01 22:30:43 +00001242 std::string filePath = "/sdcard/Documents/decoded_from_p010_yuv420p_jpeg_input.rgb";
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001243 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
1244 if (!imageFile.is_open()) {
1245 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
1246 }
1247 imageFile.write((const char*)decodedJpegR.data, decodedJpegRSize);
1248 }
1249
1250 free(jpegR.data);
1251 free(decodedJpegR.data);
1252}
1253
1254/* Test Encode API-3 and decode */
Dichen Zhang761b52d2023-02-10 22:38:38 +00001255TEST_F(JpegRTest, encodeFromJpegThenDecode) {
Dichen Zhang36c1e732022-11-23 01:25:34 +00001256 int ret;
1257
1258 // Load input files.
1259 if (!loadFile(RAW_P010_IMAGE, mRawP010Image.data, nullptr)) {
1260 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
1261 }
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001262 mRawP010Image.width = TEST_IMAGE_WIDTH;
1263 mRawP010Image.height = TEST_IMAGE_HEIGHT;
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001264 mRawP010Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
Dichen Zhang36c1e732022-11-23 01:25:34 +00001265
Harish Mahendrakar1e057282022-12-04 12:47:53 -08001266 if (SAVE_INPUT_RGBA) {
1267 size_t rgbaSize = mRawP010Image.width * mRawP010Image.height * sizeof(uint32_t);
1268 uint32_t *data = (uint32_t *)malloc(rgbaSize);
1269
1270 for (size_t y = 0; y < mRawP010Image.height; ++y) {
1271 for (size_t x = 0; x < mRawP010Image.width; ++x) {
1272 Color hdr_yuv_gamma = getP010Pixel(&mRawP010Image, x, y);
1273 Color hdr_rgb_gamma = bt2100YuvToRgb(hdr_yuv_gamma);
1274 uint32_t rgba1010102 = colorToRgba1010102(hdr_rgb_gamma);
1275 size_t pixel_idx = x + y * mRawP010Image.width;
1276 reinterpret_cast<uint32_t*>(data)[pixel_idx] = rgba1010102;
1277 }
1278 }
1279
1280 // Output image data to file
1281 std::string filePath = "/sdcard/Documents/input_from_p010.rgb10";
1282 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
1283 if (!imageFile.is_open()) {
1284 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
1285 }
1286 imageFile.write((const char*)data, rgbaSize);
1287 free(data);
1288 }
Dichen Zhang36c1e732022-11-23 01:25:34 +00001289 if (!loadFile(JPEG_IMAGE, mJpegImage.data, &mJpegImage.length)) {
1290 FAIL() << "Load file " << JPEG_IMAGE << " failed";
1291 }
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001292 mJpegImage.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709;
Dichen Zhang36c1e732022-11-23 01:25:34 +00001293
Dichen Zhang761b52d2023-02-10 22:38:38 +00001294 JpegR jpegRCodec;
Dichen Zhang36c1e732022-11-23 01:25:34 +00001295
1296 jpegr_compressed_struct jpegR;
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001297 jpegR.maxLength = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * sizeof(uint8_t);
Dichen Zhang36c1e732022-11-23 01:25:34 +00001298 jpegR.data = malloc(jpegR.maxLength);
Dichen Zhang761b52d2023-02-10 22:38:38 +00001299 ret = jpegRCodec.encodeJPEGR(
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001300 &mRawP010Image, &mJpegImage, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR);
Dichen Zhang36c1e732022-11-23 01:25:34 +00001301 if (ret != OK) {
1302 FAIL() << "Error code is " << ret;
1303 }
1304 if (SAVE_ENCODING_RESULT) {
1305 // Output image data to file
Dichen Zhang61ede362023-02-22 18:50:13 +00001306 std::string filePath = "/sdcard/Documents/encoded_from_p010_jpeg_input.jpgr";
Dichen Zhang36c1e732022-11-23 01:25:34 +00001307 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
1308 if (!imageFile.is_open()) {
1309 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
1310 }
1311 imageFile.write((const char*)jpegR.data, jpegR.length);
1312 }
1313
1314 jpegr_uncompressed_struct decodedJpegR;
Dichen Zhang3e5798c2023-03-01 22:30:43 +00001315 int decodedJpegRSize = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * 8;
Dichen Zhang36c1e732022-11-23 01:25:34 +00001316 decodedJpegR.data = malloc(decodedJpegRSize);
Dichen Zhang761b52d2023-02-10 22:38:38 +00001317 ret = jpegRCodec.decodeJPEGR(&jpegR, &decodedJpegR);
Dichen Zhang36c1e732022-11-23 01:25:34 +00001318 if (ret != OK) {
1319 FAIL() << "Error code is " << ret;
1320 }
1321 if (SAVE_DECODING_RESULT) {
1322 // Output image data to file
Dichen Zhang3e5798c2023-03-01 22:30:43 +00001323 std::string filePath = "/sdcard/Documents/decoded_from_p010_jpeg_input.rgb";
Dichen Zhang36c1e732022-11-23 01:25:34 +00001324 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
1325 if (!imageFile.is_open()) {
1326 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
1327 }
1328 imageFile.write((const char*)decodedJpegR.data, decodedJpegRSize);
1329 }
1330
1331 free(jpegR.data);
1332 free(decodedJpegR.data);
1333}
1334
Dichen Zhang10959a42023-04-10 16:28:16 -07001335TEST_F(JpegRTest, ProfileGainMapFuncs) {
Nick Deakind19e5762023-02-10 15:39:08 -05001336 const size_t kWidth = TEST_IMAGE_WIDTH;
1337 const size_t kHeight = TEST_IMAGE_HEIGHT;
1338
1339 // Load input files.
1340 if (!loadFile(RAW_P010_IMAGE, mRawP010Image.data, nullptr)) {
1341 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
1342 }
1343 mRawP010Image.width = kWidth;
1344 mRawP010Image.height = kHeight;
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001345 mRawP010Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
Nick Deakind19e5762023-02-10 15:39:08 -05001346
1347 if (!loadFile(RAW_YUV420_IMAGE, mRawYuv420Image.data, nullptr)) {
1348 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
1349 }
1350 mRawYuv420Image.width = kWidth;
1351 mRawYuv420Image.height = kHeight;
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001352 mRawYuv420Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709;
Nick Deakind19e5762023-02-10 15:39:08 -05001353
Dichen Zhang761b52d2023-02-10 22:38:38 +00001354 JpegRBenchmark benchmark;
Nick Deakind19e5762023-02-10 15:39:08 -05001355
Nick Deakin094946b2023-06-09 11:58:41 -04001356 ultrahdr_metadata_struct metadata = { .version = "1.0" };
Nick Deakind19e5762023-02-10 15:39:08 -05001357
1358 jpegr_uncompressed_struct map = { .data = NULL,
1359 .width = 0,
1360 .height = 0,
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001361 .colorGamut = ULTRAHDR_COLORGAMUT_UNSPECIFIED };
Nick Deakind19e5762023-02-10 15:39:08 -05001362
Dichen Zhang10959a42023-04-10 16:28:16 -07001363 benchmark.BenchmarkGenerateGainMap(&mRawYuv420Image, &mRawP010Image, &metadata, &map);
Nick Deakind19e5762023-02-10 15:39:08 -05001364
1365 const int dstSize = mRawYuv420Image.width * mRawYuv420Image.height * 4;
1366 auto bufferDst = std::make_unique<uint8_t[]>(dstSize);
1367 jpegr_uncompressed_struct dest = { .data = bufferDst.get(),
1368 .width = 0,
1369 .height = 0,
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001370 .colorGamut = ULTRAHDR_COLORGAMUT_UNSPECIFIED };
Nick Deakind19e5762023-02-10 15:39:08 -05001371
Dichen Zhang10959a42023-04-10 16:28:16 -07001372 benchmark.BenchmarkApplyGainMap(&mRawYuv420Image, &map, &metadata, &dest);
Nick Deakind19e5762023-02-10 15:39:08 -05001373}
1374
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001375} // namespace android::ultrahdr