blob: 34f8afd7e4e485cff8ed4e8a27cdc012d1e3f47f [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
822 free(jpegR.data);
823}
824
Dichen Zhang761b52d2023-02-10 22:38:38 +0000825TEST_F(JpegRTest, writeXmpThenRead) {
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000826 ultrahdr_metadata_struct metadata_expected;
Nick Deakin05ceebf2023-04-19 15:27:13 -0400827 metadata_expected.version = "1.0";
Nick Deakin01759062023-02-02 18:21:43 -0500828 metadata_expected.maxContentBoost = 1.25;
Nick Deakin3f89a3e2023-02-14 20:35:42 -0500829 metadata_expected.minContentBoost = 0.75;
Fyodor Kyslov8f46e2a2023-01-20 04:21:56 +0000830 const std::string nameSpace = "http://ns.adobe.com/xap/1.0/\0";
831 const int nameSpaceLength = nameSpace.size() + 1; // need to count the null terminator
832
Dichen Zhang61ede362023-02-22 18:50:13 +0000833 std::string xmp = generateXmpForSecondaryImage(metadata_expected);
Dichen Zhangdc8452b2022-11-23 17:17:56 +0000834
Fyodor Kyslov8f46e2a2023-01-20 04:21:56 +0000835 std::vector<uint8_t> xmpData;
836 xmpData.reserve(nameSpaceLength + xmp.size());
837 xmpData.insert(xmpData.end(), reinterpret_cast<const uint8_t*>(nameSpace.c_str()),
838 reinterpret_cast<const uint8_t*>(nameSpace.c_str()) + nameSpaceLength);
839 xmpData.insert(xmpData.end(), reinterpret_cast<const uint8_t*>(xmp.c_str()),
840 reinterpret_cast<const uint8_t*>(xmp.c_str()) + xmp.size());
841
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000842 ultrahdr_metadata_struct metadata_read;
Fyodor Kyslov8f46e2a2023-01-20 04:21:56 +0000843 EXPECT_TRUE(getMetadataFromXMP(xmpData.data(), xmpData.size(), &metadata_read));
Nick Deakin31f03e32023-03-31 16:00:13 -0400844 EXPECT_FLOAT_EQ(metadata_expected.maxContentBoost, metadata_read.maxContentBoost);
845 EXPECT_FLOAT_EQ(metadata_expected.minContentBoost, metadata_read.minContentBoost);
Dichen Zhangdc8452b2022-11-23 17:17:56 +0000846}
Dichen Zhang7e3ed122022-12-14 22:05:01 +0000847
Ram Mohanfd7bb542023-05-20 00:55:56 +0530848/* Test Encode API-0 */
849TEST_F(JpegRTest, encodeFromP010) {
850 int ret;
851
852 mRawP010Image.width = TEST_IMAGE_WIDTH;
853 mRawP010Image.height = TEST_IMAGE_HEIGHT;
854 mRawP010Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
855 // Load input files.
856 if (!loadP010Image(RAW_P010_IMAGE, &mRawP010Image, true)) {
857 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
858 }
859
860 JpegR jpegRCodec;
861
862 jpegr_compressed_struct jpegR;
863 jpegR.maxLength = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * sizeof(uint8_t);
864 jpegR.data = malloc(jpegR.maxLength);
865 ret = jpegRCodec.encodeJPEGR(
866 &mRawP010Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR, DEFAULT_JPEG_QUALITY,
867 nullptr);
868 if (ret != OK) {
869 FAIL() << "Error code is " << ret;
870 }
871
872 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
873 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
874 mRawP010ImageWithStride.luma_stride = TEST_IMAGE_WIDTH + 128;
875 mRawP010ImageWithStride.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
876 // Load input files.
877 if (!loadP010Image(RAW_P010_IMAGE, &mRawP010ImageWithStride, true)) {
878 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
879 }
880
881 jpegr_compressed_struct jpegRWithStride;
882 jpegRWithStride.maxLength = jpegR.length;
883 jpegRWithStride.data = malloc(jpegRWithStride.maxLength);
884 ret = jpegRCodec.encodeJPEGR(
885 &mRawP010ImageWithStride, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegRWithStride,
886 DEFAULT_JPEG_QUALITY, nullptr);
887 if (ret != OK) {
888 FAIL() << "Error code is " << ret;
889 }
890 ASSERT_EQ(jpegR.length, jpegRWithStride.length)
891 << "Same input is yielding different output";
892 ASSERT_EQ(0, memcmp(jpegR.data, jpegRWithStride.data, jpegR.length))
893 << "Same input is yielding different output";
894
895 mRawP010ImageWithChromaData.width = TEST_IMAGE_WIDTH;
896 mRawP010ImageWithChromaData.height = TEST_IMAGE_HEIGHT;
897 mRawP010ImageWithChromaData.luma_stride = TEST_IMAGE_WIDTH + 64;
898 mRawP010ImageWithChromaData.chroma_stride = TEST_IMAGE_WIDTH + 256;
899 mRawP010ImageWithChromaData.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
900 // Load input files.
901 if (!loadP010Image(RAW_P010_IMAGE, &mRawP010ImageWithChromaData, false)) {
902 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
903 }
904 jpegr_compressed_struct jpegRWithChromaData;
905 jpegRWithChromaData.maxLength = jpegR.length;
906 jpegRWithChromaData.data = malloc(jpegRWithChromaData.maxLength);
907 ret = jpegRCodec.encodeJPEGR(
908 &mRawP010ImageWithChromaData, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
909 &jpegRWithChromaData, DEFAULT_JPEG_QUALITY, nullptr);
910 if (ret != OK) {
911 FAIL() << "Error code is " << ret;
912 }
913 ASSERT_EQ(jpegR.length, jpegRWithChromaData.length)
914 << "Same input is yielding different output";
915 ASSERT_EQ(0, memcmp(jpegR.data, jpegRWithChromaData.data, jpegR.length))
916 << "Same input is yielding different output";
917
918 free(jpegR.data);
919 free(jpegRWithStride.data);
920 free(jpegRWithChromaData.data);
921}
922
Dichen Zhang7e3ed122022-12-14 22:05:01 +0000923/* Test Encode API-0 and decode */
Dichen Zhang761b52d2023-02-10 22:38:38 +0000924TEST_F(JpegRTest, encodeFromP010ThenDecode) {
Dichen Zhangc3437ca2023-01-04 14:00:08 -0800925 int ret;
926
927 // Load input files.
928 if (!loadFile(RAW_P010_IMAGE, mRawP010Image.data, nullptr)) {
929 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
930 }
931 mRawP010Image.width = TEST_IMAGE_WIDTH;
932 mRawP010Image.height = TEST_IMAGE_HEIGHT;
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000933 mRawP010Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
Dichen Zhangc3437ca2023-01-04 14:00:08 -0800934
Dichen Zhang761b52d2023-02-10 22:38:38 +0000935 JpegR jpegRCodec;
Dichen Zhangc3437ca2023-01-04 14:00:08 -0800936
937 jpegr_compressed_struct jpegR;
938 jpegR.maxLength = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * sizeof(uint8_t);
939 jpegR.data = malloc(jpegR.maxLength);
Dichen Zhang761b52d2023-02-10 22:38:38 +0000940 ret = jpegRCodec.encodeJPEGR(
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000941 &mRawP010Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR, DEFAULT_JPEG_QUALITY,
942 nullptr);
Dichen Zhangc3437ca2023-01-04 14:00:08 -0800943 if (ret != OK) {
944 FAIL() << "Error code is " << ret;
945 }
946 if (SAVE_ENCODING_RESULT) {
947 // Output image data to file
Dichen Zhang61ede362023-02-22 18:50:13 +0000948 std::string filePath = "/sdcard/Documents/encoded_from_p010_input.jpgr";
Dichen Zhangc3437ca2023-01-04 14:00:08 -0800949 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
950 if (!imageFile.is_open()) {
951 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
952 }
953 imageFile.write((const char*)jpegR.data, jpegR.length);
954 }
955
956 jpegr_uncompressed_struct decodedJpegR;
Dichen Zhang3e5798c2023-03-01 22:30:43 +0000957 int decodedJpegRSize = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * 8;
Dichen Zhangc3437ca2023-01-04 14:00:08 -0800958 decodedJpegR.data = malloc(decodedJpegRSize);
Dichen Zhang761b52d2023-02-10 22:38:38 +0000959 ret = jpegRCodec.decodeJPEGR(&jpegR, &decodedJpegR);
Dichen Zhangc3437ca2023-01-04 14:00:08 -0800960 if (ret != OK) {
961 FAIL() << "Error code is " << ret;
962 }
963 if (SAVE_DECODING_RESULT) {
964 // Output image data to file
Dichen Zhang3e5798c2023-03-01 22:30:43 +0000965 std::string filePath = "/sdcard/Documents/decoded_from_p010_input.rgb";
Dichen Zhangc3437ca2023-01-04 14:00:08 -0800966 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
967 if (!imageFile.is_open()) {
968 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
969 }
970 imageFile.write((const char*)decodedJpegR.data, decodedJpegRSize);
971 }
972
973 free(jpegR.data);
974 free(decodedJpegR.data);
975}
Dichen Zhang7e3ed122022-12-14 22:05:01 +0000976
Dichen Zhang66ca6e32023-04-05 12:22:54 -0700977/* Test Encode API-0 (with stride) and decode */
978TEST_F(JpegRTest, encodeFromP010WithStrideThenDecode) {
979 int ret;
980
981 // Load input files.
982 if (!loadFile(RAW_P010_IMAGE_WITH_STRIDE, mRawP010ImageWithStride.data, nullptr)) {
983 FAIL() << "Load file " << RAW_P010_IMAGE_WITH_STRIDE << " failed";
984 }
985 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
986 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
987 mRawP010ImageWithStride.luma_stride = TEST_IMAGE_STRIDE;
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000988 mRawP010ImageWithStride.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
Dichen Zhang66ca6e32023-04-05 12:22:54 -0700989
990 JpegR jpegRCodec;
991
992 jpegr_compressed_struct jpegR;
993 jpegR.maxLength = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * sizeof(uint8_t);
994 jpegR.data = malloc(jpegR.maxLength);
995 ret = jpegRCodec.encodeJPEGR(
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000996 &mRawP010ImageWithStride, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR,
Dichen Zhang66ca6e32023-04-05 12:22:54 -0700997 DEFAULT_JPEG_QUALITY, nullptr);
998 if (ret != OK) {
999 FAIL() << "Error code is " << ret;
1000 }
1001 if (SAVE_ENCODING_RESULT) {
1002 // Output image data to file
1003 std::string filePath = "/sdcard/Documents/encoded_from_p010_input.jpgr";
1004 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
1005 if (!imageFile.is_open()) {
1006 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
1007 }
1008 imageFile.write((const char*)jpegR.data, jpegR.length);
1009 }
1010
1011 jpegr_uncompressed_struct decodedJpegR;
1012 int decodedJpegRSize = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * 8;
1013 decodedJpegR.data = malloc(decodedJpegRSize);
1014 ret = jpegRCodec.decodeJPEGR(&jpegR, &decodedJpegR);
1015 if (ret != OK) {
1016 FAIL() << "Error code is " << ret;
1017 }
1018 if (SAVE_DECODING_RESULT) {
1019 // Output image data to file
1020 std::string filePath = "/sdcard/Documents/decoded_from_p010_input.rgb";
1021 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
1022 if (!imageFile.is_open()) {
1023 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
1024 }
1025 imageFile.write((const char*)decodedJpegR.data, decodedJpegRSize);
1026 }
1027
1028 free(jpegR.data);
1029 free(decodedJpegR.data);
1030}
1031
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001032/* Test Encode API-1 and decode */
Dichen Zhang761b52d2023-02-10 22:38:38 +00001033TEST_F(JpegRTest, encodeFromRawHdrAndSdrThenDecode) {
Dichen Zhang54444382022-12-07 20:57:49 +00001034 int ret;
1035
1036 // Load input files.
1037 if (!loadFile(RAW_P010_IMAGE, mRawP010Image.data, nullptr)) {
1038 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
1039 }
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001040 mRawP010Image.width = TEST_IMAGE_WIDTH;
1041 mRawP010Image.height = TEST_IMAGE_HEIGHT;
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001042 mRawP010Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
Dichen Zhang54444382022-12-07 20:57:49 +00001043
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001044 if (!loadFile(RAW_YUV420_IMAGE, mRawYuv420Image.data, nullptr)) {
1045 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
1046 }
1047 mRawYuv420Image.width = TEST_IMAGE_WIDTH;
1048 mRawYuv420Image.height = TEST_IMAGE_HEIGHT;
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001049 mRawYuv420Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709;
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001050
Dichen Zhang761b52d2023-02-10 22:38:38 +00001051 JpegR jpegRCodec;
Dichen Zhang54444382022-12-07 20:57:49 +00001052
1053 jpegr_compressed_struct jpegR;
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001054 jpegR.maxLength = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * sizeof(uint8_t);
Dichen Zhang54444382022-12-07 20:57:49 +00001055 jpegR.data = malloc(jpegR.maxLength);
Dichen Zhang761b52d2023-02-10 22:38:38 +00001056 ret = jpegRCodec.encodeJPEGR(
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001057 &mRawP010Image, &mRawYuv420Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR,
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001058 DEFAULT_JPEG_QUALITY, nullptr);
Dichen Zhang54444382022-12-07 20:57:49 +00001059 if (ret != OK) {
1060 FAIL() << "Error code is " << ret;
1061 }
1062 if (SAVE_ENCODING_RESULT) {
1063 // Output image data to file
Dichen Zhang61ede362023-02-22 18:50:13 +00001064 std::string filePath = "/sdcard/Documents/encoded_from_p010_yuv420p_input.jpgr";
Dichen Zhang54444382022-12-07 20:57:49 +00001065 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
1066 if (!imageFile.is_open()) {
1067 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
1068 }
1069 imageFile.write((const char*)jpegR.data, jpegR.length);
1070 }
1071
1072 jpegr_uncompressed_struct decodedJpegR;
Dichen Zhang3e5798c2023-03-01 22:30:43 +00001073 int decodedJpegRSize = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * 8;
Dichen Zhang54444382022-12-07 20:57:49 +00001074 decodedJpegR.data = malloc(decodedJpegRSize);
Dichen Zhang761b52d2023-02-10 22:38:38 +00001075 ret = jpegRCodec.decodeJPEGR(&jpegR, &decodedJpegR);
Dichen Zhang54444382022-12-07 20:57:49 +00001076 if (ret != OK) {
1077 FAIL() << "Error code is " << ret;
1078 }
1079 if (SAVE_DECODING_RESULT) {
1080 // Output image data to file
Dichen Zhang3e5798c2023-03-01 22:30:43 +00001081 std::string filePath = "/sdcard/Documents/decoded_from_p010_yuv420p_input.rgb";
Dichen Zhang54444382022-12-07 20:57:49 +00001082 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
1083 if (!imageFile.is_open()) {
1084 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
1085 }
1086 imageFile.write((const char*)decodedJpegR.data, decodedJpegRSize);
1087 }
1088
1089 free(jpegR.data);
1090 free(decodedJpegR.data);
1091}
1092
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001093/* Test Encode API-2 and decode */
Dichen Zhang761b52d2023-02-10 22:38:38 +00001094TEST_F(JpegRTest, encodeFromRawHdrAndSdrAndJpegThenDecode) {
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001095 int ret;
1096
1097 // Load input files.
1098 if (!loadFile(RAW_P010_IMAGE, mRawP010Image.data, nullptr)) {
1099 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
1100 }
1101 mRawP010Image.width = TEST_IMAGE_WIDTH;
1102 mRawP010Image.height = TEST_IMAGE_HEIGHT;
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001103 mRawP010Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001104
1105 if (!loadFile(RAW_YUV420_IMAGE, mRawYuv420Image.data, nullptr)) {
1106 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
1107 }
1108 mRawYuv420Image.width = TEST_IMAGE_WIDTH;
1109 mRawYuv420Image.height = TEST_IMAGE_HEIGHT;
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001110 mRawYuv420Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709;
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001111
1112 if (!loadFile(JPEG_IMAGE, mJpegImage.data, &mJpegImage.length)) {
1113 FAIL() << "Load file " << JPEG_IMAGE << " failed";
1114 }
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001115 mJpegImage.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709;
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001116
Dichen Zhang761b52d2023-02-10 22:38:38 +00001117 JpegR jpegRCodec;
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001118
1119 jpegr_compressed_struct jpegR;
1120 jpegR.maxLength = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * sizeof(uint8_t);
1121 jpegR.data = malloc(jpegR.maxLength);
Dichen Zhang761b52d2023-02-10 22:38:38 +00001122 ret = jpegRCodec.encodeJPEGR(
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001123 &mRawP010Image, &mRawYuv420Image, &mJpegImage, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
1124 &jpegR);
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001125 if (ret != OK) {
1126 FAIL() << "Error code is " << ret;
1127 }
1128 if (SAVE_ENCODING_RESULT) {
1129 // Output image data to file
Dichen Zhang61ede362023-02-22 18:50:13 +00001130 std::string filePath = "/sdcard/Documents/encoded_from_p010_yuv420p_jpeg_input.jpgr";
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001131 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
1132 if (!imageFile.is_open()) {
1133 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
1134 }
1135 imageFile.write((const char*)jpegR.data, jpegR.length);
1136 }
1137
1138 jpegr_uncompressed_struct decodedJpegR;
Dichen Zhang3e5798c2023-03-01 22:30:43 +00001139 int decodedJpegRSize = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * 8;
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001140 decodedJpegR.data = malloc(decodedJpegRSize);
Dichen Zhang761b52d2023-02-10 22:38:38 +00001141 ret = jpegRCodec.decodeJPEGR(&jpegR, &decodedJpegR);
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001142 if (ret != OK) {
1143 FAIL() << "Error code is " << ret;
1144 }
1145 if (SAVE_DECODING_RESULT) {
1146 // Output image data to file
Dichen Zhang3e5798c2023-03-01 22:30:43 +00001147 std::string filePath = "/sdcard/Documents/decoded_from_p010_yuv420p_jpeg_input.rgb";
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001148 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
1149 if (!imageFile.is_open()) {
1150 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
1151 }
1152 imageFile.write((const char*)decodedJpegR.data, decodedJpegRSize);
1153 }
1154
1155 free(jpegR.data);
1156 free(decodedJpegR.data);
1157}
1158
1159/* Test Encode API-3 and decode */
Dichen Zhang761b52d2023-02-10 22:38:38 +00001160TEST_F(JpegRTest, encodeFromJpegThenDecode) {
Dichen Zhang36c1e732022-11-23 01:25:34 +00001161 int ret;
1162
1163 // Load input files.
1164 if (!loadFile(RAW_P010_IMAGE, mRawP010Image.data, nullptr)) {
1165 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
1166 }
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001167 mRawP010Image.width = TEST_IMAGE_WIDTH;
1168 mRawP010Image.height = TEST_IMAGE_HEIGHT;
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001169 mRawP010Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
Dichen Zhang36c1e732022-11-23 01:25:34 +00001170
Harish Mahendrakar1e057282022-12-04 12:47:53 -08001171 if (SAVE_INPUT_RGBA) {
1172 size_t rgbaSize = mRawP010Image.width * mRawP010Image.height * sizeof(uint32_t);
1173 uint32_t *data = (uint32_t *)malloc(rgbaSize);
1174
1175 for (size_t y = 0; y < mRawP010Image.height; ++y) {
1176 for (size_t x = 0; x < mRawP010Image.width; ++x) {
1177 Color hdr_yuv_gamma = getP010Pixel(&mRawP010Image, x, y);
1178 Color hdr_rgb_gamma = bt2100YuvToRgb(hdr_yuv_gamma);
1179 uint32_t rgba1010102 = colorToRgba1010102(hdr_rgb_gamma);
1180 size_t pixel_idx = x + y * mRawP010Image.width;
1181 reinterpret_cast<uint32_t*>(data)[pixel_idx] = rgba1010102;
1182 }
1183 }
1184
1185 // Output image data to file
1186 std::string filePath = "/sdcard/Documents/input_from_p010.rgb10";
1187 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
1188 if (!imageFile.is_open()) {
1189 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
1190 }
1191 imageFile.write((const char*)data, rgbaSize);
1192 free(data);
1193 }
Dichen Zhang36c1e732022-11-23 01:25:34 +00001194 if (!loadFile(JPEG_IMAGE, mJpegImage.data, &mJpegImage.length)) {
1195 FAIL() << "Load file " << JPEG_IMAGE << " failed";
1196 }
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001197 mJpegImage.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709;
Dichen Zhang36c1e732022-11-23 01:25:34 +00001198
Dichen Zhang761b52d2023-02-10 22:38:38 +00001199 JpegR jpegRCodec;
Dichen Zhang36c1e732022-11-23 01:25:34 +00001200
1201 jpegr_compressed_struct jpegR;
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001202 jpegR.maxLength = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * sizeof(uint8_t);
Dichen Zhang36c1e732022-11-23 01:25:34 +00001203 jpegR.data = malloc(jpegR.maxLength);
Dichen Zhang761b52d2023-02-10 22:38:38 +00001204 ret = jpegRCodec.encodeJPEGR(
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001205 &mRawP010Image, &mJpegImage, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR);
Dichen Zhang36c1e732022-11-23 01:25:34 +00001206 if (ret != OK) {
1207 FAIL() << "Error code is " << ret;
1208 }
1209 if (SAVE_ENCODING_RESULT) {
1210 // Output image data to file
Dichen Zhang61ede362023-02-22 18:50:13 +00001211 std::string filePath = "/sdcard/Documents/encoded_from_p010_jpeg_input.jpgr";
Dichen Zhang36c1e732022-11-23 01:25:34 +00001212 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
1213 if (!imageFile.is_open()) {
1214 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
1215 }
1216 imageFile.write((const char*)jpegR.data, jpegR.length);
1217 }
1218
1219 jpegr_uncompressed_struct decodedJpegR;
Dichen Zhang3e5798c2023-03-01 22:30:43 +00001220 int decodedJpegRSize = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * 8;
Dichen Zhang36c1e732022-11-23 01:25:34 +00001221 decodedJpegR.data = malloc(decodedJpegRSize);
Dichen Zhang761b52d2023-02-10 22:38:38 +00001222 ret = jpegRCodec.decodeJPEGR(&jpegR, &decodedJpegR);
Dichen Zhang36c1e732022-11-23 01:25:34 +00001223 if (ret != OK) {
1224 FAIL() << "Error code is " << ret;
1225 }
1226 if (SAVE_DECODING_RESULT) {
1227 // Output image data to file
Dichen Zhang3e5798c2023-03-01 22:30:43 +00001228 std::string filePath = "/sdcard/Documents/decoded_from_p010_jpeg_input.rgb";
Dichen Zhang36c1e732022-11-23 01:25:34 +00001229 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
1230 if (!imageFile.is_open()) {
1231 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
1232 }
1233 imageFile.write((const char*)decodedJpegR.data, decodedJpegRSize);
1234 }
1235
1236 free(jpegR.data);
1237 free(decodedJpegR.data);
1238}
1239
Dichen Zhang10959a42023-04-10 16:28:16 -07001240TEST_F(JpegRTest, ProfileGainMapFuncs) {
Nick Deakind19e5762023-02-10 15:39:08 -05001241 const size_t kWidth = TEST_IMAGE_WIDTH;
1242 const size_t kHeight = TEST_IMAGE_HEIGHT;
1243
1244 // Load input files.
1245 if (!loadFile(RAW_P010_IMAGE, mRawP010Image.data, nullptr)) {
1246 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
1247 }
1248 mRawP010Image.width = kWidth;
1249 mRawP010Image.height = kHeight;
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001250 mRawP010Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
Nick Deakind19e5762023-02-10 15:39:08 -05001251
1252 if (!loadFile(RAW_YUV420_IMAGE, mRawYuv420Image.data, nullptr)) {
1253 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
1254 }
1255 mRawYuv420Image.width = kWidth;
1256 mRawYuv420Image.height = kHeight;
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001257 mRawYuv420Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709;
Nick Deakind19e5762023-02-10 15:39:08 -05001258
Dichen Zhang761b52d2023-02-10 22:38:38 +00001259 JpegRBenchmark benchmark;
Nick Deakind19e5762023-02-10 15:39:08 -05001260
Nick Deakin05ceebf2023-04-19 15:27:13 -04001261 ultrahdr_metadata_struct metadata = { .version = "1.0",
Nick Deakind19e5762023-02-10 15:39:08 -05001262 .maxContentBoost = 8.0f,
1263 .minContentBoost = 1.0f / 8.0f };
1264
1265 jpegr_uncompressed_struct map = { .data = NULL,
1266 .width = 0,
1267 .height = 0,
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001268 .colorGamut = ULTRAHDR_COLORGAMUT_UNSPECIFIED };
Nick Deakind19e5762023-02-10 15:39:08 -05001269
Dichen Zhang10959a42023-04-10 16:28:16 -07001270 benchmark.BenchmarkGenerateGainMap(&mRawYuv420Image, &mRawP010Image, &metadata, &map);
Nick Deakind19e5762023-02-10 15:39:08 -05001271
1272 const int dstSize = mRawYuv420Image.width * mRawYuv420Image.height * 4;
1273 auto bufferDst = std::make_unique<uint8_t[]>(dstSize);
1274 jpegr_uncompressed_struct dest = { .data = bufferDst.get(),
1275 .width = 0,
1276 .height = 0,
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001277 .colorGamut = ULTRAHDR_COLORGAMUT_UNSPECIFIED };
Nick Deakind19e5762023-02-10 15:39:08 -05001278
Dichen Zhang10959a42023-04-10 16:28:16 -07001279 benchmark.BenchmarkApplyGainMap(&mRawYuv420Image, &map, &metadata, &dest);
Nick Deakind19e5762023-02-10 15:39:08 -05001280}
1281
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001282} // namespace android::ultrahdr