mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-26 02:00:33 +00:00
parent
5ec2d48f0a
commit
e54e10ad19
2 changed files with 117 additions and 14 deletions
|
@ -2,6 +2,7 @@
|
||||||
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
||||||
* Copyright (C) <2003> David Schleef <ds@schleef.org>
|
* Copyright (C) <2003> David Schleef <ds@schleef.org>
|
||||||
* Copyright (C) <2006> Julien Moutte <julien@moutte.net>
|
* Copyright (C) <2006> Julien Moutte <julien@moutte.net>
|
||||||
|
* Copyright (C) <2006> Zeeshan Ali <zeeshan.ali@nokia.com>
|
||||||
* Copyright (C) <2006-2008> Tim-Philipp Müller <tim centricular net>
|
* Copyright (C) <2006-2008> Tim-Philipp Müller <tim centricular net>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
|
@ -94,7 +95,7 @@ static const GstElementDetails text_overlay_details =
|
||||||
GST_ELEMENT_DETAILS ("Text overlay",
|
GST_ELEMENT_DETAILS ("Text overlay",
|
||||||
"Filter/Editor/Video",
|
"Filter/Editor/Video",
|
||||||
"Adds text strings on top of a video buffer",
|
"Adds text strings on top of a video buffer",
|
||||||
"David Schleef <ds@schleef.org>");
|
"David Schleef <ds@schleef.org>, " "Zeeshan Ali <zeeshan.ali@nokia.com>");
|
||||||
|
|
||||||
|
|
||||||
#define DEFAULT_PROP_TEXT ""
|
#define DEFAULT_PROP_TEXT ""
|
||||||
|
@ -137,19 +138,20 @@ enum
|
||||||
PROP_LAST
|
PROP_LAST
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static GstStaticPadTemplate src_template_factory =
|
static GstStaticPadTemplate src_template_factory =
|
||||||
GST_STATIC_PAD_TEMPLATE ("src",
|
GST_STATIC_PAD_TEMPLATE ("src",
|
||||||
GST_PAD_SRC,
|
GST_PAD_SRC,
|
||||||
GST_PAD_ALWAYS,
|
GST_PAD_ALWAYS,
|
||||||
GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420"))
|
GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420") ";"
|
||||||
|
GST_VIDEO_CAPS_YUV ("UYVY"))
|
||||||
);
|
);
|
||||||
|
|
||||||
static GstStaticPadTemplate video_sink_template_factory =
|
static GstStaticPadTemplate video_sink_template_factory =
|
||||||
GST_STATIC_PAD_TEMPLATE ("video_sink",
|
GST_STATIC_PAD_TEMPLATE ("video_sink",
|
||||||
GST_PAD_SINK,
|
GST_PAD_SINK,
|
||||||
GST_PAD_ALWAYS,
|
GST_PAD_ALWAYS,
|
||||||
GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420"))
|
GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420") ";"
|
||||||
|
GST_VIDEO_CAPS_YUV ("UYVY"))
|
||||||
);
|
);
|
||||||
|
|
||||||
static GstStaticPadTemplate text_sink_template_factory =
|
static GstStaticPadTemplate text_sink_template_factory =
|
||||||
|
@ -159,7 +161,6 @@ static GstStaticPadTemplate text_sink_template_factory =
|
||||||
GST_STATIC_CAPS ("text/x-pango-markup; text/plain")
|
GST_STATIC_CAPS ("text/x-pango-markup; text/plain")
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
#define GST_TYPE_TEXT_OVERLAY_VALIGN (gst_text_overlay_valign_get_type())
|
#define GST_TYPE_TEXT_OVERLAY_VALIGN (gst_text_overlay_valign_get_type())
|
||||||
static GType
|
static GType
|
||||||
gst_text_overlay_valign_get_type (void)
|
gst_text_overlay_valign_get_type (void)
|
||||||
|
@ -581,6 +582,7 @@ gst_text_overlay_setcaps (GstPad * pad, GstCaps * caps)
|
||||||
|
|
||||||
if (gst_structure_get_int (structure, "width", &overlay->width) &&
|
if (gst_structure_get_int (structure, "width", &overlay->width) &&
|
||||||
gst_structure_get_int (structure, "height", &overlay->height) &&
|
gst_structure_get_int (structure, "height", &overlay->height) &&
|
||||||
|
gst_structure_get_fourcc (structure, "format", &overlay->format) &&
|
||||||
fps != NULL) {
|
fps != NULL) {
|
||||||
ret = gst_pad_set_caps (overlay->srcpad, caps);
|
ret = gst_pad_set_caps (overlay->srcpad, caps);
|
||||||
}
|
}
|
||||||
|
@ -856,7 +858,7 @@ gst_text_overlay_getcaps (GstPad * pad)
|
||||||
#define BOX_YPAD 6
|
#define BOX_YPAD 6
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
gst_text_overlay_shade_y (GstTextOverlay * overlay, guchar * dest,
|
gst_text_overlay_shade_I420_y (GstTextOverlay * overlay, guchar * dest,
|
||||||
gint x0, gint x1, gint y0, gint y1)
|
gint x0, gint x1, gint y0, gint y1)
|
||||||
{
|
{
|
||||||
gint i, j, dest_stride;
|
gint i, j, dest_stride;
|
||||||
|
@ -879,6 +881,33 @@ gst_text_overlay_shade_y (GstTextOverlay * overlay, guchar * dest,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
gst_text_overlay_shade_UYVY_y (GstTextOverlay * overlay, guchar * dest,
|
||||||
|
gint x0, gint x1, gint y0, gint y1)
|
||||||
|
{
|
||||||
|
gint i, j;
|
||||||
|
guint dest_stride = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_UYVY, 0,
|
||||||
|
overlay->width);
|
||||||
|
|
||||||
|
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;
|
||||||
|
gint y_pos;
|
||||||
|
|
||||||
|
y_pos = (i * dest_stride) + j * 2 + 1;
|
||||||
|
y = dest[y_pos] + overlay->shading_value;
|
||||||
|
|
||||||
|
dest[y_pos] = CLAMP (y, 0, 255);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* 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
|
||||||
|
@ -886,7 +915,7 @@ gst_text_overlay_shade_y (GstTextOverlay * overlay, guchar * dest,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
gst_text_overlay_blit_yuv420 (GstTextOverlay * overlay, FT_Bitmap * bitmap,
|
gst_text_overlay_blit_I420 (GstTextOverlay * overlay, FT_Bitmap * bitmap,
|
||||||
guint8 * yuv_pixels, gint x0, gint y0)
|
guint8 * yuv_pixels, gint x0, gint y0)
|
||||||
{
|
{
|
||||||
int y; /* text bitmap coordinates */
|
int y; /* text bitmap coordinates */
|
||||||
|
@ -982,6 +1011,58 @@ gst_text_overlay_blit_yuv420 (GstTextOverlay * overlay, FT_Bitmap * bitmap,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
gst_text_overlay_blit_UYVY (GstTextOverlay * overlay, FT_Bitmap * bitmap,
|
||||||
|
guint8 * yuv_pixels, gint x0, gint y0)
|
||||||
|
{
|
||||||
|
int y; /* text bitmap coordinates */
|
||||||
|
int x1, y1; /* video buffer coordinates */
|
||||||
|
int bit_rowinc;
|
||||||
|
guint8 *p, *bitp;
|
||||||
|
int video_width, video_height;
|
||||||
|
int bitmap_x0 = 0; //x0 < 1 ? -(x0 - 1) : 1; /* 1 pixel border */
|
||||||
|
int bitmap_y0 = y0 < 1 ? -(y0 - 1) : 1; /* 1 pixel border */
|
||||||
|
int bitmap_width = bitmap->width - bitmap_x0;
|
||||||
|
int bitmap_height = bitmap->rows - bitmap_y0;
|
||||||
|
|
||||||
|
video_width =
|
||||||
|
gst_video_format_get_row_stride (GST_VIDEO_FORMAT_UYVY, 0,
|
||||||
|
overlay->width);
|
||||||
|
video_height = overlay->height;
|
||||||
|
|
||||||
|
/*g_debug ("bliting bitmap(%d, %d) on yuv (%d,%d) at %d,%d",
|
||||||
|
bitmap_width, bitmap_height,
|
||||||
|
video_width, video_height,
|
||||||
|
x0, y0); */
|
||||||
|
|
||||||
|
if (x0 + bitmap_x0 + bitmap_width > overlay->width - 1) /* 1 pixel border */
|
||||||
|
bitmap_width -= x0 + bitmap_x0 + bitmap_width - overlay->width + 1;
|
||||||
|
if (y0 + bitmap_y0 + bitmap_height > video_height - 1) /* 1 pixel border */
|
||||||
|
bitmap_height -= y0 + bitmap_y0 + bitmap_height - video_height + 1;
|
||||||
|
|
||||||
|
bit_rowinc = bitmap->pitch - bitmap_width;
|
||||||
|
|
||||||
|
y1 = y0 + bitmap_y0;
|
||||||
|
x1 = x0 + bitmap_x0;
|
||||||
|
bitp = bitmap->buffer + bitmap->pitch * bitmap_y0 + bitmap_x0;
|
||||||
|
for (y = bitmap_y0; y < bitmap_y0 + bitmap_height; y++) {
|
||||||
|
int n;
|
||||||
|
|
||||||
|
/* Go to the Y0 of the first macroblock we wan't to write to */
|
||||||
|
p = yuv_pixels + (y0 + y) * video_width + (x1 * 2) + 1;
|
||||||
|
for (n = bitmap_width; n > 0; --n) {
|
||||||
|
if (*bitp) {
|
||||||
|
*p = *bitp;
|
||||||
|
*(p - 1) = 0x80;
|
||||||
|
}
|
||||||
|
|
||||||
|
p += 2;
|
||||||
|
bitp++;
|
||||||
|
}
|
||||||
|
bitp += bit_rowinc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_text_overlay_resize_bitmap (GstTextOverlay * overlay, gint width,
|
gst_text_overlay_resize_bitmap (GstTextOverlay * overlay, gint width,
|
||||||
gint height)
|
gint height)
|
||||||
|
@ -1093,15 +1174,36 @@ gst_text_overlay_push_frame (GstTextOverlay * overlay, GstBuffer * video_frame)
|
||||||
|
|
||||||
/* shaded background box */
|
/* shaded background box */
|
||||||
if (overlay->want_shading) {
|
if (overlay->want_shading) {
|
||||||
gst_text_overlay_shade_y (overlay,
|
switch (overlay->format) {
|
||||||
GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->bitmap.width,
|
case GST_MAKE_FOURCC ('I', '4', '2', '0'):
|
||||||
ypos, ypos + overlay->bitmap.rows);
|
gst_text_overlay_shade_I420_y (overlay,
|
||||||
|
GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->bitmap.width,
|
||||||
|
ypos, ypos + overlay->bitmap.rows);
|
||||||
|
break;
|
||||||
|
case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
|
||||||
|
gst_text_overlay_shade_UYVY_y (overlay,
|
||||||
|
GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->bitmap.width,
|
||||||
|
ypos, ypos + overlay->bitmap.rows);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (overlay->bitmap.buffer) {
|
if (overlay->bitmap.buffer) {
|
||||||
gst_text_overlay_blit_yuv420 (overlay, &overlay->bitmap,
|
switch (overlay->format) {
|
||||||
GST_BUFFER_DATA (video_frame), xpos, ypos);
|
case GST_MAKE_FOURCC ('I', '4', '2', '0'):
|
||||||
|
gst_text_overlay_blit_I420 (overlay, &overlay->bitmap,
|
||||||
|
GST_BUFFER_DATA (video_frame), xpos, ypos);
|
||||||
|
break;
|
||||||
|
case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
|
||||||
|
gst_text_overlay_blit_UYVY (overlay, &overlay->bitmap,
|
||||||
|
GST_BUFFER_DATA (video_frame), xpos, ypos);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return gst_pad_push (overlay->srcpad, video_frame);
|
return gst_pad_push (overlay->srcpad, video_frame);
|
||||||
|
|
|
@ -109,6 +109,7 @@ struct _GstTextOverlay {
|
||||||
gint height;
|
gint height;
|
||||||
gint fps_n;
|
gint fps_n;
|
||||||
gint fps_d;
|
gint fps_d;
|
||||||
|
guint32 format;
|
||||||
|
|
||||||
GstTextOverlayVAlign valign;
|
GstTextOverlayVAlign valign;
|
||||||
GstTextOverlayHAlign halign;
|
GstTextOverlayHAlign halign;
|
||||||
|
|
Loading…
Reference in a new issue