textoverlay: Added support for ARGB and other RGB alpha variants

This commit is contained in:
Lane Brooks 2011-01-17 21:12:18 -07:00 committed by Sebastian Dröge
parent e2150b11ff
commit 200ee96338

View file

@ -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 ();
} }