Camera: encode JPEG/R without hardware JPEG encoder

Bug: b/20133417, b/252835416
Test: Test: atest -c -d \
cts/tests/camera/src/android/hardware/camera2/cts/ImageReaderTest.java#testJpegR

Change-Id: I17bd9e4f8a83c422d56a2606c4c642a76885e34b
diff --git a/services/camera/libcameraservice/api2/JpegRCompositeStream.cpp b/services/camera/libcameraservice/api2/JpegRCompositeStream.cpp
index fb8979d..9857fd8 100644
--- a/services/camera/libcameraservice/api2/JpegRCompositeStream.cpp
+++ b/services/camera/libcameraservice/api2/JpegRCompositeStream.cpp
@@ -285,22 +285,37 @@
     }
 
     size_t actualJpegRSize = 0;
-    if (mSupportInternalJpeg) {
-        recoverymap::jpegr_uncompressed_struct p010;
-        recoverymap::jpegr_compressed_struct jpeg;
-        recoverymap::jpegr_compressed_struct jpegR;
+    recoverymap::jpegr_uncompressed_struct p010;
+    recoverymap::jpegr_compressed_struct jpegR;
+    recoverymap::RecoveryMap recoveryMap;
 
-        p010.height = inputFrame.p010Buffer.height;
-        p010.width = inputFrame.p010Buffer.width;
-        p010.colorGamut = recoverymap::jpegr_color_gamut::JPEGR_COLORGAMUT_BT2100;
-        size_t yChannelSizeInByte = p010.width * p010.height * 2;
-        size_t uvChannelSizeInByte = p010.width * p010.height;
-        p010.data = new uint8_t[yChannelSizeInByte + uvChannelSizeInByte];
-        std::unique_ptr<uint8_t[]> p010_data;
-        p010_data.reset(reinterpret_cast<uint8_t*>(p010.data));
-        memcpy((uint8_t*)p010.data, inputFrame.p010Buffer.data, yChannelSizeInByte);
-        memcpy((uint8_t*)p010.data + yChannelSizeInByte, inputFrame.p010Buffer.dataCb,
-               uvChannelSizeInByte);
+    p010.height = inputFrame.p010Buffer.height;
+    p010.width = inputFrame.p010Buffer.width;
+    p010.colorGamut = recoverymap::jpegr_color_gamut::JPEGR_COLORGAMUT_BT2100;
+    size_t yChannelSizeInByte = p010.width * p010.height * 2;
+    size_t uvChannelSizeInByte = p010.width * p010.height;
+    p010.data = new uint8_t[yChannelSizeInByte + uvChannelSizeInByte];
+    std::unique_ptr<uint8_t[]> p010_data;
+    p010_data.reset(reinterpret_cast<uint8_t*>(p010.data));
+    memcpy((uint8_t*)p010.data, inputFrame.p010Buffer.data, yChannelSizeInByte);
+    memcpy((uint8_t*)p010.data + yChannelSizeInByte, inputFrame.p010Buffer.dataCb,
+           uvChannelSizeInByte);
+
+    jpegR.data = dstBuffer;
+    jpegR.maxLength = maxJpegRBufferSize;
+
+    recoverymap::jpegr_transfer_function transferFunction;
+    switch (mP010DynamicRange) {
+        case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10:
+        case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10_PLUS:
+            transferFunction = recoverymap::jpegr_transfer_function::JPEGR_TF_PQ;
+            break;
+        default:
+            transferFunction = recoverymap::jpegr_transfer_function::JPEGR_TF_HLG;
+    }
+
+    if (mSupportInternalJpeg) {
+        recoverymap::jpegr_compressed_struct jpeg;
 
         jpeg.data = inputFrame.jpegBuffer.data;
         jpeg.length = android::camera2::JpegProcessor::findJpegSize(inputFrame.jpegBuffer.data,
@@ -317,28 +332,7 @@
             jpeg.colorGamut = recoverymap::jpegr_color_gamut::JPEGR_COLORGAMUT_BT709;
         }
 
-        recoverymap::jpegr_transfer_function transferFunction;
-        switch (mP010DynamicRange) {
-            case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10:
-            case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10_PLUS:
-                transferFunction = recoverymap::jpegr_transfer_function::JPEGR_TF_PQ;
-                break;
-            default:
-                transferFunction = recoverymap::jpegr_transfer_function::JPEGR_TF_HLG;
-        }
-
-        jpegR.data = dstBuffer;
-        jpegR.maxLength = maxJpegRBufferSize;
-
-        recoverymap::RecoveryMap recoveryMap;
         res = recoveryMap.encodeJPEGR(&p010, &jpeg, transferFunction, &jpegR);
-        if (res != OK) {
-            ALOGE("%s: Error trying to encode JPEG/R: %s (%d)", __FUNCTION__, strerror(-res), res);
-            return res;
-        }
-
-        actualJpegRSize = jpegR.length;
-        p010_data.release();
     } else {
         const uint8_t* exifBuffer = nullptr;
         size_t exifBufferSize = 0;
@@ -352,8 +346,22 @@
         } else {
             ALOGE("%s: Unable to generate App1 buffer", __FUNCTION__);
         }
+
+        recoverymap::jpegr_exif_struct exif;
+        exif.data = reinterpret_cast<void*>(const_cast<uint8_t*>(exifBuffer));
+        exif.length = exifBufferSize;
+
+        res = recoveryMap.encodeJPEGR(&p010, transferFunction, &jpegR, jpegQuality, &exif);
     }
 
+    if (res != OK) {
+        ALOGE("%s: Error trying to encode JPEG/R: %s (%d)", __FUNCTION__, strerror(-res), res);
+        return res;
+    }
+
+    actualJpegRSize = jpegR.length;
+    p010_data.release();
+
     size_t finalJpegRSize = actualJpegRSize + sizeof(CameraBlob);
     if (finalJpegRSize > maxJpegRBufferSize) {
         ALOGE("%s: Final jpeg buffer not large enough for the jpeg blob header", __FUNCTION__);