xref: /aosp_15_r20/external/libultrahdr/tests/jpegr_test.cpp (revision 89a0ef05262152531a00a15832a2d3b1e3990773)
1 /*
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 
17 #ifdef _WIN32
18 #include <windows.h>
19 #else
20 #include <sys/time.h>
21 #endif
22 #include <gtest/gtest.h>
23 
24 #include <fstream>
25 #include <iostream>
26 
27 #include "ultrahdr_api.h"
28 
29 #include "ultrahdr/ultrahdrcommon.h"
30 #include "ultrahdr/jpegr.h"
31 #include "ultrahdr/jpegrutils.h"
32 
33 //#define DUMP_OUTPUT
34 
35 namespace ultrahdr {
36 
37 // resources used by unit tests
38 #ifdef __ANDROID__
39 const char* kYCbCrP010FileName = "/data/local/tmp/raw_p010_image.p010";
40 const char* kYCbCr420FileName = "/data/local/tmp/raw_yuv420_image.yuv420";
41 const char* kSdrJpgFileName = "/data/local/tmp/jpeg_image.jpg";
42 #else
43 const char* kYCbCrP010FileName = "./data/raw_p010_image.p010";
44 const char* kYCbCr420FileName = "./data/raw_yuv420_image.yuv420";
45 const char* kSdrJpgFileName = "./data/jpeg_image.jpg";
46 #endif
47 const size_t kImageWidth = 1280;
48 const size_t kImageHeight = 720;
49 const int kQuality = 90;
50 
51 // Wrapper to describe the input type
52 typedef enum {
53   YCbCr_p010 = 0,
54   YCbCr_420 = 1,
55 } UhdrInputFormat;
56 
57 /**
58  * Wrapper class for raw resource
59  * Sample usage:
60  *   UhdrUnCompressedStructWrapper rawImg(width, height, YCbCr_p010);
61  *   rawImg.setImageColorGamut(colorGamut));
62  *   rawImg.setImageStride(strideLuma, strideChroma); // optional
63  *   rawImg.setChromaMode(false); // optional
64  *   rawImg.allocateMemory();
65  *   rawImg.loadRawResource(kYCbCrP010FileName);
66  */
67 class UhdrUnCompressedStructWrapper {
68  public:
69   UhdrUnCompressedStructWrapper(unsigned int width, unsigned int height, UhdrInputFormat format);
70   ~UhdrUnCompressedStructWrapper() = default;
71 
72   bool setChromaMode(bool isChromaContiguous);
73   bool setImageStride(unsigned int lumaStride, unsigned int chromaStride);
74   bool setImageColorGamut(ultrahdr_color_gamut colorGamut);
75   bool allocateMemory();
76   bool loadRawResource(const char* fileName);
77   jr_uncompressed_ptr getImageHandle();
78 
79  private:
80   std::unique_ptr<uint8_t[]> mLumaData;
81   std::unique_ptr<uint8_t[]> mChromaData;
82   jpegr_uncompressed_struct mImg;
83   UhdrInputFormat mFormat;
84   bool mIsChromaContiguous;
85 };
86 
87 /**
88  * Wrapper class for compressed resource
89  * Sample usage:
90  *   UhdrCompressedStructWrapper jpgImg(width, height);
91  *   rawImg.allocateMemory();
92  */
93 class UhdrCompressedStructWrapper {
94  public:
95   UhdrCompressedStructWrapper(unsigned int width, unsigned int height);
96   ~UhdrCompressedStructWrapper() = default;
97 
98   bool allocateMemory();
99   jr_compressed_ptr getImageHandle();
100 
101  private:
102   std::unique_ptr<uint8_t[]> mData;
103   jpegr_compressed_struct mImg{};
104   unsigned int mWidth;
105   unsigned int mHeight;
106 };
107 
UhdrUnCompressedStructWrapper(unsigned int width,unsigned int height,UhdrInputFormat format)108 UhdrUnCompressedStructWrapper::UhdrUnCompressedStructWrapper(unsigned int width,
109                                                              unsigned int height,
110                                                              UhdrInputFormat format) {
111   mImg.data = nullptr;
112   mImg.width = width;
113   mImg.height = height;
114   mImg.colorGamut = ULTRAHDR_COLORGAMUT_UNSPECIFIED;
115   mImg.chroma_data = nullptr;
116   mImg.luma_stride = 0;
117   mImg.chroma_stride = 0;
118   mFormat = format;
119   mIsChromaContiguous = true;
120 }
121 
setChromaMode(bool isChromaContiguous)122 bool UhdrUnCompressedStructWrapper::setChromaMode(bool isChromaContiguous) {
123   if (mLumaData.get() != nullptr) {
124     std::cerr << "Object has sailed, no further modifications are allowed" << std::endl;
125     return false;
126   }
127   mIsChromaContiguous = isChromaContiguous;
128   return true;
129 }
130 
setImageStride(unsigned int lumaStride,unsigned int chromaStride)131 bool UhdrUnCompressedStructWrapper::setImageStride(unsigned int lumaStride,
132                                                    unsigned int chromaStride) {
133   if (mLumaData.get() != nullptr) {
134     std::cerr << "Object has sailed, no further modifications are allowed" << std::endl;
135     return false;
136   }
137   if (lumaStride != 0) {
138     if (lumaStride < mImg.width) {
139       std::cerr << "Bad luma stride received" << std::endl;
140       return false;
141     }
142     mImg.luma_stride = lumaStride;
143   }
144   if (chromaStride != 0) {
145     if (mFormat == YCbCr_p010 && chromaStride < mImg.width) {
146       std::cerr << "Bad chroma stride received for format YCbCrP010" << std::endl;
147       return false;
148     }
149     if (mFormat == YCbCr_420 && chromaStride < (mImg.width >> 1)) {
150       std::cerr << "Bad chroma stride received for format YCbCr420" << std::endl;
151       return false;
152     }
153     mImg.chroma_stride = chromaStride;
154   }
155   return true;
156 }
157 
setImageColorGamut(ultrahdr_color_gamut colorGamut)158 bool UhdrUnCompressedStructWrapper::setImageColorGamut(ultrahdr_color_gamut colorGamut) {
159   if (mLumaData.get() != nullptr) {
160     std::cerr << "Object has sailed, no further modifications are allowed" << std::endl;
161     return false;
162   }
163   mImg.colorGamut = colorGamut;
164   return true;
165 }
166 
allocateMemory()167 bool UhdrUnCompressedStructWrapper::allocateMemory() {
168   if (mImg.width == 0 || (mImg.width % 2 != 0) || mImg.height == 0 || (mImg.height % 2 != 0) ||
169       (mFormat != YCbCr_p010 && mFormat != YCbCr_420)) {
170     std::cerr << "Object in bad state, mem alloc failed" << std::endl;
171     return false;
172   }
173   int lumaStride = mImg.luma_stride == 0 ? mImg.width : mImg.luma_stride;
174   int lumaSize = lumaStride * mImg.height * (mFormat == YCbCr_p010 ? 2 : 1);
175   int chromaSize = (mImg.height >> 1) * (mFormat == YCbCr_p010 ? 2 : 1);
176   if (mIsChromaContiguous) {
177     chromaSize *= lumaStride;
178   } else {
179     if (mImg.chroma_stride == 0) {
180       std::cerr << "Object in bad state, mem alloc failed" << std::endl;
181       return false;
182     }
183     if (mFormat == YCbCr_p010) {
184       chromaSize *= mImg.chroma_stride;
185     } else {
186       chromaSize *= (mImg.chroma_stride * 2);
187     }
188   }
189   if (mIsChromaContiguous) {
190     mLumaData = std::make_unique<uint8_t[]>(lumaSize + chromaSize);
191     mImg.data = mLumaData.get();
192     mImg.chroma_data = nullptr;
193   } else {
194     mLumaData = std::make_unique<uint8_t[]>(lumaSize);
195     mImg.data = mLumaData.get();
196     mChromaData = std::make_unique<uint8_t[]>(chromaSize);
197     mImg.chroma_data = mChromaData.get();
198   }
199   return true;
200 }
201 
loadRawResource(const char * fileName)202 bool UhdrUnCompressedStructWrapper::loadRawResource(const char* fileName) {
203   if (!mImg.data) {
204     std::cerr << "memory is not allocated, read not possible" << std::endl;
205     return false;
206   }
207   std::ifstream ifd(fileName, std::ios::binary | std::ios::ate);
208   if (ifd.good()) {
209     int bpp = mFormat == YCbCr_p010 ? 2 : 1;
210     int size = ifd.tellg();
211     int length = mImg.width * mImg.height * bpp * 3 / 2;  // 2x2 subsampling
212     if (size < length) {
213       std::cerr << "requested to read " << length << " bytes from file : " << fileName
214                 << ", file contains only " << length << " bytes" << std::endl;
215       return false;
216     }
217     ifd.seekg(0, std::ios::beg);
218     size_t lumaStride = mImg.luma_stride == 0 ? mImg.width : mImg.luma_stride;
219     char* mem = static_cast<char*>(mImg.data);
220     for (size_t i = 0; i < mImg.height; i++) {
221       ifd.read(mem, mImg.width * bpp);
222       mem += lumaStride * bpp;
223     }
224     if (!mIsChromaContiguous) {
225       mem = static_cast<char*>(mImg.chroma_data);
226     }
227     size_t chromaStride;
228     if (mIsChromaContiguous) {
229       chromaStride = mFormat == YCbCr_p010 ? lumaStride : lumaStride / 2;
230     } else {
231       if (mFormat == YCbCr_p010) {
232         chromaStride = mImg.chroma_stride == 0 ? lumaStride : mImg.chroma_stride;
233       } else {
234         chromaStride = mImg.chroma_stride == 0 ? (lumaStride / 2) : mImg.chroma_stride;
235       }
236     }
237     if (mFormat == YCbCr_p010) {
238       for (size_t i = 0; i < mImg.height / 2; i++) {
239         ifd.read(mem, mImg.width * 2);
240         mem += chromaStride * 2;
241       }
242     } else {
243       for (size_t i = 0; i < mImg.height / 2; i++) {
244         ifd.read(mem, (mImg.width / 2));
245         mem += chromaStride;
246       }
247       for (size_t i = 0; i < mImg.height / 2; i++) {
248         ifd.read(mem, (mImg.width / 2));
249         mem += chromaStride;
250       }
251     }
252     return true;
253   }
254   std::cerr << "unable to open file : " << fileName << std::endl;
255   return false;
256 }
257 
getImageHandle()258 jr_uncompressed_ptr UhdrUnCompressedStructWrapper::getImageHandle() { return &mImg; }
259 
UhdrCompressedStructWrapper(unsigned int width,unsigned int height)260 UhdrCompressedStructWrapper::UhdrCompressedStructWrapper(unsigned int width, unsigned int height) {
261   mWidth = width;
262   mHeight = height;
263 }
264 
allocateMemory()265 bool UhdrCompressedStructWrapper::allocateMemory() {
266   if (mWidth == 0 || (mWidth % 2 != 0) || mHeight == 0 || (mHeight % 2 != 0)) {
267     std::cerr << "Object in bad state, mem alloc failed" << std::endl;
268     return false;
269   }
270   int maxLength = (std::max)(8 * 1024 /* min size 8kb */, (int)(mWidth * mHeight * 3 * 2));
271   mData = std::make_unique<uint8_t[]>(maxLength);
272   mImg.data = mData.get();
273   mImg.length = 0;
274   mImg.maxLength = maxLength;
275   return true;
276 }
277 
getImageHandle()278 jr_compressed_ptr UhdrCompressedStructWrapper::getImageHandle() { return &mImg; }
279 
280 #ifdef DUMP_OUTPUT
writeFile(const char * filename,void * & result,int length)281 static bool writeFile(const char* filename, void*& result, int length) {
282   std::ofstream ofd(filename, std::ios::binary);
283   if (ofd.is_open()) {
284     ofd.write(static_cast<char*>(result), length);
285     return true;
286   }
287   std::cerr << "unable to write to file : " << filename << std::endl;
288   return false;
289 }
290 #endif
291 
readFile(const char * fileName,void * & result,size_t maxLength,size_t & length)292 static bool readFile(const char* fileName, void*& result, size_t maxLength, size_t& length) {
293   std::ifstream ifd(fileName, std::ios::binary | std::ios::ate);
294   if (ifd.good()) {
295     length = ifd.tellg();
296     if (length > maxLength) {
297       std::cerr << "not enough space to read file" << std::endl;
298       return false;
299     }
300     ifd.seekg(0, std::ios::beg);
301     ifd.read(static_cast<char*>(result), length);
302     return true;
303   }
304   std::cerr << "unable to read file : " << fileName << std::endl;
305   return false;
306 }
307 
map_internal_cg_to_cg(ultrahdr::ultrahdr_color_gamut cg)308 uhdr_color_gamut_t map_internal_cg_to_cg(ultrahdr::ultrahdr_color_gamut cg) {
309   switch (cg) {
310     case ultrahdr::ULTRAHDR_COLORGAMUT_BT2100:
311       return UHDR_CG_BT_2100;
312     case ultrahdr::ULTRAHDR_COLORGAMUT_BT709:
313       return UHDR_CG_BT_709;
314     case ultrahdr::ULTRAHDR_COLORGAMUT_P3:
315       return UHDR_CG_DISPLAY_P3;
316     default:
317       return UHDR_CG_UNSPECIFIED;
318   }
319 }
320 
map_internal_ct_to_ct(ultrahdr::ultrahdr_transfer_function ct)321 uhdr_color_transfer_t map_internal_ct_to_ct(ultrahdr::ultrahdr_transfer_function ct) {
322   switch (ct) {
323     case ultrahdr::ULTRAHDR_TF_HLG:
324       return UHDR_CT_HLG;
325     case ultrahdr::ULTRAHDR_TF_PQ:
326       return UHDR_CT_PQ;
327     case ultrahdr::ULTRAHDR_TF_LINEAR:
328       return UHDR_CT_LINEAR;
329     case ultrahdr::ULTRAHDR_TF_SRGB:
330       return UHDR_CT_SRGB;
331     default:
332       return UHDR_CT_UNSPECIFIED;
333   }
334 }
335 
decodeJpegRImg(jr_compressed_ptr img,const char * outFileName)336 void decodeJpegRImg(jr_compressed_ptr img, [[maybe_unused]] const char* outFileName) {
337   jpegr_info_struct info{};
338   JpegR jpegHdr;
339   ASSERT_EQ(JPEGR_NO_ERROR, jpegHdr.getJPEGRInfo(img, &info));
340   ASSERT_EQ(kImageWidth, info.width);
341   ASSERT_EQ(kImageHeight, info.height);
342   size_t outSize = info.width * info.height * 8;
343   std::unique_ptr<uint8_t[]> data = std::make_unique<uint8_t[]>(outSize);
344   jpegr_uncompressed_struct destImage{};
345   destImage.data = data.get();
346   ASSERT_EQ(JPEGR_NO_ERROR, jpegHdr.decodeJPEGR(img, &destImage));
347   ASSERT_EQ(kImageWidth, destImage.width);
348   ASSERT_EQ(kImageHeight, destImage.height);
349 #ifdef DUMP_OUTPUT
350   if (!writeFile(outFileName, destImage.data, outSize)) {
351     std::cerr << "unable to write output file" << std::endl;
352   }
353 #endif
354   uhdr_codec_private_t* obj = uhdr_create_decoder();
355   uhdr_compressed_image_t uhdr_image{};
356   uhdr_image.data = img->data;
357   uhdr_image.data_sz = img->length;
358   uhdr_image.capacity = img->length;
359   uhdr_image.cg = UHDR_CG_UNSPECIFIED;
360   uhdr_image.ct = UHDR_CT_UNSPECIFIED;
361   uhdr_image.range = UHDR_CR_UNSPECIFIED;
362   uhdr_error_info_t status = uhdr_dec_set_image(obj, &uhdr_image);
363   ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
364   status = uhdr_decode(obj);
365   ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
366   uhdr_raw_image_t* raw_image = uhdr_get_decoded_image(obj);
367   ASSERT_NE(nullptr, raw_image);
368   ASSERT_EQ(map_internal_cg_to_cg(destImage.colorGamut), raw_image->cg);
369   ASSERT_EQ(destImage.width, raw_image->w);
370   ASSERT_EQ(destImage.height, raw_image->h);
371   char* testData = static_cast<char*>(raw_image->planes[UHDR_PLANE_PACKED]);
372   char* refData = static_cast<char*>(destImage.data);
373   int bpp = (raw_image->fmt == UHDR_IMG_FMT_64bppRGBAHalfFloat) ? 8 : 4;
374   const size_t testStride = raw_image->stride[UHDR_PLANE_PACKED] * bpp;
375   const size_t refStride = destImage.width * bpp;
376   const size_t length = destImage.width * bpp;
377   for (unsigned i = 0; i < destImage.height; i++, testData += testStride, refData += refStride) {
378     ASSERT_EQ(0, memcmp(testData, refData, length));
379   }
380   uhdr_release_decoder(obj);
381 }
382 
383 // ============================================================================
384 // Unit Tests
385 // ============================================================================
386 
387 // Test Encode API-0 invalid arguments
TEST(JpegRTest,EncodeAPI0WithInvalidArgs)388 TEST(JpegRTest, EncodeAPI0WithInvalidArgs) {
389   JpegR uHdrLib;
390 
391   UhdrCompressedStructWrapper jpgImg(16, 16);
392   ASSERT_TRUE(jpgImg.allocateMemory());
393 
394   // test quality factor and transfer function
395   {
396     UhdrUnCompressedStructWrapper rawImg(16, 16, YCbCr_p010);
397     ASSERT_TRUE(rawImg.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100));
398     ASSERT_TRUE(rawImg.allocateMemory());
399 
400     ASSERT_NE(
401         uHdrLib.encodeJPEGR(rawImg.getImageHandle(), ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
402                             jpgImg.getImageHandle(), -1, nullptr),
403         JPEGR_NO_ERROR)
404         << "fail, API allows bad jpeg quality factor";
405     ASSERT_NE(
406         uHdrLib.encodeJPEGR(rawImg.getImageHandle(), ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
407                             jpgImg.getImageHandle(), 101, nullptr),
408         JPEGR_NO_ERROR)
409         << "fail, API allows bad jpeg quality factor";
410 
411     ASSERT_NE(uHdrLib.encodeJPEGR(rawImg.getImageHandle(),
412                                   ultrahdr_transfer_function::ULTRAHDR_TF_UNSPECIFIED,
413                                   jpgImg.getImageHandle(), kQuality, nullptr),
414               JPEGR_NO_ERROR)
415         << "fail, API allows bad hdr transfer function";
416     ASSERT_NE(uHdrLib.encodeJPEGR(rawImg.getImageHandle(),
417                                   static_cast<ultrahdr_transfer_function>(
418                                       ultrahdr_transfer_function::ULTRAHDR_TF_MAX + 1),
419                                   jpgImg.getImageHandle(), kQuality, nullptr),
420               JPEGR_NO_ERROR)
421         << "fail, API allows bad hdr transfer function";
422     ASSERT_NE(
423         uHdrLib.encodeJPEGR(rawImg.getImageHandle(), static_cast<ultrahdr_transfer_function>(-10),
424                             jpgImg.getImageHandle(), kQuality, nullptr),
425         JPEGR_NO_ERROR)
426         << "fail, API allows bad hdr transfer function";
427   }
428 
429   // test dest
430   {
431     UhdrUnCompressedStructWrapper rawImg(16, 16, YCbCr_p010);
432     ASSERT_TRUE(rawImg.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100));
433     ASSERT_TRUE(rawImg.allocateMemory());
434 
435     ASSERT_NE(
436         uHdrLib.encodeJPEGR(rawImg.getImageHandle(), ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
437                             nullptr, kQuality, nullptr),
438         JPEGR_NO_ERROR)
439         << "fail, API allows nullptr dest";
440     UhdrCompressedStructWrapper jpgImg2(16, 16);
441     ASSERT_NE(
442         uHdrLib.encodeJPEGR(rawImg.getImageHandle(), ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
443                             jpgImg2.getImageHandle(), kQuality, nullptr),
444         JPEGR_NO_ERROR)
445         << "fail, API allows nullptr dest";
446   }
447 
448   // test p010 input
449   {
450     ASSERT_NE(uHdrLib.encodeJPEGR(nullptr, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
451                                   jpgImg.getImageHandle(), kQuality, nullptr),
452               JPEGR_NO_ERROR)
453         << "fail, API allows nullptr p010 image";
454 
455     UhdrUnCompressedStructWrapper rawImg(16, 16, YCbCr_p010);
456     ASSERT_TRUE(rawImg.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100));
457     ASSERT_NE(
458         uHdrLib.encodeJPEGR(rawImg.getImageHandle(), ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
459                             jpgImg.getImageHandle(), kQuality, nullptr),
460         JPEGR_NO_ERROR)
461         << "fail, API allows nullptr p010 image";
462   }
463 
464   {
465     UhdrUnCompressedStructWrapper rawImg(16, 16, YCbCr_p010);
466     ASSERT_TRUE(rawImg.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_UNSPECIFIED));
467     ASSERT_TRUE(rawImg.allocateMemory());
468     ASSERT_NE(
469         uHdrLib.encodeJPEGR(rawImg.getImageHandle(), ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
470                             jpgImg.getImageHandle(), kQuality, nullptr),
471         JPEGR_NO_ERROR)
472         << "fail, API allows bad p010 color gamut";
473 
474     UhdrUnCompressedStructWrapper rawImg2(16, 16, YCbCr_p010);
475     ASSERT_TRUE(rawImg2.setImageColorGamut(
476         static_cast<ultrahdr_color_gamut>(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_MAX + 1)));
477     ASSERT_TRUE(rawImg2.allocateMemory());
478     ASSERT_NE(
479         uHdrLib.encodeJPEGR(rawImg2.getImageHandle(), ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
480                             jpgImg.getImageHandle(), kQuality, nullptr),
481         JPEGR_NO_ERROR)
482         << "fail, API allows bad p010 color gamut";
483   }
484 
485   {
486     const int kWidth = 32, kHeight = 32;
487     UhdrUnCompressedStructWrapper rawImg(kWidth, kHeight, YCbCr_p010);
488     ASSERT_TRUE(rawImg.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100));
489     ASSERT_TRUE(rawImg.allocateMemory());
490     auto rawImgP010 = rawImg.getImageHandle();
491 
492     rawImgP010->width = kWidth - 1;
493     rawImgP010->height = kHeight;
494     ASSERT_NE(uHdrLib.encodeJPEGR(rawImgP010, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
495                                   jpgImg.getImageHandle(), kQuality, nullptr),
496               JPEGR_NO_ERROR)
497         << "fail, API allows bad image width";
498 
499     rawImgP010->width = kWidth;
500     rawImgP010->height = kHeight - 1;
501     ASSERT_NE(uHdrLib.encodeJPEGR(rawImgP010, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
502                                   jpgImg.getImageHandle(), kQuality, nullptr),
503               JPEGR_NO_ERROR)
504         << "fail, API allows bad image height";
505 
506     rawImgP010->width = 0;
507     rawImgP010->height = kHeight;
508     ASSERT_NE(uHdrLib.encodeJPEGR(rawImgP010, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
509                                   jpgImg.getImageHandle(), kQuality, nullptr),
510               JPEGR_NO_ERROR)
511         << "fail, API allows bad image width";
512 
513     rawImgP010->width = kWidth;
514     rawImgP010->height = 0;
515     ASSERT_NE(uHdrLib.encodeJPEGR(rawImgP010, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
516                                   jpgImg.getImageHandle(), kQuality, nullptr),
517               JPEGR_NO_ERROR)
518         << "fail, API allows bad image height";
519 
520     rawImgP010->width = kWidth;
521     rawImgP010->height = kHeight;
522     rawImgP010->luma_stride = kWidth - 2;
523     ASSERT_NE(uHdrLib.encodeJPEGR(rawImgP010, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
524                                   jpgImg.getImageHandle(), kQuality, nullptr),
525               JPEGR_NO_ERROR)
526         << "fail, API allows bad luma stride";
527 
528     rawImgP010->width = kWidth;
529     rawImgP010->height = kHeight;
530     rawImgP010->luma_stride = kWidth + 64;
531     rawImgP010->chroma_data = rawImgP010->data;
532     rawImgP010->chroma_stride = kWidth - 2;
533     ASSERT_NE(uHdrLib.encodeJPEGR(rawImgP010, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
534                                   jpgImg.getImageHandle(), kQuality, nullptr),
535               JPEGR_NO_ERROR)
536         << "fail, API allows bad chroma stride";
537   }
538 }
539 
540 /* Test Encode API-1 invalid arguments */
TEST(JpegRTest,EncodeAPI1WithInvalidArgs)541 TEST(JpegRTest, EncodeAPI1WithInvalidArgs) {
542   JpegR uHdrLib;
543 
544   UhdrCompressedStructWrapper jpgImg(16, 16);
545   ASSERT_TRUE(jpgImg.allocateMemory());
546 
547   // test quality factor and transfer function
548   {
549     UhdrUnCompressedStructWrapper rawImg(16, 16, YCbCr_p010);
550     ASSERT_TRUE(rawImg.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100));
551     ASSERT_TRUE(rawImg.allocateMemory());
552     UhdrUnCompressedStructWrapper rawImg2(16, 16, YCbCr_420);
553     ASSERT_TRUE(rawImg2.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709));
554     ASSERT_TRUE(rawImg2.allocateMemory());
555 
556     ASSERT_NE(uHdrLib.encodeJPEGR(rawImg.getImageHandle(), rawImg2.getImageHandle(),
557                                   ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
558                                   jpgImg.getImageHandle(), -1, nullptr),
559               JPEGR_NO_ERROR)
560         << "fail, API allows bad jpeg quality factor";
561     ASSERT_NE(uHdrLib.encodeJPEGR(rawImg.getImageHandle(), rawImg2.getImageHandle(),
562                                   ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
563                                   jpgImg.getImageHandle(), 101, nullptr),
564               JPEGR_NO_ERROR)
565         << "fail, API allows bad jpeg quality factor";
566 
567     ASSERT_NE(uHdrLib.encodeJPEGR(rawImg.getImageHandle(), rawImg2.getImageHandle(),
568                                   ultrahdr_transfer_function::ULTRAHDR_TF_UNSPECIFIED,
569                                   jpgImg.getImageHandle(), kQuality, nullptr),
570               JPEGR_NO_ERROR)
571         << "fail, API allows bad hdr transfer function";
572     ASSERT_NE(uHdrLib.encodeJPEGR(rawImg.getImageHandle(), rawImg2.getImageHandle(),
573                                   static_cast<ultrahdr_transfer_function>(
574                                       ultrahdr_transfer_function::ULTRAHDR_TF_MAX + 1),
575                                   jpgImg.getImageHandle(), kQuality, nullptr),
576               JPEGR_NO_ERROR)
577         << "fail, API allows bad hdr transfer function";
578     ASSERT_NE(uHdrLib.encodeJPEGR(rawImg.getImageHandle(), rawImg2.getImageHandle(),
579                                   static_cast<ultrahdr_transfer_function>(-10),
580                                   jpgImg.getImageHandle(), kQuality, nullptr),
581               JPEGR_NO_ERROR)
582         << "fail, API allows bad hdr transfer function";
583   }
584 
585   // test dest
586   {
587     UhdrUnCompressedStructWrapper rawImg(16, 16, YCbCr_p010);
588     ASSERT_TRUE(rawImg.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100));
589     ASSERT_TRUE(rawImg.allocateMemory());
590     UhdrUnCompressedStructWrapper rawImg2(16, 16, YCbCr_420);
591     ASSERT_TRUE(rawImg2.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709));
592     ASSERT_TRUE(rawImg2.allocateMemory());
593 
594     ASSERT_NE(uHdrLib.encodeJPEGR(rawImg.getImageHandle(), rawImg2.getImageHandle(),
595                                   ultrahdr_transfer_function::ULTRAHDR_TF_HLG, nullptr, kQuality,
596                                   nullptr),
597               JPEGR_NO_ERROR)
598         << "fail, API allows nullptr dest";
599     UhdrCompressedStructWrapper jpgImg2(16, 16);
600     ASSERT_NE(uHdrLib.encodeJPEGR(rawImg.getImageHandle(), rawImg2.getImageHandle(),
601                                   ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
602                                   jpgImg2.getImageHandle(), kQuality, nullptr),
603               JPEGR_NO_ERROR)
604         << "fail, API allows nullptr dest";
605   }
606 
607   // test p010 input
608   {
609     UhdrUnCompressedStructWrapper rawImg2(16, 16, YCbCr_420);
610     ASSERT_TRUE(rawImg2.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709));
611     ASSERT_TRUE(rawImg2.allocateMemory());
612     ASSERT_NE(uHdrLib.encodeJPEGR(nullptr, rawImg2.getImageHandle(),
613                                   ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
614                                   jpgImg.getImageHandle(), kQuality, nullptr),
615               JPEGR_NO_ERROR)
616         << "fail, API allows nullptr p010 image";
617 
618     UhdrUnCompressedStructWrapper rawImg(16, 16, YCbCr_p010);
619     ASSERT_TRUE(rawImg.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100));
620     ASSERT_NE(uHdrLib.encodeJPEGR(rawImg.getImageHandle(), rawImg2.getImageHandle(),
621                                   ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
622                                   jpgImg.getImageHandle(), kQuality, nullptr),
623               JPEGR_NO_ERROR)
624         << "fail, API allows nullptr p010 image";
625   }
626 
627   {
628     const int kWidth = 32, kHeight = 32;
629     UhdrUnCompressedStructWrapper rawImg(kWidth, kHeight, YCbCr_p010);
630     ASSERT_TRUE(rawImg.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100));
631     ASSERT_TRUE(rawImg.allocateMemory());
632     auto rawImgP010 = rawImg.getImageHandle();
633     UhdrUnCompressedStructWrapper rawImg2(kWidth, kHeight, YCbCr_420);
634     ASSERT_TRUE(rawImg2.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709));
635     ASSERT_TRUE(rawImg2.allocateMemory());
636     auto rawImg420 = rawImg2.getImageHandle();
637 
638     rawImgP010->width = kWidth;
639     rawImgP010->height = kHeight;
640     rawImgP010->colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_UNSPECIFIED;
641     ASSERT_NE(
642         uHdrLib.encodeJPEGR(rawImgP010, rawImg420, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
643                             jpgImg.getImageHandle(), kQuality, nullptr),
644         JPEGR_NO_ERROR)
645         << "fail, API allows bad p010 color gamut";
646 
647     rawImgP010->width = kWidth;
648     rawImgP010->height = kHeight;
649     rawImgP010->colorGamut =
650         static_cast<ultrahdr_color_gamut>(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_MAX + 1);
651     ASSERT_NE(
652         uHdrLib.encodeJPEGR(rawImgP010, rawImg420, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
653                             jpgImg.getImageHandle(), kQuality, nullptr),
654         JPEGR_NO_ERROR)
655         << "fail, API allows bad p010 color gamut";
656 
657     rawImgP010->width = kWidth - 1;
658     rawImgP010->height = kHeight;
659     rawImgP010->colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
660     ASSERT_NE(
661         uHdrLib.encodeJPEGR(rawImgP010, rawImg420, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
662                             jpgImg.getImageHandle(), kQuality, nullptr),
663         JPEGR_NO_ERROR)
664         << "fail, API allows bad image width";
665 
666     rawImgP010->width = kWidth;
667     rawImgP010->height = kHeight - 1;
668     ASSERT_NE(
669         uHdrLib.encodeJPEGR(rawImgP010, rawImg420, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
670                             jpgImg.getImageHandle(), kQuality, nullptr),
671         JPEGR_NO_ERROR)
672         << "fail, API allows bad image height";
673 
674     rawImgP010->width = 0;
675     rawImgP010->height = kHeight;
676     ASSERT_NE(
677         uHdrLib.encodeJPEGR(rawImgP010, rawImg420, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
678                             jpgImg.getImageHandle(), kQuality, nullptr),
679         JPEGR_NO_ERROR)
680         << "fail, API allows bad image width";
681 
682     rawImgP010->width = kWidth;
683     rawImgP010->height = 0;
684     ASSERT_NE(
685         uHdrLib.encodeJPEGR(rawImgP010, rawImg420, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
686                             jpgImg.getImageHandle(), kQuality, nullptr),
687         JPEGR_NO_ERROR)
688         << "fail, API allows bad image height";
689 
690     rawImgP010->width = kWidth;
691     rawImgP010->height = kHeight;
692     rawImgP010->luma_stride = kWidth - 2;
693     ASSERT_NE(
694         uHdrLib.encodeJPEGR(rawImgP010, rawImg420, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
695                             jpgImg.getImageHandle(), kQuality, nullptr),
696         JPEGR_NO_ERROR)
697         << "fail, API allows bad luma stride";
698 
699     rawImgP010->width = kWidth;
700     rawImgP010->height = kHeight;
701     rawImgP010->luma_stride = kWidth + 64;
702     rawImgP010->chroma_data = rawImgP010->data;
703     rawImgP010->chroma_stride = kWidth - 2;
704     ASSERT_NE(
705         uHdrLib.encodeJPEGR(rawImgP010, rawImg420, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
706                             jpgImg.getImageHandle(), kQuality, nullptr),
707         JPEGR_NO_ERROR)
708         << "fail, API allows bad chroma stride";
709   }
710 
711   // test 420 input
712   {
713     UhdrUnCompressedStructWrapper rawImg(16, 16, YCbCr_p010);
714     ASSERT_TRUE(rawImg.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100));
715     ASSERT_TRUE(rawImg.allocateMemory());
716     ASSERT_NE(uHdrLib.encodeJPEGR(rawImg.getImageHandle(), nullptr,
717                                   ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
718                                   jpgImg.getImageHandle(), kQuality, nullptr),
719               JPEGR_NO_ERROR)
720         << "fail, API allows nullptr 420 image";
721 
722     UhdrUnCompressedStructWrapper rawImg2(16, 16, YCbCr_420);
723     ASSERT_TRUE(rawImg2.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100));
724     ASSERT_NE(uHdrLib.encodeJPEGR(rawImg.getImageHandle(), rawImg2.getImageHandle(),
725                                   ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
726                                   jpgImg.getImageHandle(), kQuality, nullptr),
727               JPEGR_NO_ERROR)
728         << "fail, API allows nullptr 420 image";
729   }
730   {
731     const int kWidth = 32, kHeight = 32;
732     UhdrUnCompressedStructWrapper rawImg(kWidth, kHeight, YCbCr_p010);
733     ASSERT_TRUE(rawImg.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100));
734     ASSERT_TRUE(rawImg.allocateMemory());
735     auto rawImgP010 = rawImg.getImageHandle();
736     UhdrUnCompressedStructWrapper rawImg2(kWidth, kHeight, YCbCr_420);
737     ASSERT_TRUE(rawImg2.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709));
738     ASSERT_TRUE(rawImg2.allocateMemory());
739     auto rawImg420 = rawImg2.getImageHandle();
740 
741     rawImg420->width = kWidth;
742     rawImg420->height = kHeight;
743     rawImg420->colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_UNSPECIFIED;
744     ASSERT_NE(
745         uHdrLib.encodeJPEGR(rawImgP010, rawImg420, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
746                             jpgImg.getImageHandle(), kQuality, nullptr),
747         JPEGR_NO_ERROR)
748         << "fail, API allows bad 420 color gamut";
749 
750     rawImg420->width = kWidth;
751     rawImg420->height = kHeight;
752     rawImg420->colorGamut =
753         static_cast<ultrahdr_color_gamut>(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_MAX + 1);
754     ASSERT_NE(
755         uHdrLib.encodeJPEGR(rawImgP010, rawImg420, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
756                             jpgImg.getImageHandle(), kQuality, nullptr),
757         JPEGR_NO_ERROR)
758         << "fail, API allows bad 420 color gamut";
759 
760     rawImg420->width = kWidth - 1;
761     rawImg420->height = kHeight;
762     rawImg420->colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709;
763     ASSERT_NE(
764         uHdrLib.encodeJPEGR(rawImgP010, rawImg420, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
765                             jpgImg.getImageHandle(), kQuality, nullptr),
766         JPEGR_NO_ERROR)
767         << "fail, API allows bad image width for 420";
768 
769     rawImg420->width = kWidth;
770     rawImg420->height = kHeight - 1;
771     ASSERT_NE(
772         uHdrLib.encodeJPEGR(rawImgP010, rawImg420, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
773                             jpgImg.getImageHandle(), kQuality, nullptr),
774         JPEGR_NO_ERROR)
775         << "fail, API allows bad image height for 420";
776 
777     rawImg420->width = 0;
778     rawImg420->height = kHeight;
779     ASSERT_NE(
780         uHdrLib.encodeJPEGR(rawImgP010, rawImg420, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
781                             jpgImg.getImageHandle(), kQuality, nullptr),
782         JPEGR_NO_ERROR)
783         << "fail, API allows bad image width for 420";
784 
785     rawImg420->width = kWidth;
786     rawImg420->height = 0;
787     ASSERT_NE(
788         uHdrLib.encodeJPEGR(rawImgP010, rawImg420, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
789                             jpgImg.getImageHandle(), kQuality, nullptr),
790         JPEGR_NO_ERROR)
791         << "fail, API allows bad image height for 420";
792 
793     rawImg420->width = kWidth;
794     rawImg420->height = kHeight;
795     rawImg420->luma_stride = kWidth - 2;
796     ASSERT_NE(
797         uHdrLib.encodeJPEGR(rawImgP010, rawImg420, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
798                             jpgImg.getImageHandle(), kQuality, nullptr),
799         JPEGR_NO_ERROR)
800         << "fail, API allows bad luma stride for 420";
801 
802     rawImg420->width = kWidth;
803     rawImg420->height = kHeight;
804     rawImg420->luma_stride = 0;
805     rawImg420->chroma_data = rawImgP010->data;
806     rawImg420->chroma_stride = kWidth / 2 - 2;
807     ASSERT_NE(
808         uHdrLib.encodeJPEGR(rawImgP010, rawImg420, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
809                             jpgImg.getImageHandle(), kQuality, nullptr),
810         JPEGR_NO_ERROR)
811         << "fail, API allows bad chroma stride for 420";
812   }
813 }
814 
815 /* Test Encode API-2 invalid arguments */
TEST(JpegRTest,EncodeAPI2WithInvalidArgs)816 TEST(JpegRTest, EncodeAPI2WithInvalidArgs) {
817   JpegR uHdrLib;
818 
819   UhdrCompressedStructWrapper jpgImg(16, 16);
820   ASSERT_TRUE(jpgImg.allocateMemory());
821 
822   // test quality factor and transfer function
823   {
824     UhdrUnCompressedStructWrapper rawImg(16, 16, YCbCr_p010);
825     ASSERT_TRUE(rawImg.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100));
826     ASSERT_TRUE(rawImg.allocateMemory());
827     UhdrUnCompressedStructWrapper rawImg2(16, 16, YCbCr_420);
828     ASSERT_TRUE(rawImg2.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709));
829     ASSERT_TRUE(rawImg2.allocateMemory());
830 
831     ASSERT_NE(uHdrLib.encodeJPEGR(
832                   rawImg.getImageHandle(), rawImg2.getImageHandle(), jpgImg.getImageHandle(),
833                   ultrahdr_transfer_function::ULTRAHDR_TF_UNSPECIFIED, jpgImg.getImageHandle()),
834               JPEGR_NO_ERROR)
835         << "fail, API allows bad hdr transfer function";
836     ASSERT_NE(uHdrLib.encodeJPEGR(rawImg.getImageHandle(), rawImg2.getImageHandle(),
837                                   jpgImg.getImageHandle(),
838                                   static_cast<ultrahdr_transfer_function>(
839                                       ultrahdr_transfer_function::ULTRAHDR_TF_MAX + 1),
840                                   jpgImg.getImageHandle()),
841               JPEGR_NO_ERROR)
842         << "fail, API allows bad hdr transfer function";
843     ASSERT_NE(uHdrLib.encodeJPEGR(
844                   rawImg.getImageHandle(), rawImg2.getImageHandle(), jpgImg.getImageHandle(),
845                   static_cast<ultrahdr_transfer_function>(-10), jpgImg.getImageHandle()),
846               JPEGR_NO_ERROR)
847         << "fail, API allows bad hdr transfer function";
848   }
849 
850   // test dest
851   {
852     UhdrUnCompressedStructWrapper rawImg(16, 16, YCbCr_p010);
853     ASSERT_TRUE(rawImg.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100));
854     ASSERT_TRUE(rawImg.allocateMemory());
855     UhdrUnCompressedStructWrapper rawImg2(16, 16, YCbCr_420);
856     ASSERT_TRUE(rawImg2.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709));
857     ASSERT_TRUE(rawImg2.allocateMemory());
858 
859     ASSERT_NE(uHdrLib.encodeJPEGR(rawImg.getImageHandle(), rawImg2.getImageHandle(),
860                                   jpgImg.getImageHandle(),
861                                   ultrahdr_transfer_function::ULTRAHDR_TF_HLG, nullptr),
862               JPEGR_NO_ERROR)
863         << "fail, API allows nullptr dest";
864     UhdrCompressedStructWrapper jpgImg2(16, 16);
865     ASSERT_NE(uHdrLib.encodeJPEGR(
866                   rawImg.getImageHandle(), rawImg2.getImageHandle(), jpgImg.getImageHandle(),
867                   ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg2.getImageHandle()),
868               JPEGR_NO_ERROR)
869         << "fail, API allows nullptr dest";
870   }
871 
872   // test compressed image
873   {
874     UhdrUnCompressedStructWrapper rawImg(16, 16, YCbCr_p010);
875     ASSERT_TRUE(rawImg.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100));
876     ASSERT_TRUE(rawImg.allocateMemory());
877     UhdrUnCompressedStructWrapper rawImg2(16, 16, YCbCr_420);
878     ASSERT_TRUE(rawImg2.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709));
879     ASSERT_TRUE(rawImg2.allocateMemory());
880 
881     ASSERT_NE(
882         uHdrLib.encodeJPEGR(rawImg.getImageHandle(), rawImg2.getImageHandle(), nullptr,
883                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
884         JPEGR_NO_ERROR)
885         << "fail, API allows nullptr for compressed image";
886     UhdrCompressedStructWrapper jpgImg2(16, 16);
887     ASSERT_NE(uHdrLib.encodeJPEGR(
888                   rawImg.getImageHandle(), rawImg2.getImageHandle(), jpgImg2.getImageHandle(),
889                   ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
890               JPEGR_NO_ERROR)
891         << "fail, API allows nullptr for compressed image";
892   }
893 
894   // test p010 input
895   {
896     UhdrUnCompressedStructWrapper rawImg2(16, 16, YCbCr_420);
897     ASSERT_TRUE(rawImg2.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709));
898     ASSERT_TRUE(rawImg2.allocateMemory());
899     ASSERT_NE(
900         uHdrLib.encodeJPEGR(nullptr, rawImg2.getImageHandle(), jpgImg.getImageHandle(),
901                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
902         JPEGR_NO_ERROR)
903         << "fail, API allows nullptr p010 image";
904 
905     UhdrUnCompressedStructWrapper rawImg(16, 16, YCbCr_p010);
906     ASSERT_TRUE(rawImg.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100));
907     ASSERT_NE(uHdrLib.encodeJPEGR(
908                   rawImg.getImageHandle(), rawImg2.getImageHandle(), jpgImg.getImageHandle(),
909                   ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
910               JPEGR_NO_ERROR)
911         << "fail, API allows nullptr p010 image";
912   }
913 
914   {
915     const int kWidth = 32, kHeight = 32;
916     UhdrUnCompressedStructWrapper rawImg(kWidth, kHeight, YCbCr_p010);
917     ASSERT_TRUE(rawImg.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100));
918     ASSERT_TRUE(rawImg.allocateMemory());
919     auto rawImgP010 = rawImg.getImageHandle();
920     UhdrUnCompressedStructWrapper rawImg2(kWidth, kHeight, YCbCr_420);
921     ASSERT_TRUE(rawImg2.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709));
922     ASSERT_TRUE(rawImg2.allocateMemory());
923     auto rawImg420 = rawImg2.getImageHandle();
924 
925     rawImgP010->width = kWidth;
926     rawImgP010->height = kHeight;
927     rawImgP010->colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_UNSPECIFIED;
928     ASSERT_NE(
929         uHdrLib.encodeJPEGR(rawImgP010, rawImg420, jpgImg.getImageHandle(),
930                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
931         JPEGR_NO_ERROR)
932         << "fail, API allows bad p010 color gamut";
933 
934     rawImgP010->width = kWidth;
935     rawImgP010->height = kHeight;
936     rawImgP010->colorGamut =
937         static_cast<ultrahdr_color_gamut>(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_MAX + 1);
938     ASSERT_NE(
939         uHdrLib.encodeJPEGR(rawImgP010, rawImg420, jpgImg.getImageHandle(),
940                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
941         JPEGR_NO_ERROR)
942         << "fail, API allows bad p010 color gamut";
943 
944     rawImgP010->width = kWidth - 1;
945     rawImgP010->height = kHeight;
946     rawImgP010->colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
947     ASSERT_NE(
948         uHdrLib.encodeJPEGR(rawImgP010, rawImg420, jpgImg.getImageHandle(),
949                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
950         JPEGR_NO_ERROR)
951         << "fail, API allows bad image width";
952 
953     rawImgP010->width = kWidth;
954     rawImgP010->height = kHeight - 1;
955     ASSERT_NE(
956         uHdrLib.encodeJPEGR(rawImgP010, rawImg420, jpgImg.getImageHandle(),
957                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
958         JPEGR_NO_ERROR)
959         << "fail, API allows bad image height";
960 
961     rawImgP010->width = 0;
962     rawImgP010->height = kHeight;
963     ASSERT_NE(
964         uHdrLib.encodeJPEGR(rawImgP010, rawImg420, jpgImg.getImageHandle(),
965                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
966         JPEGR_NO_ERROR)
967         << "fail, API allows bad image width";
968 
969     rawImgP010->width = kWidth;
970     rawImgP010->height = 0;
971     ASSERT_NE(
972         uHdrLib.encodeJPEGR(rawImgP010, rawImg420, jpgImg.getImageHandle(),
973                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
974         JPEGR_NO_ERROR)
975         << "fail, API allows bad image height";
976 
977     rawImgP010->width = kWidth;
978     rawImgP010->height = kHeight;
979     rawImgP010->luma_stride = kWidth - 2;
980     ASSERT_NE(
981         uHdrLib.encodeJPEGR(rawImgP010, rawImg420, jpgImg.getImageHandle(),
982                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
983         JPEGR_NO_ERROR)
984         << "fail, API allows bad luma stride";
985 
986     rawImgP010->width = kWidth;
987     rawImgP010->height = kHeight;
988     rawImgP010->luma_stride = kWidth + 64;
989     rawImgP010->chroma_data = rawImgP010->data;
990     rawImgP010->chroma_stride = kWidth - 2;
991     ASSERT_NE(
992         uHdrLib.encodeJPEGR(rawImgP010, rawImg420, jpgImg.getImageHandle(),
993                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
994         JPEGR_NO_ERROR)
995         << "fail, API allows bad chroma stride";
996   }
997 
998   // test 420 input
999   {
1000     UhdrUnCompressedStructWrapper rawImg(16, 16, YCbCr_p010);
1001     ASSERT_TRUE(rawImg.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100));
1002     ASSERT_TRUE(rawImg.allocateMemory());
1003     ASSERT_NE(
1004         uHdrLib.encodeJPEGR(rawImg.getImageHandle(), nullptr, jpgImg.getImageHandle(),
1005                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
1006         JPEGR_NO_ERROR)
1007         << "fail, API allows nullptr 420 image";
1008 
1009     UhdrUnCompressedStructWrapper rawImg2(16, 16, YCbCr_420);
1010     ASSERT_TRUE(rawImg2.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100));
1011     ASSERT_NE(uHdrLib.encodeJPEGR(
1012                   rawImg.getImageHandle(), rawImg2.getImageHandle(), jpgImg.getImageHandle(),
1013                   ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
1014               JPEGR_NO_ERROR)
1015         << "fail, API allows nullptr 420 image";
1016   }
1017   {
1018     const int kWidth = 32, kHeight = 32;
1019     UhdrUnCompressedStructWrapper rawImg(kWidth, kHeight, YCbCr_p010);
1020     ASSERT_TRUE(rawImg.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100));
1021     ASSERT_TRUE(rawImg.allocateMemory());
1022     auto rawImgP010 = rawImg.getImageHandle();
1023     UhdrUnCompressedStructWrapper rawImg2(kWidth, kHeight, YCbCr_420);
1024     ASSERT_TRUE(rawImg2.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709));
1025     ASSERT_TRUE(rawImg2.allocateMemory());
1026     auto rawImg420 = rawImg2.getImageHandle();
1027 
1028     rawImg420->width = kWidth;
1029     rawImg420->height = kHeight;
1030     rawImg420->colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_UNSPECIFIED;
1031     ASSERT_NE(
1032         uHdrLib.encodeJPEGR(rawImgP010, rawImg420, jpgImg.getImageHandle(),
1033                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
1034         JPEGR_NO_ERROR)
1035         << "fail, API allows bad 420 color gamut";
1036 
1037     rawImg420->width = kWidth;
1038     rawImg420->height = kHeight;
1039     rawImg420->colorGamut =
1040         static_cast<ultrahdr_color_gamut>(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_MAX + 1);
1041     ASSERT_NE(
1042         uHdrLib.encodeJPEGR(rawImgP010, rawImg420, jpgImg.getImageHandle(),
1043                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
1044         JPEGR_NO_ERROR)
1045         << "fail, API allows bad 420 color gamut";
1046 
1047     rawImg420->width = kWidth - 1;
1048     rawImg420->height = kHeight;
1049     rawImg420->colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709;
1050     ASSERT_NE(
1051         uHdrLib.encodeJPEGR(rawImgP010, rawImg420, jpgImg.getImageHandle(),
1052                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
1053         JPEGR_NO_ERROR)
1054         << "fail, API allows bad image width for 420";
1055 
1056     rawImg420->width = kWidth;
1057     rawImg420->height = kHeight - 1;
1058     ASSERT_NE(
1059         uHdrLib.encodeJPEGR(rawImgP010, rawImg420, jpgImg.getImageHandle(),
1060                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
1061         JPEGR_NO_ERROR)
1062         << "fail, API allows bad image height for 420";
1063 
1064     rawImg420->width = 0;
1065     rawImg420->height = kHeight;
1066     ASSERT_NE(
1067         uHdrLib.encodeJPEGR(rawImgP010, rawImg420, jpgImg.getImageHandle(),
1068                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
1069         JPEGR_NO_ERROR)
1070         << "fail, API allows bad image width for 420";
1071 
1072     rawImg420->width = kWidth;
1073     rawImg420->height = 0;
1074     ASSERT_NE(
1075         uHdrLib.encodeJPEGR(rawImgP010, rawImg420, jpgImg.getImageHandle(),
1076                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
1077         JPEGR_NO_ERROR)
1078         << "fail, API allows bad image height for 420";
1079 
1080     rawImg420->width = kWidth;
1081     rawImg420->height = kHeight;
1082     rawImg420->luma_stride = kWidth - 2;
1083     ASSERT_NE(
1084         uHdrLib.encodeJPEGR(rawImgP010, rawImg420, jpgImg.getImageHandle(),
1085                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
1086         JPEGR_NO_ERROR)
1087         << "fail, API allows bad luma stride for 420";
1088 
1089     rawImg420->width = kWidth;
1090     rawImg420->height = kHeight;
1091     rawImg420->luma_stride = 0;
1092     rawImg420->chroma_data = rawImgP010->data;
1093     rawImg420->chroma_stride = kWidth / 2 - 2;
1094     ASSERT_NE(
1095         uHdrLib.encodeJPEGR(rawImgP010, rawImg420, jpgImg.getImageHandle(),
1096                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
1097         JPEGR_NO_ERROR)
1098         << "fail, API allows bad chroma stride for 420";
1099   }
1100 }
1101 
1102 /* Test Encode API-3 invalid arguments */
TEST(JpegRTest,EncodeAPI3WithInvalidArgs)1103 TEST(JpegRTest, EncodeAPI3WithInvalidArgs) {
1104   JpegR uHdrLib;
1105 
1106   UhdrCompressedStructWrapper jpgImg(16, 16);
1107   ASSERT_TRUE(jpgImg.allocateMemory());
1108 
1109   // test quality factor and transfer function
1110   {
1111     UhdrUnCompressedStructWrapper rawImg(16, 16, YCbCr_p010);
1112     ASSERT_TRUE(rawImg.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100));
1113     ASSERT_TRUE(rawImg.allocateMemory());
1114 
1115     ASSERT_NE(uHdrLib.encodeJPEGR(rawImg.getImageHandle(), jpgImg.getImageHandle(),
1116                                   ultrahdr_transfer_function::ULTRAHDR_TF_UNSPECIFIED,
1117                                   jpgImg.getImageHandle()),
1118               JPEGR_NO_ERROR)
1119         << "fail, API allows bad hdr transfer function";
1120     ASSERT_NE(uHdrLib.encodeJPEGR(rawImg.getImageHandle(), jpgImg.getImageHandle(),
1121                                   static_cast<ultrahdr_transfer_function>(
1122                                       ultrahdr_transfer_function::ULTRAHDR_TF_MAX + 1),
1123                                   jpgImg.getImageHandle()),
1124               JPEGR_NO_ERROR)
1125         << "fail, API allows bad hdr transfer function";
1126     ASSERT_NE(
1127         uHdrLib.encodeJPEGR(rawImg.getImageHandle(), jpgImg.getImageHandle(),
1128                             static_cast<ultrahdr_transfer_function>(-10), jpgImg.getImageHandle()),
1129         JPEGR_NO_ERROR)
1130         << "fail, API allows bad hdr transfer function";
1131   }
1132 
1133   // test dest
1134   {
1135     UhdrUnCompressedStructWrapper rawImg(16, 16, YCbCr_p010);
1136     ASSERT_TRUE(rawImg.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100));
1137     ASSERT_TRUE(rawImg.allocateMemory());
1138 
1139     ASSERT_NE(uHdrLib.encodeJPEGR(rawImg.getImageHandle(), jpgImg.getImageHandle(),
1140                                   ultrahdr_transfer_function::ULTRAHDR_TF_HLG, nullptr),
1141               JPEGR_NO_ERROR)
1142         << "fail, API allows nullptr dest";
1143     UhdrCompressedStructWrapper jpgImg2(16, 16);
1144     ASSERT_NE(
1145         uHdrLib.encodeJPEGR(rawImg.getImageHandle(), jpgImg.getImageHandle(),
1146                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg2.getImageHandle()),
1147         JPEGR_NO_ERROR)
1148         << "fail, API allows nullptr dest";
1149   }
1150 
1151   // test compressed image
1152   {
1153     UhdrUnCompressedStructWrapper rawImg(16, 16, YCbCr_p010);
1154     ASSERT_TRUE(rawImg.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100));
1155     ASSERT_TRUE(rawImg.allocateMemory());
1156 
1157     ASSERT_NE(
1158         uHdrLib.encodeJPEGR(rawImg.getImageHandle(), nullptr,
1159                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
1160         JPEGR_NO_ERROR)
1161         << "fail, API allows nullptr for compressed image";
1162     UhdrCompressedStructWrapper jpgImg2(16, 16);
1163     ASSERT_NE(
1164         uHdrLib.encodeJPEGR(rawImg.getImageHandle(), jpgImg2.getImageHandle(),
1165                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
1166         JPEGR_NO_ERROR)
1167         << "fail, API allows nullptr for compressed image";
1168   }
1169 
1170   // test p010 input
1171   {
1172     ASSERT_NE(
1173         uHdrLib.encodeJPEGR(nullptr, jpgImg.getImageHandle(),
1174                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
1175         JPEGR_NO_ERROR)
1176         << "fail, API allows nullptr p010 image";
1177 
1178     UhdrUnCompressedStructWrapper rawImg(16, 16, YCbCr_p010);
1179     ASSERT_TRUE(rawImg.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100));
1180     ASSERT_NE(
1181         uHdrLib.encodeJPEGR(rawImg.getImageHandle(), jpgImg.getImageHandle(),
1182                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
1183         JPEGR_NO_ERROR)
1184         << "fail, API allows nullptr p010 image";
1185   }
1186 
1187   {
1188     const int kWidth = 32, kHeight = 32;
1189     UhdrUnCompressedStructWrapper rawImg(kWidth, kHeight, YCbCr_p010);
1190     ASSERT_TRUE(rawImg.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100));
1191     ASSERT_TRUE(rawImg.allocateMemory());
1192     auto rawImgP010 = rawImg.getImageHandle();
1193 
1194     rawImgP010->width = kWidth;
1195     rawImgP010->height = kHeight;
1196     rawImgP010->colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_UNSPECIFIED;
1197     ASSERT_NE(
1198         uHdrLib.encodeJPEGR(rawImgP010, jpgImg.getImageHandle(),
1199                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
1200         JPEGR_NO_ERROR)
1201         << "fail, API allows bad p010 color gamut";
1202 
1203     rawImgP010->width = kWidth;
1204     rawImgP010->height = kHeight;
1205     rawImgP010->colorGamut =
1206         static_cast<ultrahdr_color_gamut>(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_MAX + 1);
1207     ASSERT_NE(
1208         uHdrLib.encodeJPEGR(rawImgP010, jpgImg.getImageHandle(),
1209                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
1210         JPEGR_NO_ERROR)
1211         << "fail, API allows bad p010 color gamut";
1212 
1213     rawImgP010->width = kWidth - 1;
1214     rawImgP010->height = kHeight;
1215     rawImgP010->colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
1216     ASSERT_NE(
1217         uHdrLib.encodeJPEGR(rawImgP010, jpgImg.getImageHandle(),
1218                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
1219         JPEGR_NO_ERROR)
1220         << "fail, API allows bad image width";
1221 
1222     rawImgP010->width = kWidth;
1223     rawImgP010->height = kHeight - 1;
1224     ASSERT_NE(
1225         uHdrLib.encodeJPEGR(rawImgP010, jpgImg.getImageHandle(),
1226                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
1227         JPEGR_NO_ERROR)
1228         << "fail, API allows bad image height";
1229 
1230     rawImgP010->width = 0;
1231     rawImgP010->height = kHeight;
1232     ASSERT_NE(
1233         uHdrLib.encodeJPEGR(rawImgP010, jpgImg.getImageHandle(),
1234                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
1235         JPEGR_NO_ERROR)
1236         << "fail, API allows bad image width";
1237 
1238     rawImgP010->width = kWidth;
1239     rawImgP010->height = 0;
1240     ASSERT_NE(
1241         uHdrLib.encodeJPEGR(rawImgP010, jpgImg.getImageHandle(),
1242                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
1243         JPEGR_NO_ERROR)
1244         << "fail, API allows bad image height";
1245 
1246     rawImgP010->width = kWidth;
1247     rawImgP010->height = kHeight;
1248     rawImgP010->luma_stride = kWidth - 2;
1249     ASSERT_NE(
1250         uHdrLib.encodeJPEGR(rawImgP010, jpgImg.getImageHandle(),
1251                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
1252         JPEGR_NO_ERROR)
1253         << "fail, API allows bad luma stride";
1254 
1255     rawImgP010->width = kWidth;
1256     rawImgP010->height = kHeight;
1257     rawImgP010->luma_stride = kWidth + 64;
1258     rawImgP010->chroma_data = rawImgP010->data;
1259     rawImgP010->chroma_stride = kWidth - 2;
1260     ASSERT_NE(
1261         uHdrLib.encodeJPEGR(rawImgP010, jpgImg.getImageHandle(),
1262                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
1263         JPEGR_NO_ERROR)
1264         << "fail, API allows bad chroma stride";
1265   }
1266 }
1267 
1268 /* Test Encode API-4 invalid arguments */
TEST(JpegRTest,EncodeAPI4WithInvalidArgs)1269 TEST(JpegRTest, EncodeAPI4WithInvalidArgs) {
1270   UhdrCompressedStructWrapper jpgImg(16, 16);
1271   ASSERT_TRUE(jpgImg.allocateMemory());
1272   UhdrCompressedStructWrapper jpgImg2(16, 16);
1273   JpegR uHdrLib;
1274 
1275   // test dest
1276   ASSERT_NE(uHdrLib.encodeJPEGR(jpgImg.getImageHandle(), jpgImg.getImageHandle(), nullptr, nullptr),
1277             JPEGR_NO_ERROR)
1278       << "fail, API allows nullptr dest";
1279   ASSERT_NE(uHdrLib.encodeJPEGR(jpgImg.getImageHandle(), jpgImg.getImageHandle(), nullptr,
1280                                 jpgImg2.getImageHandle()),
1281             JPEGR_NO_ERROR)
1282       << "fail, API allows nullptr dest";
1283 
1284   // test primary image
1285   ASSERT_NE(uHdrLib.encodeJPEGR(nullptr, jpgImg.getImageHandle(), nullptr, jpgImg.getImageHandle()),
1286             JPEGR_NO_ERROR)
1287       << "fail, API allows nullptr primary image";
1288   ASSERT_NE(uHdrLib.encodeJPEGR(jpgImg2.getImageHandle(), jpgImg.getImageHandle(), nullptr,
1289                                 jpgImg.getImageHandle()),
1290             JPEGR_NO_ERROR)
1291       << "fail, API allows nullptr primary image";
1292 
1293   // test gain map
1294   ASSERT_NE(uHdrLib.encodeJPEGR(jpgImg.getImageHandle(), nullptr, nullptr, jpgImg.getImageHandle()),
1295             JPEGR_NO_ERROR)
1296       << "fail, API allows nullptr gain map image";
1297   ASSERT_NE(uHdrLib.encodeJPEGR(jpgImg.getImageHandle(), jpgImg2.getImageHandle(), nullptr,
1298                                 jpgImg.getImageHandle()),
1299             JPEGR_NO_ERROR)
1300       << "fail, API allows nullptr gain map image";
1301 
1302   // test metadata
1303   ultrahdr_metadata_struct good_metadata;
1304   good_metadata.version = "1.0";
1305   good_metadata.minContentBoost = 1.0f;
1306   good_metadata.maxContentBoost = 2.0f;
1307   good_metadata.gamma = 1.0f;
1308   good_metadata.offsetSdr = 0.0f;
1309   good_metadata.offsetHdr = 0.0f;
1310   good_metadata.hdrCapacityMin = 1.0f;
1311   good_metadata.hdrCapacityMax = 2.0f;
1312 
1313   ultrahdr_metadata_struct metadata = good_metadata;
1314   metadata.version = "1.1";
1315   ASSERT_NE(uHdrLib.encodeJPEGR(jpgImg.getImageHandle(), jpgImg.getImageHandle(), &metadata,
1316                                 jpgImg.getImageHandle()),
1317             JPEGR_NO_ERROR)
1318       << "fail, API allows bad metadata version";
1319 
1320   metadata = good_metadata;
1321   metadata.minContentBoost = 3.0f;
1322   ASSERT_NE(uHdrLib.encodeJPEGR(jpgImg.getImageHandle(), jpgImg.getImageHandle(), &metadata,
1323                                 jpgImg.getImageHandle()),
1324             JPEGR_NO_ERROR)
1325       << "fail, API allows bad metadata content boost";
1326 
1327   metadata = good_metadata;
1328   metadata.gamma = -0.1f;
1329   ASSERT_NE(uHdrLib.encodeJPEGR(jpgImg.getImageHandle(), jpgImg.getImageHandle(), &metadata,
1330                                 jpgImg.getImageHandle()),
1331             JPEGR_NO_ERROR)
1332       << "fail, API allows bad metadata gamma";
1333 
1334   metadata = good_metadata;
1335   metadata.offsetSdr = -0.1f;
1336   ASSERT_NE(uHdrLib.encodeJPEGR(jpgImg.getImageHandle(), jpgImg.getImageHandle(), &metadata,
1337                                 jpgImg.getImageHandle()),
1338             JPEGR_NO_ERROR)
1339       << "fail, API allows bad metadata offset sdr";
1340 
1341   metadata = good_metadata;
1342   metadata.offsetHdr = -0.1f;
1343   ASSERT_NE(uHdrLib.encodeJPEGR(jpgImg.getImageHandle(), jpgImg.getImageHandle(), &metadata,
1344                                 jpgImg.getImageHandle()),
1345             JPEGR_NO_ERROR)
1346       << "fail, API allows bad metadata offset hdr";
1347 
1348   metadata = good_metadata;
1349   metadata.hdrCapacityMax = 0.5f;
1350   ASSERT_NE(uHdrLib.encodeJPEGR(jpgImg.getImageHandle(), jpgImg.getImageHandle(), &metadata,
1351                                 jpgImg.getImageHandle()),
1352             JPEGR_NO_ERROR)
1353       << "fail, API allows bad metadata hdr capacity max";
1354 
1355   metadata = good_metadata;
1356   metadata.hdrCapacityMin = 0.5f;
1357   ASSERT_NE(uHdrLib.encodeJPEGR(jpgImg.getImageHandle(), jpgImg.getImageHandle(), &metadata,
1358                                 jpgImg.getImageHandle()),
1359             JPEGR_NO_ERROR)
1360       << "fail, API allows bad metadata hdr capacity min";
1361 }
1362 
1363 /* Test Decode API invalid arguments */
TEST(JpegRTest,DecodeAPIWithInvalidArgs)1364 TEST(JpegRTest, DecodeAPIWithInvalidArgs) {
1365   JpegR uHdrLib;
1366 
1367   UhdrCompressedStructWrapper jpgImg(16, 16);
1368   jpegr_uncompressed_struct destImage{};
1369   size_t outSize = 16 * 16 * 8;
1370   std::unique_ptr<uint8_t[]> data = std::make_unique<uint8_t[]>(outSize);
1371   destImage.data = data.get();
1372 
1373   // test jpegr image
1374   ASSERT_NE(uHdrLib.decodeJPEGR(nullptr, &destImage), JPEGR_NO_ERROR)
1375       << "fail, API allows nullptr for jpegr img";
1376   ASSERT_NE(uHdrLib.decodeJPEGR(jpgImg.getImageHandle(), &destImage), JPEGR_NO_ERROR)
1377       << "fail, API allows nullptr for jpegr img";
1378   ASSERT_TRUE(jpgImg.allocateMemory());
1379 
1380   // test dest image
1381   ASSERT_NE(uHdrLib.decodeJPEGR(jpgImg.getImageHandle(), nullptr), JPEGR_NO_ERROR)
1382       << "fail, API allows nullptr for dest";
1383   destImage.data = nullptr;
1384   ASSERT_NE(uHdrLib.decodeJPEGR(jpgImg.getImageHandle(), &destImage), JPEGR_NO_ERROR)
1385       << "fail, API allows nullptr for dest";
1386   destImage.data = data.get();
1387 
1388   // test max display boost
1389   ASSERT_NE(uHdrLib.decodeJPEGR(jpgImg.getImageHandle(), &destImage, 0.5), JPEGR_NO_ERROR)
1390       << "fail, API allows invalid max display boost";
1391 
1392   // test output format
1393   ASSERT_NE(uHdrLib.decodeJPEGR(jpgImg.getImageHandle(), &destImage, FLT_MAX, nullptr,
1394                                 static_cast<ultrahdr_output_format>(-1)),
1395             JPEGR_NO_ERROR)
1396       << "fail, API allows invalid output format";
1397   ASSERT_NE(uHdrLib.decodeJPEGR(jpgImg.getImageHandle(), &destImage, FLT_MAX, nullptr,
1398                                 static_cast<ultrahdr_output_format>(ULTRAHDR_OUTPUT_MAX + 1)),
1399             JPEGR_NO_ERROR)
1400       << "fail, API allows invalid output format";
1401 }
1402 
TEST(JpegRTest,writeXmpThenRead)1403 TEST(JpegRTest, writeXmpThenRead) {
1404   uhdr_gainmap_metadata_ext_t metadata_expected;
1405   metadata_expected.version = "1.0";
1406   metadata_expected.max_content_boost = 1.25f;
1407   metadata_expected.min_content_boost = 0.75f;
1408   metadata_expected.gamma = 1.0f;
1409   metadata_expected.offset_sdr = 0.0f;
1410   metadata_expected.offset_hdr = 0.0f;
1411   metadata_expected.hdr_capacity_min = 1.0f;
1412   metadata_expected.hdr_capacity_max = metadata_expected.max_content_boost;
1413   const std::string nameSpace = "http://ns.adobe.com/xap/1.0/\0";
1414   const size_t nameSpaceLength = nameSpace.size() + 1;  // need to count the null terminator
1415 
1416   std::string xmp = generateXmpForSecondaryImage(metadata_expected);
1417 
1418   std::vector<uint8_t> xmpData;
1419   xmpData.reserve(nameSpaceLength + xmp.size());
1420   xmpData.insert(xmpData.end(), reinterpret_cast<const uint8_t*>(nameSpace.c_str()),
1421                  reinterpret_cast<const uint8_t*>(nameSpace.c_str()) + nameSpaceLength);
1422   xmpData.insert(xmpData.end(), reinterpret_cast<const uint8_t*>(xmp.c_str()),
1423                  reinterpret_cast<const uint8_t*>(xmp.c_str()) + xmp.size());
1424 
1425   uhdr_gainmap_metadata_ext_t metadata_read;
1426   EXPECT_EQ(getMetadataFromXMP(xmpData.data(), xmpData.size(), &metadata_read).error_code,
1427             UHDR_CODEC_OK);
1428   EXPECT_FLOAT_EQ(metadata_expected.max_content_boost, metadata_read.max_content_boost);
1429   EXPECT_FLOAT_EQ(metadata_expected.min_content_boost, metadata_read.min_content_boost);
1430   EXPECT_FLOAT_EQ(metadata_expected.gamma, metadata_read.gamma);
1431   EXPECT_FLOAT_EQ(metadata_expected.offset_sdr, metadata_read.offset_sdr);
1432   EXPECT_FLOAT_EQ(metadata_expected.offset_hdr, metadata_read.offset_hdr);
1433   EXPECT_FLOAT_EQ(metadata_expected.hdr_capacity_min, metadata_read.hdr_capacity_min);
1434   EXPECT_FLOAT_EQ(metadata_expected.hdr_capacity_max, metadata_read.hdr_capacity_max);
1435 }
1436 
1437 class JpegRAPIEncodeAndDecodeTest
1438     : public ::testing::TestWithParam<std::tuple<ultrahdr_color_gamut, ultrahdr_color_gamut>> {
1439  public:
JpegRAPIEncodeAndDecodeTest()1440   JpegRAPIEncodeAndDecodeTest()
1441       : mP010ColorGamut(std::get<0>(GetParam())), mYuv420ColorGamut(std::get<1>(GetParam())){};
1442 
1443   const ultrahdr_color_gamut mP010ColorGamut;
1444   const ultrahdr_color_gamut mYuv420ColorGamut;
1445 };
1446 
1447 /* Test Encode API-0 and Decode */
TEST_P(JpegRAPIEncodeAndDecodeTest,EncodeAPI0AndDecodeTest)1448 TEST_P(JpegRAPIEncodeAndDecodeTest, EncodeAPI0AndDecodeTest) {
1449   // reference encode
1450   UhdrUnCompressedStructWrapper rawImg(kImageWidth, kImageHeight, YCbCr_p010);
1451   ASSERT_TRUE(rawImg.setImageColorGamut(mP010ColorGamut));
1452   ASSERT_TRUE(rawImg.allocateMemory());
1453   ASSERT_TRUE(rawImg.loadRawResource(kYCbCrP010FileName));
1454   UhdrCompressedStructWrapper jpgImg(kImageWidth, kImageHeight);
1455   ASSERT_TRUE(jpgImg.allocateMemory());
1456   JpegR uHdrLib;
1457   ASSERT_EQ(
1458       uHdrLib.encodeJPEGR(rawImg.getImageHandle(), ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
1459                           jpgImg.getImageHandle(), kQuality, nullptr),
1460       JPEGR_NO_ERROR);
1461 
1462   uhdr_codec_private_t* obj = uhdr_create_encoder();
1463   uhdr_raw_image_t uhdrRawImg{};
1464   uhdrRawImg.fmt = UHDR_IMG_FMT_24bppYCbCrP010;
1465   uhdrRawImg.cg = map_internal_cg_to_cg(mP010ColorGamut);
1466   uhdrRawImg.ct = map_internal_ct_to_ct(ultrahdr_transfer_function::ULTRAHDR_TF_HLG);
1467   uhdrRawImg.range = UHDR_CR_LIMITED_RANGE;
1468   uhdrRawImg.w = kImageWidth;
1469   uhdrRawImg.h = kImageHeight;
1470   uhdrRawImg.planes[UHDR_PLANE_Y] = rawImg.getImageHandle()->data;
1471   uhdrRawImg.stride[UHDR_PLANE_Y] = kImageWidth;
1472   uhdrRawImg.planes[UHDR_PLANE_UV] =
1473       ((uint8_t*)(rawImg.getImageHandle()->data)) + kImageWidth * kImageHeight * 2;
1474   uhdrRawImg.stride[UHDR_PLANE_UV] = kImageWidth;
1475   uhdr_error_info_t status = uhdr_enc_set_raw_image(obj, &uhdrRawImg, UHDR_HDR_IMG);
1476   ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
1477   status = uhdr_enc_set_quality(obj, kQuality, UHDR_BASE_IMG);
1478   ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
1479   status = uhdr_enc_set_using_multi_channel_gainmap(obj, false);
1480   ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
1481   status = uhdr_enc_set_gainmap_scale_factor(obj, 4);
1482   ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
1483   status = uhdr_enc_set_quality(obj, 85, UHDR_GAIN_MAP_IMG);
1484   ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
1485   status = uhdr_enc_set_preset(obj, UHDR_USAGE_REALTIME);
1486   ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
1487   status = uhdr_encode(obj);
1488   ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
1489   uhdr_compressed_image_t* compressedImage = uhdr_get_encoded_stream(obj);
1490   ASSERT_NE(nullptr, compressedImage);
1491   ASSERT_EQ(jpgImg.getImageHandle()->length, compressedImage->data_sz);
1492   ASSERT_EQ(0,
1493             memcmp(jpgImg.getImageHandle()->data, compressedImage->data, compressedImage->data_sz));
1494   uhdr_release_encoder(obj);
1495 
1496   // encode with luma stride set
1497   {
1498     UhdrUnCompressedStructWrapper rawImg2(kImageWidth, kImageHeight, YCbCr_p010);
1499     ASSERT_TRUE(rawImg2.setImageColorGamut(mP010ColorGamut));
1500     ASSERT_TRUE(rawImg2.setImageStride(kImageWidth + 18, 0));
1501     ASSERT_TRUE(rawImg2.allocateMemory());
1502     ASSERT_TRUE(rawImg2.loadRawResource(kYCbCrP010FileName));
1503     UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight);
1504     ASSERT_TRUE(jpgImg2.allocateMemory());
1505     ASSERT_EQ(
1506         uHdrLib.encodeJPEGR(rawImg2.getImageHandle(), ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
1507                             jpgImg2.getImageHandle(), kQuality, nullptr),
1508         JPEGR_NO_ERROR);
1509     auto jpg1 = jpgImg.getImageHandle();
1510     auto jpg2 = jpgImg2.getImageHandle();
1511     ASSERT_EQ(jpg1->length, jpg2->length);
1512     ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length));
1513   }
1514   // encode with luma and chroma stride set
1515   {
1516     UhdrUnCompressedStructWrapper rawImg2(kImageWidth, kImageHeight, YCbCr_p010);
1517     ASSERT_TRUE(rawImg2.setImageColorGamut(mP010ColorGamut));
1518     ASSERT_TRUE(rawImg2.setImageStride(kImageWidth + 18, kImageWidth + 28));
1519     ASSERT_TRUE(rawImg2.setChromaMode(false));
1520     ASSERT_TRUE(rawImg2.allocateMemory());
1521     ASSERT_TRUE(rawImg2.loadRawResource(kYCbCrP010FileName));
1522     UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight);
1523     ASSERT_TRUE(jpgImg2.allocateMemory());
1524     ASSERT_EQ(
1525         uHdrLib.encodeJPEGR(rawImg2.getImageHandle(), ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
1526                             jpgImg2.getImageHandle(), kQuality, nullptr),
1527         JPEGR_NO_ERROR);
1528     auto jpg1 = jpgImg.getImageHandle();
1529     auto jpg2 = jpgImg2.getImageHandle();
1530     ASSERT_EQ(jpg1->length, jpg2->length);
1531     ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length));
1532 
1533     uhdr_codec_private_t* obj = uhdr_create_encoder();
1534     uhdr_raw_image_t uhdrRawImg{};
1535     uhdrRawImg.fmt = UHDR_IMG_FMT_24bppYCbCrP010;
1536     uhdrRawImg.cg = map_internal_cg_to_cg(mP010ColorGamut);
1537     uhdrRawImg.ct = map_internal_ct_to_ct(ultrahdr_transfer_function::ULTRAHDR_TF_HLG);
1538     uhdrRawImg.range = UHDR_CR_LIMITED_RANGE;
1539     uhdrRawImg.w = kImageWidth;
1540     uhdrRawImg.h = kImageHeight;
1541     uhdrRawImg.planes[UHDR_PLANE_Y] = rawImg2.getImageHandle()->data;
1542     uhdrRawImg.stride[UHDR_PLANE_Y] = rawImg2.getImageHandle()->luma_stride;
1543     uhdrRawImg.planes[UHDR_PLANE_UV] = rawImg2.getImageHandle()->chroma_data;
1544     uhdrRawImg.stride[UHDR_PLANE_UV] = rawImg2.getImageHandle()->chroma_stride;
1545     uhdr_error_info_t status = uhdr_enc_set_raw_image(obj, &uhdrRawImg, UHDR_HDR_IMG);
1546     ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
1547     status = uhdr_enc_set_quality(obj, kQuality, UHDR_BASE_IMG);
1548     ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
1549     status = uhdr_enc_set_using_multi_channel_gainmap(obj, false);
1550     ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
1551     status = uhdr_enc_set_gainmap_scale_factor(obj, 4);
1552     ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
1553     status = uhdr_enc_set_quality(obj, 85, UHDR_GAIN_MAP_IMG);
1554     ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
1555     status = uhdr_enc_set_preset(obj, UHDR_USAGE_REALTIME);
1556     ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
1557     status = uhdr_encode(obj);
1558     ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
1559     uhdr_compressed_image_t* compressedImage = uhdr_get_encoded_stream(obj);
1560     ASSERT_NE(nullptr, compressedImage);
1561     ASSERT_EQ(jpg1->length, compressedImage->data_sz);
1562     ASSERT_EQ(0, memcmp(jpg1->data, compressedImage->data, jpg1->length));
1563     uhdr_release_encoder(obj);
1564   }
1565   // encode with chroma stride set
1566   {
1567     UhdrUnCompressedStructWrapper rawImg2(kImageWidth, kImageHeight, YCbCr_p010);
1568     ASSERT_TRUE(rawImg2.setImageColorGamut(mP010ColorGamut));
1569     ASSERT_TRUE(rawImg2.setImageStride(0, kImageWidth + 34));
1570     ASSERT_TRUE(rawImg2.setChromaMode(false));
1571     ASSERT_TRUE(rawImg2.allocateMemory());
1572     ASSERT_TRUE(rawImg2.loadRawResource(kYCbCrP010FileName));
1573     UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight);
1574     ASSERT_TRUE(jpgImg2.allocateMemory());
1575     ASSERT_EQ(
1576         uHdrLib.encodeJPEGR(rawImg2.getImageHandle(), ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
1577                             jpgImg2.getImageHandle(), kQuality, nullptr),
1578         JPEGR_NO_ERROR);
1579     auto jpg1 = jpgImg.getImageHandle();
1580     auto jpg2 = jpgImg2.getImageHandle();
1581     ASSERT_EQ(jpg1->length, jpg2->length);
1582     ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length));
1583   }
1584   // encode with luma and chroma stride set but no chroma ptr
1585   {
1586     UhdrUnCompressedStructWrapper rawImg2(kImageWidth, kImageHeight, YCbCr_p010);
1587     ASSERT_TRUE(rawImg2.setImageColorGamut(mP010ColorGamut));
1588     ASSERT_TRUE(rawImg2.setImageStride(kImageWidth, kImageWidth + 38));
1589     ASSERT_TRUE(rawImg2.allocateMemory());
1590     ASSERT_TRUE(rawImg2.loadRawResource(kYCbCrP010FileName));
1591     UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight);
1592     ASSERT_TRUE(jpgImg2.allocateMemory());
1593     ASSERT_EQ(
1594         uHdrLib.encodeJPEGR(rawImg2.getImageHandle(), ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
1595                             jpgImg2.getImageHandle(), kQuality, nullptr),
1596         JPEGR_NO_ERROR);
1597     auto jpg1 = jpgImg.getImageHandle();
1598     auto jpg2 = jpgImg2.getImageHandle();
1599     ASSERT_EQ(jpg1->length, jpg2->length);
1600     ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length));
1601   }
1602 
1603   auto jpg1 = jpgImg.getImageHandle();
1604 #ifdef DUMP_OUTPUT
1605   if (!writeFile("encode_api0_output.jpeg", jpg1->data, jpg1->length)) {
1606     std::cerr << "unable to write output file" << std::endl;
1607   }
1608 #endif
1609 
1610   ASSERT_NO_FATAL_FAILURE(decodeJpegRImg(jpg1, "decode_api0_output.rgb"));
1611 }
1612 
1613 /* Test Encode API-1 and Decode */
TEST_P(JpegRAPIEncodeAndDecodeTest,EncodeAPI1AndDecodeTest)1614 TEST_P(JpegRAPIEncodeAndDecodeTest, EncodeAPI1AndDecodeTest) {
1615   UhdrUnCompressedStructWrapper rawImgP010(kImageWidth, kImageHeight, YCbCr_p010);
1616   ASSERT_TRUE(rawImgP010.setImageColorGamut(mP010ColorGamut));
1617   ASSERT_TRUE(rawImgP010.allocateMemory());
1618   ASSERT_TRUE(rawImgP010.loadRawResource(kYCbCrP010FileName));
1619   UhdrUnCompressedStructWrapper rawImg420(kImageWidth, kImageHeight, YCbCr_420);
1620   ASSERT_TRUE(rawImg420.setImageColorGamut(mYuv420ColorGamut));
1621   ASSERT_TRUE(rawImg420.allocateMemory());
1622   ASSERT_TRUE(rawImg420.loadRawResource(kYCbCr420FileName));
1623   UhdrCompressedStructWrapper jpgImg(kImageWidth, kImageHeight);
1624   ASSERT_TRUE(jpgImg.allocateMemory());
1625   JpegR uHdrLib;
1626   ASSERT_EQ(uHdrLib.encodeJPEGR(rawImgP010.getImageHandle(), rawImg420.getImageHandle(),
1627                                 ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
1628                                 jpgImg.getImageHandle(), kQuality, nullptr),
1629             JPEGR_NO_ERROR);
1630   // encode with luma stride set p010
1631   {
1632     UhdrUnCompressedStructWrapper rawImg2P010(kImageWidth, kImageHeight, YCbCr_p010);
1633     ASSERT_TRUE(rawImg2P010.setImageColorGamut(mP010ColorGamut));
1634     ASSERT_TRUE(rawImg2P010.setImageStride(kImageWidth + 128, 0));
1635     ASSERT_TRUE(rawImg2P010.allocateMemory());
1636     ASSERT_TRUE(rawImg2P010.loadRawResource(kYCbCrP010FileName));
1637     UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight);
1638     ASSERT_TRUE(jpgImg2.allocateMemory());
1639     ASSERT_EQ(uHdrLib.encodeJPEGR(rawImg2P010.getImageHandle(), rawImg420.getImageHandle(),
1640                                   ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
1641                                   jpgImg2.getImageHandle(), kQuality, nullptr),
1642               JPEGR_NO_ERROR);
1643     auto jpg1 = jpgImg.getImageHandle();
1644     auto jpg2 = jpgImg2.getImageHandle();
1645     ASSERT_EQ(jpg1->length, jpg2->length);
1646     ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length));
1647   }
1648   // encode with luma and chroma stride set p010
1649   {
1650     UhdrUnCompressedStructWrapper rawImg2P010(kImageWidth, kImageHeight, YCbCr_p010);
1651     ASSERT_TRUE(rawImg2P010.setImageColorGamut(mP010ColorGamut));
1652     ASSERT_TRUE(rawImg2P010.setImageStride(kImageWidth + 128, kImageWidth + 256));
1653     ASSERT_TRUE(rawImg2P010.setChromaMode(false));
1654     ASSERT_TRUE(rawImg2P010.allocateMemory());
1655     ASSERT_TRUE(rawImg2P010.loadRawResource(kYCbCrP010FileName));
1656     UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight);
1657     ASSERT_TRUE(jpgImg2.allocateMemory());
1658     ASSERT_EQ(uHdrLib.encodeJPEGR(rawImg2P010.getImageHandle(), rawImg420.getImageHandle(),
1659                                   ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
1660                                   jpgImg2.getImageHandle(), kQuality, nullptr),
1661               JPEGR_NO_ERROR);
1662     auto jpg1 = jpgImg.getImageHandle();
1663     auto jpg2 = jpgImg2.getImageHandle();
1664     ASSERT_EQ(jpg1->length, jpg2->length);
1665     ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length));
1666   }
1667   // encode with chroma stride set p010
1668   {
1669     UhdrUnCompressedStructWrapper rawImg2P010(kImageWidth, kImageHeight, YCbCr_p010);
1670     ASSERT_TRUE(rawImg2P010.setImageColorGamut(mP010ColorGamut));
1671     ASSERT_TRUE(rawImg2P010.setImageStride(0, kImageWidth + 64));
1672     ASSERT_TRUE(rawImg2P010.setChromaMode(false));
1673     ASSERT_TRUE(rawImg2P010.allocateMemory());
1674     ASSERT_TRUE(rawImg2P010.loadRawResource(kYCbCrP010FileName));
1675     UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight);
1676     ASSERT_TRUE(jpgImg2.allocateMemory());
1677     ASSERT_EQ(uHdrLib.encodeJPEGR(rawImg2P010.getImageHandle(), rawImg420.getImageHandle(),
1678                                   ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
1679                                   jpgImg2.getImageHandle(), kQuality, nullptr),
1680               JPEGR_NO_ERROR);
1681     auto jpg1 = jpgImg.getImageHandle();
1682     auto jpg2 = jpgImg2.getImageHandle();
1683     ASSERT_EQ(jpg1->length, jpg2->length);
1684     ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length));
1685   }
1686   // encode with luma and chroma stride set but no chroma ptr p010
1687   {
1688     UhdrUnCompressedStructWrapper rawImg2P010(kImageWidth, kImageHeight, YCbCr_p010);
1689     ASSERT_TRUE(rawImg2P010.setImageColorGamut(mP010ColorGamut));
1690     ASSERT_TRUE(rawImg2P010.setImageStride(kImageWidth + 64, kImageWidth + 256));
1691     ASSERT_TRUE(rawImg2P010.allocateMemory());
1692     ASSERT_TRUE(rawImg2P010.loadRawResource(kYCbCrP010FileName));
1693     UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight);
1694     ASSERT_TRUE(jpgImg2.allocateMemory());
1695     ASSERT_EQ(uHdrLib.encodeJPEGR(rawImg2P010.getImageHandle(), rawImg420.getImageHandle(),
1696                                   ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
1697                                   jpgImg2.getImageHandle(), kQuality, nullptr),
1698               JPEGR_NO_ERROR);
1699     auto jpg1 = jpgImg.getImageHandle();
1700     auto jpg2 = jpgImg2.getImageHandle();
1701     ASSERT_EQ(jpg1->length, jpg2->length);
1702     ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length));
1703   }
1704   // encode with luma stride set 420
1705   {
1706     UhdrUnCompressedStructWrapper rawImg2420(kImageWidth, kImageHeight, YCbCr_420);
1707     ASSERT_TRUE(rawImg2420.setImageColorGamut(mYuv420ColorGamut));
1708     ASSERT_TRUE(rawImg2420.setImageStride(kImageWidth + 14, 0));
1709     ASSERT_TRUE(rawImg2420.allocateMemory());
1710     ASSERT_TRUE(rawImg2420.loadRawResource(kYCbCr420FileName));
1711     UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight);
1712     ASSERT_TRUE(jpgImg2.allocateMemory());
1713     ASSERT_EQ(uHdrLib.encodeJPEGR(rawImgP010.getImageHandle(), rawImg2420.getImageHandle(),
1714                                   ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
1715                                   jpgImg2.getImageHandle(), kQuality, nullptr),
1716               JPEGR_NO_ERROR);
1717     auto jpg1 = jpgImg.getImageHandle();
1718     auto jpg2 = jpgImg2.getImageHandle();
1719     ASSERT_EQ(jpg1->length, jpg2->length);
1720     ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length));
1721   }
1722   // encode with luma and chroma stride set 420
1723   {
1724     UhdrUnCompressedStructWrapper rawImg2420(kImageWidth, kImageHeight, YCbCr_420);
1725     ASSERT_TRUE(rawImg2420.setImageColorGamut(mYuv420ColorGamut));
1726     ASSERT_TRUE(rawImg2420.setImageStride(kImageWidth + 46, kImageWidth / 2 + 34));
1727     ASSERT_TRUE(rawImg2420.setChromaMode(false));
1728     ASSERT_TRUE(rawImg2420.allocateMemory());
1729     ASSERT_TRUE(rawImg2420.loadRawResource(kYCbCr420FileName));
1730     UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight);
1731     ASSERT_TRUE(jpgImg2.allocateMemory());
1732     ASSERT_EQ(uHdrLib.encodeJPEGR(rawImgP010.getImageHandle(), rawImg2420.getImageHandle(),
1733                                   ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
1734                                   jpgImg2.getImageHandle(), kQuality, nullptr),
1735               JPEGR_NO_ERROR);
1736     auto jpg1 = jpgImg.getImageHandle();
1737     auto jpg2 = jpgImg2.getImageHandle();
1738     ASSERT_EQ(jpg1->length, jpg2->length);
1739     ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length));
1740 
1741     uhdr_codec_private_t* obj = uhdr_create_encoder();
1742     uhdr_raw_image_t uhdrRawImg{};
1743     uhdrRawImg.fmt = UHDR_IMG_FMT_24bppYCbCrP010;
1744     uhdrRawImg.cg = map_internal_cg_to_cg(mP010ColorGamut);
1745     uhdrRawImg.ct = map_internal_ct_to_ct(ultrahdr_transfer_function::ULTRAHDR_TF_HLG);
1746     uhdrRawImg.range = UHDR_CR_LIMITED_RANGE;
1747     uhdrRawImg.w = kImageWidth;
1748     uhdrRawImg.h = kImageHeight;
1749     uhdrRawImg.planes[UHDR_PLANE_Y] = rawImgP010.getImageHandle()->data;
1750     uhdrRawImg.stride[UHDR_PLANE_Y] = kImageWidth;
1751     uhdrRawImg.planes[UHDR_PLANE_UV] =
1752         ((uint8_t*)(rawImgP010.getImageHandle()->data)) + kImageWidth * kImageHeight * 2;
1753     uhdrRawImg.stride[UHDR_PLANE_UV] = kImageWidth;
1754     uhdr_error_info_t status = uhdr_enc_set_raw_image(obj, &uhdrRawImg, UHDR_HDR_IMG);
1755     ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
1756 
1757     uhdrRawImg.fmt = UHDR_IMG_FMT_12bppYCbCr420;
1758     uhdrRawImg.cg = map_internal_cg_to_cg(mYuv420ColorGamut);
1759     uhdrRawImg.ct = map_internal_ct_to_ct(ultrahdr_transfer_function::ULTRAHDR_TF_SRGB);
1760     uhdrRawImg.range = UHDR_CR_FULL_RANGE;
1761     uhdrRawImg.w = kImageWidth;
1762     uhdrRawImg.h = kImageHeight;
1763     uhdrRawImg.planes[UHDR_PLANE_Y] = rawImg2420.getImageHandle()->data;
1764     uhdrRawImg.stride[UHDR_PLANE_Y] = rawImg2420.getImageHandle()->luma_stride;
1765     uhdrRawImg.planes[UHDR_PLANE_U] = rawImg2420.getImageHandle()->chroma_data;
1766     uhdrRawImg.stride[UHDR_PLANE_U] = rawImg2420.getImageHandle()->chroma_stride;
1767     uhdrRawImg.planes[UHDR_PLANE_V] = ((uint8_t*)(rawImg2420.getImageHandle()->chroma_data)) +
1768                                       rawImg2420.getImageHandle()->chroma_stride * kImageHeight / 2;
1769     uhdrRawImg.stride[UHDR_PLANE_V] = rawImg2420.getImageHandle()->chroma_stride;
1770     status = uhdr_enc_set_raw_image(obj, &uhdrRawImg, UHDR_SDR_IMG);
1771     ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
1772 
1773     status = uhdr_enc_set_quality(obj, kQuality, UHDR_BASE_IMG);
1774     ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
1775     status = uhdr_enc_set_using_multi_channel_gainmap(obj, false);
1776     ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
1777     status = uhdr_enc_set_gainmap_scale_factor(obj, 4);
1778     ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
1779     status = uhdr_enc_set_quality(obj, 85, UHDR_GAIN_MAP_IMG);
1780     ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
1781     status = uhdr_enc_set_preset(obj, UHDR_USAGE_REALTIME);
1782     ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
1783     status = uhdr_encode(obj);
1784     ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
1785     uhdr_compressed_image_t* compressedImage = uhdr_get_encoded_stream(obj);
1786     ASSERT_NE(nullptr, compressedImage);
1787     ASSERT_EQ(jpgImg.getImageHandle()->length, compressedImage->data_sz);
1788     ASSERT_EQ(
1789         0, memcmp(jpgImg.getImageHandle()->data, compressedImage->data, compressedImage->data_sz));
1790     uhdr_release_encoder(obj);
1791   }
1792   // encode with chroma stride set 420
1793   {
1794     UhdrUnCompressedStructWrapper rawImg2420(kImageWidth, kImageHeight, YCbCr_420);
1795     ASSERT_TRUE(rawImg2420.setImageColorGamut(mYuv420ColorGamut));
1796     ASSERT_TRUE(rawImg2420.setImageStride(0, kImageWidth / 2 + 38));
1797     ASSERT_TRUE(rawImg2420.setChromaMode(false));
1798     ASSERT_TRUE(rawImg2420.allocateMemory());
1799     ASSERT_TRUE(rawImg2420.loadRawResource(kYCbCr420FileName));
1800     UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight);
1801     ASSERT_TRUE(jpgImg2.allocateMemory());
1802     ASSERT_EQ(uHdrLib.encodeJPEGR(rawImgP010.getImageHandle(), rawImg2420.getImageHandle(),
1803                                   ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
1804                                   jpgImg2.getImageHandle(), kQuality, nullptr),
1805               JPEGR_NO_ERROR);
1806     auto jpg1 = jpgImg.getImageHandle();
1807     auto jpg2 = jpgImg2.getImageHandle();
1808     ASSERT_EQ(jpg1->length, jpg2->length);
1809     ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length));
1810   }
1811   // encode with luma and chroma stride set but no chroma ptr 420
1812   {
1813     UhdrUnCompressedStructWrapper rawImg2420(kImageWidth, kImageHeight, YCbCr_420);
1814     ASSERT_TRUE(rawImg2420.setImageColorGamut(mYuv420ColorGamut));
1815     ASSERT_TRUE(rawImg2420.setImageStride(kImageWidth + 26, kImageWidth / 2 + 44));
1816     ASSERT_TRUE(rawImg2420.allocateMemory());
1817     ASSERT_TRUE(rawImg2420.loadRawResource(kYCbCr420FileName));
1818     UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight);
1819     ASSERT_TRUE(jpgImg2.allocateMemory());
1820     ASSERT_EQ(uHdrLib.encodeJPEGR(rawImgP010.getImageHandle(), rawImg2420.getImageHandle(),
1821                                   ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
1822                                   jpgImg2.getImageHandle(), kQuality, nullptr),
1823               JPEGR_NO_ERROR);
1824     auto jpg1 = jpgImg.getImageHandle();
1825     auto jpg2 = jpgImg2.getImageHandle();
1826     ASSERT_EQ(jpg1->length, jpg2->length);
1827     ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length));
1828   }
1829 
1830   auto jpg1 = jpgImg.getImageHandle();
1831 
1832 #ifdef DUMP_OUTPUT
1833   if (!writeFile("encode_api1_output.jpeg", jpg1->data, jpg1->length)) {
1834     std::cerr << "unable to write output file" << std::endl;
1835   }
1836 #endif
1837 
1838   ASSERT_NO_FATAL_FAILURE(decodeJpegRImg(jpg1, "decode_api1_output.rgb"));
1839 }
1840 
1841 /* Test Encode API-2 and Decode */
TEST_P(JpegRAPIEncodeAndDecodeTest,EncodeAPI2AndDecodeTest)1842 TEST_P(JpegRAPIEncodeAndDecodeTest, EncodeAPI2AndDecodeTest) {
1843   UhdrUnCompressedStructWrapper rawImgP010(kImageWidth, kImageHeight, YCbCr_p010);
1844   ASSERT_TRUE(rawImgP010.setImageColorGamut(mP010ColorGamut));
1845   ASSERT_TRUE(rawImgP010.allocateMemory());
1846   ASSERT_TRUE(rawImgP010.loadRawResource(kYCbCrP010FileName));
1847   UhdrUnCompressedStructWrapper rawImg420(kImageWidth, kImageHeight, YCbCr_420);
1848   ASSERT_TRUE(rawImg420.setImageColorGamut(mYuv420ColorGamut));
1849   ASSERT_TRUE(rawImg420.allocateMemory());
1850   ASSERT_TRUE(rawImg420.loadRawResource(kYCbCr420FileName));
1851   UhdrCompressedStructWrapper jpgImg(kImageWidth, kImageHeight);
1852   ASSERT_TRUE(jpgImg.allocateMemory());
1853   UhdrCompressedStructWrapper jpgSdr(kImageWidth, kImageHeight);
1854   ASSERT_TRUE(jpgSdr.allocateMemory());
1855   auto sdr = jpgSdr.getImageHandle();
1856   ASSERT_TRUE(readFile(kSdrJpgFileName, sdr->data, sdr->maxLength, sdr->length));
1857   JpegR uHdrLib;
1858   ASSERT_EQ(
1859       uHdrLib.encodeJPEGR(rawImgP010.getImageHandle(), rawImg420.getImageHandle(), sdr,
1860                           ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
1861       JPEGR_NO_ERROR);
1862   // encode with luma stride set
1863   {
1864     UhdrUnCompressedStructWrapper rawImg2P010(kImageWidth, kImageHeight, YCbCr_p010);
1865     ASSERT_TRUE(rawImg2P010.setImageColorGamut(mP010ColorGamut));
1866     ASSERT_TRUE(rawImg2P010.setImageStride(kImageWidth + 128, 0));
1867     ASSERT_TRUE(rawImg2P010.allocateMemory());
1868     ASSERT_TRUE(rawImg2P010.loadRawResource(kYCbCrP010FileName));
1869     UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight);
1870     ASSERT_TRUE(jpgImg2.allocateMemory());
1871     ASSERT_EQ(
1872         uHdrLib.encodeJPEGR(rawImg2P010.getImageHandle(), rawImg420.getImageHandle(), sdr,
1873                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg2.getImageHandle()),
1874         JPEGR_NO_ERROR);
1875     auto jpg1 = jpgImg.getImageHandle();
1876     auto jpg2 = jpgImg2.getImageHandle();
1877     ASSERT_EQ(jpg1->length, jpg2->length);
1878     ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length));
1879   }
1880   // encode with luma and chroma stride set
1881   {
1882     UhdrUnCompressedStructWrapper rawImg2P010(kImageWidth, kImageHeight, YCbCr_p010);
1883     ASSERT_TRUE(rawImg2P010.setImageColorGamut(mP010ColorGamut));
1884     ASSERT_TRUE(rawImg2P010.setImageStride(kImageWidth + 128, kImageWidth + 256));
1885     ASSERT_TRUE(rawImg2P010.setChromaMode(false));
1886     ASSERT_TRUE(rawImg2P010.allocateMemory());
1887     ASSERT_TRUE(rawImg2P010.loadRawResource(kYCbCrP010FileName));
1888     UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight);
1889     ASSERT_TRUE(jpgImg2.allocateMemory());
1890     ASSERT_EQ(
1891         uHdrLib.encodeJPEGR(rawImg2P010.getImageHandle(), rawImg420.getImageHandle(), sdr,
1892                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg2.getImageHandle()),
1893         JPEGR_NO_ERROR);
1894     auto jpg1 = jpgImg.getImageHandle();
1895     auto jpg2 = jpgImg2.getImageHandle();
1896     ASSERT_EQ(jpg1->length, jpg2->length);
1897     ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length));
1898   }
1899   // encode with chroma stride set
1900   {
1901     UhdrUnCompressedStructWrapper rawImg2P010(kImageWidth, kImageHeight, YCbCr_p010);
1902     ASSERT_TRUE(rawImg2P010.setImageColorGamut(mP010ColorGamut));
1903     ASSERT_TRUE(rawImg2P010.setImageStride(0, kImageWidth + 64));
1904     ASSERT_TRUE(rawImg2P010.setChromaMode(false));
1905     ASSERT_TRUE(rawImg2P010.allocateMemory());
1906     ASSERT_TRUE(rawImg2P010.loadRawResource(kYCbCrP010FileName));
1907     UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight);
1908     ASSERT_TRUE(jpgImg2.allocateMemory());
1909     ASSERT_EQ(
1910         uHdrLib.encodeJPEGR(rawImg2P010.getImageHandle(), rawImg420.getImageHandle(), sdr,
1911                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg2.getImageHandle()),
1912         JPEGR_NO_ERROR);
1913     auto jpg1 = jpgImg.getImageHandle();
1914     auto jpg2 = jpgImg2.getImageHandle();
1915     ASSERT_EQ(jpg1->length, jpg2->length);
1916     ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length));
1917   }
1918   // encode with luma stride set
1919   {
1920     UhdrUnCompressedStructWrapper rawImg2420(kImageWidth, kImageHeight, YCbCr_420);
1921     ASSERT_TRUE(rawImg2420.setImageColorGamut(mYuv420ColorGamut));
1922     ASSERT_TRUE(rawImg2420.setImageStride(kImageWidth + 128, 0));
1923     ASSERT_TRUE(rawImg2420.allocateMemory());
1924     ASSERT_TRUE(rawImg2420.loadRawResource(kYCbCr420FileName));
1925     UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight);
1926     ASSERT_TRUE(jpgImg2.allocateMemory());
1927     ASSERT_EQ(
1928         uHdrLib.encodeJPEGR(rawImgP010.getImageHandle(), rawImg2420.getImageHandle(), sdr,
1929                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg2.getImageHandle()),
1930         JPEGR_NO_ERROR);
1931     auto jpg1 = jpgImg.getImageHandle();
1932     auto jpg2 = jpgImg2.getImageHandle();
1933     ASSERT_EQ(jpg1->length, jpg2->length);
1934     ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length));
1935   }
1936   // encode with luma and chroma stride set
1937   {
1938     UhdrUnCompressedStructWrapper rawImg2420(kImageWidth, kImageHeight, YCbCr_420);
1939     ASSERT_TRUE(rawImg2420.setImageColorGamut(mYuv420ColorGamut));
1940     ASSERT_TRUE(rawImg2420.setImageStride(kImageWidth + 128, kImageWidth + 256));
1941     ASSERT_TRUE(rawImg2420.setChromaMode(false));
1942     ASSERT_TRUE(rawImg2420.allocateMemory());
1943     ASSERT_TRUE(rawImg2420.loadRawResource(kYCbCr420FileName));
1944     UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight);
1945     ASSERT_TRUE(jpgImg2.allocateMemory());
1946     ASSERT_EQ(
1947         uHdrLib.encodeJPEGR(rawImgP010.getImageHandle(), rawImg2420.getImageHandle(), sdr,
1948                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg2.getImageHandle()),
1949         JPEGR_NO_ERROR);
1950     auto jpg1 = jpgImg.getImageHandle();
1951     auto jpg2 = jpgImg2.getImageHandle();
1952     ASSERT_EQ(jpg1->length, jpg2->length);
1953     ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length));
1954 
1955     uhdr_codec_private_t* obj = uhdr_create_encoder();
1956     uhdr_raw_image_t uhdrRawImg{};
1957     uhdrRawImg.fmt = UHDR_IMG_FMT_24bppYCbCrP010;
1958     uhdrRawImg.cg = map_internal_cg_to_cg(mP010ColorGamut);
1959     uhdrRawImg.ct = map_internal_ct_to_ct(ultrahdr_transfer_function::ULTRAHDR_TF_HLG);
1960     uhdrRawImg.range = UHDR_CR_LIMITED_RANGE;
1961     uhdrRawImg.w = kImageWidth;
1962     uhdrRawImg.h = kImageHeight;
1963     uhdrRawImg.planes[UHDR_PLANE_Y] = rawImgP010.getImageHandle()->data;
1964     uhdrRawImg.stride[UHDR_PLANE_Y] = kImageWidth;
1965     uhdrRawImg.planes[UHDR_PLANE_UV] =
1966         ((uint8_t*)(rawImgP010.getImageHandle()->data)) + kImageWidth * kImageHeight * 2;
1967     uhdrRawImg.stride[UHDR_PLANE_UV] = kImageWidth;
1968     uhdr_error_info_t status = uhdr_enc_set_raw_image(obj, &uhdrRawImg, UHDR_HDR_IMG);
1969     ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
1970 
1971     uhdrRawImg.fmt = UHDR_IMG_FMT_12bppYCbCr420;
1972     uhdrRawImg.cg = map_internal_cg_to_cg(mYuv420ColorGamut);
1973     uhdrRawImg.ct = map_internal_ct_to_ct(ultrahdr_transfer_function::ULTRAHDR_TF_SRGB);
1974     uhdrRawImg.range = UHDR_CR_FULL_RANGE;
1975     uhdrRawImg.w = kImageWidth;
1976     uhdrRawImg.h = kImageHeight;
1977     uhdrRawImg.planes[UHDR_PLANE_Y] = rawImg2420.getImageHandle()->data;
1978     uhdrRawImg.stride[UHDR_PLANE_Y] = rawImg2420.getImageHandle()->luma_stride;
1979     uhdrRawImg.planes[UHDR_PLANE_U] = rawImg2420.getImageHandle()->chroma_data;
1980     uhdrRawImg.stride[UHDR_PLANE_U] = rawImg2420.getImageHandle()->chroma_stride;
1981     uhdrRawImg.planes[UHDR_PLANE_V] = ((uint8_t*)(rawImg2420.getImageHandle()->chroma_data)) +
1982                                       rawImg2420.getImageHandle()->chroma_stride * kImageHeight / 2;
1983     uhdrRawImg.stride[UHDR_PLANE_V] = rawImg2420.getImageHandle()->chroma_stride;
1984     status = uhdr_enc_set_raw_image(obj, &uhdrRawImg, UHDR_SDR_IMG);
1985     ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
1986 
1987     uhdr_compressed_image_t uhdrCompressedImg;
1988     uhdrCompressedImg.data = sdr->data;
1989     uhdrCompressedImg.data_sz = sdr->length;
1990     uhdrCompressedImg.capacity = sdr->length;
1991     uhdrCompressedImg.cg = map_internal_cg_to_cg(sdr->colorGamut);
1992     uhdrCompressedImg.ct = UHDR_CT_UNSPECIFIED;
1993     uhdrCompressedImg.range = UHDR_CR_UNSPECIFIED;
1994     status = uhdr_enc_set_compressed_image(obj, &uhdrCompressedImg, UHDR_SDR_IMG);
1995     ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
1996 
1997     status = uhdr_enc_set_quality(obj, kQuality, UHDR_BASE_IMG);
1998     ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
1999     status = uhdr_enc_set_using_multi_channel_gainmap(obj, false);
2000     ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
2001     status = uhdr_enc_set_gainmap_scale_factor(obj, 4);
2002     ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
2003     status = uhdr_enc_set_quality(obj, 85, UHDR_GAIN_MAP_IMG);
2004     ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
2005     status = uhdr_enc_set_preset(obj, UHDR_USAGE_REALTIME);
2006     ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
2007     status = uhdr_encode(obj);
2008     ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
2009     uhdr_compressed_image_t* compressedImage = uhdr_get_encoded_stream(obj);
2010     ASSERT_NE(nullptr, compressedImage);
2011     ASSERT_EQ(jpgImg.getImageHandle()->length, compressedImage->data_sz);
2012     ASSERT_EQ(
2013         0, memcmp(jpgImg.getImageHandle()->data, compressedImage->data, compressedImage->data_sz));
2014     uhdr_release_encoder(obj);
2015   }
2016   // encode with chroma stride set
2017   {
2018     UhdrUnCompressedStructWrapper rawImg2420(kImageWidth, kImageHeight, YCbCr_420);
2019     ASSERT_TRUE(rawImg2420.setImageColorGamut(mYuv420ColorGamut));
2020     ASSERT_TRUE(rawImg2420.setImageStride(0, kImageWidth + 64));
2021     ASSERT_TRUE(rawImg2420.setChromaMode(false));
2022     ASSERT_TRUE(rawImg2420.allocateMemory());
2023     ASSERT_TRUE(rawImg2420.loadRawResource(kYCbCr420FileName));
2024     UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight);
2025     ASSERT_TRUE(jpgImg2.allocateMemory());
2026     ASSERT_EQ(
2027         uHdrLib.encodeJPEGR(rawImgP010.getImageHandle(), rawImg2420.getImageHandle(), sdr,
2028                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg2.getImageHandle()),
2029         JPEGR_NO_ERROR);
2030     auto jpg1 = jpgImg.getImageHandle();
2031     auto jpg2 = jpgImg2.getImageHandle();
2032     ASSERT_EQ(jpg1->length, jpg2->length);
2033     ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length));
2034   }
2035 
2036   auto jpg1 = jpgImg.getImageHandle();
2037 
2038 #ifdef DUMP_OUTPUT
2039   if (!writeFile("encode_api2_output.jpeg", jpg1->data, jpg1->length)) {
2040     std::cerr << "unable to write output file" << std::endl;
2041   }
2042 #endif
2043 
2044   ASSERT_NO_FATAL_FAILURE(decodeJpegRImg(jpg1, "decode_api2_output.rgb"));
2045 }
2046 
2047 /* Test Encode API-3 and Decode */
TEST_P(JpegRAPIEncodeAndDecodeTest,EncodeAPI3AndDecodeTest)2048 TEST_P(JpegRAPIEncodeAndDecodeTest, EncodeAPI3AndDecodeTest) {
2049   UhdrUnCompressedStructWrapper rawImgP010(kImageWidth, kImageHeight, YCbCr_p010);
2050   ASSERT_TRUE(rawImgP010.setImageColorGamut(mP010ColorGamut));
2051   ASSERT_TRUE(rawImgP010.allocateMemory());
2052   ASSERT_TRUE(rawImgP010.loadRawResource(kYCbCrP010FileName));
2053   UhdrCompressedStructWrapper jpgImg(kImageWidth, kImageHeight);
2054   ASSERT_TRUE(jpgImg.allocateMemory());
2055   UhdrCompressedStructWrapper jpgSdr(kImageWidth, kImageHeight);
2056   ASSERT_TRUE(jpgSdr.allocateMemory());
2057   auto sdr = jpgSdr.getImageHandle();
2058   ASSERT_TRUE(readFile(kSdrJpgFileName, sdr->data, sdr->maxLength, sdr->length));
2059   JpegR uHdrLib;
2060   ASSERT_EQ(
2061       uHdrLib.encodeJPEGR(rawImgP010.getImageHandle(), sdr,
2062                           ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()),
2063       JPEGR_NO_ERROR);
2064   // encode with luma stride set
2065   {
2066     UhdrUnCompressedStructWrapper rawImg2P010(kImageWidth, kImageHeight, YCbCr_p010);
2067     ASSERT_TRUE(rawImg2P010.setImageColorGamut(mP010ColorGamut));
2068     ASSERT_TRUE(rawImg2P010.setImageStride(kImageWidth + 128, 0));
2069     ASSERT_TRUE(rawImg2P010.allocateMemory());
2070     ASSERT_TRUE(rawImg2P010.loadRawResource(kYCbCrP010FileName));
2071     UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight);
2072     ASSERT_TRUE(jpgImg2.allocateMemory());
2073     ASSERT_EQ(
2074         uHdrLib.encodeJPEGR(rawImg2P010.getImageHandle(), sdr,
2075                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg2.getImageHandle()),
2076         JPEGR_NO_ERROR);
2077     auto jpg1 = jpgImg.getImageHandle();
2078     auto jpg2 = jpgImg2.getImageHandle();
2079     ASSERT_EQ(jpg1->length, jpg2->length);
2080     ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length));
2081   }
2082   // encode with luma and chroma stride set
2083   {
2084     UhdrUnCompressedStructWrapper rawImg2P010(kImageWidth, kImageHeight, YCbCr_p010);
2085     ASSERT_TRUE(rawImg2P010.setImageColorGamut(mP010ColorGamut));
2086     ASSERT_TRUE(rawImg2P010.setImageStride(kImageWidth + 128, kImageWidth + 256));
2087     ASSERT_TRUE(rawImg2P010.setChromaMode(false));
2088     ASSERT_TRUE(rawImg2P010.allocateMemory());
2089     ASSERT_TRUE(rawImg2P010.loadRawResource(kYCbCrP010FileName));
2090     UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight);
2091     ASSERT_TRUE(jpgImg2.allocateMemory());
2092     ASSERT_EQ(
2093         uHdrLib.encodeJPEGR(rawImg2P010.getImageHandle(), sdr,
2094                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg2.getImageHandle()),
2095         JPEGR_NO_ERROR);
2096     auto jpg1 = jpgImg.getImageHandle();
2097     auto jpg2 = jpgImg2.getImageHandle();
2098     ASSERT_EQ(jpg1->length, jpg2->length);
2099     ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length));
2100   }
2101   // encode with chroma stride set
2102   {
2103     UhdrUnCompressedStructWrapper rawImg2P010(kImageWidth, kImageHeight, YCbCr_p010);
2104     ASSERT_TRUE(rawImg2P010.setImageColorGamut(mP010ColorGamut));
2105     ASSERT_TRUE(rawImg2P010.setImageStride(0, kImageWidth + 64));
2106     ASSERT_TRUE(rawImg2P010.setChromaMode(false));
2107     ASSERT_TRUE(rawImg2P010.allocateMemory());
2108     ASSERT_TRUE(rawImg2P010.loadRawResource(kYCbCrP010FileName));
2109     UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight);
2110     ASSERT_TRUE(jpgImg2.allocateMemory());
2111     ASSERT_EQ(
2112         uHdrLib.encodeJPEGR(rawImg2P010.getImageHandle(), sdr,
2113                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg2.getImageHandle()),
2114         JPEGR_NO_ERROR);
2115     auto jpg1 = jpgImg.getImageHandle();
2116     auto jpg2 = jpgImg2.getImageHandle();
2117     ASSERT_EQ(jpg1->length, jpg2->length);
2118     ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length));
2119   }
2120   // encode with luma and chroma stride set and no chroma ptr
2121   {
2122     UhdrUnCompressedStructWrapper rawImg2P010(kImageWidth, kImageHeight, YCbCr_p010);
2123     ASSERT_TRUE(rawImg2P010.setImageColorGamut(mP010ColorGamut));
2124     ASSERT_TRUE(rawImg2P010.setImageStride(kImageWidth + 32, kImageWidth + 256));
2125     ASSERT_TRUE(rawImg2P010.allocateMemory());
2126     ASSERT_TRUE(rawImg2P010.loadRawResource(kYCbCrP010FileName));
2127     UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight);
2128     ASSERT_TRUE(jpgImg2.allocateMemory());
2129     ASSERT_EQ(
2130         uHdrLib.encodeJPEGR(rawImg2P010.getImageHandle(), sdr,
2131                             ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg2.getImageHandle()),
2132         JPEGR_NO_ERROR);
2133     auto jpg1 = jpgImg.getImageHandle();
2134     auto jpg2 = jpgImg2.getImageHandle();
2135     ASSERT_EQ(jpg1->length, jpg2->length);
2136     ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length));
2137   }
2138 
2139   {
2140     uhdr_codec_private_t* obj = uhdr_create_encoder();
2141     uhdr_raw_image_t uhdrRawImg{};
2142     uhdrRawImg.fmt = UHDR_IMG_FMT_24bppYCbCrP010;
2143     uhdrRawImg.cg = map_internal_cg_to_cg(mP010ColorGamut);
2144     uhdrRawImg.ct = map_internal_ct_to_ct(ultrahdr_transfer_function::ULTRAHDR_TF_HLG);
2145     uhdrRawImg.range = UHDR_CR_LIMITED_RANGE;
2146     uhdrRawImg.w = kImageWidth;
2147     uhdrRawImg.h = kImageHeight;
2148     uhdrRawImg.planes[UHDR_PLANE_Y] = rawImgP010.getImageHandle()->data;
2149     uhdrRawImg.stride[UHDR_PLANE_Y] = kImageWidth;
2150     uhdrRawImg.planes[UHDR_PLANE_UV] =
2151         ((uint8_t*)(rawImgP010.getImageHandle()->data)) + kImageWidth * kImageHeight * 2;
2152     uhdrRawImg.stride[UHDR_PLANE_UV] = kImageWidth;
2153     uhdr_error_info_t status = uhdr_enc_set_raw_image(obj, &uhdrRawImg, UHDR_HDR_IMG);
2154     ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
2155 
2156     uhdr_compressed_image_t uhdrCompressedImg;
2157     uhdrCompressedImg.data = sdr->data;
2158     uhdrCompressedImg.data_sz = sdr->length;
2159     uhdrCompressedImg.capacity = sdr->length;
2160     uhdrCompressedImg.cg = map_internal_cg_to_cg(sdr->colorGamut);
2161     uhdrCompressedImg.ct = UHDR_CT_UNSPECIFIED;
2162     uhdrCompressedImg.range = UHDR_CR_UNSPECIFIED;
2163     status = uhdr_enc_set_compressed_image(obj, &uhdrCompressedImg, UHDR_SDR_IMG);
2164     ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
2165 
2166     status = uhdr_enc_set_quality(obj, kQuality, UHDR_BASE_IMG);
2167     ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
2168     status = uhdr_enc_set_using_multi_channel_gainmap(obj, false);
2169     ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
2170     status = uhdr_enc_set_gainmap_scale_factor(obj, 4);
2171     ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
2172     status = uhdr_enc_set_quality(obj, 85, UHDR_GAIN_MAP_IMG);
2173     ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
2174     status = uhdr_enc_set_preset(obj, UHDR_USAGE_REALTIME);
2175     ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
2176     status = uhdr_encode(obj);
2177     ASSERT_EQ(UHDR_CODEC_OK, status.error_code) << status.detail;
2178     uhdr_compressed_image_t* compressedImage = uhdr_get_encoded_stream(obj);
2179     ASSERT_NE(nullptr, compressedImage);
2180     ASSERT_EQ(jpgImg.getImageHandle()->length, compressedImage->data_sz);
2181     ASSERT_EQ(
2182         0, memcmp(jpgImg.getImageHandle()->data, compressedImage->data, compressedImage->data_sz));
2183     uhdr_release_encoder(obj);
2184   }
2185 
2186   auto jpg1 = jpgImg.getImageHandle();
2187 
2188 #ifdef DUMP_OUTPUT
2189   if (!writeFile("encode_api3_output.jpeg", jpg1->data, jpg1->length)) {
2190     std::cerr << "unable to write output file" << std::endl;
2191   }
2192 #endif
2193 
2194   ASSERT_NO_FATAL_FAILURE(decodeJpegRImg(jpg1, "decode_api3_output.rgb"));
2195 }
2196 
2197 INSTANTIATE_TEST_SUITE_P(
2198     JpegRAPIParameterizedTests, JpegRAPIEncodeAndDecodeTest,
2199     ::testing::Combine(::testing::Values(ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_P3,
2200                                          ULTRAHDR_COLORGAMUT_BT2100),
2201                        ::testing::Values(ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_P3,
2202                                          ULTRAHDR_COLORGAMUT_BT2100)));
2203 
2204 // ============================================================================
2205 // Profiling
2206 // ============================================================================
2207 #ifdef _WIN32
2208 class Profiler {
2209  public:
timerStart()2210   void timerStart() { QueryPerformanceCounter(&mStartingTime); }
2211 
timerStop()2212   void timerStop() { QueryPerformanceCounter(&mEndingTime); }
2213 
elapsedTime()2214   double elapsedTime() {
2215     LARGE_INTEGER frequency;
2216     LARGE_INTEGER elapsedMicroseconds;
2217     QueryPerformanceFrequency(&frequency);
2218     elapsedMicroseconds.QuadPart = mEndingTime.QuadPart - mStartingTime.QuadPart;
2219     return (double)elapsedMicroseconds.QuadPart / (double)frequency.QuadPart * 1000000;
2220   }
2221 
2222  private:
2223   LARGE_INTEGER mStartingTime;
2224   LARGE_INTEGER mEndingTime;
2225 };
2226 #else
2227 class Profiler {
2228  public:
timerStart()2229   void timerStart() { gettimeofday(&mStartingTime, nullptr); }
2230 
timerStop()2231   void timerStop() { gettimeofday(&mEndingTime, nullptr); }
2232 
elapsedTime()2233   int64_t elapsedTime() {
2234     struct timeval elapsedMicroseconds;
2235     elapsedMicroseconds.tv_sec = mEndingTime.tv_sec - mStartingTime.tv_sec;
2236     elapsedMicroseconds.tv_usec = mEndingTime.tv_usec - mStartingTime.tv_usec;
2237     return elapsedMicroseconds.tv_sec * 1000000 + elapsedMicroseconds.tv_usec;
2238   }
2239 
2240  private:
2241   struct timeval mStartingTime;
2242   struct timeval mEndingTime;
2243 };
2244 #endif
2245 
2246 class JpegRBenchmark : public JpegR {
2247  public:
2248 #ifdef UHDR_ENABLE_GLES
JpegRBenchmark(uhdr_opengl_ctxt_t * uhdrGLCtxt)2249   JpegRBenchmark(uhdr_opengl_ctxt_t* uhdrGLCtxt) : JpegR(uhdrGLCtxt) {}
2250 #endif
2251   void BenchmarkGenerateGainMap(uhdr_raw_image_t* yuv420Image, uhdr_raw_image_t* p010Image,
2252                                 uhdr_gainmap_metadata_ext_t* metadata,
2253                                 std::unique_ptr<uhdr_raw_image_ext_t>& gainmap);
2254   void BenchmarkApplyGainMap(uhdr_raw_image_t* yuv420Image, uhdr_raw_image_t* map,
2255                              uhdr_gainmap_metadata_ext_t* metadata, uhdr_raw_image_t* dest);
2256 
2257  private:
2258   const int kProfileCount = 10;
2259 };
2260 
BenchmarkGenerateGainMap(uhdr_raw_image_t * yuv420Image,uhdr_raw_image_t * p010Image,uhdr_gainmap_metadata_ext_t * metadata,std::unique_ptr<uhdr_raw_image_ext_t> & gainmap)2261 void JpegRBenchmark::BenchmarkGenerateGainMap(uhdr_raw_image_t* yuv420Image,
2262                                               uhdr_raw_image_t* p010Image,
2263                                               uhdr_gainmap_metadata_ext_t* metadata,
2264                                               std::unique_ptr<uhdr_raw_image_ext_t>& gainmap) {
2265   ASSERT_EQ(yuv420Image->w, p010Image->w);
2266   ASSERT_EQ(yuv420Image->h, p010Image->h);
2267   Profiler profileGenerateMap;
2268   profileGenerateMap.timerStart();
2269   for (auto i = 0; i < kProfileCount; i++) {
2270     ASSERT_EQ(UHDR_CODEC_OK, generateGainMap(yuv420Image, p010Image, metadata, gainmap).error_code);
2271   }
2272   profileGenerateMap.timerStop();
2273   ALOGV("Generate Gain Map:- Res = %u x %u, time = %f ms", yuv420Image->w, yuv420Image->h,
2274         profileGenerateMap.elapsedTime() / (kProfileCount * 1000.f));
2275 }
2276 
BenchmarkApplyGainMap(uhdr_raw_image_t * yuv420Image,uhdr_raw_image_t * map,uhdr_gainmap_metadata_ext_t * metadata,uhdr_raw_image_t * dest)2277 void JpegRBenchmark::BenchmarkApplyGainMap(uhdr_raw_image_t* yuv420Image, uhdr_raw_image_t* map,
2278                                            uhdr_gainmap_metadata_ext_t* metadata,
2279                                            uhdr_raw_image_t* dest) {
2280   Profiler profileRecMap;
2281   profileRecMap.timerStart();
2282   for (auto i = 0; i < kProfileCount; i++) {
2283     ASSERT_EQ(UHDR_CODEC_OK, applyGainMap(yuv420Image, map, metadata, UHDR_CT_HLG,
2284                                           UHDR_IMG_FMT_32bppRGBA1010102, FLT_MAX, dest)
2285                                  .error_code);
2286   }
2287   profileRecMap.timerStop();
2288   ALOGV("Apply Gain Map:- Res = %u x %u, time = %f ms", yuv420Image->w, yuv420Image->h,
2289         profileRecMap.elapsedTime() / (kProfileCount * 1000.f));
2290 }
2291 
TEST(JpegRTest,ProfileGainMapFuncs)2292 TEST(JpegRTest, ProfileGainMapFuncs) {
2293   UhdrUnCompressedStructWrapper rawImgP010(kImageWidth, kImageHeight, YCbCr_p010);
2294   ASSERT_TRUE(rawImgP010.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100));
2295   ASSERT_TRUE(rawImgP010.allocateMemory());
2296   ASSERT_TRUE(rawImgP010.loadRawResource(kYCbCrP010FileName));
2297   UhdrUnCompressedStructWrapper rawImg420(kImageWidth, kImageHeight, YCbCr_420);
2298   ASSERT_TRUE(rawImg420.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709));
2299   ASSERT_TRUE(rawImg420.allocateMemory());
2300   ASSERT_TRUE(rawImg420.loadRawResource(kYCbCr420FileName));
2301   uhdr_gainmap_metadata_ext_t metadata(kJpegrVersion);
2302 
2303   uhdr_raw_image_t hdr_intent, sdr_intent;
2304 
2305   {
2306     auto rawImg = rawImgP010.getImageHandle();
2307     if (rawImg->luma_stride == 0) rawImg->luma_stride = rawImg->width;
2308     if (!rawImg->chroma_data) {
2309       uint16_t* data = reinterpret_cast<uint16_t*>(rawImg->data);
2310       rawImg->chroma_data = data + rawImg->luma_stride * rawImg->height;
2311       rawImg->chroma_stride = rawImg->luma_stride;
2312     }
2313     hdr_intent.fmt = UHDR_IMG_FMT_24bppYCbCrP010;
2314     hdr_intent.cg = UHDR_CG_BT_2100;
2315     hdr_intent.ct = UHDR_CT_HLG;
2316     hdr_intent.range = UHDR_CR_LIMITED_RANGE;
2317     hdr_intent.w = rawImg->width;
2318     hdr_intent.h = rawImg->height;
2319     hdr_intent.planes[UHDR_PLANE_Y] = rawImg->data;
2320     hdr_intent.stride[UHDR_PLANE_Y] = rawImg->luma_stride;
2321     hdr_intent.planes[UHDR_PLANE_UV] = rawImg->chroma_data;
2322     hdr_intent.stride[UHDR_PLANE_UV] = rawImg->chroma_stride;
2323     hdr_intent.planes[UHDR_PLANE_V] = nullptr;
2324     hdr_intent.stride[UHDR_PLANE_V] = 0;
2325   }
2326   {
2327     auto rawImg = rawImg420.getImageHandle();
2328     if (rawImg->luma_stride == 0) rawImg->luma_stride = rawImg->width;
2329     if (!rawImg->chroma_data) {
2330       uint8_t* data = reinterpret_cast<uint8_t*>(rawImg->data);
2331       rawImg->chroma_data = data + rawImg->luma_stride * rawImg->height;
2332       rawImg->chroma_stride = rawImg->luma_stride / 2;
2333     }
2334     sdr_intent.fmt = UHDR_IMG_FMT_12bppYCbCr420;
2335     sdr_intent.cg = UHDR_CG_DISPLAY_P3;
2336     sdr_intent.ct = UHDR_CT_SRGB;
2337     sdr_intent.range = rawImg->colorRange;
2338     sdr_intent.w = rawImg->width;
2339     sdr_intent.h = rawImg->height;
2340     sdr_intent.planes[UHDR_PLANE_Y] = rawImg->data;
2341     sdr_intent.stride[UHDR_PLANE_Y] = rawImg->luma_stride;
2342     sdr_intent.planes[UHDR_PLANE_U] = rawImg->chroma_data;
2343     sdr_intent.stride[UHDR_PLANE_U] = rawImg->chroma_stride;
2344     uint8_t* data = reinterpret_cast<uint8_t*>(rawImg->chroma_data);
2345     data += (rawImg->height * rawImg->chroma_stride) / 2;
2346     sdr_intent.planes[UHDR_PLANE_V] = data;
2347     sdr_intent.stride[UHDR_PLANE_V] = rawImg->chroma_stride;
2348   }
2349 
2350   std::unique_ptr<uhdr_raw_image_ext_t> gainmap;
2351 
2352 #ifdef UHDR_ENABLE_GLES
2353   uhdr_opengl_ctxt_t glCtxt;
2354   glCtxt.init_opengl_ctxt();
2355   JpegRBenchmark benchmark(glCtxt.mErrorStatus.error_code == UHDR_CODEC_OK ? &glCtxt : nullptr);
2356 #else
2357   JpegRBenchmark benchmark;
2358 #endif
2359 
2360   ASSERT_NO_FATAL_FAILURE(
2361       benchmark.BenchmarkGenerateGainMap(&sdr_intent, &hdr_intent, &metadata, gainmap));
2362 
2363   const int dstSize = kImageWidth * kImageWidth * 4;
2364   auto bufferDst = std::make_unique<uint8_t[]>(dstSize);
2365   uhdr_raw_image_t output;
2366   output.fmt = UHDR_IMG_FMT_32bppRGBA1010102;
2367   output.cg = UHDR_CG_UNSPECIFIED;
2368   output.ct = UHDR_CT_UNSPECIFIED;
2369   output.range = UHDR_CR_UNSPECIFIED;
2370   output.w = kImageWidth;
2371   output.h = kImageHeight;
2372   output.planes[UHDR_PLANE_PACKED] = bufferDst.get();
2373   output.stride[UHDR_PLANE_PACKED] = kImageWidth;
2374   output.planes[UHDR_PLANE_U] = nullptr;
2375   output.stride[UHDR_PLANE_U] = 0;
2376   output.planes[UHDR_PLANE_V] = nullptr;
2377   output.stride[UHDR_PLANE_V] = 0;
2378 
2379   ASSERT_NO_FATAL_FAILURE(
2380       benchmark.BenchmarkApplyGainMap(&sdr_intent, gainmap.get(), &metadata, &output));
2381 
2382 #ifdef UHDR_ENABLE_GLES
2383   glCtxt.delete_opengl_ctxt();
2384 #endif
2385 }
2386 
2387 }  // namespace ultrahdr
2388