From 0e74e190adecd209d142669cd200e2822fcec97e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 12 Mar 2020 15:18:22 +0200 Subject: [PATCH] video-blend: Add support for blending on top of 16 bit per component formats With this we can support every currently supported video format for blending. --- gst-libs/gst/video/video-blend.c | 101 ++++++++++++++++--------- gst-libs/gst/video/video-overlay-composition.h | 5 +- 2 files changed, 68 insertions(+), 38 deletions(-) diff --git a/gst-libs/gst/video/video-blend.c b/gst-libs/gst/video/video-blend.c index 097269f..3970990 100644 --- a/gst-libs/gst/video/video-blend.c +++ b/gst-libs/gst/video/video-blend.c @@ -269,10 +269,10 @@ gst_video_blend_scale_linear_RGBA (GstVideoInfo * src, GstBuffer * src_buffer, #define OVER11(alphaG, alphaA, colorA, alphaB, colorB, alphaD) \ ((colorA * alphaG + colorB * (255 - alphaA)) / 255) -#define BLENDC(op, global_alpha, aa, ca, ab, cb, dest_alpha) \ +#define BLENDC(op, max, global_alpha, aa, ca, ab, cb, dest_alpha) \ G_STMT_START { \ - int c = op(global_alpha, aa, ca, ab, cb, dest_alpha); \ - cb = MIN(c, 255); \ + int c = op((global_alpha), (aa), (ca), (ab), (cb), (dest_alpha)); \ + cb = MIN(c, (max)); \ } G_STMT_END @@ -295,6 +295,7 @@ gst_video_blend (GstVideoFrame * dest, gint src_xoff = 0, src_yoff = 0; guint8 *tmpdestline = NULL, *tmpsrcline = NULL; gboolean src_premultiplied_alpha, dest_premultiplied_alpha; + gint bpp; void (*matrix) (guint8 * tmpline, guint width); const GstVideoFormatInfo *sinfo, *dinfo, *dunpackinfo, *sunpackinfo; @@ -339,11 +340,12 @@ gst_video_blend (GstVideoFrame * dest, g_assert (GST_VIDEO_FORMAT_INFO_BITS (sunpackinfo) == 8); - if (GST_VIDEO_FORMAT_INFO_BITS (dunpackinfo) != 8) + if (GST_VIDEO_FORMAT_INFO_BITS (dunpackinfo) != 8 + && GST_VIDEO_FORMAT_INFO_BITS (dunpackinfo) != 16) goto unpack_format_not_supported; - tmpdestline = g_malloc (sizeof (guint8) * (dest_width + 8) * 4); - tmpsrcline = g_malloc (sizeof (guint8) * (src_width + 8) * 4); + /* Source is always 8 bit but destination might be 8 or 16 bit */ + bpp = 4 * (GST_VIDEO_FORMAT_INFO_BITS (dunpackinfo) / 8); matrix = matrix_identity; if (GST_VIDEO_INFO_IS_RGB (&src->info) != GST_VIDEO_INFO_IS_RGB (&dest->info)) { @@ -383,6 +385,9 @@ gst_video_blend (GstVideoFrame * dest, if (y + src_height > dest_height) src_height = dest_height - y; + tmpsrcline = g_malloc (sizeof (guint8) * (src_width + 8) * 4); + tmpdestline = g_malloc (sizeof (guint8) * (dest_width + 8) * bpp); + /* Mainloop doing the needed conversions, and blending */ for (i = y; i < y + src_height; i++, src_yoff++) { @@ -392,58 +397,86 @@ gst_video_blend (GstVideoFrame * dest, src_xoff, src_yoff, src_width); /* FIXME: use the x parameter of the unpack func once implemented */ - tmpdestline += 4 * x; + tmpdestline += bpp * x; matrix (tmpsrcline, src_width); -#define BLENDLOOP(op, alpha_val) \ +#define BLENDLOOP(op, dest_type, max, shift, alpha_val) \ G_STMT_START { \ for (j = 0; j < src_width * 4; j += 4) { \ - guint8 asrc, adst; \ - gint final_alpha; \ + guint asrc, adst; \ + guint final_alpha; \ + dest_type * dest = (dest_type *) tmpdestline; \ \ - asrc = tmpsrcline[j] * alpha_val / 255; \ - if (!asrc) \ + asrc = ((guint) tmpsrcline[j]) * alpha_val / 255; \ + asrc = asrc << shift; \ + if (asrc == 0) \ continue; \ \ - adst = tmpdestline[j]; \ - final_alpha = asrc + adst * (255 - asrc) / 255; \ - tmpdestline[j] = final_alpha; \ + adst = dest[j]; \ + final_alpha = asrc + adst * (max - asrc) / max; \ + dest[j] = final_alpha; \ if (final_alpha == 0) \ final_alpha = 1; \ \ - BLENDC (op, alpha_val, asrc, tmpsrcline[j + 1], adst, tmpdestline[j + 1], final_alpha); \ - BLENDC (op, alpha_val, asrc, tmpsrcline[j + 2], adst, tmpdestline[j + 2], final_alpha); \ - BLENDC (op, alpha_val, asrc, tmpsrcline[j + 3], adst, tmpdestline[j + 3], final_alpha); \ + BLENDC (op, max, alpha_val, asrc, tmpsrcline[j + 1] << shift, adst, dest[j + 1], final_alpha); \ + BLENDC (op, max, alpha_val, asrc, tmpsrcline[j + 2] << shift, adst, dest[j + 2], final_alpha); \ + BLENDC (op, max, alpha_val, asrc, tmpsrcline[j + 3] << shift, adst, dest[j + 3], final_alpha); \ } \ } G_STMT_END - if (G_LIKELY (global_alpha == 1.0)) { - if (src_premultiplied_alpha && dest_premultiplied_alpha) { - BLENDLOOP (OVER11, 255); - } else if (!src_premultiplied_alpha && dest_premultiplied_alpha) { - BLENDLOOP (OVER01, 255); - } else if (src_premultiplied_alpha && !dest_premultiplied_alpha) { - BLENDLOOP (OVER10, 255); + if (bpp == 4) { + if (G_LIKELY (global_alpha_val == 255)) { + if (src_premultiplied_alpha && dest_premultiplied_alpha) { + BLENDLOOP (OVER11, guint8, 255, 0, 255); + } else if (!src_premultiplied_alpha && dest_premultiplied_alpha) { + BLENDLOOP (OVER01, guint8, 255, 0, 255); + } else if (src_premultiplied_alpha && !dest_premultiplied_alpha) { + BLENDLOOP (OVER10, guint8, 255, 0, 255); + } else { + BLENDLOOP (OVER00, guint8, 255, 0, 255); + } } else { - BLENDLOOP (OVER00, 255); + if (src_premultiplied_alpha && dest_premultiplied_alpha) { + BLENDLOOP (OVER11, guint8, 255, 0, global_alpha_val); + } else if (!src_premultiplied_alpha && dest_premultiplied_alpha) { + BLENDLOOP (OVER01, guint8, 255, 0, global_alpha_val); + } else if (src_premultiplied_alpha && !dest_premultiplied_alpha) { + BLENDLOOP (OVER10, guint8, 255, 0, global_alpha_val); + } else { + BLENDLOOP (OVER00, guint8, 255, 0, global_alpha_val); + } } } else { - if (src_premultiplied_alpha && dest_premultiplied_alpha) { - BLENDLOOP (OVER11, global_alpha_val); - } else if (!src_premultiplied_alpha && dest_premultiplied_alpha) { - BLENDLOOP (OVER01, global_alpha_val); - } else if (src_premultiplied_alpha && !dest_premultiplied_alpha) { - BLENDLOOP (OVER10, global_alpha_val); + g_assert (bpp == 8); + + if (G_LIKELY (global_alpha_val == 255)) { + if (src_premultiplied_alpha && dest_premultiplied_alpha) { + BLENDLOOP (OVER11, guint16, 65535, 8, 255); + } else if (!src_premultiplied_alpha && dest_premultiplied_alpha) { + BLENDLOOP (OVER01, guint16, 65535, 8, 255); + } else if (src_premultiplied_alpha && !dest_premultiplied_alpha) { + BLENDLOOP (OVER10, guint16, 65535, 8, 255); + } else { + BLENDLOOP (OVER00, guint16, 65535, 8, 255); + } } else { - BLENDLOOP (OVER00, global_alpha_val); + if (src_premultiplied_alpha && dest_premultiplied_alpha) { + BLENDLOOP (OVER11, guint16, 65535, 8, global_alpha_val); + } else if (!src_premultiplied_alpha && dest_premultiplied_alpha) { + BLENDLOOP (OVER01, guint16, 65535, 8, global_alpha_val); + } else if (src_premultiplied_alpha && !dest_premultiplied_alpha) { + BLENDLOOP (OVER10, guint16, 65535, 8, global_alpha_val); + } else { + BLENDLOOP (OVER00, guint16, 65535, 8, global_alpha_val); + } } } #undef BLENDLOOP /* undo previous pointer adjustments to pass right pointer to g_free */ - tmpdestline -= 4 * x; + tmpdestline -= bpp * x; /* FIXME * #if G_BYTE_ORDER == LITTLE_ENDIAN diff --git a/gst-libs/gst/video/video-overlay-composition.h b/gst-libs/gst/video/video-overlay-composition.h index 062dae7..7981e02 100644 --- a/gst-libs/gst/video/video-overlay-composition.h +++ b/gst-libs/gst/video/video-overlay-composition.h @@ -119,10 +119,7 @@ typedef enum { * * Since: 1.2 */ -#define GST_VIDEO_OVERLAY_COMPOSITION_BLEND_FORMATS \ - "{ BGRx, RGBx, xRGB, xBGR, RGBA, BGRA, ARGB, ABGR, RGB, BGR," \ - " I420, YV12, AYUV, YUY2, UYVY, v308, Y41B, Y42B, Y444," \ - " NV12, NV21, A420, YUV9, YVU9, IYU1, GRAY8 }" +#define GST_VIDEO_OVERLAY_COMPOSITION_BLEND_FORMATS GST_VIDEO_FORMATS_ALL GST_VIDEO_API GType gst_video_overlay_rectangle_get_type (void); -- 2.7.4