blob: d482ea1f79a98e592b7bca139131096dcb9667f7 [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
Ram Mohanb0375052023-05-20 04:03:48 +0530825/* Test Decode API invalid arguments */
826TEST_F(JpegRTest, decodeAPIForInvalidArgs) {
827 int ret;
828
829 // we are not really compressing anything so lets keep allocs to a minimum
830 jpegr_compressed_struct jpegR;
831 jpegR.maxLength = 16 * sizeof(uint8_t);
832 jpegR.data = malloc(jpegR.maxLength);
833
834 // we are not really decoding anything so lets keep allocs to a minimum
835 mRawP010Image.data = malloc(16);
836
837 JpegR jpegRCodec;
838
839 // test jpegr image
840 EXPECT_NE(OK, jpegRCodec.decodeJPEGR(
841 nullptr, &mRawP010Image)) << "fail, API allows nullptr for jpegr img";
842
843 // test dest image
844 EXPECT_NE(OK, jpegRCodec.decodeJPEGR(
845 &jpegR, nullptr)) << "fail, API allows nullptr for dest";
846
847 // test max display boost
848 EXPECT_NE(OK, jpegRCodec.decodeJPEGR(
849 &jpegR, &mRawP010Image, 0.5)) << "fail, API allows invalid max display boost";
850
851 // test output format
852 EXPECT_NE(OK, jpegRCodec.decodeJPEGR(
853 &jpegR, &mRawP010Image, 0.5, nullptr,
854 static_cast<ultrahdr_output_format>(-1))) << "fail, API allows invalid output format";
855
856 EXPECT_NE(OK, jpegRCodec.decodeJPEGR(
857 &jpegR, &mRawP010Image, 0.5, nullptr,
858 static_cast<ultrahdr_output_format>(ULTRAHDR_OUTPUT_MAX + 1)))
859 << "fail, API allows invalid output format";
860
861 free(jpegR.data);
862}
863
Dichen Zhang761b52d2023-02-10 22:38:38 +0000864TEST_F(JpegRTest, writeXmpThenRead) {
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000865 ultrahdr_metadata_struct metadata_expected;
Nick Deakin05ceebf2023-04-19 15:27:13 -0400866 metadata_expected.version = "1.0";
Nick Deakin01759062023-02-02 18:21:43 -0500867 metadata_expected.maxContentBoost = 1.25;
Nick Deakin3f89a3e2023-02-14 20:35:42 -0500868 metadata_expected.minContentBoost = 0.75;
Fyodor Kyslov8f46e2a2023-01-20 04:21:56 +0000869 const std::string nameSpace = "http://ns.adobe.com/xap/1.0/\0";
870 const int nameSpaceLength = nameSpace.size() + 1; // need to count the null terminator
871
Dichen Zhang61ede362023-02-22 18:50:13 +0000872 std::string xmp = generateXmpForSecondaryImage(metadata_expected);
Dichen Zhangdc8452b2022-11-23 17:17:56 +0000873
Fyodor Kyslov8f46e2a2023-01-20 04:21:56 +0000874 std::vector<uint8_t> xmpData;
875 xmpData.reserve(nameSpaceLength + xmp.size());
876 xmpData.insert(xmpData.end(), reinterpret_cast<const uint8_t*>(nameSpace.c_str()),
877 reinterpret_cast<const uint8_t*>(nameSpace.c_str()) + nameSpaceLength);
878 xmpData.insert(xmpData.end(), reinterpret_cast<const uint8_t*>(xmp.c_str()),
879 reinterpret_cast<const uint8_t*>(xmp.c_str()) + xmp.size());
880
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000881 ultrahdr_metadata_struct metadata_read;
Fyodor Kyslov8f46e2a2023-01-20 04:21:56 +0000882 EXPECT_TRUE(getMetadataFromXMP(xmpData.data(), xmpData.size(), &metadata_read));
Nick Deakin31f03e32023-03-31 16:00:13 -0400883 EXPECT_FLOAT_EQ(metadata_expected.maxContentBoost, metadata_read.maxContentBoost);
884 EXPECT_FLOAT_EQ(metadata_expected.minContentBoost, metadata_read.minContentBoost);
Dichen Zhangdc8452b2022-11-23 17:17:56 +0000885}
Dichen Zhang7e3ed122022-12-14 22:05:01 +0000886
Ram Mohanfd7bb542023-05-20 00:55:56 +0530887/* Test Encode API-0 */
888TEST_F(JpegRTest, encodeFromP010) {
889 int ret;
890
891 mRawP010Image.width = TEST_IMAGE_WIDTH;
892 mRawP010Image.height = TEST_IMAGE_HEIGHT;
893 mRawP010Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
894 // Load input files.
895 if (!loadP010Image(RAW_P010_IMAGE, &mRawP010Image, true)) {
896 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
897 }
898
899 JpegR jpegRCodec;
900
901 jpegr_compressed_struct jpegR;
902 jpegR.maxLength = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * sizeof(uint8_t);
903 jpegR.data = malloc(jpegR.maxLength);
904 ret = jpegRCodec.encodeJPEGR(
905 &mRawP010Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR, DEFAULT_JPEG_QUALITY,
906 nullptr);
907 if (ret != OK) {
908 FAIL() << "Error code is " << ret;
909 }
910
911 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
912 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
913 mRawP010ImageWithStride.luma_stride = TEST_IMAGE_WIDTH + 128;
914 mRawP010ImageWithStride.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
915 // Load input files.
916 if (!loadP010Image(RAW_P010_IMAGE, &mRawP010ImageWithStride, true)) {
917 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
918 }
919
920 jpegr_compressed_struct jpegRWithStride;
921 jpegRWithStride.maxLength = jpegR.length;
922 jpegRWithStride.data = malloc(jpegRWithStride.maxLength);
923 ret = jpegRCodec.encodeJPEGR(
924 &mRawP010ImageWithStride, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegRWithStride,
925 DEFAULT_JPEG_QUALITY, nullptr);
926 if (ret != OK) {
927 FAIL() << "Error code is " << ret;
928 }
929 ASSERT_EQ(jpegR.length, jpegRWithStride.length)
930 << "Same input is yielding different output";
931 ASSERT_EQ(0, memcmp(jpegR.data, jpegRWithStride.data, jpegR.length))
932 << "Same input is yielding different output";
933
934 mRawP010ImageWithChromaData.width = TEST_IMAGE_WIDTH;
935 mRawP010ImageWithChromaData.height = TEST_IMAGE_HEIGHT;
936 mRawP010ImageWithChromaData.luma_stride = TEST_IMAGE_WIDTH + 64;
937 mRawP010ImageWithChromaData.chroma_stride = TEST_IMAGE_WIDTH + 256;
938 mRawP010ImageWithChromaData.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
939 // Load input files.
940 if (!loadP010Image(RAW_P010_IMAGE, &mRawP010ImageWithChromaData, false)) {
941 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
942 }
943 jpegr_compressed_struct jpegRWithChromaData;
944 jpegRWithChromaData.maxLength = jpegR.length;
945 jpegRWithChromaData.data = malloc(jpegRWithChromaData.maxLength);
946 ret = jpegRCodec.encodeJPEGR(
947 &mRawP010ImageWithChromaData, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
948 &jpegRWithChromaData, DEFAULT_JPEG_QUALITY, nullptr);
949 if (ret != OK) {
950 FAIL() << "Error code is " << ret;
951 }
952 ASSERT_EQ(jpegR.length, jpegRWithChromaData.length)
953 << "Same input is yielding different output";
954 ASSERT_EQ(0, memcmp(jpegR.data, jpegRWithChromaData.data, jpegR.length))
955 << "Same input is yielding different output";
956
957 free(jpegR.data);
958 free(jpegRWithStride.data);
959 free(jpegRWithChromaData.data);
960}
961
Dichen Zhang7e3ed122022-12-14 22:05:01 +0000962/* Test Encode API-0 and decode */
Dichen Zhang761b52d2023-02-10 22:38:38 +0000963TEST_F(JpegRTest, encodeFromP010ThenDecode) {
Dichen Zhangc3437ca2023-01-04 14:00:08 -0800964 int ret;
965
966 // Load input files.
967 if (!loadFile(RAW_P010_IMAGE, mRawP010Image.data, nullptr)) {
968 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
969 }
970 mRawP010Image.width = TEST_IMAGE_WIDTH;
971 mRawP010Image.height = TEST_IMAGE_HEIGHT;
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000972 mRawP010Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
Dichen Zhangc3437ca2023-01-04 14:00:08 -0800973
Dichen Zhang761b52d2023-02-10 22:38:38 +0000974 JpegR jpegRCodec;
Dichen Zhangc3437ca2023-01-04 14:00:08 -0800975
976 jpegr_compressed_struct jpegR;
977 jpegR.maxLength = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * sizeof(uint8_t);
978 jpegR.data = malloc(jpegR.maxLength);
Dichen Zhang761b52d2023-02-10 22:38:38 +0000979 ret = jpegRCodec.encodeJPEGR(
Dichen Zhangdbceb0e2023-04-14 19:03:18 +0000980 &mRawP010Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR, DEFAULT_JPEG_QUALITY,
981 nullptr);
Dichen Zhangc3437ca2023-01-04 14:00:08 -0800982 if (ret != OK) {
983 FAIL() << "Error code is " << ret;
984 }
985 if (SAVE_ENCODING_RESULT) {
986 // Output image data to file
Dichen Zhang61ede362023-02-22 18:50:13 +0000987 std::string filePath = "/sdcard/Documents/encoded_from_p010_input.jpgr";
Dichen Zhangc3437ca2023-01-04 14:00:08 -0800988 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
989 if (!imageFile.is_open()) {
990 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
991 }
992 imageFile.write((const char*)jpegR.data, jpegR.length);
993 }
994
995 jpegr_uncompressed_struct decodedJpegR;
Dichen Zhang3e5798c2023-03-01 22:30:43 +0000996 int decodedJpegRSize = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * 8;
Dichen Zhangc3437ca2023-01-04 14:00:08 -0800997 decodedJpegR.data = malloc(decodedJpegRSize);
Dichen Zhang761b52d2023-02-10 22:38:38 +0000998 ret = jpegRCodec.decodeJPEGR(&jpegR, &decodedJpegR);
Dichen Zhangc3437ca2023-01-04 14:00:08 -0800999 if (ret != OK) {
1000 FAIL() << "Error code is " << ret;
1001 }
1002 if (SAVE_DECODING_RESULT) {
1003 // Output image data to file
Dichen Zhang3e5798c2023-03-01 22:30:43 +00001004 std::string filePath = "/sdcard/Documents/decoded_from_p010_input.rgb";
Dichen Zhangc3437ca2023-01-04 14:00:08 -08001005 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
1006 if (!imageFile.is_open()) {
1007 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
1008 }
1009 imageFile.write((const char*)decodedJpegR.data, decodedJpegRSize);
1010 }
1011
1012 free(jpegR.data);
1013 free(decodedJpegR.data);
1014}
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001015
Dichen Zhang66ca6e32023-04-05 12:22:54 -07001016/* Test Encode API-0 (with stride) and decode */
1017TEST_F(JpegRTest, encodeFromP010WithStrideThenDecode) {
1018 int ret;
1019
1020 // Load input files.
1021 if (!loadFile(RAW_P010_IMAGE_WITH_STRIDE, mRawP010ImageWithStride.data, nullptr)) {
1022 FAIL() << "Load file " << RAW_P010_IMAGE_WITH_STRIDE << " failed";
1023 }
1024 mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
1025 mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
1026 mRawP010ImageWithStride.luma_stride = TEST_IMAGE_STRIDE;
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001027 mRawP010ImageWithStride.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
Dichen Zhang66ca6e32023-04-05 12:22:54 -07001028
1029 JpegR jpegRCodec;
1030
1031 jpegr_compressed_struct jpegR;
1032 jpegR.maxLength = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * sizeof(uint8_t);
1033 jpegR.data = malloc(jpegR.maxLength);
1034 ret = jpegRCodec.encodeJPEGR(
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001035 &mRawP010ImageWithStride, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR,
Dichen Zhang66ca6e32023-04-05 12:22:54 -07001036 DEFAULT_JPEG_QUALITY, nullptr);
1037 if (ret != OK) {
1038 FAIL() << "Error code is " << ret;
1039 }
1040 if (SAVE_ENCODING_RESULT) {
1041 // Output image data to file
1042 std::string filePath = "/sdcard/Documents/encoded_from_p010_input.jpgr";
1043 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
1044 if (!imageFile.is_open()) {
1045 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
1046 }
1047 imageFile.write((const char*)jpegR.data, jpegR.length);
1048 }
1049
1050 jpegr_uncompressed_struct decodedJpegR;
1051 int decodedJpegRSize = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * 8;
1052 decodedJpegR.data = malloc(decodedJpegRSize);
1053 ret = jpegRCodec.decodeJPEGR(&jpegR, &decodedJpegR);
1054 if (ret != OK) {
1055 FAIL() << "Error code is " << ret;
1056 }
1057 if (SAVE_DECODING_RESULT) {
1058 // Output image data to file
1059 std::string filePath = "/sdcard/Documents/decoded_from_p010_input.rgb";
1060 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
1061 if (!imageFile.is_open()) {
1062 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
1063 }
1064 imageFile.write((const char*)decodedJpegR.data, decodedJpegRSize);
1065 }
1066
1067 free(jpegR.data);
1068 free(decodedJpegR.data);
1069}
1070
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001071/* Test Encode API-1 and decode */
Dichen Zhang761b52d2023-02-10 22:38:38 +00001072TEST_F(JpegRTest, encodeFromRawHdrAndSdrThenDecode) {
Dichen Zhang54444382022-12-07 20:57:49 +00001073 int ret;
1074
1075 // Load input files.
1076 if (!loadFile(RAW_P010_IMAGE, mRawP010Image.data, nullptr)) {
1077 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
1078 }
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001079 mRawP010Image.width = TEST_IMAGE_WIDTH;
1080 mRawP010Image.height = TEST_IMAGE_HEIGHT;
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001081 mRawP010Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
Dichen Zhang54444382022-12-07 20:57:49 +00001082
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001083 if (!loadFile(RAW_YUV420_IMAGE, mRawYuv420Image.data, nullptr)) {
1084 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
1085 }
1086 mRawYuv420Image.width = TEST_IMAGE_WIDTH;
1087 mRawYuv420Image.height = TEST_IMAGE_HEIGHT;
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001088 mRawYuv420Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709;
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001089
Dichen Zhang761b52d2023-02-10 22:38:38 +00001090 JpegR jpegRCodec;
Dichen Zhang54444382022-12-07 20:57:49 +00001091
1092 jpegr_compressed_struct jpegR;
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001093 jpegR.maxLength = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * sizeof(uint8_t);
Dichen Zhang54444382022-12-07 20:57:49 +00001094 jpegR.data = malloc(jpegR.maxLength);
Dichen Zhang761b52d2023-02-10 22:38:38 +00001095 ret = jpegRCodec.encodeJPEGR(
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001096 &mRawP010Image, &mRawYuv420Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR,
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001097 DEFAULT_JPEG_QUALITY, nullptr);
Dichen Zhang54444382022-12-07 20:57:49 +00001098 if (ret != OK) {
1099 FAIL() << "Error code is " << ret;
1100 }
1101 if (SAVE_ENCODING_RESULT) {
1102 // Output image data to file
Dichen Zhang61ede362023-02-22 18:50:13 +00001103 std::string filePath = "/sdcard/Documents/encoded_from_p010_yuv420p_input.jpgr";
Dichen Zhang54444382022-12-07 20:57:49 +00001104 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
1105 if (!imageFile.is_open()) {
1106 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
1107 }
1108 imageFile.write((const char*)jpegR.data, jpegR.length);
1109 }
1110
1111 jpegr_uncompressed_struct decodedJpegR;
Dichen Zhang3e5798c2023-03-01 22:30:43 +00001112 int decodedJpegRSize = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * 8;
Dichen Zhang54444382022-12-07 20:57:49 +00001113 decodedJpegR.data = malloc(decodedJpegRSize);
Dichen Zhang761b52d2023-02-10 22:38:38 +00001114 ret = jpegRCodec.decodeJPEGR(&jpegR, &decodedJpegR);
Dichen Zhang54444382022-12-07 20:57:49 +00001115 if (ret != OK) {
1116 FAIL() << "Error code is " << ret;
1117 }
1118 if (SAVE_DECODING_RESULT) {
1119 // Output image data to file
Dichen Zhang3e5798c2023-03-01 22:30:43 +00001120 std::string filePath = "/sdcard/Documents/decoded_from_p010_yuv420p_input.rgb";
Dichen Zhang54444382022-12-07 20:57:49 +00001121 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
1122 if (!imageFile.is_open()) {
1123 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
1124 }
1125 imageFile.write((const char*)decodedJpegR.data, decodedJpegRSize);
1126 }
1127
1128 free(jpegR.data);
1129 free(decodedJpegR.data);
1130}
1131
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001132/* Test Encode API-2 and decode */
Dichen Zhang761b52d2023-02-10 22:38:38 +00001133TEST_F(JpegRTest, encodeFromRawHdrAndSdrAndJpegThenDecode) {
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001134 int ret;
1135
1136 // Load input files.
1137 if (!loadFile(RAW_P010_IMAGE, mRawP010Image.data, nullptr)) {
1138 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
1139 }
1140 mRawP010Image.width = TEST_IMAGE_WIDTH;
1141 mRawP010Image.height = TEST_IMAGE_HEIGHT;
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001142 mRawP010Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001143
1144 if (!loadFile(RAW_YUV420_IMAGE, mRawYuv420Image.data, nullptr)) {
1145 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
1146 }
1147 mRawYuv420Image.width = TEST_IMAGE_WIDTH;
1148 mRawYuv420Image.height = TEST_IMAGE_HEIGHT;
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001149 mRawYuv420Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709;
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001150
1151 if (!loadFile(JPEG_IMAGE, mJpegImage.data, &mJpegImage.length)) {
1152 FAIL() << "Load file " << JPEG_IMAGE << " failed";
1153 }
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001154 mJpegImage.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709;
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001155
Dichen Zhang761b52d2023-02-10 22:38:38 +00001156 JpegR jpegRCodec;
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001157
1158 jpegr_compressed_struct jpegR;
1159 jpegR.maxLength = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * sizeof(uint8_t);
1160 jpegR.data = malloc(jpegR.maxLength);
Dichen Zhang761b52d2023-02-10 22:38:38 +00001161 ret = jpegRCodec.encodeJPEGR(
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001162 &mRawP010Image, &mRawYuv420Image, &mJpegImage, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
1163 &jpegR);
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001164 if (ret != OK) {
1165 FAIL() << "Error code is " << ret;
1166 }
1167 if (SAVE_ENCODING_RESULT) {
1168 // Output image data to file
Dichen Zhang61ede362023-02-22 18:50:13 +00001169 std::string filePath = "/sdcard/Documents/encoded_from_p010_yuv420p_jpeg_input.jpgr";
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001170 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
1171 if (!imageFile.is_open()) {
1172 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
1173 }
1174 imageFile.write((const char*)jpegR.data, jpegR.length);
1175 }
1176
1177 jpegr_uncompressed_struct decodedJpegR;
Dichen Zhang3e5798c2023-03-01 22:30:43 +00001178 int decodedJpegRSize = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * 8;
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001179 decodedJpegR.data = malloc(decodedJpegRSize);
Dichen Zhang761b52d2023-02-10 22:38:38 +00001180 ret = jpegRCodec.decodeJPEGR(&jpegR, &decodedJpegR);
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001181 if (ret != OK) {
1182 FAIL() << "Error code is " << ret;
1183 }
1184 if (SAVE_DECODING_RESULT) {
1185 // Output image data to file
Dichen Zhang3e5798c2023-03-01 22:30:43 +00001186 std::string filePath = "/sdcard/Documents/decoded_from_p010_yuv420p_jpeg_input.rgb";
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001187 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*)decodedJpegR.data, decodedJpegRSize);
1192 }
1193
1194 free(jpegR.data);
1195 free(decodedJpegR.data);
1196}
1197
1198/* Test Encode API-3 and decode */
Dichen Zhang761b52d2023-02-10 22:38:38 +00001199TEST_F(JpegRTest, encodeFromJpegThenDecode) {
Dichen Zhang36c1e732022-11-23 01:25:34 +00001200 int ret;
1201
1202 // Load input files.
1203 if (!loadFile(RAW_P010_IMAGE, mRawP010Image.data, nullptr)) {
1204 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
1205 }
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001206 mRawP010Image.width = TEST_IMAGE_WIDTH;
1207 mRawP010Image.height = TEST_IMAGE_HEIGHT;
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001208 mRawP010Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
Dichen Zhang36c1e732022-11-23 01:25:34 +00001209
Harish Mahendrakar1e057282022-12-04 12:47:53 -08001210 if (SAVE_INPUT_RGBA) {
1211 size_t rgbaSize = mRawP010Image.width * mRawP010Image.height * sizeof(uint32_t);
1212 uint32_t *data = (uint32_t *)malloc(rgbaSize);
1213
1214 for (size_t y = 0; y < mRawP010Image.height; ++y) {
1215 for (size_t x = 0; x < mRawP010Image.width; ++x) {
1216 Color hdr_yuv_gamma = getP010Pixel(&mRawP010Image, x, y);
1217 Color hdr_rgb_gamma = bt2100YuvToRgb(hdr_yuv_gamma);
1218 uint32_t rgba1010102 = colorToRgba1010102(hdr_rgb_gamma);
1219 size_t pixel_idx = x + y * mRawP010Image.width;
1220 reinterpret_cast<uint32_t*>(data)[pixel_idx] = rgba1010102;
1221 }
1222 }
1223
1224 // Output image data to file
1225 std::string filePath = "/sdcard/Documents/input_from_p010.rgb10";
1226 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*)data, rgbaSize);
1231 free(data);
1232 }
Dichen Zhang36c1e732022-11-23 01:25:34 +00001233 if (!loadFile(JPEG_IMAGE, mJpegImage.data, &mJpegImage.length)) {
1234 FAIL() << "Load file " << JPEG_IMAGE << " failed";
1235 }
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001236 mJpegImage.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709;
Dichen Zhang36c1e732022-11-23 01:25:34 +00001237
Dichen Zhang761b52d2023-02-10 22:38:38 +00001238 JpegR jpegRCodec;
Dichen Zhang36c1e732022-11-23 01:25:34 +00001239
1240 jpegr_compressed_struct jpegR;
Dichen Zhang7e3ed122022-12-14 22:05:01 +00001241 jpegR.maxLength = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * sizeof(uint8_t);
Dichen Zhang36c1e732022-11-23 01:25:34 +00001242 jpegR.data = malloc(jpegR.maxLength);
Dichen Zhang761b52d2023-02-10 22:38:38 +00001243 ret = jpegRCodec.encodeJPEGR(
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001244 &mRawP010Image, &mJpegImage, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR);
Dichen Zhang36c1e732022-11-23 01:25:34 +00001245 if (ret != OK) {
1246 FAIL() << "Error code is " << ret;
1247 }
1248 if (SAVE_ENCODING_RESULT) {
1249 // Output image data to file
Dichen Zhang61ede362023-02-22 18:50:13 +00001250 std::string filePath = "/sdcard/Documents/encoded_from_p010_jpeg_input.jpgr";
Dichen Zhang36c1e732022-11-23 01:25:34 +00001251 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
1252 if (!imageFile.is_open()) {
1253 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
1254 }
1255 imageFile.write((const char*)jpegR.data, jpegR.length);
1256 }
1257
1258 jpegr_uncompressed_struct decodedJpegR;
Dichen Zhang3e5798c2023-03-01 22:30:43 +00001259 int decodedJpegRSize = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * 8;
Dichen Zhang36c1e732022-11-23 01:25:34 +00001260 decodedJpegR.data = malloc(decodedJpegRSize);
Dichen Zhang761b52d2023-02-10 22:38:38 +00001261 ret = jpegRCodec.decodeJPEGR(&jpegR, &decodedJpegR);
Dichen Zhang36c1e732022-11-23 01:25:34 +00001262 if (ret != OK) {
1263 FAIL() << "Error code is " << ret;
1264 }
1265 if (SAVE_DECODING_RESULT) {
1266 // Output image data to file
Dichen Zhang3e5798c2023-03-01 22:30:43 +00001267 std::string filePath = "/sdcard/Documents/decoded_from_p010_jpeg_input.rgb";
Dichen Zhang36c1e732022-11-23 01:25:34 +00001268 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
1269 if (!imageFile.is_open()) {
1270 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
1271 }
1272 imageFile.write((const char*)decodedJpegR.data, decodedJpegRSize);
1273 }
1274
1275 free(jpegR.data);
1276 free(decodedJpegR.data);
1277}
1278
Dichen Zhang10959a42023-04-10 16:28:16 -07001279TEST_F(JpegRTest, ProfileGainMapFuncs) {
Nick Deakind19e5762023-02-10 15:39:08 -05001280 const size_t kWidth = TEST_IMAGE_WIDTH;
1281 const size_t kHeight = TEST_IMAGE_HEIGHT;
1282
1283 // Load input files.
1284 if (!loadFile(RAW_P010_IMAGE, mRawP010Image.data, nullptr)) {
1285 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
1286 }
1287 mRawP010Image.width = kWidth;
1288 mRawP010Image.height = kHeight;
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001289 mRawP010Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
Nick Deakind19e5762023-02-10 15:39:08 -05001290
1291 if (!loadFile(RAW_YUV420_IMAGE, mRawYuv420Image.data, nullptr)) {
1292 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
1293 }
1294 mRawYuv420Image.width = kWidth;
1295 mRawYuv420Image.height = kHeight;
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001296 mRawYuv420Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709;
Nick Deakind19e5762023-02-10 15:39:08 -05001297
Dichen Zhang761b52d2023-02-10 22:38:38 +00001298 JpegRBenchmark benchmark;
Nick Deakind19e5762023-02-10 15:39:08 -05001299
Nick Deakin05ceebf2023-04-19 15:27:13 -04001300 ultrahdr_metadata_struct metadata = { .version = "1.0",
Nick Deakind19e5762023-02-10 15:39:08 -05001301 .maxContentBoost = 8.0f,
1302 .minContentBoost = 1.0f / 8.0f };
1303
1304 jpegr_uncompressed_struct map = { .data = NULL,
1305 .width = 0,
1306 .height = 0,
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001307 .colorGamut = ULTRAHDR_COLORGAMUT_UNSPECIFIED };
Nick Deakind19e5762023-02-10 15:39:08 -05001308
Dichen Zhang10959a42023-04-10 16:28:16 -07001309 benchmark.BenchmarkGenerateGainMap(&mRawYuv420Image, &mRawP010Image, &metadata, &map);
Nick Deakind19e5762023-02-10 15:39:08 -05001310
1311 const int dstSize = mRawYuv420Image.width * mRawYuv420Image.height * 4;
1312 auto bufferDst = std::make_unique<uint8_t[]>(dstSize);
1313 jpegr_uncompressed_struct dest = { .data = bufferDst.get(),
1314 .width = 0,
1315 .height = 0,
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001316 .colorGamut = ULTRAHDR_COLORGAMUT_UNSPECIFIED };
Nick Deakind19e5762023-02-10 15:39:08 -05001317
Dichen Zhang10959a42023-04-10 16:28:16 -07001318 benchmark.BenchmarkApplyGainMap(&mRawYuv420Image, &map, &metadata, &dest);
Nick Deakind19e5762023-02-10 15:39:08 -05001319}
1320
Dichen Zhangdbceb0e2023-04-14 19:03:18 +00001321} // namespace android::ultrahdr