[FFmpeg-devel] [PATCH]ffplay 2/2: Fix subtitle rendering for special cases

Björn Axelsson gecko
Sun Feb 1 23:19:37 CET 2009


Second subtitle-related patch.

The ffplay.c subtitle renderer (blend_subrect) fails to handle some of the
special cases with odd widths, odd heights and/or odd positions. For
example it could insert an empty line, wraparound the subrect one pixel
vertically, misalign the UV components and generally make a mess of things.

This fix could have been smaller, since I didn't care to track down the
original error in the offset calculations. Instead I replaced the
calculations with an arguably simpler and seemingly more correct
implementation.

A sample that works better with this patch is
http://samples.mplayerhq.hu/MPEG-VOB/ClosedCaptions/Starship_Troopers.vob

-- 
Bj?rn Axelsson
-------------- next part --------------
Index: ffplay.c
===================================================================
--- ffplay.c.orig	2009-02-01 21:23:05.000000000 +0100
+++ ffplay.c	2009-02-01 21:23:11.000000000 +0100
@@ -434,8 +434,9 @@
 
 static void blend_subrect(AVPicture *dst, const AVSubtitleRect *rect, int imgw, int imgh)
 {
-    int wrap, wrap3, width2, skip2;
     int y, u, v, a, u1, v1, a1, w, h;
+    uint8_t *lum0, *cb0, *cr0;
+    const uint8_t *p0;
     uint8_t *lum, *cb, *cr;
     const uint8_t *p;
     const uint32_t *pal;
@@ -445,22 +446,13 @@
     dsth = av_clip(rect->h, 0, imgh);
     dstx = av_clip(rect->x, 0, imgw - dstw);
     dsty = av_clip(rect->y, 0, imgh - dsth);
-    lum = dst->data[0] + dsty * dst->linesize[0];
-    cb = dst->data[1] + (dsty >> 1) * dst->linesize[1];
-    cr = dst->data[2] + (dsty >> 1) * dst->linesize[2];
-
-    width2 = (dstw + 1) >> 1;
-    skip2 = dstx >> 1;
-    wrap = dst->linesize[0];
-    wrap3 = rect->pict.linesize[0];
-    p = rect->pict.data[0];
+    lum = lum0 = dst->data[0] + dsty * dst->linesize[0] + dstx;
+    cb  = cb0  = dst->data[1] + (dsty >> 1) * dst->linesize[1] + (dstx >> 1);
+    cr  = cr0  = dst->data[2] + (dsty >> 1) * dst->linesize[2] + (dstx >> 1);
+    p   = p0   = rect->pict.data[0];
     pal = (const uint32_t *)rect->pict.data[1];  /* Now in YCrCb! */
 
     if (dsty & 1) {
-        lum += dstx;
-        cb += skip2;
-        cr += skip2;
-
         if (dstx & 1) {
             YUVA_IN(y, u, v, a, p, pal);
             lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
@@ -496,35 +488,33 @@
             cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
             cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
         }
-        p += wrap3 + (wrap3 - dstw * BPP);
-        lum += wrap + (wrap - dstw - dstx);
-        cb += dst->linesize[1] - width2 - skip2;
-        cr += dst->linesize[2] - width2 - skip2;
+        p0   += rect->pict.linesize[0];
+        lum0 += dst->linesize[0];
+        cb0  += dst->linesize[1];
+        cr0  += dst->linesize[2];
     }
     for(h = dsth - (dsty & 1); h >= 2; h -= 2) {
-        lum += dstx;
-        cb += skip2;
-        cr += skip2;
-
+        lum = lum0;
+        cb  = cb0;
+        cr  = cr0;
+        p   = p0;
         if (dstx & 1) {
             YUVA_IN(y, u, v, a, p, pal);
             u1 = u;
             v1 = v;
             a1 = a;
             lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
-            p += wrap3;
-            lum += wrap;
-            YUVA_IN(y, u, v, a, p, pal);
+            YUVA_IN(y, u, v, a, p + rect->pict.linesize[0], pal);
             u1 += u;
             v1 += v;
             a1 += a;
-            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
+            lum[dst->linesize[0]] = ALPHA_BLEND(a, lum[dst->linesize[0]], y, 0);
             cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
             cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
             cb++;
             cr++;
-            p += -wrap3 + BPP;
-            lum += -wrap + 1;
+            p += BPP;
+            lum++;
         }
         for(w = dstw - (dstx & 1); w >= 2; w -= 2) {
             YUVA_IN(y, u, v, a, p, pal);
@@ -538,28 +528,25 @@
             v1 += v;
             a1 += a;
             lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
-            p += wrap3;
-            lum += wrap;
 
-            YUVA_IN(y, u, v, a, p, pal);
+            YUVA_IN(y, u, v, a, p + rect->pict.linesize[0], pal);
             u1 += u;
             v1 += v;
             a1 += a;
-            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
+            lum[dst->linesize[0]] = ALPHA_BLEND(a, lum[dst->linesize[0]], y, 0);
 
-            YUVA_IN(y, u, v, a, p + BPP, pal);
+            YUVA_IN(y, u, v, a, p + BPP + rect->pict.linesize[0], pal);
             u1 += u;
             v1 += v;
             a1 += a;
-            lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
-
+            lum[dst->linesize[0] + 1] = ALPHA_BLEND(a, lum[dst->linesize[0] + 1], y, 0);
             cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 2);
             cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 2);
 
             cb++;
             cr++;
-            p += -wrap3 + 2 * BPP;
-            lum += -wrap + 2;
+            p += 2 * BPP;
+            lum += 2;
         }
         if (w) {
             YUVA_IN(y, u, v, a, p, pal);
@@ -567,65 +554,59 @@
             v1 = v;
             a1 = a;
             lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
-            p += wrap3;
-            lum += wrap;
-            YUVA_IN(y, u, v, a, p, pal);
+            YUVA_IN(y, u, v, a, p + rect->pict.linesize[0], pal);
             u1 += u;
             v1 += v;
             a1 += a;
-            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
+            lum[dst->linesize[0]] = ALPHA_BLEND(a, lum[dst->linesize[0]], y, 0);
             cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
             cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
             cb++;
             cr++;
-            p += -wrap3 + BPP;
-            lum += -wrap + 1;
+            p += BPP;
+            lum++;
         }
