ultrahdr: unit test for encode api0

This test checks if luma stride, chroma stride, chroma_data, data
fields of p010 raw struct have expected effects on the compressed
jpegr data.

Bug: 283495487
Test: ./libultrahdr_test

Change-Id: Ie5c2e04181c08bb4ea7b2ba4cfcb56b0acc661f5
diff --git a/libs/ultrahdr/tests/jpegr_test.cpp b/libs/ultrahdr/tests/jpegr_test.cpp
index ac35887..34f8afd 100644
--- a/libs/ultrahdr/tests/jpegr_test.cpp
+++ b/libs/ultrahdr/tests/jpegr_test.cpp
@@ -89,6 +89,51 @@
   return true;
 }
 
+static bool loadP010Image(const char *filename, jr_uncompressed_ptr img,
+                          bool isUVContiguous) {
+  int fd = open(filename, O_CLOEXEC);
+  if (fd < 0) {
+    return false;
+  }
+  const int bpp = 2;
+  int lumaStride = img->luma_stride == 0 ? img->width : img->luma_stride;
+  int lumaSize = bpp * lumaStride * img->height;
+  int chromaSize = bpp * (img->height / 2) *
+                   (isUVContiguous ? lumaStride : img->chroma_stride);
+  img->data = malloc(lumaSize + (isUVContiguous ? chromaSize : 0));
+  if (img->data == nullptr) {
+    ALOGE("loadP010Image(): failed to allocate memory for luma data.");
+    return false;
+  }
+  uint8_t *mem = static_cast<uint8_t *>(img->data);
+  for (int i = 0; i < img->height; i++) {
+    if (read(fd, mem, img->width * bpp) != img->width * bpp) {
+      close(fd);
+      return false;
+    }
+    mem += lumaStride * bpp;
+  }
+  int chromaStride = lumaStride;
+  if (!isUVContiguous) {
+    img->chroma_data = malloc(chromaSize);
+    if (img->chroma_data == nullptr) {
+      ALOGE("loadP010Image(): failed to allocate memory for chroma data.");
+      return false;
+    }
+    mem = static_cast<uint8_t *>(img->chroma_data);
+    chromaStride = img->chroma_stride;
+  }
+  for (int i = 0; i < img->height / 2; i++) {
+    if (read(fd, mem, img->width * bpp) != img->width * bpp) {
+      close(fd);
+      return false;
+    }
+    mem += chromaStride * bpp;
+  }
+  close(fd);
+  return true;
+}
+
 class JpegRTest : public testing::Test {
 public:
   JpegRTest();
@@ -98,10 +143,11 @@
   virtual void SetUp();
   virtual void TearDown();
 
-  struct jpegr_uncompressed_struct mRawP010Image;
-  struct jpegr_uncompressed_struct mRawP010ImageWithStride;
-  struct jpegr_uncompressed_struct mRawYuv420Image;
-  struct jpegr_compressed_struct mJpegImage;
+  struct jpegr_uncompressed_struct mRawP010Image{};
+  struct jpegr_uncompressed_struct mRawP010ImageWithStride{};
+  struct jpegr_uncompressed_struct mRawP010ImageWithChromaData{};
+  struct jpegr_uncompressed_struct mRawYuv420Image{};
+  struct jpegr_compressed_struct mJpegImage{};
 };
 
 JpegRTest::JpegRTest() {}
@@ -110,7 +156,11 @@
 void JpegRTest::SetUp() {}
 void JpegRTest::TearDown() {
   free(mRawP010Image.data);
+  free(mRawP010Image.chroma_data);
   free(mRawP010ImageWithStride.data);
+  free(mRawP010ImageWithStride.chroma_data);
+  free(mRawP010ImageWithChromaData.data);
+  free(mRawP010ImageWithChromaData.chroma_data);
   free(mRawYuv420Image.data);
   free(mJpegImage.data);
 }
@@ -286,6 +336,8 @@
       &mRawP010ImageWithStride, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR,
       DEFAULT_JPEG_QUALITY, nullptr)) << "fail, API allows bad chroma stride";
 
+  mRawP010ImageWithStride.chroma_data = nullptr;
+
   free(jpegR.data);
 }
 
@@ -734,6 +786,7 @@
   EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
       &mRawP010ImageWithStride, &jpegR, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
       &jpegR)) << "fail, API allows bad chroma stride";
