[go: nahoru, domu]

Revert "Sync latest YuvToRgbComverter"

This reverts commit 69fa9445adda8297b60bdfba78e0c82c953cd1b3.

Reason for revert: breaks build of androidx-platform-dev/androidx_max_dep_versions

Change-Id: Ib8c7624b91b46eae1a686dc7445e94351cc28958
diff --git a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/util/YuvToRgbConverter.kt b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/util/YuvToRgbConverter.kt
index 32ee4e3..424f50c 100644
--- a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/util/YuvToRgbConverter.kt
+++ b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/util/YuvToRgbConverter.kt
@@ -1,11 +1,11 @@
 /*
- * Copyright 2020 The Android Open Source Project
+ * Copyright 2021 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *     https://www.apache.org/licenses/LICENSE-2.0
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -16,16 +16,13 @@
 
 package androidx.camera.integration.core.util
 
+import android.annotation.SuppressLint
 import android.content.Context
 import android.graphics.Bitmap
 import android.graphics.ImageFormat
 import android.graphics.Rect
 import android.media.Image
-import android.renderscript.Allocation
-import android.renderscript.Element
-import android.renderscript.RenderScript
-import android.renderscript.ScriptIntrinsicYuvToRGB
-import android.renderscript.Type
+import java.nio.ByteBuffer
 
 /**
  * Copy from the github for testing.
@@ -45,53 +42,61 @@
  */
 @Suppress("DEPRECATION")
 class YuvToRgbConverter(context: Context) {
-    private val rs = RenderScript.create(context)
-    private val scriptYuvToRgb = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs))
+    private val rs = android.renderscript.RenderScript.create(context)
+    private val scriptYuvToRgb = android.renderscript.ScriptIntrinsicYuvToRGB.create(
+        rs,
+        android.renderscript.Element.U8_4(rs)
+    )
 
     private var pixelCount: Int = -1
-    private lateinit var yuvBuffer: ByteArray
-    private lateinit var inputAllocation: Allocation
-    private lateinit var outputAllocation: Allocation
+    private lateinit var yuvBuffer: ByteBuffer
+    private lateinit var inputAllocation: android.renderscript.Allocation
+    private lateinit var outputAllocation: android.renderscript.Allocation
 
+    @SuppressLint("BanSynchronizedMethods")
     @Synchronized
     fun yuvToRgb(image: Image, output: Bitmap) {
 
         // Ensure that the intermediate output byte buffer is allocated
         if (!::yuvBuffer.isInitialized) {
             pixelCount = image.cropRect.width() * image.cropRect.height()
-            // Bits per pixel is an average for the whole image, so it's useful to compute the size
-            // of the full buffer but should not be used to determine pixel offsets
-            val pixelSizeBits = ImageFormat.getBitsPerPixel(ImageFormat.YUV_420_888)
-            yuvBuffer = ByteArray(pixelCount * pixelSizeBits / 8)
+            yuvBuffer = ByteBuffer.allocateDirect(
+                pixelCount * ImageFormat.getBitsPerPixel(ImageFormat.YUV_420_888) / 8
+            )
         }
 
-        // Get the YUV data in byte array form using NV21 format
-        imageToByteArray(image, yuvBuffer)
+        // Get the YUV data in byte array form
+        imageToByteBuffer(image, yuvBuffer)
 
         // Ensure that the RenderScript inputs and outputs are allocated
         if (!::inputAllocation.isInitialized) {
-            // Explicitly create an element with type NV21, since that's the pixel format we use
-            val elemType = Type.Builder(rs, Element.YUV(rs)).setYuvFormat(ImageFormat.NV21).create()
-            inputAllocation = Allocation.createSized(rs, elemType.element, yuvBuffer.size)
+            inputAllocation = android.renderscript.Allocation.createSized(
+                rs,
+                android.renderscript.Element.U8(rs),
+                yuvBuffer.array().size
+            )
         }
         if (!::outputAllocation.isInitialized) {
-            outputAllocation = Allocation.createFromBitmap(rs, output)
+            outputAllocation = android.renderscript.Allocation.createFromBitmap(rs, output)
         }
 
-        // Convert NV21 format YUV to RGB
-        inputAllocation.copyFrom(yuvBuffer)
+        // Convert YUV to RGB
+        inputAllocation.copyFrom(yuvBuffer.array())
         scriptYuvToRgb.setInput(inputAllocation)
         scriptYuvToRgb.forEach(outputAllocation)
         outputAllocation.copyTo(output)
     }
 
