From b76595d67eb8c56830ab7c1cb55a45c660b3394f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Thu, 25 Dec 2014 14:53:09 +0000 Subject: [PATCH] gdkpixbufoverlay: add "positioning-mode" property to allow absolute positions Set positioning-mode=pixels-absolute to allow positioning with absolute coordinates, meaning negative x/y offsets will be interpreted as being to the left/above the video frame instead of being interpreted as relative to the right/bottom edge of the video frame (which is a silly default, but that's how it is). This means we can nicely slide images into and out of the frame, see gdkpixbufoverlay-test. https://bugzilla.gnome.org/show_bug.cgi?id=739566 --- ext/gdk_pixbuf/gstgdkpixbufoverlay.c | 79 +++++++++++++++++++++++++--- ext/gdk_pixbuf/gstgdkpixbufoverlay.h | 7 +++ 2 files changed, 78 insertions(+), 8 deletions(-) diff --git a/ext/gdk_pixbuf/gstgdkpixbufoverlay.c b/ext/gdk_pixbuf/gstgdkpixbufoverlay.c index 34b4f0a192..8da40761d6 100644 --- a/ext/gdk_pixbuf/gstgdkpixbufoverlay.c +++ b/ext/gdk_pixbuf/gstgdkpixbufoverlay.c @@ -81,6 +81,7 @@ enum PROP_0, PROP_LOCATION, PROP_PIXBUF, + PROP_POSITIONING_MODE, PROP_OFFSET_X, PROP_OFFSET_Y, PROP_RELATIVE_X, @@ -97,6 +98,10 @@ enum "IYU1, ARGB64, AYUV64, r210, I420_10LE, I420_10BE, " \ "GRAY8, GRAY16_BE, GRAY16_LE }" +/* FIXME 2.0: change to absolute positioning */ +#define DEFAULT_POSITIONING_MODE \ + GST_GDK_PIXBUF_POSITIONING_PIXELS_RELATIVE_TO_EDGES + static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, @@ -112,6 +117,29 @@ static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", G_DEFINE_TYPE (GstGdkPixbufOverlay, gst_gdk_pixbuf_overlay, GST_TYPE_VIDEO_FILTER); +#define GST_TYPE_GDK_PIXBUF_POSITIONING_MODE \ + (gst_gdk_pixbuf_positioning_mode_get_type()) + +static GType +gst_gdk_pixbuf_positioning_mode_get_type (void) +{ + static const GEnumValue pos_modes[] = { + {GST_GDK_PIXBUF_POSITIONING_PIXELS_RELATIVE_TO_EDGES, + "pixels-relative-to-edges", "pixels-relative-to-edges"}, + {GST_GDK_PIXBUF_POSITIONING_PIXELS_ABSOLUTE, "pixels-absolute", + "pixels-absolute"}, + {0, NULL, NULL}, + }; + + static GType type; /* 0 */ + + if (!type) { + type = g_enum_register_static ("GstGdkPixbufPositioningMode", pos_modes); + } + + return type; +} + static void gst_gdk_pixbuf_overlay_class_init (GstGdkPixbufOverlayClass * klass) { @@ -193,6 +221,24 @@ gst_gdk_pixbuf_overlay_class_init (GstGdkPixbufOverlayClass * klass) g_param_spec_object ("pixbuf", "Pixbuf", "GdkPixbuf object to render", GDK_TYPE_PIXBUF, GST_PARAM_CONTROLLABLE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstGdkPixbufOverlay:positioning-mode: + * + * Positioning mode of offset-x and offset-y properties. Determines how + * negative x/y offsets will be interpreted. By default negative values + * are for positioning relative to the right/bottom edge of the video + * image, but you can use this property to select absolute positioning + * relative to a (0, 0) origin in the top-left corner. That way negative + * offsets will be to the left/above the video image, which allows you to + * smoothly slide logos into and out of the frame if desired. + * + * Since: 1.6 + */ + g_object_class_install_property (gobject_class, PROP_POSITIONING_MODE, + g_param_spec_enum ("positioning-mode", "Positioning mode", + "Positioning mode of offset-x and offset-y properties", + GST_TYPE_GDK_PIXBUF_POSITIONING_MODE, DEFAULT_POSITIONING_MODE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&sink_template)); @@ -216,6 +262,8 @@ gst_gdk_pixbuf_overlay_init (GstGdkPixbufOverlay * overlay) overlay->relative_x = 0.0; overlay->relative_y = 0.0; + overlay->positioning_mode = DEFAULT_POSITIONING_MODE; + overlay->overlay_width = 0; overlay->overlay_height = 0; @@ -281,6 +329,10 @@ gst_gdk_pixbuf_overlay_set_property (GObject * object, guint property_id, overlay->alpha = g_value_get_double (value); overlay->update_composition = TRUE; break; + case PROP_POSITIONING_MODE: + overlay->positioning_mode = g_value_get_enum (value); + overlay->update_composition = TRUE; + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -325,6 +377,9 @@ gst_gdk_pixbuf_overlay_get_property (GObject * object, guint property_id, case PROP_ALPHA: g_value_set_double (value, overlay->alpha); break; + case PROP_POSITIONING_MODE: + g_value_set_enum (value, overlay->positioning_mode); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -479,6 +534,7 @@ gst_gdk_pixbuf_overlay_set_info (GstVideoFilter * filter, GstCaps * incaps, static void gst_gdk_pixbuf_overlay_update_composition (GstGdkPixbufOverlay * overlay) { + GstGdkPixbufPositioningMode positioning_mode; GstVideoOverlayComposition *comp; GstVideoOverlayRectangle *rect; GstVideoMeta *overlay_meta; @@ -498,14 +554,21 @@ gst_gdk_pixbuf_overlay_update_composition (GstGdkPixbufOverlay * overlay) overlay_meta = gst_buffer_get_video_meta (overlay->pixels); - x = overlay->offset_x < 0 ? - video_width + overlay->offset_x - overlay_meta->width + - (overlay->relative_x * overlay_meta->width) : - overlay->offset_x + (overlay->relative_x * overlay_meta->width); - y = overlay->offset_y < 0 ? - video_height + overlay->offset_y - overlay_meta->height + - (overlay->relative_y * overlay_meta->height) : - overlay->offset_y + (overlay->relative_y * overlay_meta->height); + positioning_mode = overlay->positioning_mode; + + if (positioning_mode == GST_GDK_PIXBUF_POSITIONING_PIXELS_ABSOLUTE) { + x = overlay->offset_x + (overlay->relative_x * overlay_meta->width); + y = overlay->offset_y + (overlay->relative_y * overlay_meta->height); + } else { + x = overlay->offset_x < 0 ? + video_width + overlay->offset_x - overlay_meta->width + + (overlay->relative_x * overlay_meta->width) : + overlay->offset_x + (overlay->relative_x * overlay_meta->width); + y = overlay->offset_y < 0 ? + video_height + overlay->offset_y - overlay_meta->height + + (overlay->relative_y * overlay_meta->height) : + overlay->offset_y + (overlay->relative_y * overlay_meta->height); + } width = overlay->overlay_width; if (width == 0) diff --git a/ext/gdk_pixbuf/gstgdkpixbufoverlay.h b/ext/gdk_pixbuf/gstgdkpixbufoverlay.h index 2b7ab1eabc..36b919b286 100644 --- a/ext/gdk_pixbuf/gstgdkpixbufoverlay.h +++ b/ext/gdk_pixbuf/gstgdkpixbufoverlay.h @@ -37,6 +37,11 @@ G_BEGIN_DECLS typedef struct _GstGdkPixbufOverlay GstGdkPixbufOverlay; typedef struct _GstGdkPixbufOverlayClass GstGdkPixbufOverlayClass; +typedef enum { + GST_GDK_PIXBUF_POSITIONING_PIXELS_RELATIVE_TO_EDGES, + GST_GDK_PIXBUF_POSITIONING_PIXELS_ABSOLUTE +} GstGdkPixbufPositioningMode; + /** * GstGdkPixbufOverlay: * @@ -58,6 +63,8 @@ struct _GstGdkPixbufOverlay gdouble relative_x; gdouble relative_y; + GstGdkPixbufPositioningMode positioning_mode; + gint overlay_width; gint overlay_height;