From: Joshua Lang Date: Fri, 5 Aug 2016 21:18:52 +0000 (-0700) Subject: Change yv12 conversion from rgb565 to 888 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=88c3a27bbeb43a17689f9717b10943a55dde7f0e;p=android-x86%2Fdevice-generic-goldfish-opengl.git Change yv12 conversion from rgb565 to 888 Media codec tests that caused back to back yv12 - rgb565 conversions were failing color threshold assertions. Changed the conversion to rgb888 instead to keep more precision during conversions. Bug: 28750939 Change-Id: I75001261db82b9ecfa943d9a791a737a811cb168 --- diff --git a/system/gralloc/gralloc.cpp b/system/gralloc/gralloc.cpp index 69ea198..bc1e5c9 100644 --- a/system/gralloc/gralloc.cpp +++ b/system/gralloc/gralloc.cpp @@ -291,9 +291,9 @@ static int gralloc_alloc(alloc_device_t* dev, align = 16; bpp = 1; // per-channel bpp yuv_format = true; + // We are going to use RGB888 on the host glFormat = GL_RGB; - glType = GL_UNSIGNED_SHORT_5_6_5; - // Not expecting to actually create any GL surfaces for this + glType = GL_UNSIGNED_BYTE; break; default: ALOGE("gralloc_alloc: Unknown format %d", format); @@ -719,6 +719,44 @@ static void rgb565_to_yv12(char* dest, char* src, int width, int height, } } +static void rgb888_to_yv12(char* dest, char* src, int width, int height, + int left, int top, int right, int bottom) { + DD("%s convert %d by %d", __func__, width, height); + int align = 16; + int yStride = (width + (align -1)) & ~(align-1); + int cStride = (yStride / 2 + (align - 1)) & ~(align-1); + int yOffset = 0; + int cSize = cStride * height/2; + int rgb_stride = 3; + + uint8_t *rgb_ptr0 = (uint8_t *)src; + uint8_t *yv12_y0 = (uint8_t *)dest; + uint8_t *yv12_v0 = yv12_y0 + yStride * height; + uint8_t *yv12_u0 = yv12_v0 + cSize; + + for (int j = top; j <= bottom; ++j) { + uint8_t *yv12_y = yv12_y0 + j * yStride; + uint8_t *yv12_v = yv12_v0 + (j/2) * cStride; + uint8_t *yv12_u = yv12_v + cSize; + uint8_t *rgb_ptr = rgb_ptr0 + j * width*rgb_stride; + bool jeven = (j & 1) == 0; + for (int i = left; i <= right; ++i) { + uint8_t R = rgb_ptr[i*rgb_stride]; + uint8_t G = rgb_ptr[i*rgb_stride+1]; + uint8_t B = rgb_ptr[i*rgb_stride+2]; + // convert to YV12 + // frameworks/base/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp + yv12_y[i] = clamp_rgb((77 * R + 150 * G + 29 * B) >> 8); + bool ieven = (i & 1) == 0; + if (jeven && ieven) { + yv12_u[i] = clamp_rgb((( -43 * R - 85 * G + 128 * B) >> 8) + 128); + yv12_v[i] = clamp_rgb((( 128 * R - 107 * G - 21 * B) >> 8) + 128); + } + } + } +} + + static int gralloc_lock(gralloc_module_t const* module, buffer_handle_t handle, int usage, int l, int t, int w, int h, @@ -825,14 +863,15 @@ static int gralloc_lock(gralloc_module_t const* module, char* tmpBuf = 0; if (cb->frameworkFormat == HAL_PIXEL_FORMAT_YV12 || cb->frameworkFormat == HAL_PIXEL_FORMAT_YCbCr_420_888) { - tmpBuf = new char[cb->width * cb->height * 2]; + // We are using RGB88 + tmpBuf = new char[cb->width * cb->height * 3]; rgb_addr = tmpBuf; } D("gralloc_lock read back color buffer %d %d\n", cb->width, cb->height); rcEnc->rcReadColorBuffer(rcEnc, cb->hostHandle, 0, 0, cb->width, cb->height, cb->glFormat, cb->glType, rgb_addr); if (tmpBuf) { - rgb565_to_yv12((char*)cpu_addr, tmpBuf, cb->width, cb->height, l, t, l+w-1, t+h-1); + rgb888_to_yv12((char*)cpu_addr, tmpBuf, cb->width, cb->height, l, t, l+w-1, t+h-1); delete [] tmpBuf; } } @@ -906,6 +945,53 @@ static void yv12_to_rgb565(char* dest, char* src, int width, int height, } } +// YV12 is aka YUV420Planar, or YUV420p; the only difference is that YV12 has +// certain stride requirements for Y and UV respectively. +static void yv12_to_rgb888(char* dest, char* src, int width, int height, + int left, int top, int right, int bottom) { + DD("%s convert %d by %d", __func__, width, height); + int align = 16; + int yStride = (width + (align -1)) & ~(align-1); + int cStride = (yStride / 2 + (align - 1)) & ~(align-1); + int yOffset = 0; + int cSize = cStride * height/2; + int rgb_stride = 3; + + uint8_t *rgb_ptr0 = (uint8_t *)dest; + uint8_t *yv12_y0 = (uint8_t *)src; + uint8_t *yv12_v0 = yv12_y0 + yStride * height; + uint8_t *yv12_u0 = yv12_v0 + cSize; + + for (int j = top; j <= bottom; ++j) { + uint8_t *yv12_y = yv12_y0 + j * yStride; + uint8_t *yv12_v = yv12_v0 + (j/2) * cStride; + uint8_t *yv12_u = yv12_v + cSize; + uint8_t *rgb_ptr = rgb_ptr0 + (j-top) * (right-left+1) * rgb_stride; + for (int i = left; i <= right; ++i) { + // convert to rgb + // frameworks/av/media/libstagefright/colorconversion/ColorConverter.cpp + signed y1 = (signed)yv12_y[i] - 16; + signed u = (signed)yv12_u[i / 2] - 128; + signed v = (signed)yv12_v[i / 2] - 128; + + signed u_b = u * 517; + signed u_g = -u * 100; + signed v_g = -v * 208; + signed v_r = v * 409; + + signed tmp1 = y1 * 298; + signed b1 = clamp_rgb((tmp1 + u_b) / 256); + signed g1 = clamp_rgb((tmp1 + v_g + u_g) / 256); + signed r1 = clamp_rgb((tmp1 + v_r) / 256); + + rgb_ptr[(i-left)*rgb_stride] = r1; + rgb_ptr[(i-left)*rgb_stride+1] = g1; + rgb_ptr[(i-left)*rgb_stride+2] = b1; + } + } +} + + static int gralloc_unlock(gralloc_module_t const* module, buffer_handle_t handle) { @@ -943,8 +1029,7 @@ static int gralloc_unlock(gralloc_module_t const* module, char *tmpBuf = new char[cb->lockedWidth * cb->lockedHeight * bpp]; if (cb->frameworkFormat == HAL_PIXEL_FORMAT_YV12 || cb->frameworkFormat == HAL_PIXEL_FORMAT_YCbCr_420_888) { - // bpp should be 2 - yv12_to_rgb565(tmpBuf, (char*)cpu_addr, cb->width, cb->height, cb->lockedLeft, + yv12_to_rgb888(tmpBuf, (char*)cpu_addr, cb->width, cb->height, cb->lockedLeft, cb->lockedTop, cb->lockedLeft+cb->lockedWidth-1, cb->lockedTop+cb->lockedHeight-1); } else { int dst_line_len = cb->lockedWidth * bpp; @@ -970,10 +1055,10 @@ static int gralloc_unlock(gralloc_module_t const* module, char* rgbBuf = 0; if (cb->frameworkFormat == HAL_PIXEL_FORMAT_YV12 || cb->frameworkFormat == HAL_PIXEL_FORMAT_YCbCr_420_888) { - // for this format, we need to conver to RGB565 format + // for this format, we need to convert to RGB888 format // before updating host - rgbBuf = new char[cb->width * cb->height * 2]; - yv12_to_rgb565(rgbBuf, (char*)cpu_addr, cb->width, cb->height, 0, 0, cb->width-1, cb->height-1); + rgbBuf = new char[cb->width * cb->height * 3]; + yv12_to_rgb888(rgbBuf, (char*)cpu_addr, cb->width, cb->height, 0, 0, cb->width-1, cb->height-1); rgb_addr = rgbBuf; }