Merge the csc_matrix() function into image_convert_rgb_to_yuv() to avoid unnecessary copies of the matrix. Signed-off-by: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx> --- src/gen-image.c | 105 +++++++++++++++++++++--------------------------- 1 file changed, 46 insertions(+), 59 deletions(-) diff --git a/src/gen-image.c b/src/gen-image.c index d2d4870a699a..2f854634a986 100644 --- a/src/gen-image.c +++ b/src/gen-image.c @@ -758,9 +758,37 @@ static void image_convert_rgb_to_rgb(const struct image *input, } /* RGB to YUV */ -static void csc_matrix(enum v4l2_ycbcr_encoding encoding, - enum v4l2_quantization quantization, - int (*matrix)[3][3]) +static void csc_rgb_to_yuv(const int ccm[3][3], bool full_range, + const uint8_t rgb[3], uint8_t ycbcr[3]) +{ + int y_min = full_range ? 0 : 16; + int y_max = full_range ? 255 : 235; + int cbcr_min = full_range ? 0 : 16; + int cbcr_max = full_range ? 255 : 240; + int div = 1 << 11; + int r, g, b; + int y, cb, cr; + + r = rgb[0]; + g = rgb[1]; + b = rgb[2]; + + y = (ccm[0][0] * r + ccm[0][1] * g + ccm[0][2] * b + y_min * div + div / 2) / div; + cb = (ccm[1][0] * r + ccm[1][1] * g + ccm[1][2] * b + 128 * div + div / 2) / div; + cr = (ccm[2][0] * r + ccm[2][1] * g + ccm[2][2] * b + 128 * div + div / 2) / div; + +#define CLAMP(x, low, high) \ + ((x) < (low) ? (low) : ( (x) > (high) ? (high) : (x) )) + + ycbcr[0] = CLAMP(y, y_min, y_max); + ycbcr[1] = CLAMP(cb, cbcr_min, cbcr_max); + ycbcr[2] = CLAMP(cr, cbcr_min, cbcr_max); +} + +static void image_convert_rgb_to_yuv(const struct image *input, + struct image *output, + const struct format_info *format, + const struct csc_params *params) { /* * The value of the coefficients has been reverse-engineered by @@ -802,76 +830,35 @@ static void csc_matrix(enum v4l2_ycbcr_encoding encoding, { 1047, -951, -96 }, }; - bool full = quantization == V4L2_QUANTIZATION_FULL_RANGE; - unsigned int i; - const int (*m)[3][3]; - - switch (encoding) { - case V4L2_YCBCR_ENC_601: - default: - m = full ? &bt601_full : &bt601; - break; - case V4L2_YCBCR_ENC_709: - m = full ? &rec709_full : &rec709; - break; - } - - for (i = 0; i < ARRAY_SIZE(*m); ++i) - memcpy((*matrix)[i], (*m)[i], sizeof((*m)[i])); -} - -static void csc_rgb_to_yuv(int m[3][3], enum v4l2_quantization quantization, - const uint8_t rgb[3], uint8_t ycbcr[3]) -{ - bool full = quantization == V4L2_QUANTIZATION_FULL_RANGE; - int y_min = full ? 0 : 16; - int y_max = full ? 255 : 235; - int cbcr_min = full ? 0 : 16; - int cbcr_max = full ? 255 : 240; - int div = 1 << 11; - int r, g, b; - int y, cb, cr; - - r = rgb[0]; - g = rgb[1]; - b = rgb[2]; - - y = (m[0][0] * r + m[0][1] * g + m[0][2] * b + y_min * div + div / 2) / div; - cb = (m[1][0] * r + m[1][1] * g + m[1][2] * b + 128 * div + div / 2) / div; - cr = (m[2][0] * r + m[2][1] * g + m[2][2] * b + 128 * div + div / 2) / div; - -#define CLAMP(x, low, high) \ - ((x) < (low) ? (low) : ( (x) > (high) ? (high) : (x) )) - - ycbcr[0] = CLAMP(y, y_min, y_max); - ycbcr[1] = CLAMP(cb, cbcr_min, cbcr_max); - ycbcr[2] = CLAMP(cr, cbcr_min, cbcr_max); -} - -static void image_convert_rgb_to_yuv(const struct image *input, - struct image *output, - const struct format_info *format, - const struct csc_params *params) -{ - int matrix[3][3]; + bool full_range = params->quantization == V4L2_QUANTIZATION_FULL_RANGE; + const int (*matrix)[3][3]; const uint8_t *idata = input->data; uint8_t *odata = output->data; unsigned int x; unsigned int y; - csc_matrix(params->encoding, params->quantization, &matrix); + switch (params->encoding) { + case V4L2_YCBCR_ENC_601: + default: + matrix = full_range ? &bt601_full : &bt601; + break; + case V4L2_YCBCR_ENC_709: + matrix = full_range ? &rec709_full : &rec709; + break; + } for (y = 0; y < output->height; ++y) { - for (x = 0; x < output->width; ++x) { - csc_rgb_to_yuv(matrix, params->quantization, + for (x = 0; x < output->width; ++x) + csc_rgb_to_yuv(*matrix, full_range, &idata[3*x], &odata[3*x]); - } + if (format->yuv.xsub == 2) { for (x = 1; x < output->width - 1; x += 2) { odata[3*x + 1] = (odata[3*(x-1) + 1] + odata[3*(x+1) + 1]) / 2; odata[3*x + 2] = (odata[3*(x-1) + 2] + odata[3*(x+1) + 2]) / 2; } } + idata += 3 * output->width; odata += 3 * output->width; } -- Regards, Laurent Pinchart