Improve YUY2 to RGBA color conversion
Uses libyuv to accelerate YUV2 into RGBA conversion.
Fix: 189610770
Test: Run evs_app
Change-Id: Iae282241fc30895c810c665d1b261a732f4ba174
diff --git a/cpp/evs/sampleDriver/Android.bp b/cpp/evs/sampleDriver/Android.bp
index e3572c3..d18dae2 100644
--- a/cpp/evs/sampleDriver/Android.bp
+++ b/cpp/evs/sampleDriver/Android.bp
@@ -38,26 +38,27 @@
],
shared_libs: [
+ "android.frameworks.automotive.display@1.0",
"android.hardware.automotive.evs@1.0",
"android.hardware.automotive.evs@1.1",
"android.hardware.camera.device@3.2",
- "libui",
+ "android.hardware.graphics.bufferqueue@1.0",
+ "android.hardware.graphics.bufferqueue@2.0",
+ "android.hidl.token@1.0-utils",
"libEGL",
"libGLESv2",
"libbase",
"libbinder",
+ "libbufferqueueconverter",
+ "libcamera_metadata",
"libcutils",
"libhardware",
- "libhidlbase",
- "libutils",
"libhardware_legacy",
- "libcamera_metadata",
+ "libhidlbase",
"libtinyxml2",
- "libbufferqueueconverter",
- "android.hidl.token@1.0-utils",
- "android.frameworks.automotive.display@1.0",
- "android.hardware.graphics.bufferqueue@1.0",
- "android.hardware.graphics.bufferqueue@2.0",
+ "libui",
+ "libutils",
+ "libyuv",
],
init_rc: ["android.hardware.automotive.evs@1.1-sample.rc"],
diff --git a/cpp/evs/sampleDriver/bufferCopy.cpp b/cpp/evs/sampleDriver/bufferCopy.cpp
index 1c07478..d9578e6 100644
--- a/cpp/evs/sampleDriver/bufferCopy.cpp
+++ b/cpp/evs/sampleDriver/bufferCopy.cpp
@@ -16,6 +16,8 @@
#include "bufferCopy.h"
+#include <android-base/logging.h>
+#include <libyuv.h>
namespace android {
namespace hardware {
@@ -36,35 +38,6 @@
}
-// Limit the given value to the provided range. :)
-static inline float clamp(float v, float min, float max) {
- if (v < min) return min;
- if (v > max) return max;
- return v;
-}
-
-
-static uint32_t yuvToRgbx(const unsigned char Y, const unsigned char Uin, const unsigned char Vin) {
- // Don't use this if you want to see the best performance. :)
- // Better to do this in a pixel shader if we really have to, but on actual
- // embedded hardware we expect to be able to texture directly from the YUV data
- float U = Uin - 128.0f;
- float V = Vin - 128.0f;
-
- float Rf = Y + 1.140f*V;
- float Gf = Y - 0.395f*U - 0.581f*V;
- float Bf = Y + 2.032f*U;
- unsigned char R = (unsigned char)clamp(Rf, 0.0f, 255.0f);
- unsigned char G = (unsigned char)clamp(Gf, 0.0f, 255.0f);
- unsigned char B = (unsigned char)clamp(Bf, 0.0f, 255.0f);
-
- return ((R & 0xFF)) |
- ((G & 0xFF) << 8) |
- ((B & 0xFF) << 16) |
- 0xFF000000; // Fill the alpha channel with ones
-}
-
-
void fillNV21FromNV21(const BufferDesc& tgtBuff, uint8_t* tgt, void* imgData, unsigned) {
// The NV21 format provides a Y array of 8bit values, followed by a 1/2 x 1/2 interleave U/V array.
// It assumes an even width and height for the overall image, and a horizontal stride that is
@@ -150,35 +123,14 @@
void fillRGBAFromYUYV(const BufferDesc& tgtBuff, uint8_t* tgt, void* imgData, unsigned imgStride) {
const AHardwareBuffer_Desc* pDesc =
reinterpret_cast<const AHardwareBuffer_Desc*>(&tgtBuff.buffer.description);
- unsigned width = pDesc->width;
- unsigned height = pDesc->height;
- uint32_t* src = (uint32_t*)imgData;
- uint32_t* dst = (uint32_t*)tgt;
- unsigned srcStridePixels = imgStride / 2;
- unsigned dstStridePixels = pDesc->stride;
-
- const int srcRowPadding32 = srcStridePixels/2 - width/2; // 2 bytes per pixel, 4 bytes per word
- const int dstRowPadding32 = dstStridePixels - width; // 4 bytes per pixel, 4 bytes per word
-
- for (unsigned r=0; r<height; r++) {
- for (unsigned c=0; c<width/2; c++) {
- // Note: we're walking two pixels at a time here (even/odd)
- uint32_t srcPixel = *src++;
-
- uint8_t Y1 = (srcPixel) & 0xFF;
- uint8_t U = (srcPixel >> 8) & 0xFF;
- uint8_t Y2 = (srcPixel >> 16) & 0xFF;
- uint8_t V = (srcPixel >> 24) & 0xFF;
-
- // On the RGB output, we're writing one pixel at a time
- *(dst+0) = yuvToRgbx(Y1, U, V);
- *(dst+1) = yuvToRgbx(Y2, U, V);
- dst += 2;
- }
-
- // Skip over any extra data or end of row alignment padding
- src += srcRowPadding32;
- dst += dstRowPadding32;
+ auto result = libyuv::YUY2ToARGB((const uint8_t*)imgData,
+ imgStride, // input stride in bytes
+ tgt,
+ (pDesc->stride << 2), // output stride in bytes
+ pDesc->width,
+ pDesc->height);
+ if (result) {
+ LOG(ERROR) << "Failed to convert YUYV to ARGB.";
}
}