commit 13b938c11711b5a90a117652772e7ebe5c696ba3
Author: Arnaud Vrac <avrac@freebox.fr>
Date:   Tue Aug 7 15:12:12 2012

    video-blend: use OVER operator for blending
    
    Also implement missing premultiplied/non-premultiplied combinations

diff --git a/gst-libs/gst/video/video-blend.c b/gst-libs/gst/video/video-blend.c
index 5816183..b6242fd 100644
--- a/gst-libs/gst/video/video-blend.c
+++ b/gst-libs/gst/video/video-blend.c
@@ -136,14 +136,29 @@ matrix_yuv_to_rgb (guint8 * tmpline, guint width)
   }
 }
 
-#define BLEND00(ret, alpha, v0, v1) \
+#define BLENDA(ret, aa, ab) \
 G_STMT_START { \
-  ret = (v0 * alpha + v1 * (255 - alpha)) / 255; \
+  ret = aa + ab * (255 - aa) / 255; \
 } G_STMT_END
 
-#define BLEND10(ret, alpha, v0, v1) \
+#define BLEND00(ret, aa, ca, ab, cb) \
 G_STMT_START { \
-  ret = v0 + (v1 * (255 - alpha)) / 255; \
+  ret = (ca * aa + cb * ab * (255 - aa) / 255) / 255; \
+} G_STMT_END
+
+#define BLEND10(ret, aa, ca, ab, cb) \
+G_STMT_START { \
+  ret = ca + cb * ab * (255 - aa) / 255; \
+} G_STMT_END
+
+#define BLEND01(ret, aa, ca, ab, cb) \
+G_STMT_START { \
+  ret = ca * aa / 255 + cb * (255 - aa) / 255; \
+} G_STMT_END
+
+#define BLEND11(ret, aa, ca, ab, cb) \
+G_STMT_START { \
+  ret = ca + cb * (255 - aa) / 255; \
 } G_STMT_END
 
 /* returns newly-allocated buffer, which caller must unref */
@@ -261,10 +276,6 @@ gst_video_blend (GstVideoFrame * dest,
   src_premultiplied_alpha =
       GST_VIDEO_INFO_FLAGS (&src->info) & GST_VIDEO_FLAG_PREMULTIPLIED_ALPHA;
 
-  /* we do no support writing to premultiplied alpha, though that should
-     just be a matter of adding blenders below (BLEND01 and BLEND11) */
-  g_return_val_if_fail (!dest_premultiplied_alpha, FALSE);
-
   src_width = GST_VIDEO_FRAME_WIDTH (src);
   src_height = GST_VIDEO_FRAME_HEIGHT (src);
 
@@ -331,24 +342,27 @@ gst_video_blend (GstVideoFrame * dest,
 
     /* Here dest and src are both either in AYUV or ARGB
      * TODO: Make the orc version working properly*/
-#define BLENDLOOP(blender,alpha_val,alpha_scale)                                  \
-  do {                                                                            \
-    for (j = 0; j < src_width * 4; j += 4) {                                      \
-      guint8 alpha;                                                               \
-                                                                                  \
-      alpha = (tmpsrcline[j] * alpha_val) / alpha_scale;                          \
-                                                                                  \
-      blender (tmpdestline[j + 1], alpha, tmpsrcline[j + 1], tmpdestline[j + 1]); \
-      blender (tmpdestline[j + 2], alpha, tmpsrcline[j + 2], tmpdestline[j + 2]); \
-      blender (tmpdestline[j + 3], alpha, tmpsrcline[j + 3], tmpdestline[j + 3]); \
-    }                                                                             \
+#define BLENDLOOP(blender,alpha_val,alpha_scale)                                       \
+  do {                                                                                 \
+    for (j = 0; j < src_width * 4; j += 4) {                                           \
+      guint8 asrc;                                                                     \
+      guint8 adst;                                                                     \
+                                                                                       \
+      asrc = (tmpsrcline[j] * alpha_val) / alpha_scale;                                \
+      adst = tmpdestline[j];                                                           \
+                                                                                       \
+      BLENDA (tmpdestline[j], asrc, adst);                                             \
+      blender (tmpdestline[j + 1], asrc, tmpsrcline[j + 1], adst, tmpdestline[j + 1]); \
+      blender (tmpdestline[j + 2], asrc, tmpsrcline[j + 2], adst, tmpdestline[j + 2]); \
+      blender (tmpdestline[j + 3], asrc, tmpsrcline[j + 3], adst, tmpdestline[j + 3]); \
+    }                                                                                  \
   } while(0)
 
     if (G_LIKELY (global_alpha == 1.0)) {
       if (src_premultiplied_alpha && dest_premultiplied_alpha) {
-        /* BLENDLOOP (BLEND11, 1, 1); */
+        BLENDLOOP (BLEND11, 1, 1);
       } else if (!src_premultiplied_alpha && dest_premultiplied_alpha) {
-        /* BLENDLOOP (BLEND01, 1, 1); */
+        BLENDLOOP (BLEND01, 1, 1);
       } else if (src_premultiplied_alpha && !dest_premultiplied_alpha) {
         BLENDLOOP (BLEND10, 1, 1);
       } else {
@@ -356,9 +370,9 @@ gst_video_blend (GstVideoFrame * dest,
       }
     } else {
       if (src_premultiplied_alpha && dest_premultiplied_alpha) {
-        /* BLENDLOOP (BLEND11, global_alpha_val, 256); */
+        BLENDLOOP (BLEND11, global_alpha_val, 256);
       } else if (!src_premultiplied_alpha && dest_premultiplied_alpha) {
-        /* BLENDLOOP (BLEND01, global_alpha_val, 256); */
+        BLENDLOOP (BLEND01, global_alpha_val, 256);
       } else if (src_premultiplied_alpha && !dest_premultiplied_alpha) {
         BLENDLOOP (BLEND10, global_alpha_val, 256);
       } else {