+  mRawP010ImageWithStride.chroma_data = nullptr;
 
   // bad compressed image
   EXPECT_NE(OK, jpegRCodec.encodeJPEGR(
@@ -792,6 +845,81 @@
   EXPECT_FLOAT_EQ(metadata_expected.minContentBoost, metadata_read.minContentBoost);
 }
 
+/* Test Encode API-0 */
+TEST_F(JpegRTest, encodeFromP010) {
+  int ret;
+
+  mRawP010Image.width = TEST_IMAGE_WIDTH;
+  mRawP010Image.height = TEST_IMAGE_HEIGHT;
+  mRawP010Image.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
+  // Load input files.
+  if (!loadP010Image(RAW_P010_IMAGE, &mRawP010Image, true)) {
+    FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
+  }
+
+  JpegR jpegRCodec;
+
+  jpegr_compressed_struct jpegR;
+  jpegR.maxLength = TEST_IMAGE_WIDTH * TEST_IMAGE_HEIGHT * sizeof(uint8_t);
+  jpegR.data = malloc(jpegR.maxLength);
+  ret = jpegRCodec.encodeJPEGR(
+      &mRawP010Image, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegR, DEFAULT_JPEG_QUALITY,
+      nullptr);
+  if (ret != OK) {
+    FAIL() << "Error code is " << ret;
+  }
+
+  mRawP010ImageWithStride.width = TEST_IMAGE_WIDTH;
+  mRawP010ImageWithStride.height = TEST_IMAGE_HEIGHT;
+  mRawP010ImageWithStride.luma_stride = TEST_IMAGE_WIDTH + 128;
+  mRawP010ImageWithStride.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
+  // Load input files.
+  if (!loadP010Image(RAW_P010_IMAGE, &mRawP010ImageWithStride, true)) {
+    FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
+  }
+
+  jpegr_compressed_struct jpegRWithStride;
+  jpegRWithStride.maxLength = jpegR.length;
+  jpegRWithStride.data = malloc(jpegRWithStride.maxLength);
+  ret = jpegRCodec.encodeJPEGR(
+      &mRawP010ImageWithStride, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, &jpegRWithStride,
+      DEFAULT_JPEG_QUALITY, nullptr);
+  if (ret != OK) {
+    FAIL() << "Error code is " << ret;
+  }
+  ASSERT_EQ(jpegR.length, jpegRWithStride.length)
+      << "Same input is yielding different output";
+  ASSERT_EQ(0, memcmp(jpegR.data, jpegRWithStride.data, jpegR.length))
+      << "Same input is yielding different output";
+
+  mRawP010ImageWithChromaData.width = TEST_IMAGE_WIDTH;
+  mRawP010ImageWithChromaData.height = TEST_IMAGE_HEIGHT;
+  mRawP010ImageWithChromaData.luma_stride = TEST_IMAGE_WIDTH + 64;
+  mRawP010ImageWithChromaData.chroma_stride = TEST_IMAGE_WIDTH + 256;
+  mRawP010ImageWithChromaData.colorGamut = ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
+  // Load input files.
+  if (!loadP010Image(RAW_P010_IMAGE, &mRawP010ImageWithChromaData, false)) {
+    FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
+  }
+  jpegr_compressed_struct jpegRWithChromaData;
+  jpegRWithChromaData.maxLength = jpegR.length;
+  jpegRWithChromaData.data = malloc(jpegRWithChromaData.maxLength);
+  ret = jpegRCodec.encodeJPEGR(
+      &mRawP010ImageWithChromaData, ultrahdr_transfer_function::ULTRAHDR_TF_HLG,
+      &jpegRWithChromaData, DEFAULT_JPEG_QUALITY, nullptr);
+  if (ret != OK) {
+    FAIL() << "Error code is " << ret;
+  }
+  ASSERT_EQ(jpegR.length, jpegRWithChromaData.length)
+      << "Same input is yielding different output";
+  ASSERT_EQ(0, memcmp(jpegR.data, jpegRWithChromaData.data, jpegR.length))
+      << "Same input is yielding different output";
+
+  free(jpegR.data);
+  free(jpegRWithStride.data);
+  free(jpegRWithChromaData.data);
+}
+
 /* Test Encode API-0 and decode */
 TEST_F(JpegRTest, encodeFromP010ThenDecode) {
   int ret;