aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRamiro Polla <ramiro.polla@gmail.com>2024-08-28 19:51:55 +0200
committerRamiro Polla <ramiro.polla@gmail.com>2024-09-06 23:06:32 +0200
commit3604b2403c86b0c9f7d26fcea875e0a0739b7b29 (patch)
treeeceab318db547e6b300ac74f4fb9b757b1109f3a
parentd8848325a61813f81db7d2495f7d1fa41d7beb22 (diff)
downloadffmpeg-3604b2403c86b0c9f7d26fcea875e0a0739b7b29.tar.gz
swscale/rgb2rgb: improve chroma conversion in ff_rgb24toyv12_c
The current code subsamples by dropping 3/4 pixels to calculate the chroma components. This commit calculates the average of 4 rgb pixels before calculating the chroma components, putting it in line with the mmxext implementation.
-rw-r--r--libswscale/rgb2rgb.h2
-rw-r--r--libswscale/rgb2rgb_template.c88
2 files changed, 41 insertions, 49 deletions
diff --git a/libswscale/rgb2rgb.h b/libswscale/rgb2rgb.h
index f3951d523e..e3b0883901 100644
--- a/libswscale/rgb2rgb.h
+++ b/libswscale/rgb2rgb.h
@@ -121,8 +121,6 @@ extern void (*yuv422ptouyvy)(const uint8_t *ysrc, const uint8_t *usrc, const uin
/**
* Height should be a multiple of 2 and width should be a multiple of 2.
* (If this is a problem for anyone then tell me, and I will fix it.)
- * Chrominance data is only taken from every second line, others are ignored.
- * FIXME: Write high quality version.
*/
extern void (*ff_rgb24toyv12)(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
int width, int height,
diff --git a/libswscale/rgb2rgb_template.c b/libswscale/rgb2rgb_template.c
index 42c69801ba..32d90d44fe 100644
--- a/libswscale/rgb2rgb_template.c
+++ b/libswscale/rgb2rgb_template.c
@@ -642,9 +642,6 @@ static inline void uyvytoyv12_c(const uint8_t *src, uint8_t *ydst,
/**
* Height should be a multiple of 2 and width should be a multiple of 2.
* (If this is a problem for anyone then tell me, and I will fix it.)
- * Chrominance data is only taken from every second line,
- * others are ignored in the C version.
- * FIXME: Write HQ version.
*/
void ff_rgb24toyv12_c(const uint8_t *src, uint8_t *ydst, uint8_t *udst,
uint8_t *vdst, int width, int height, int lumStride,
@@ -655,55 +652,52 @@ void ff_rgb24toyv12_c(const uint8_t *src, uint8_t *ydst, uint8_t *udst,
int32_t rv = rgb2yuv[RV_IDX], gv = rgb2yuv[GV_IDX], bv = rgb2yuv[BV_IDX];
int y;
const int chromWidth = width >> 1;
+ const uint8_t *src1 = src;
+ const uint8_t *src2 = src1 + srcStride;
+ uint8_t *ydst1 = ydst;
+ uint8_t *ydst2 = ydst + lumStride;
for (y = 0; y < height; y += 2) {
int i;
for (i = 0; i < chromWidth; i++) {
- unsigned int b = src[6 * i + 0];
- unsigned int g = src[6 * i + 1];
- unsigned int r = src[6 * i + 2];
-
- unsigned int Y = ((ry * r + gy * g + by * b) >> RGB2YUV_SHIFT) + 16;
- unsigned int V = ((rv * r + gv * g + bv * b) >> RGB2YUV_SHIFT) + 128;
- unsigned int U = ((ru * r + gu * g + bu * b) >> RGB2YUV_SHIFT) + 128;
-
- udst[i] = U;
- vdst[i] = V;
- ydst[2 * i] = Y;
-
- b = src[6 * i + 3];
- g = src[6 * i + 4];
- r = src[6 * i + 5];
-
- Y = ((ry * r + gy * g + by * b) >> RGB2YUV_SHIFT) + 16;
- ydst[2 * i + 1] = Y;
+ unsigned int b11 = src1[6 * i + 0];
+ unsigned int g11 = src1[6 * i + 1];
+ unsigned int r11 = src1[6 * i + 2];
+ unsigned int b12 = src1[6 * i + 3];
+ unsigned int g12 = src1[6 * i + 4];
+ unsigned int r12 = src1[6 * i + 5];
+ unsigned int b21 = src2[6 * i + 0];
+ unsigned int g21 = src2[6 * i + 1];
+ unsigned int r21 = src2[6 * i + 2];
+ unsigned int b22 = src2[6 * i + 3];
+ unsigned int g22 = src2[6 * i + 4];
+ unsigned int r22 = src2[6 * i + 5];
+
+ unsigned int Y11 = ((ry * r11 + gy * g11 + by * b11) >> RGB2YUV_SHIFT) + 16;
+ unsigned int Y12 = ((ry * r12 + gy * g12 + by * b12) >> RGB2YUV_SHIFT) + 16;
+ unsigned int Y21 = ((ry * r21 + gy * g21 + by * b21) >> RGB2YUV_SHIFT) + 16;
+ unsigned int Y22 = ((ry * r22 + gy * g22 + by * b22) >> RGB2YUV_SHIFT) + 16;
+
+ unsigned int bx = (b11 + b12 + b21 + b22) >> 2;
+ unsigned int gx = (g11 + g12 + g21 + g22) >> 2;
+ unsigned int rx = (r11 + r12 + r21 + r22) >> 2;
+
+ unsigned int U = ((ru * rx + gu * gx + bu * bx) >> RGB2YUV_SHIFT) + 128;
+ unsigned int V = ((rv * rx + gv * gx + bv * bx) >> RGB2YUV_SHIFT) + 128;
+
+ ydst1[2 * i + 0] = Y11;
+ ydst1[2 * i + 1] = Y12;
+ ydst2[2 * i + 0] = Y21;
+ ydst2[2 * i + 1] = Y22;
+ udst[i] = U;
+ vdst[i] = V;
}
- ydst += lumStride;
- src += srcStride;
-
- if (y+1 == height)
- break;
-
- for (i = 0; i < chromWidth; i++) {
- unsigned int b = src[6 * i + 0];
- unsigned int g = src[6 * i + 1];
- unsigned int r = src[6 * i + 2];
-
- unsigned int Y = ((ry * r + gy * g + by * b) >> RGB2YUV_SHIFT) + 16;
-
- ydst[2 * i] = Y;
-
- b = src[6 * i + 3];
- g = src[6 * i + 4];
- r = src[6 * i + 5];
-
- Y = ((ry * r + gy * g + by * b) >> RGB2YUV_SHIFT) + 16;
- ydst[2 * i + 1] = Y;
- }
- udst += chromStride;
- vdst += chromStride;
- ydst += lumStride;
- src += srcStride;
+ src1 += srcStride * 2;
+ src2 += srcStride * 2;
+ ydst1 += lumStride * 2;
+ ydst2 += lumStride * 2;
+ udst += chromStride;
+ vdst += chromStride;
}
}