-        p += wrap3 + (wrap3 - dstw * BPP);
-        lum += wrap + (wrap - dstw - dstx);
-        cb += dst->linesize[1] - width2 - skip2;
-        cr += dst->linesize[2] - width2 - skip2;
+        p0   += rect->pict.linesize[0] << 1;
+        lum0 += dst->linesize[0] << 1;
+        cb0  += dst->linesize[1];
+        cr0  += dst->linesize[2];
     }
     /* handle odd height */
     if (h) {
-        lum += dstx;
-        cb += skip2;
-        cr += skip2;
-
         if (dstx & 1) {
-            YUVA_IN(y, u, v, a, p, pal);
-            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
-            cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
-            cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
-            cb++;
-            cr++;
-            lum++;
-            p += BPP;
+            YUVA_IN(y, u, v, a, p0, pal);
+            lum0[0] = ALPHA_BLEND(a, lum0[0], y, 0);
+            cb0[0]  = ALPHA_BLEND(a >> 2, cb0[0], u, 0);
+            cr0[0]  = ALPHA_BLEND(a >> 2, cr0[0], v, 0);
+            cb0++;
+            cr0++;
+            lum0++;
+            p0 += BPP;
         }
         for(w = dstw - (dstx & 1); w >= 2; w -= 2) {
-            YUVA_IN(y, u, v, a, p, pal);
+            YUVA_IN(y, u, v, a, p0, pal);
             u1 = u;
             v1 = v;
             a1 = a;
-            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
+            lum0[0] = ALPHA_BLEND(a, lum0[0], y, 0);
 
-            YUVA_IN(y, u, v, a, p + BPP, pal);
+            YUVA_IN(y, u, v, a, p0 + BPP, pal);
             u1 += u;
             v1 += v;
             a1 += a;
-            lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
-            cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u, 1);
-            cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v, 1);
-            cb++;
-            cr++;
-            p += 2 * BPP;
-            lum += 2;
+            lum0[1] = ALPHA_BLEND(a, lum0[1], y, 0);
+            cb0[0]  = ALPHA_BLEND(a1 >> 2, cb0[0], u, 1);
+            cr0[0]  = ALPHA_BLEND(a1 >> 2, cr0[0], v, 1);
+            cb0++;
+            cr0++;
+            p0 += 2 * BPP;
+            lum0 += 2;
         }
         if (w) {
-            YUVA_IN(y, u, v, a, p, pal);
-            lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
-            cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
-            cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
+            YUVA_IN(y, u, v, a, p0, pal);
+            lum0[0] = ALPHA_BLEND(a, lum0[0], y, 0);
+            cb0[0]  = ALPHA_BLEND(a >> 2, cb0[0], u, 0);
+            cr0[0]  = ALPHA_BLEND(a >> 2, cr0[0], v, 0);
         }
     }
 }



More information about the ffmpeg-devel mailing list