dvbsuboverlay: Fix more of the blending, so it looks quite good now
authorMart Raudsepp <mart.raudsepp@collabora.co.uk>
Wed, 1 Dec 2010 07:59:14 +0000 (09:59 +0200)
committerEdward Hervey <edward.hervey@collabora.co.uk>
Wed, 8 Dec 2010 15:30:10 +0000 (16:30 +0100)
* libdvbsub gives us alpha channel already, not transparency level, so
don't do another "alpha = 255 - alpha", this is done by libdvbsub.
* Fix alpha channel handling in interpolation - assrender had an additional
1bpp alpha bitmap as a possible mask, we don't. So don't use the palette
index array as alpha values; bug from quick code porting long ago to
changing pixel colors (assrender has a single pixel color for whole
regions or something, unlike dvbsub, which has indexed colors).
* Don't forget to reassign our YUV and other local pixel color variables
after shifting to work on the bottom part of a 2x2 subsample block, or
it's obviously very blocky.

Remaining issues in blending:

* Should probably be interpolating or doing something else useful with the
resulting U and V channels, so that most of the source pixel UV values would
actually be actually cared about, except for just one out of possibly four.

* Don't convert AYUV to ARGB in libdvbsub, and then back from ARGB to AYUV in
dvbsuboverlay for no reason

* Re-factor the whole thing to something more like textoverlay blending
* Related to that, perhaps cache the current spu in a good format for quick
blending on each frame, after which the more often called blending parts
might become more straightforward

gst/dvbsuboverlay/gstdvbsuboverlay.c

index 71b3119..5dbdf61 100644 (file)
@@ -566,8 +566,8 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer)
 {
   guint counter;
   DVBSubtitleRect *sub_region;
-  gint alpha, r, g, b, k, k2;
-  gint Y, U, V;
+  gint alpha, alpha2, r, g, b, r2, g2, b2, k, k2;
+  gint Y, U, V, Y2, U2, V2;
   guint32 color, color2;
   const guint8 *src;
   guint8 *dst_y, *dst_u, *dst_v;
@@ -631,12 +631,12 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer)
         buffer->data + v_offset + ((sub_region->y + 1) / 2) * v_stride +
         (sub_region->x + 1) / 2;
 
+    /* FIXME: This whole blending business will need a refactor */
+    /* FIXME: Also interpolation for Cr and Cb channels missing */
     for (y = 0; y < h - 1; y += 2) {
       for (x = 0; x < w - 1; x += 2) {
-        /* FIXME: Completely wrong blending code */
         color = sub_region->pict.palette[src[0]];
-        color2 = sub_region->pict.palette[src[1]];
-        alpha = 255 - ((color >> 24) & 0xff);
+        alpha = (color >> 24) & 0xff;
         r = (color >> 16) & 0xff;
         g = (color >> 8) & 0xff;
         b = color & 0xff;
@@ -645,24 +645,54 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer)
         U = rgb_to_u (r, g, b);
         V = rgb_to_v (r, g, b);
 
-        k = src[0] * alpha / 255;
+        color2 = sub_region->pict.palette[src[1]];
+        alpha2 = (color2 >> 24) & 0xff;
+        r2 = (color2 >> 16) & 0xff;
+        g2 = (color2 >> 8) & 0xff;
+        b2 = color2 & 0xff;
+
+        Y2 = rgb_to_y (r2, g2, b2);
+        U2 = rgb_to_u (r2, g2, b2);
+        V2 = rgb_to_v (r2, g2, b2);
+
+        k = alpha;
         k2 = k;
         dst_y[0] = (k * Y + (255 - k) * dst_y[0]) / 255;
 
-        k = src[1] * alpha / 255;
+        k = alpha2;
         k2 += k;
-        dst_y[1] = (k * Y + (255 - k) * dst_y[1]) / 255;
+        dst_y[1] = (k * Y2 + (255 - k) * dst_y[1]) / 255;
 
         src += src_stride;
         dst_y += y_stride;
 
-        k = src[0] * alpha / 255;
+        color = sub_region->pict.palette[src[0]];
+        alpha = (color >> 24) & 0xff;
+        r = (color >> 16) & 0xff;
+        g = (color >> 8) & 0xff;
+        b = color & 0xff;
+
+        Y = rgb_to_y (r, g, b);
+        U = rgb_to_u (r, g, b);
+        V = rgb_to_v (r, g, b);
+
+        color2 = sub_region->pict.palette[src[1]];
+        alpha2 = (color2 >> 24) & 0xff;
+        r2 = (color2 >> 16) & 0xff;
+        g2 = (color2 >> 8) & 0xff;
+        b2 = color2 & 0xff;
+
+        Y2 = rgb_to_y (r2, g2, b2);
+        U2 = rgb_to_u (r2, g2, b2);
+        V2 = rgb_to_v (r2, g2, b2);
+
+        k = alpha;
         k2 += k;
         dst_y[0] = (k * Y + (255 - k) * dst_y[0]) / 255;
 
-        k = src[1] * alpha / 255;
+        k = alpha2;
         k2 += k;
-        dst_y[1] = (k * Y + (255 - k) * dst_y[1]) / 255;
+        dst_y[1] = (k * Y2 + (255 - k) * dst_y[1]) / 255;
 
         k2 /= 4;
         dst_u[0] = (k2 * U + (255 - k2) * dst_u[0]) / 255;
@@ -675,10 +705,8 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer)
       }
 
       if (x < w) {
-        /* FIXME: Completely wrong blending code */
         color = sub_region->pict.palette[src[0]];
-        color2 = sub_region->pict.palette[src[1]];
-        alpha = 255 - ((color >> 24) & 0xff);
+        alpha = (color >> 24) & 0xff;
         r = (color >> 16) & 0xff;
         g = (color >> 8) & 0xff;
         b = color & 0xff;
@@ -687,14 +715,14 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer)
         U = rgb_to_u (r, g, b);
         V = rgb_to_v (r, g, b);
 
