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