diff --git a/ext/pango/gsttextoverlay.c b/ext/pango/gsttextoverlay.c index b735bf454c..d05f3d47dc 100644 --- a/ext/pango/gsttextoverlay.c +++ b/ext/pango/gsttextoverlay.c @@ -179,16 +179,18 @@ static GstStaticPadTemplate src_template_factory = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420") ";" - GST_VIDEO_CAPS_YUV ("UYVY")) + GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRx ";" + GST_VIDEO_CAPS_xRGB ";" + GST_VIDEO_CAPS_YUV ("I420") ";" GST_VIDEO_CAPS_YUV ("UYVY")) ); static GstStaticPadTemplate video_sink_template_factory = GST_STATIC_PAD_TEMPLATE ("video_sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420") ";" - GST_VIDEO_CAPS_YUV ("UYVY")) + GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRx ";" + GST_VIDEO_CAPS_xRGB ";" + GST_VIDEO_CAPS_YUV ("I420") ";" GST_VIDEO_CAPS_YUV ("UYVY")) ); static GstStaticPadTemplate text_sink_template_factory = @@ -686,10 +688,9 @@ gst_text_overlay_setcaps (GstPad * pad, GstCaps * caps) structure = gst_caps_get_structure (caps, 0); fps = gst_structure_get_value (structure, "framerate"); - if (gst_structure_get_int (structure, "width", &overlay->width) && - gst_structure_get_int (structure, "height", &overlay->height) && - gst_structure_get_fourcc (structure, "format", &overlay->format) && - fps != NULL) { + if (fps + && gst_video_format_parse_caps (caps, &overlay->format, &overlay->width, + &overlay->height)) { ret = gst_pad_set_caps (overlay->srcpad, caps); } @@ -1319,6 +1320,32 @@ gst_text_overlay_shade_UYVY_y (GstTextOverlay * overlay, guchar * dest, } } +#define gst_text_overlay_shade_BGRx gst_text_overlay_shade_xRGB +static inline void +gst_text_overlay_shade_xRGB (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 = 0; k < 4; k++) { + y = dest[y_pos + k] + overlay->shading_value; + dest[y_pos + k] = CLAMP (y, 0, 255); + } + } + } +} + /* FIXME: * - use proper strides and offset for I420 * - don't draw over the edge of the picture (try a longer @@ -1426,6 +1453,51 @@ gst_text_overlay_blit_UYVY (GstTextOverlay * overlay, } } +#define xRGB_BLIT_FUNCTION(name, 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; \ + 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] * a + dest[B] * (255-a)) / 255; \ + g = (pimage[CAIRO_ARGB_G] * a + dest[G] * (255-a)) / 255; \ + r = (pimage[CAIRO_ARGB_R] * a + dest[R] * (255-a)) / 255; \ + \ + dest[B] = b; \ + dest[G] = g; \ + dest[R] = r; \ + pimage += 4; \ + dest += 4; \ + } \ + } \ +} +xRGB_BLIT_FUNCTION (xRGB, 1, 2, 3); +xRGB_BLIT_FUNCTION (BGRx, 2, 1, 0); + static void gst_text_overlay_render_text (GstTextOverlay * overlay, const gchar * text, gint textlen) @@ -1515,16 +1587,26 @@ gst_text_overlay_push_frame (GstTextOverlay * overlay, GstBuffer * video_frame) /* shaded background box */ if (overlay->want_shading) { switch (overlay->format) { - case GST_MAKE_FOURCC ('I', '4', '2', '0'): + case GST_VIDEO_FORMAT_I420: gst_text_overlay_shade_I420_y (overlay, GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->image_width, ypos, ypos + overlay->image_height); break; - case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'): + case GST_VIDEO_FORMAT_UYVY: gst_text_overlay_shade_UYVY_y (overlay, GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->image_width, ypos, ypos + overlay->image_height); break; + case GST_VIDEO_FORMAT_xRGB: + gst_text_overlay_shade_xRGB (overlay, + GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->image_width, + ypos, ypos + overlay->image_height); + break; + case GST_VIDEO_FORMAT_BGRx: + gst_text_overlay_shade_BGRx (overlay, + GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->image_width, + ypos, ypos + overlay->image_height); + break; default: g_assert_not_reached (); } @@ -1535,14 +1617,22 @@ gst_text_overlay_push_frame (GstTextOverlay * overlay, GstBuffer * video_frame) if (overlay->text_image) { switch (overlay->format) { - case GST_MAKE_FOURCC ('I', '4', '2', '0'): + case GST_VIDEO_FORMAT_I420: gst_text_overlay_blit_I420 (overlay, GST_BUFFER_DATA (video_frame), xpos, ypos); break; - case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'): + case GST_VIDEO_FORMAT_UYVY: gst_text_overlay_blit_UYVY (overlay, GST_BUFFER_DATA (video_frame), xpos, ypos); break; + case GST_VIDEO_FORMAT_BGRx: + gst_text_overlay_blit_BGRx (overlay, + GST_BUFFER_DATA (video_frame), xpos, ypos); + break; + case GST_VIDEO_FORMAT_xRGB: + gst_text_overlay_blit_xRGB (overlay, + GST_BUFFER_DATA (video_frame), xpos, ypos); + break; default: g_assert_not_reached (); } diff --git a/ext/pango/gsttextoverlay.h b/ext/pango/gsttextoverlay.h index 94ef1f81a5..232d97a2b7 100644 --- a/ext/pango/gsttextoverlay.h +++ b/ext/pango/gsttextoverlay.h @@ -2,6 +2,7 @@ #define __GST_TEXT_OVERLAY_H__ #include +#include #include G_BEGIN_DECLS @@ -109,7 +110,7 @@ struct _GstTextOverlay { gint height; gint fps_n; gint fps_d; - guint32 format; + GstVideoFormat format; GstTextOverlayVAlign valign; GstTextOverlayHAlign halign;