[FFmpeg-devel] [PATCH 2/4] swscale/rgb2rgb: improve chroma conversion in ff_rgb24toyv12_c

Ramiro Polla ramiro.polla at gmail.com
Wed Aug 28 23:43:01 EEST 2024


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.
---
 libswscale/rgb2rgb_template.c | 88 ++++++++++++++++-------------------
 1 file changed, 41 insertions(+), 47 deletions(-)

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;
     }
 }
 
-- 
2.30.2



More information about the ffmpeg-devel mailing list