mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-22 00:06:36 +00:00
textoverlay: Added support for ARGB and other RGB alpha variants
This commit is contained in:
parent
e2150b11ff
commit
200ee96338
1 changed files with 123 additions and 0 deletions
|
@ -193,6 +193,10 @@ static GstStaticPadTemplate src_template_factory =
|
||||||
GST_PAD_ALWAYS,
|
GST_PAD_ALWAYS,
|
||||||
GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRx ";"
|
GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRx ";"
|
||||||
GST_VIDEO_CAPS_xRGB ";"
|
GST_VIDEO_CAPS_xRGB ";"
|
||||||
|
GST_VIDEO_CAPS_RGBA ";"
|
||||||
|
GST_VIDEO_CAPS_BGRA ";"
|
||||||
|
GST_VIDEO_CAPS_ARGB ";"
|
||||||
|
GST_VIDEO_CAPS_ABGR ";"
|
||||||
GST_VIDEO_CAPS_YUV ("{AYUV, I420, UYVY, NV12, NV21}"))
|
GST_VIDEO_CAPS_YUV ("{AYUV, I420, UYVY, NV12, NV21}"))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -202,6 +206,10 @@ static GstStaticPadTemplate video_sink_template_factory =
|
||||||
GST_PAD_ALWAYS,
|
GST_PAD_ALWAYS,
|
||||||
GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRx ";"
|
GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRx ";"
|
||||||
GST_VIDEO_CAPS_xRGB ";"
|
GST_VIDEO_CAPS_xRGB ";"
|
||||||
|
GST_VIDEO_CAPS_RGBA ";"
|
||||||
|
GST_VIDEO_CAPS_BGRA ";"
|
||||||
|
GST_VIDEO_CAPS_ARGB ";"
|
||||||
|
GST_VIDEO_CAPS_ABGR ";"
|
||||||
GST_VIDEO_CAPS_YUV ("{AYUV, I420, UYVY, NV12, NV21}"))
|
GST_VIDEO_CAPS_YUV ("{AYUV, I420, UYVY, NV12, NV21}"))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1470,6 +1478,36 @@ gst_text_overlay_shade_xRGB (GstTextOverlay * overlay, guchar * dest,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define ARGB_SHADE_FUNCTION(name, OFFSET) \
|
||||||
|
static inline void \
|
||||||
|
gst_text_overlay_shade_##name (GstTextOverlay * overlay, guchar * dest, \
|
||||||
|
gint x0, gint x1, gint y0, gint y1) \
|
||||||
|
{ \
|
||||||
|
gint i, j;\
|
||||||
|
\
|
||||||
|
x0 = CLAMP (x0 - BOX_XPAD, 0, overlay->width);\
|
||||||
|
x1 = CLAMP (x1 + BOX_XPAD, 0, overlay->width);\
|
||||||
|
\
|
||||||
|
y0 = CLAMP (y0 - BOX_YPAD, 0, overlay->height);\
|
||||||
|
y1 = CLAMP (y1 + BOX_YPAD, 0, overlay->height);\
|
||||||
|
\
|
||||||
|
for (i = y0; i < y1; i++) {\
|
||||||
|
for (j = x0; j < x1; j++) {\
|
||||||
|
gint y, y_pos, k;\
|
||||||
|
y_pos = (i * 4 * overlay->width) + j * 4;\
|
||||||
|
for (k = OFFSET; k < 3+OFFSET; k++) {\
|
||||||
|
y = dest[y_pos + k] + overlay->shading_value;\
|
||||||
|
dest[y_pos + k] = CLAMP (y, 0, 255);\
|
||||||
|
}\
|
||||||
|
}\
|
||||||
|
}\
|
||||||
|
}
|
||||||
|
ARGB_SHADE_FUNCTION (ARGB, 1);
|
||||||
|
ARGB_SHADE_FUNCTION (ABGR, 1);
|
||||||
|
ARGB_SHADE_FUNCTION (RGBA, 0);
|
||||||
|
ARGB_SHADE_FUNCTION (BGRA, 0);
|
||||||
|
|
||||||
|
|
||||||
/* FIXME:
|
/* FIXME:
|
||||||
* - use proper strides and offset for I420
|
* - use proper strides and offset for I420
|
||||||
* - don't draw over the edge of the picture (try a longer
|
* - don't draw over the edge of the picture (try a longer
|
||||||
|
@ -1722,6 +1760,55 @@ gst_text_overlay_blit_##name (GstTextOverlay * overlay, \
|
||||||
xRGB_BLIT_FUNCTION (xRGB, 1, 2, 3);
|
xRGB_BLIT_FUNCTION (xRGB, 1, 2, 3);
|
||||||
xRGB_BLIT_FUNCTION (BGRx, 2, 1, 0);
|
xRGB_BLIT_FUNCTION (BGRx, 2, 1, 0);
|
||||||
|
|
||||||
|
#define ARGB_BLIT_FUNCTION(name, A, R, G, B) \
|
||||||
|
static inline void \
|
||||||
|
gst_text_overlay_blit_##name (GstTextOverlay * overlay, \
|
||||||
|
guint8 * rgb_pixels, gint xpos, gint ypos) \
|
||||||
|
{ \
|
||||||
|
int a, r, g, b, a1; \
|
||||||
|
int i, j; \
|
||||||
|
int h, w; \
|
||||||
|
guchar *pimage, *dest; \
|
||||||
|
\
|
||||||
|
w = overlay->image_width; \
|
||||||
|
h = overlay->image_height; \
|
||||||
|
\
|
||||||
|
if (xpos < 0) { \
|
||||||
|
xpos = 0; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
if (xpos + w > overlay->width) { \
|
||||||
|
w = overlay->width - xpos; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
if (ypos + h > overlay->height) { \
|
||||||
|
h = overlay->height - ypos; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
for (i = 0; i < h; i++) { \
|
||||||
|
pimage = overlay->text_image + i * overlay->image_width * 4; \
|
||||||
|
dest = rgb_pixels + (i + ypos) * 4 * overlay->width + xpos * 4; \
|
||||||
|
for (j = 0; j < w; j++) { \
|
||||||
|
a = pimage[CAIRO_ARGB_A]; \
|
||||||
|
b = pimage[CAIRO_ARGB_B]; \
|
||||||
|
g = pimage[CAIRO_ARGB_G]; \
|
||||||
|
r = pimage[CAIRO_ARGB_R]; \
|
||||||
|
CAIRO_UNPREMULTIPLY (a, r, g, b); \
|
||||||
|
a1 = a + (dest[A] * (255 - a)) / 255 + 1; \
|
||||||
|
OVER (dest[R], a, r, dest[0], dest[R], a1); \
|
||||||
|
OVER (dest[G], a, g, dest[0], dest[G], a1); \
|
||||||
|
OVER (dest[B], a, b, dest[0], dest[B], a1); \
|
||||||
|
dest[A] = a1 - 1; \
|
||||||
|
pimage += 4; \
|
||||||
|
dest += 4; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
ARGB_BLIT_FUNCTION (RGBA, 3, 0, 1, 2);
|
||||||
|
ARGB_BLIT_FUNCTION (BGRA, 3, 2, 1, 0);
|
||||||
|
ARGB_BLIT_FUNCTION (ARGB, 0, 1, 2, 3);
|
||||||
|
ARGB_BLIT_FUNCTION (ABGR, 0, 3, 2, 1);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_text_overlay_render_text (GstTextOverlay * overlay,
|
gst_text_overlay_render_text (GstTextOverlay * overlay,
|
||||||
const gchar * text, gint textlen)
|
const gchar * text, gint textlen)
|
||||||
|
@ -1849,6 +1936,26 @@ gst_text_overlay_push_frame (GstTextOverlay * overlay, GstBuffer * video_frame)
|
||||||
GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->image_width,
|
GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->image_width,
|
||||||
ypos, ypos + overlay->image_height);
|
ypos, ypos + overlay->image_height);
|
||||||
break;
|
break;
|
||||||
|
case GST_VIDEO_FORMAT_ARGB:
|
||||||
|
gst_text_overlay_shade_ARGB (overlay,
|
||||||
|
GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->image_width,
|
||||||
|
ypos, ypos + overlay->image_height);
|
||||||
|
break;
|
||||||
|
case GST_VIDEO_FORMAT_ABGR:
|
||||||
|
gst_text_overlay_shade_ABGR (overlay,
|
||||||
|
GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->image_width,
|
||||||
|
ypos, ypos + overlay->image_height);
|
||||||
|
break;
|
||||||
|
case GST_VIDEO_FORMAT_RGBA:
|
||||||
|
gst_text_overlay_shade_RGBA (overlay,
|
||||||
|
GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->image_width,
|
||||||
|
ypos, ypos + overlay->image_height);
|
||||||
|
break;
|
||||||
|
case GST_VIDEO_FORMAT_BGRA:
|
||||||
|
gst_text_overlay_shade_BGRA (overlay,
|
||||||
|
GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->image_width,
|
||||||
|
ypos, ypos + overlay->image_height);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
}
|
}
|
||||||
|
@ -1884,6 +1991,22 @@ gst_text_overlay_push_frame (GstTextOverlay * overlay, GstBuffer * video_frame)
|
||||||
gst_text_overlay_blit_xRGB (overlay,
|
gst_text_overlay_blit_xRGB (overlay,
|
||||||
GST_BUFFER_DATA (video_frame), xpos, ypos);
|
GST_BUFFER_DATA (video_frame), xpos, ypos);
|
||||||
break;
|
break;
|
||||||
|
case GST_VIDEO_FORMAT_ARGB:
|
||||||
|
gst_text_overlay_blit_ARGB (overlay,
|
||||||
|
GST_BUFFER_DATA (video_frame), xpos, ypos);
|
||||||
|
break;
|
||||||
|
case GST_VIDEO_FORMAT_ABGR:
|
||||||
|
gst_text_overlay_blit_ABGR (overlay,
|
||||||
|
GST_BUFFER_DATA (video_frame), xpos, ypos);
|
||||||
|
break;
|
||||||
|
case GST_VIDEO_FORMAT_RGBA:
|
||||||
|
gst_text_overlay_blit_RGBA (overlay,
|
||||||
|
GST_BUFFER_DATA (video_frame), xpos, ypos);
|
||||||
|
break;
|
||||||
|
case GST_VIDEO_FORMAT_BGRA:
|
||||||
|
gst_text_overlay_blit_BGRA (overlay,
|
||||||
|
GST_BUFFER_DATA (video_frame), xpos, ypos);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue