mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 05:46:13 +00:00
gdkpixbufoverlay: add properties for positioning and sizing
This commit is contained in:
parent
729a30c38b
commit
fdb7ec12b4
2 changed files with 150 additions and 6 deletions
|
@ -18,10 +18,20 @@
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* SECTION:element-gdkpixbufoverlay
|
* SECTION:element-gdkpixbufoverlay
|
||||||
|
* @see_also:
|
||||||
*
|
*
|
||||||
* The gdkpixbufoverlay element overlays an image loaded from file onto
|
* The gdkpixbufoverlay element overlays an image loaded from file onto
|
||||||
* a video stream.
|
* a video stream.
|
||||||
*
|
*
|
||||||
|
* Changing the positioning or overlay width and height properties at runtime
|
||||||
|
* is supported, but it might be prudent to to protect the property setting
|
||||||
|
* code with GST_BASE_TRANSFORM_LOCK and GST_BASE_TRANSFORM_UNLOCK, as
|
||||||
|
* g_object_set() is not atomic for multiple properties passed in one go.
|
||||||
|
*
|
||||||
|
* Changing the image at runtime is currently not supported.
|
||||||
|
*
|
||||||
|
* Negative offsets are also not yet supported.
|
||||||
|
*
|
||||||
* <refsect2>
|
* <refsect2>
|
||||||
* <title>Example launch line</title>
|
* <title>Example launch line</title>
|
||||||
* |[
|
* |[
|
||||||
|
@ -30,6 +40,8 @@
|
||||||
* Overlays the image in image.png onto the test video picture produced by
|
* Overlays the image in image.png onto the test video picture produced by
|
||||||
* videotestsrc.
|
* videotestsrc.
|
||||||
* </refsect2>
|
* </refsect2>
|
||||||
|
*
|
||||||
|
* Since: 0.10.33
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
|
@ -60,7 +72,13 @@ gst_gdk_pixbuf_overlay_set_caps (GstBaseTransform * trans, GstCaps * incaps,
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
PROP_0,
|
PROP_0,
|
||||||
PROP_LOCATION
|
PROP_LOCATION,
|
||||||
|
PROP_OFFSET_X,
|
||||||
|
PROP_OFFSET_Y,
|
||||||
|
PROP_RELATIVE_X,
|
||||||
|
PROP_RELATIVE_Y,
|
||||||
|
PROP_OVERLAY_WIDTH,
|
||||||
|
PROP_OVERLAY_HEIGHT
|
||||||
};
|
};
|
||||||
|
|
||||||
#define VIDEO_CAPS \
|
#define VIDEO_CAPS \
|
||||||
|
@ -126,8 +144,36 @@ gst_gdk_pixbuf_overlay_class_init (GstGdkPixbufOverlayClass * klass)
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class, PROP_LOCATION,
|
g_object_class_install_property (gobject_class, PROP_LOCATION,
|
||||||
g_param_spec_string ("location", "location",
|
g_param_spec_string ("location", "location",
|
||||||
"location of image file to overlay", "",
|
"location of image file to overlay", NULL,
|
||||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
g_object_class_install_property (gobject_class, PROP_OFFSET_X,
|
||||||
|
g_param_spec_int ("offset-x", "X Offset",
|
||||||
|
"horizontal offset of overlay image in pixels from top-left corner "
|
||||||
|
"of video image", G_MININT, G_MAXINT, 0,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
g_object_class_install_property (gobject_class, PROP_OFFSET_Y,
|
||||||
|
g_param_spec_int ("offset-y", "Y Offset",
|
||||||
|
"vertical offset of overlay image in pixels from top-left corner "
|
||||||
|
"of video image", G_MININT, G_MAXINT, 0,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
g_object_class_install_property (gobject_class, PROP_RELATIVE_X,
|
||||||
|
g_param_spec_double ("relative-x", "Relative X Offset",
|
||||||
|
"horizontal offset of overlay image in fractions of video image "
|
||||||
|
"width, from top-left corner of video image",
|
||||||
|
0.0, 1.0, 0.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
g_object_class_install_property (gobject_class, PROP_RELATIVE_Y,
|
||||||
|
g_param_spec_double ("relative-y", "Relative Y Offset",
|
||||||
|
"vertical offset of overlay image in fractions of video image "
|
||||||
|
"height, from top-left corner of video image",
|
||||||
|
0.0, 1.0, 0.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
g_object_class_install_property (gobject_class, PROP_OVERLAY_WIDTH,
|
||||||
|
g_param_spec_int ("overlay-width", "Overlay Width",
|
||||||
|
"width of overlay image in pixels (0 = same as overlay image)",
|
||||||
|
0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
g_object_class_install_property (gobject_class, PROP_OVERLAY_HEIGHT,
|
||||||
|
g_param_spec_int ("overlay-height", "Overlay Height",
|
||||||
|
"height of overlay image in pixels (0 = same as overlay image)",
|
||||||
|
0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_INIT (gdkpixbufoverlay_debug, "gdkpixbufoverlay", 0,
|
GST_DEBUG_CATEGORY_INIT (gdkpixbufoverlay_debug, "gdkpixbufoverlay", 0,
|
||||||
"debug category for gdkpixbufoverlay element");
|
"debug category for gdkpixbufoverlay element");
|
||||||
|
@ -137,7 +183,14 @@ static void
|
||||||
gst_gdk_pixbuf_overlay_init (GstGdkPixbufOverlay * overlay,
|
gst_gdk_pixbuf_overlay_init (GstGdkPixbufOverlay * overlay,
|
||||||
GstGdkPixbufOverlayClass * overlay_class)
|
GstGdkPixbufOverlayClass * overlay_class)
|
||||||
{
|
{
|
||||||
/* nothing to do here for now */
|
overlay->offset_x = 0;
|
||||||
|
overlay->offset_y = 0;
|
||||||
|
|
||||||
|
overlay->relative_x = 0.0;
|
||||||
|
overlay->relative_y = 0.0;
|
||||||
|
|
||||||
|
overlay->overlay_width = 0;
|
||||||
|
overlay->overlay_height = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -146,15 +199,43 @@ gst_gdk_pixbuf_overlay_set_property (GObject * object, guint property_id,
|
||||||
{
|
{
|
||||||
GstGdkPixbufOverlay *overlay = GST_GDK_PIXBUF_OVERLAY (object);
|
GstGdkPixbufOverlay *overlay = GST_GDK_PIXBUF_OVERLAY (object);
|
||||||
|
|
||||||
|
GST_OBJECT_LOCK (overlay);
|
||||||
|
|
||||||
switch (property_id) {
|
switch (property_id) {
|
||||||
case PROP_LOCATION:
|
case PROP_LOCATION:
|
||||||
g_free (overlay->location);
|
g_free (overlay->location);
|
||||||
overlay->location = g_value_dup_string (value);
|
overlay->location = g_value_dup_string (value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_OFFSET_X:
|
||||||
|
overlay->offset_x = g_value_get_int (value);
|
||||||
|
overlay->update_composition = TRUE;
|
||||||
|
break;
|
||||||
|
case PROP_OFFSET_Y:
|
||||||
|
overlay->offset_y = g_value_get_int (value);
|
||||||
|
overlay->update_composition = TRUE;
|
||||||
|
break;
|
||||||
|
case PROP_RELATIVE_X:
|
||||||
|
overlay->relative_x = g_value_get_double (value);
|
||||||
|
overlay->update_composition = TRUE;
|
||||||
|
break;
|
||||||
|
case PROP_RELATIVE_Y:
|
||||||
|
overlay->relative_y = g_value_get_double (value);
|
||||||
|
overlay->update_composition = TRUE;
|
||||||
|
break;
|
||||||
|
case PROP_OVERLAY_WIDTH:
|
||||||
|
overlay->overlay_width = g_value_get_int (value);
|
||||||
|
overlay->update_composition = TRUE;
|
||||||
|
break;
|
||||||
|
case PROP_OVERLAY_HEIGHT:
|
||||||
|
overlay->overlay_height = g_value_get_int (value);
|
||||||
|
overlay->update_composition = TRUE;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GST_OBJECT_UNLOCK (overlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -163,14 +244,36 @@ gst_gdk_pixbuf_overlay_get_property (GObject * object, guint property_id,
|
||||||
{
|
{
|
||||||
GstGdkPixbufOverlay *overlay = GST_GDK_PIXBUF_OVERLAY (object);
|
GstGdkPixbufOverlay *overlay = GST_GDK_PIXBUF_OVERLAY (object);
|
||||||
|
|
||||||
|
GST_OBJECT_LOCK (overlay);
|
||||||
|
|
||||||
switch (property_id) {
|
switch (property_id) {
|
||||||
case PROP_LOCATION:
|
case PROP_LOCATION:
|
||||||
g_value_set_string (value, overlay->location);
|
g_value_set_string (value, overlay->location);
|
||||||
break;
|
break;
|
||||||
|
case PROP_OFFSET_X:
|
||||||
|
g_value_set_int (value, overlay->offset_x);
|
||||||
|
break;
|
||||||
|
case PROP_OFFSET_Y:
|
||||||
|
g_value_set_int (value, overlay->offset_y);
|
||||||
|
break;
|
||||||
|
case PROP_RELATIVE_X:
|
||||||
|
g_value_set_double (value, overlay->relative_x);
|
||||||
|
break;
|
||||||
|
case PROP_RELATIVE_Y:
|
||||||
|
g_value_set_double (value, overlay->relative_y);
|
||||||
|
break;
|
||||||
|
case PROP_OVERLAY_WIDTH:
|
||||||
|
g_value_set_int (value, overlay->overlay_width);
|
||||||
|
break;
|
||||||
|
case PROP_OVERLAY_HEIGHT:
|
||||||
|
g_value_set_int (value, overlay->overlay_height);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GST_OBJECT_UNLOCK (overlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -319,12 +422,37 @@ gst_gdk_pixbuf_overlay_update_composition (GstGdkPixbufOverlay * overlay)
|
||||||
{
|
{
|
||||||
GstVideoOverlayComposition *comp;
|
GstVideoOverlayComposition *comp;
|
||||||
GstVideoOverlayRectangle *rect;
|
GstVideoOverlayRectangle *rect;
|
||||||
|
gint x, y, width, height;
|
||||||
|
|
||||||
|
x = overlay->offset_x + (overlay->relative_x * overlay->pixels_width);
|
||||||
|
y = overlay->offset_y + (overlay->relative_y * overlay->pixels_height);
|
||||||
|
|
||||||
|
/* FIXME: this should work, but seems to crash */
|
||||||
|
if (x < 0)
|
||||||
|
x = 0;
|
||||||
|
if (y < 0)
|
||||||
|
y = 0;
|
||||||
|
|
||||||
|
width = overlay->overlay_width;
|
||||||
|
if (width == 0)
|
||||||
|
width = overlay->pixels_width;
|
||||||
|
|
||||||
|
height = overlay->overlay_height;
|
||||||
|
if (height == 0)
|
||||||
|
height = overlay->pixels_height;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (overlay, "overlay image dimensions: %d x %d",
|
||||||
|
overlay->pixels_width, overlay->pixels_height);
|
||||||
|
GST_DEBUG_OBJECT (overlay, "properties: x,y: %d,%d (%g%%,%g%%) - WxH: %dx%d",
|
||||||
|
overlay->offset_x, overlay->offset_y,
|
||||||
|
overlay->relative_x * 100.0, overlay->relative_y * 100.0,
|
||||||
|
overlay->overlay_height, overlay->overlay_width);
|
||||||
|
GST_DEBUG_OBJECT (overlay, "overlay rendered: %d x %d @ %d,%d (onto %d x %d)",
|
||||||
|
width, height, x, y, overlay->width, overlay->height);
|
||||||
|
|
||||||
/* FIXME: add properties for position and render width and height */
|
|
||||||
rect = gst_video_overlay_rectangle_new_argb (overlay->pixels,
|
rect = gst_video_overlay_rectangle_new_argb (overlay->pixels,
|
||||||
overlay->pixels_width, overlay->pixels_height, overlay->pixels_stride,
|
overlay->pixels_width, overlay->pixels_height, overlay->pixels_stride,
|
||||||
0, 0, overlay->pixels_width, overlay->pixels_height,
|
x, y, width, height, GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
|
||||||
GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
|
|
||||||
|
|
||||||
comp = gst_video_overlay_composition_new (rect);
|
comp = gst_video_overlay_composition_new (rect);
|
||||||
gst_video_overlay_rectangle_unref (rect);
|
gst_video_overlay_rectangle_unref (rect);
|
||||||
|
@ -341,11 +469,15 @@ gst_gdk_pixbuf_overlay_transform_ip (GstBaseTransform * trans, GstBuffer * buf)
|
||||||
|
|
||||||
overlay = GST_GDK_PIXBUF_OVERLAY (trans);
|
overlay = GST_GDK_PIXBUF_OVERLAY (trans);
|
||||||
|
|
||||||
|
GST_OBJECT_LOCK (overlay);
|
||||||
|
|
||||||
if (G_UNLIKELY (overlay->update_composition)) {
|
if (G_UNLIKELY (overlay->update_composition)) {
|
||||||
gst_gdk_pixbuf_overlay_update_composition (overlay);
|
gst_gdk_pixbuf_overlay_update_composition (overlay);
|
||||||
overlay->update_composition = FALSE;
|
overlay->update_composition = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GST_OBJECT_UNLOCK (overlay);
|
||||||
|
|
||||||
gst_video_overlay_composition_blend (overlay->comp, buf);
|
gst_video_overlay_composition_blend (overlay->comp, buf);
|
||||||
|
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
|
|
|
@ -41,12 +41,24 @@ struct _GstGdkPixbufOverlay
|
||||||
{
|
{
|
||||||
GstVideoFilter videofilter;
|
GstVideoFilter videofilter;
|
||||||
|
|
||||||
|
/* negotiated format */
|
||||||
GstVideoFormat format;
|
GstVideoFormat format;
|
||||||
gint width;
|
gint width;
|
||||||
gint height;
|
gint height;
|
||||||
|
|
||||||
|
/* properties */
|
||||||
gchar * location;
|
gchar * location;
|
||||||
|
|
||||||
|
gint offset_x;
|
||||||
|
gint offset_y;
|
||||||
|
|
||||||
|
gdouble relative_x;
|
||||||
|
gdouble relative_y;
|
||||||
|
|
||||||
|
gint overlay_width;
|
||||||
|
gint overlay_height;
|
||||||
|
|
||||||
|
/* the loaded image */
|
||||||
GstBuffer * pixels;
|
GstBuffer * pixels;
|
||||||
guint pixels_width;
|
guint pixels_width;
|
||||||
guint pixels_height;
|
guint pixels_height;
|
||||||
|
|
Loading…
Reference in a new issue