-    private fun imageToByteArray(image: Image, outputBuffer: ByteArray) {
-        assert(image.format == ImageFormat.YUV_420_888)
+    private fun imageToByteBuffer(image: Image, outputBuffer: ByteBuffer) {
+        if (image.format != ImageFormat.YUV_420_888)
+            throw AssertionError("ImageFormat incorrect")
 
         val imageCrop = image.cropRect
         val imagePlanes = image.planes
+        val rowData = ByteArray(imagePlanes.first().rowStride)
 
         imagePlanes.forEachIndexed { planeIndex, plane ->
+
             // How many values are read in input for each output value written
             // Only the Y plane has a value for every pixel, U and V have half the resolution i.e.
             //
@@ -111,10 +116,10 @@
             //
             // First chunk        Second chunk
             // ===============    ===============
-            // Y Y Y Y Y Y Y Y    V U V U V U V U
-            // Y Y Y Y Y Y Y Y    V U V U V U V U
-            // Y Y Y Y Y Y Y Y    V U V U V U V U
-            // Y Y Y Y Y Y Y Y    V U V U V U V U
+            // Y Y Y Y Y Y Y Y    U V U V U V U V
+            // Y Y Y Y Y Y Y Y    U V U V U V U V
+            // Y Y Y Y Y Y Y Y    U V U V U V U V
+            // Y Y Y Y Y Y Y Y    U V U V U V U V
             // Y Y Y Y Y Y Y Y
             // Y Y Y Y Y Y Y Y
             // Y Y Y Y Y Y Y Y
@@ -127,12 +132,10 @@
                 }
                 1 -> {
                     outputStride = 2
-                    // For NV21 format, U is in odd-numbered indices
                     outputOffset = pixelCount + 1
                 }
                 2 -> {
                     outputStride = 2
-                    // For NV21 format, V is in even-numbered indices
                     outputOffset = pixelCount
                 }
                 else -> {
@@ -141,7 +144,7 @@
                 }
             }
 
-            val planeBuffer = plane.buffer
+            val buffer = plane.buffer
             val rowStride = plane.rowStride
             val pixelStride = plane.pixelStride
 
@@ -160,43 +163,28 @@
             val planeWidth = planeCrop.width()
             val planeHeight = planeCrop.height()
 
-            // Intermediate buffer used to store the bytes of each row
-            val rowBuffer = ByteArray(plane.rowStride)
-
-            // Size of each row in bytes
-            val rowLength = if (pixelStride == 1 && outputStride == 1) {
-                planeWidth
-            } else {
-                // Take into account that the stride may include data from pixels other than this
-                // particular plane and row, and that could be between pixels and not after every
-                // pixel:
-                //
-                // |---- Pixel stride ----|                    Row ends here --> |
-                // | Pixel 1 | Other Data | Pixel 2 | Other Data | ... | Pixel N |
-                //
-                // We need to get (N-1) * (pixel stride bytes) per row + 1 byte for the last pixel
-                (planeWidth - 1) * pixelStride + 1
-            }
-
+            buffer.position(rowStride * planeCrop.top + pixelStride * planeCrop.left)
             for (row in 0 until planeHeight) {
-                // Move buffer position to the beginning of this row
-                planeBuffer.position(
-                    (row + planeCrop.top) * rowStride + planeCrop.left * pixelStride
-                )
-
+                val length: Int
                 if (pixelStride == 1 && outputStride == 1) {
                     // When there is a single stride value for pixel and output, we can just copy
                     // the entire row in a single step
-                    planeBuffer.get(outputBuffer, outputOffset, rowLength)
-                    outputOffset += rowLength
+                    length = planeWidth
+                    buffer.get(outputBuffer.array(), outputOffset, length)
+                    outputOffset += length
                 } else {
                     // When either pixel or output have a stride > 1 we must copy pixel by pixel
-                    planeBuffer.get(rowBuffer, 0, rowLength)
+                    length = (planeWidth - 1) * pixelStride + 1
+                    buffer.get(rowData, 0, length)
                     for (col in 0 until planeWidth) {
-                        outputBuffer[outputOffset] = rowBuffer[col * pixelStride]
+                        outputBuffer.array()[outputOffset] = rowData[col * pixelStride]
                         outputOffset += outputStride
                     }
                 }
+
+                if (row < planeHeight - 1) {
+                    buffer.position(buffer.position() + rowStride - length)
+                }
             }
         }
     }