-        k = src[0] * alpha / 255;
+        k = alpha;
         k2 = k;
         dst_y[0] = (k * Y + (255 - k) * dst_y[0]) / 255;
 
         src += src_stride;
         dst_y += y_stride;
 
-        k = src[0] * alpha / 255;
+        k = alpha;
         k2 += k;
         dst_y[0] = (k * Y + (255 - k) * dst_y[0]) / 255;
 
@@ -716,10 +744,8 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer)
 
     if (y < h) {
       for (x = 0; x < w - 1; x += 2) {
-        /* FIXME: Completely wrong blending code */
         color = sub_region->pict.palette[src[0]];
-        color2 = sub_region->pict.palette[src[1]];
-        alpha = 255 - ((color >> 24) & 0xff);
+        alpha = (color >> 24) & 0xff;
         r = (color >> 16) & 0xff;
         g = (color >> 8) & 0xff;
         b = color & 0xff;
@@ -728,13 +754,23 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer)
         U = rgb_to_u (r, g, b);
         V = rgb_to_v (r, g, b);
 
-        k = src[0] * alpha / 255;
+        color2 = sub_region->pict.palette[src[1]];
+        alpha2 = (color2 >> 24) & 0xff;
+        r2 = (color2 >> 16) & 0xff;
+        g2 = (color2 >> 8) & 0xff;
+        b2 = color2 & 0xff;
+
+        Y2 = rgb_to_y (r2, g2, b2);
+        U2 = rgb_to_u (r2, g2, b2);
+        V2 = rgb_to_v (r2, g2, b2);
+
+        k = alpha;
         k2 = k;
         dst_y[0] = (k * Y + (255 - k) * dst_y[0]) / 255;
 
-        k = src[1] * alpha / 255;
+        k = alpha2;
         k2 += k;
-        dst_y[1] = (k * Y + (255 - k) * dst_y[1]) / 255;
+        dst_y[1] = (k * Y2 + (255 - k) * dst_y[1]) / 255;
 
         k2 /= 2;
         dst_u[0] = (k2 * U + (255 - k2) * dst_u[0]) / 255;
@@ -747,10 +783,8 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer)
       }
 
       if (x < w) {
-        /* FIXME: Completely wrong blending code */
         color = sub_region->pict.palette[src[0]];
-        color2 = sub_region->pict.palette[src[1]];
-        alpha = 255 - ((color >> 24) & 0xff);
+        alpha = (color >> 24) & 0xff;
         r = (color >> 16) & 0xff;
         g = (color >> 8) & 0xff;
         b = color & 0xff;
@@ -759,7 +793,7 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer)
         U = rgb_to_u (r, g, b);
         V = rgb_to_v (r, g, b);
 
-        k = src[0] * alpha / 255;
+        k = alpha;
         k2 = k;
         dst_y[0] = (k * Y + (255 - k) * dst_y[0]) / 255;