mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-28 03:00:35 +00:00
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.
This commit is contained in:
parent
7f59cefafb
commit
0e74e190ad
2 changed files with 68 additions and 38 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue