From 73a6055bdf16990ff6abaed612b8527db439a9f8 Mon Sep 17 00:00:00 2001 From: Edgard Lima Date: Fri, 24 Feb 2006 19:51:29 +0000 Subject: I'm too lazy to comment this Original commit message from CVS: Gdkpixbuf ported from 0.8 to 0.10 by Renato Filho . gst_loader and gdkpixbufanimation still need port. --- ext/Makefile.am | 9 +- ext/gdk_pixbuf/Makefile.am | 39 +-- ext/gdk_pixbuf/gstgdkpixbuf.c | 332 +++++++++++++------------ ext/gdk_pixbuf/gstgdkpixbuf.h | 14 +- ext/gdk_pixbuf/pixbufscale.c | 561 +++++++++++++++++++++--------------------- ext/gdk_pixbuf/pixbufscale.h | 29 ++- 6 files changed, 501 insertions(+), 483 deletions(-) (limited to 'ext') diff --git a/ext/Makefile.am b/ext/Makefile.am index e8bdd8c5..bfc10ccf 100644 --- a/ext/Makefile.am +++ b/ext/Makefile.am @@ -40,11 +40,11 @@ else GCONF_DIR = endif -# if USE_GDK_PIXBUF -# GDK_PIXBUF_DIR = gdk_pixbuf -# else +if USE_GDK_PIXBUF +GDK_PIXBUF_DIR = gdk_pixbuf +else GDK_PIXBUF_DIR = -# endif +endif if USE_HAL HAL_DIR = hal @@ -141,6 +141,7 @@ DIST_SUBDIRS = \ esd \ flac \ gconf \ + gdk_pixbuf \ hal \ jpeg \ ladspa \ diff --git a/ext/gdk_pixbuf/Makefile.am b/ext/gdk_pixbuf/Makefile.am index ac18389a..8d5abb03 100644 --- a/ext/gdk_pixbuf/Makefile.am +++ b/ext/gdk_pixbuf/Makefile.am @@ -1,30 +1,31 @@ plugin_LTLIBRARIES = libgstgdkpixbuf.la libgstgdkpixbuf_la_SOURCES = gstgdkpixbuf.c pixbufscale.c -libgstgdkpixbuf_la_CFLAGS = $(GST_CFLAGS) $(GTK_CFLAGS) -libgstgdkpixbuf_la_LIBADD = $(GST_LIBS) $(GTK_LIBS) +libgstgdkpixbuf_la_CFLAGS = $(GST_CFLAGS) $(GTK_CFLAGS) $(GST_BASE_CFLAGS) +libgstgdkpixbuf_la_LIBADD = $(GTK_LIBS) $(GST_BASE_LIBS) libgstgdkpixbuf_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -if HAVE_GDK_LOADERS -loaderdir = $(DESTDIR)$(GDK_PIXBUF_LOADER_DIR) -loader_LTLIBRARIES = gst_loader.la -install-data-hook: - if test -z "$(DESTDIR)" ; then \ - $(mkinstalldirs) $(DESTDIR)$(GDK_PIXBUF_CONF_DIR) ; \ - $(QUERYLOADERS) > $(DESTDIR)$(GDK_PIXBUF_CONF_DIR)/gdk-pixbuf.loaders ; \ - fi - -gst_loader_la_CFLAGS = $(GST_CFLAGS) $(GTK_CFLAGS) -DGDK_PIXBUF_ENABLE_BACKEND -gst_loader_la_SOURCES = \ - gstgdkanimation.c \ - gst_loader.c -gst_loader_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -gst_loader_la_LIBADD = $(GTK_LIBS) $(GST_LIBS) -else +#if +#loaderdir = $(DESTDIR)$(GDK_PIXBUF_LOADER_DIR) +#loader_LTLIBRARIES = gst_loader.la +# +#install-data-hook: +# if test -z "$(DESTDIR)" ; then \ +# $(mkinstalldirs) $(DESTDIR)$(GDK_PIXBUF_CONF_DIR) ; \ +# $(QUERYLOADERS) > $(DESTDIR)$(GDK_PIXBUF_CONF_DIR)/gdk-pixbuf.loaders ; \ +# fi +# +#gst_loader_la_CFLAGS = $(GST_CFLAGS) $(GTK_CFLAGS) -DGDK_PIXBUF_ENABLE_BACKEND +#gst_loader_la_SOURCES = \ +# gstgdkanimation.c \ +# gst_loader.c +#gst_loader_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) --avoid-version --module +#gst_loader_la_LIBADD = $(GTK_LIBS) $(GST_LIBS) +#else install-data-hook: true -endif +#endif noinst_HEADERS = gstgdkpixbuf.h \ pixbufscale.h \ diff --git a/ext/gdk_pixbuf/gstgdkpixbuf.c b/ext/gdk_pixbuf/gstgdkpixbuf.c index 34a1678e..34dcae94 100644 --- a/ext/gdk_pixbuf/gstgdkpixbuf.c +++ b/ext/gdk_pixbuf/gstgdkpixbuf.c @@ -37,7 +37,7 @@ static GstElementDetails plugin_details = { "GdkPixbuf image decoder", "Codec/Decoder/Image", "Decodes images in a video stream using GdkPixbuf", - "David A. Schleef ", + "David A. Schleef , Renato Filho ", }; /* Filter signals and args */ @@ -53,6 +53,8 @@ enum ARG_SILENT }; + + static GstStaticPadTemplate gst_gdk_pixbuf_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, @@ -88,46 +90,53 @@ gboolean pixbufscale_init (GstPlugin * plugin); static void gst_gdk_pixbuf_base_init (gpointer g_class); static void gst_gdk_pixbuf_class_init (GstGdkPixbufClass * klass); -static void gst_gdk_pixbuf_init (GstGdkPixbuf * filter); +static void gst_gdk_pixbuf_init (GstGdkPixbuf * filter, + GstGdkPixbufClass * klass); static void gst_gdk_pixbuf_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void gst_gdk_pixbuf_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -static void gst_gdk_pixbuf_chain (GstPad * pad, GstData * _data); +static GstFlowReturn gst_gdk_pixbuf_chain (GstPad * pad, GstBuffer * buffer); +static gboolean gst_gdk_pixbuf_event (GstPad * pad, GstEvent * event); #ifdef enable_typefind static void gst_gdk_pixbuf_type_find (GstTypeFind * tf, gpointer ignore); #endif -static GstElementClass *parent_class = NULL; -static GstPadLinkReturn -gst_gdk_pixbuf_sink_link (GstPad * pad, const GstCaps * caps) +GST_BOILERPLATE (GstGdkPixbuf, gst_gdk_pixbuf, GstElement, GST_TYPE_ELEMENT) + + static gboolean gst_gdk_pixbuf_sink_setcaps (GstPad * pad, GstCaps * caps) { GstGdkPixbuf *filter; - const GValue *fps; + const GValue *framerate; + GstStructure *s; filter = GST_GDK_PIXBUF (gst_pad_get_parent (pad)); - g_return_val_if_fail (filter != NULL, GST_PAD_LINK_REFUSED); - g_return_val_if_fail (GST_IS_GDK_PIXBUF (filter), GST_PAD_LINK_REFUSED); - - fps = gst_structure_get_value (gst_caps_get_structure (caps, 0), "framerate"); - if (fps != NULL && GST_VALUE_HOLDS_FRACTION (fps)) { - filter->fps_n = gst_value_get_fraction_numerator (fps); - filter->fps_d = gst_value_get_fraction_denominator (fps); - } else - return GST_PAD_LINK_REFUSED; + s = gst_caps_get_structure (caps, 0); + + filter->framerate_numerator = 0; + filter->framerate_denominator = 1; + if ((framerate = gst_structure_get_value (s, "framerate")) != NULL) { + filter->framerate_numerator = gst_value_get_fraction_numerator (framerate); + filter->framerate_denominator = + gst_value_get_fraction_denominator (framerate); + GST_DEBUG ("got framerate of %d/%d fps => packetized mode", + filter->framerate_numerator, filter->framerate_denominator); + } - return GST_PAD_LINK_OK; + return TRUE; } + #if GDK_PIXBUF_MAJOR == 2 && GDK_PIXBUF_MINOR < 2 /* gdk-pixbuf prior to 2.2 didn't have gdk_pixbuf_get_formats(). * These are just the formats that gdk-pixbuf is known to support. * But maybe not -- it may have been compiled without an external * library. */ + static GstCaps * gst_gdk_pixbuf_get_capslist (void) { @@ -162,7 +171,7 @@ gst_gdk_pixbuf_get_capslist (void) return_caps = gst_caps_intersect (capslist, gst_static_caps_get (&gst_gdk_pixbuf_sink_template.static_caps)); - gst_caps_free (capslist); + gst_caps_unref (capslist); return return_caps; } #endif @@ -179,30 +188,6 @@ gst_gdk_pixbuf_sink_getcaps (GstPad * pad) return gst_gdk_pixbuf_get_capslist (); } -GType -gst_gdk_pixbuf_get_type (void) -{ - static GType plugin_type = 0; - - if (!plugin_type) { - static const GTypeInfo plugin_info = { - sizeof (GstGdkPixbufClass), - gst_gdk_pixbuf_base_init, - NULL, - (GClassInitFunc) gst_gdk_pixbuf_class_init, - NULL, - NULL, - sizeof (GstGdkPixbuf), - 0, - (GInstanceInitFunc) gst_gdk_pixbuf_init, - }; - - plugin_type = g_type_register_static (GST_TYPE_ELEMENT, - "GstGdkPixbuf", &plugin_info, 0); - } - return plugin_type; -} - static void gst_gdk_pixbuf_base_init (gpointer g_class) { @@ -227,161 +212,189 @@ gst_gdk_pixbuf_class_init (GstGdkPixbufClass * klass) parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + gobject_class->set_property = gst_gdk_pixbuf_set_property; + gobject_class->get_property = gst_gdk_pixbuf_get_property; + + g_object_class_install_property (gobject_class, ARG_SILENT, g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?", FALSE, G_PARAM_READWRITE)); - gobject_class->set_property = gst_gdk_pixbuf_set_property; - gobject_class->get_property = gst_gdk_pixbuf_get_property; } static void -gst_gdk_pixbuf_init (GstGdkPixbuf * filter) +gst_gdk_pixbuf_init (GstGdkPixbuf * filter, GstGdkPixbufClass * klass) { filter->sinkpad = gst_pad_new_from_template (gst_static_pad_template_get (&gst_gdk_pixbuf_sink_template), "sink"); - gst_pad_set_link_function (filter->sinkpad, gst_gdk_pixbuf_sink_link); + gst_pad_set_setcaps_function (filter->sinkpad, gst_gdk_pixbuf_sink_setcaps); gst_pad_set_getcaps_function (filter->sinkpad, gst_gdk_pixbuf_sink_getcaps); - filter->srcpad = - gst_pad_new_from_template (gst_static_pad_template_get - (&gst_gdk_pixbuf_src_template), "src"); - gst_pad_use_explicit_caps (filter->srcpad); + gst_pad_set_chain_function (filter->sinkpad, + (GstPadChainFunction) gst_gdk_pixbuf_chain); + + gst_pad_set_event_function (filter->sinkpad, gst_gdk_pixbuf_event); + gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad); + + + filter->srcpad = gst_pad_new_from_template (gst_static_pad_template_get + (&gst_gdk_pixbuf_src_template), "src"); + + gst_pad_use_fixed_caps (filter->srcpad); gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad); - gst_pad_set_chain_function (filter->sinkpad, gst_gdk_pixbuf_chain); - GST_OBJECT_FLAG_SET (GST_ELEMENT (filter), GST_ELEMENT_EVENT_AWARE); + filter->last_timestamp = GST_CLOCK_TIME_NONE; + filter->pixbuf_loader = NULL; } -static void -gst_gdk_pixbuf_chain (GstPad * pad, GstData * _data) +static GstFlowReturn +gst_gdk_pixbuf_flush (GstGdkPixbuf * filter) { - GstBuffer *buf = GST_BUFFER (_data); - GstGdkPixbuf *filter; - GError *error = NULL; - gboolean push_buffer = FALSE; - gboolean dump_buffer = FALSE; - gboolean got_eos = FALSE; - - GST_DEBUG ("gst_gdk_pixbuf_chain"); + GstBuffer *outbuf; + GdkPixbuf *pixbuf; + int y; + guint8 *out_pix; + guint8 *in_pix; + int in_rowstride; + GstFlowReturn ret; + GstCaps *caps = NULL; + + pixbuf = gdk_pixbuf_loader_get_pixbuf (filter->pixbuf_loader); + if (pixbuf == NULL) { + GST_DEBUG ("error geting pixbuf"); + return GST_FLOW_ERROR; + } - g_return_if_fail (GST_IS_PAD (pad)); - g_return_if_fail (buf != NULL); - - filter = GST_GDK_PIXBUF (GST_OBJECT_PARENT (pad)); - g_return_if_fail (GST_IS_GDK_PIXBUF (filter)); - - if (GST_IS_EVENT (_data)) { - GstEvent *event = GST_EVENT (buf); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_EOS: - push_buffer = TRUE; - got_eos = TRUE; - break; - case GST_EVENT_DISCONTINUOUS: - dump_buffer = TRUE; - break; - default: - gst_pad_event_default (pad, event); - return; + if (filter->image_size == 0) { + filter->width = gdk_pixbuf_get_width (pixbuf); + filter->height = gdk_pixbuf_get_height (pixbuf); + filter->rowstride = gdk_pixbuf_get_rowstride (pixbuf); + filter->image_size = filter->rowstride * filter->height; + + if (gdk_pixbuf_get_rowstride (pixbuf) / filter->width == 4) { + caps = gst_caps_from_string (GST_VIDEO_CAPS_RGBA); + } else if (gdk_pixbuf_get_rowstride (pixbuf) / filter->width == 3) { + caps = gst_caps_from_string (GST_VIDEO_CAPS_RGB); + } else { + GST_ELEMENT_ERROR (filter, CORE, NEGOTIATION, (NULL), + ("Bpp %d not supported", gdk_pixbuf_get_bits_per_sample (pixbuf))); + return GST_FLOW_ERROR; } + gst_caps_set_simple (caps, + "width", G_TYPE_INT, filter->width, + "height", G_TYPE_INT, filter->height, + "framerate", GST_TYPE_FRACTION, filter->framerate_numerator, + filter->framerate_denominator, NULL); + + GST_DEBUG ("Set size to %dx%d", filter->width, filter->height); + gst_pad_set_caps (filter->srcpad, caps); + gst_caps_unref (caps); } - if (filter->last_timestamp != GST_BUFFER_TIMESTAMP (buf)) { - push_buffer = TRUE; + ret = gst_pad_alloc_buffer_and_set_caps (filter->srcpad, + GST_BUFFER_OFFSET_NONE, + filter->image_size, GST_PAD_CAPS (filter->srcpad), &outbuf); + + if (ret != GST_FLOW_OK) { + GST_DEBUG ("Failed to create outbuffer - %d", ret); + return GST_FLOW_ERROR; } - if (push_buffer) { - if (filter->pixbuf_loader != NULL) { - GstBuffer *outbuf; - GdkPixbuf *pixbuf; - GError *error = NULL; + gst_caps_unref (caps); + caps = gst_pad_get_negotiated_caps (filter->srcpad); + GST_DEBUG ("Caps negotiated %s", gst_caps_to_string (caps)); + gst_caps_unref (caps); - if (!gdk_pixbuf_loader_close (filter->pixbuf_loader, &error)) { - GST_ELEMENT_ERROR (filter, LIBRARY, SHUTDOWN, (NULL), (error->message)); - g_error_free (error); - return; - } + GST_BUFFER_TIMESTAMP (outbuf) = filter->last_timestamp; + GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE; - pixbuf = gdk_pixbuf_loader_get_pixbuf (filter->pixbuf_loader); + in_pix = gdk_pixbuf_get_pixels (pixbuf); + in_rowstride = gdk_pixbuf_get_rowstride (pixbuf); + out_pix = GST_BUFFER_DATA (outbuf); - if (filter->image_size == 0) { - GstCaps *caps; + for (y = 0; y < filter->height; y++) { + memcpy (out_pix, in_pix, filter->rowstride); + in_pix += in_rowstride; + out_pix += filter->rowstride; + } - filter->width = gdk_pixbuf_get_width (pixbuf); - filter->height = gdk_pixbuf_get_height (pixbuf); - /* gdk_pixbuf likes to pad rowstride to 4 byte boundaries which we can't do - * at the moment - */ - filter->rowstride = filter->width * 3; - filter->image_size = filter->rowstride * filter->height; + GST_DEBUG ("pushing... %d bytes", GST_BUFFER_SIZE (outbuf)); + return gst_pad_push (filter->srcpad, outbuf); +} - caps = gst_caps_copy (gst_pad_get_pad_template_caps (filter->srcpad)); - gst_caps_set_simple (caps, - "width", G_TYPE_INT, filter->width, - "height", G_TYPE_INT, filter->height, - "framerate", G_TYPE_DOUBLE, filter->framerate, NULL); +static gboolean +gst_gdk_pixbuf_event (GstPad * pad, GstEvent * event) +{ + GstFlowReturn res = GST_FLOW_OK; + gboolean ret = TRUE; + GstGdkPixbuf *pixbuf; - gst_pad_set_explicit_caps (filter->srcpad, caps); - } + pixbuf = GST_GDK_PIXBUF (gst_pad_get_parent (pad)); - outbuf = - gst_pad_alloc_buffer_and_set_caps (filter->srcpad, - GST_BUFFER_OFFSET_NONE, filter->image_size); - GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf); - GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buf); - - { - int y; - guint8 *out_pix; - guint8 *in_pix; - int in_rowstride; - - in_pix = gdk_pixbuf_get_pixels (pixbuf); - in_rowstride = gdk_pixbuf_get_rowstride (pixbuf); - out_pix = GST_BUFFER_DATA (outbuf); - - for (y = 0; y < filter->height; y++) { - memcpy (out_pix, in_pix, filter->rowstride); - in_pix += in_rowstride; - out_pix += filter->rowstride; - } + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_EOS: + gdk_pixbuf_loader_close (pixbuf->pixbuf_loader, NULL); + res = gst_gdk_pixbuf_flush (pixbuf); + g_object_unref (G_OBJECT (pixbuf->pixbuf_loader)); + break; + case GST_EVENT_NEWSEGMENT: + case GST_EVENT_FLUSH_STOP: + if (pixbuf->pixbuf_loader != NULL) { + gdk_pixbuf_loader_close (pixbuf->pixbuf_loader, NULL); + g_object_unref (G_OBJECT (pixbuf->pixbuf_loader)); + pixbuf->pixbuf_loader = NULL; } - - gst_pad_push (filter->srcpad, GST_DATA (outbuf)); - - g_object_unref (G_OBJECT (filter->pixbuf_loader)); - filter->pixbuf_loader = NULL; - dump_buffer = FALSE; - } + break; + default: + break; } - if (dump_buffer) { - if (filter->pixbuf_loader != NULL) { - gdk_pixbuf_loader_close (filter->pixbuf_loader, NULL); - g_object_unref (G_OBJECT (filter->pixbuf_loader)); - filter->pixbuf_loader = NULL; - } + if (res == GST_FLOW_OK) { + ret = gst_pad_event_default (pad, event); + } else { + ret = FALSE; } - if (GST_IS_BUFFER (_data)) { - if (filter->pixbuf_loader == NULL) { - filter->pixbuf_loader = gdk_pixbuf_loader_new (); - filter->last_timestamp = GST_BUFFER_TIMESTAMP (buf); - } + gst_object_unref (pixbuf); + + return ret; +} + +static GstFlowReturn +gst_gdk_pixbuf_chain (GstPad * pad, GstBuffer * buf) +{ + GstGdkPixbuf *filter; + GstFlowReturn ret = GST_FLOW_OK; + GError *error = NULL; + GstClockTime timestamp; - gdk_pixbuf_loader_write (filter->pixbuf_loader, GST_BUFFER_DATA (buf), - GST_BUFFER_SIZE (buf), &error); - gst_buffer_unref (buf); + GST_DEBUG ("gst_gdk_pixbuf_chain"); + filter = GST_GDK_PIXBUF (gst_pad_get_parent (pad)); + + timestamp = GST_BUFFER_TIMESTAMP (buf); + + if (GST_CLOCK_TIME_IS_VALID (timestamp)) { + filter->last_timestamp = timestamp; } - if (got_eos) { - gst_pad_event_default (pad, GST_EVENT (_data)); + if (filter->pixbuf_loader == NULL) { + filter->pixbuf_loader = gdk_pixbuf_loader_new (); } + + GST_DEBUG ("Writing buffer size %d", GST_BUFFER_SIZE (buf)); + if (gdk_pixbuf_loader_write (filter->pixbuf_loader, GST_BUFFER_DATA (buf), + GST_BUFFER_SIZE (buf), &error) == FALSE) { + GST_DEBUG ("gst_gdk_pixbuf_chain ERROR: %s", error->message); + ret = GST_FLOW_ERROR; + goto need_more_data; + } + +need_more_data: + gst_object_unref (filter); + return ret; } static void @@ -395,7 +408,7 @@ gst_gdk_pixbuf_set_property (GObject * object, guint prop_id, switch (prop_id) { case ARG_SILENT: - //filter->silent = g_value_get_boolean (value); + /* filter->silent = g_value_get_boolean (value); */ break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -414,7 +427,7 @@ gst_gdk_pixbuf_get_property (GObject * object, guint prop_id, switch (prop_id) { case ARG_SILENT: - //g_value_set_boolean (value, filter->silent); + /* g_value_set_boolean (value, filter->silent); */ break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -496,10 +509,11 @@ plugin_init (GstPlugin * plugin) return TRUE; } + /* this is the structure that gst-register looks for * so keep the name plugin_desc, or you cannot get your plug-in registered */ GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, "gdkpixbuf", - "GDK Pixbuf decoder & scaler", plugin_init, VERSION, "LGPL", - GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) + "GDK Pixbuf decoder & scaler", + plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/ext/gdk_pixbuf/gstgdkpixbuf.h b/ext/gdk_pixbuf/gstgdkpixbuf.h index 4a1f9a3d..a6f527a2 100644 --- a/ext/gdk_pixbuf/gstgdkpixbuf.h +++ b/ext/gdk_pixbuf/gstgdkpixbuf.h @@ -28,15 +28,15 @@ G_BEGIN_DECLS /* #define's don't like whitespacey bits */ -#define GST_TYPE_GDK_PIXBUF \ +#define GST_TYPE_GDK_PIXBUF \ (gst_gdk_pixbuf_get_type()) -#define GST_GDK_PIXBUF(obj) \ +#define GST_GDK_PIXBUF(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GDK_PIXBUF,GstGdkPixbuf)) -#define GST_GDK_PIXBUF_CLASS(klass) \ +#define GST_GDK_PIXBUF_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GDK_PIXBUF,GstGdkPixbuf)) -#define GST_IS_GDK_PIXBUF(obj) \ +#define GST_IS_GDK_PIXBUF(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GDK_PIXBUF)) -#define GST_IS_GDK_PIXBUF_CLASS(obj) \ +#define GST_IS_GDK_PIXBUF_CLASS(obj) \ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GDK_PIXBUF)) typedef struct _GstGdkPixbuf GstGdkPixbuf; @@ -56,8 +56,8 @@ struct _GstGdkPixbuf int rowstride; unsigned int image_size; - gint fps_n; - gint fps_d; + gint framerate_numerator; + gint framerate_denominator; }; struct _GstGdkPixbufClass diff --git a/ext/gdk_pixbuf/pixbufscale.c b/ext/gdk_pixbuf/pixbufscale.c index 6b52b426..77b955bc 100644 --- a/ext/gdk_pixbuf/pixbufscale.c +++ b/ext/gdk_pixbuf/pixbufscale.c @@ -36,7 +36,6 @@ #define GST_RGB24_SIZE(width,height) ((height)*GST_RGB24_ROWSTRIDE(width)) -/* debug variable definition */ GST_DEBUG_CATEGORY (pixbufscale_debug); #define GST_CAT_DEFAULT pixbufscale_debug @@ -45,7 +44,9 @@ static GstElementDetails pixbufscale_details = GST_ELEMENT_DETAILS ("Gdk Pixbuf scaler", "Filter/Effect/Video", "Resizes video", - "Jan Schmidt \nWim Taymans "); + "Jan Schmidt \n" + "Wim Taymans \n" + "Renato Filho "); /* GstPixbufScale signals and args */ enum @@ -81,10 +82,10 @@ gst_pixbufscale_method_get_type (void) { static GType pixbufscale_method_type = 0; static GEnumValue pixbufscale_methods[] = { - {GST_PIXBUFSCALE_NEAREST, "Nearest Neighbour", "nearest"}, - {GST_PIXBUFSCALE_TILES, "Tiles", "tiles"}, - {GST_PIXBUFSCALE_BILINEAR, "Bilinear", "bilinear"}, - {GST_PIXBUFSCALE_HYPER, "Hyper", "hyper"}, + {GST_PIXBUFSCALE_NEAREST, "0", "Nearest Neighbour"}, + {GST_PIXBUFSCALE_TILES, "1", "Tiles"}, + {GST_PIXBUFSCALE_BILINEAR, "2", "Bilinear"}, + {GST_PIXBUFSCALE_HYPER, "3", "Hyper"}, {0, NULL, NULL}, }; @@ -97,46 +98,33 @@ gst_pixbufscale_method_get_type (void) static void gst_pixbufscale_base_init (gpointer g_class); static void gst_pixbufscale_class_init (GstPixbufScaleClass * klass); -static void gst_pixbufscale_init (GstPixbufScale * pixbufscale); -static gboolean gst_pixbufscale_handle_src_event (GstPad * pad, - GstEvent * event); - +static void gst_pixbufscale_init (GstPixbufScale * pixbufscale, + GstPixbufScaleClass * kclass); static void gst_pixbufscale_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void gst_pixbufscale_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -static void gst_pixbufscale_chain (GstPad * pad, GstData * _data); +static GstCaps *gst_pixbufscale_transform_caps (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps); +static gboolean gst_pixbufscale_set_caps (GstBaseTransform * trans, + GstCaps * in, GstCaps * out); +static gboolean gst_pixbufscale_get_unit_size (GstBaseTransform * trans, + GstCaps * caps, guint * size); +static void gst_pixbufscale_fixate_caps (GstBaseTransform * base, + GstPadDirection direction, GstCaps * caps, GstCaps * othercaps); +static GstFlowReturn gst_pixbufscale_transform (GstBaseTransform * trans, + GstBuffer * in, GstBuffer * out); +static gboolean gst_pixbufscale_handle_src_event (GstPad * pad, + GstEvent * event); -static GstElementClass *parent_class = NULL; -GType -gst_pixbufscale_get_type (void) -{ - static GType pixbufscale_type = 0; - - if (!pixbufscale_type) { - static const GTypeInfo pixbufscale_info = { - sizeof (GstPixbufScaleClass), - gst_pixbufscale_base_init, - NULL, - (GClassInitFunc) gst_pixbufscale_class_init, - NULL, - NULL, - sizeof (GstPixbufScale), - 0, - (GInstanceInitFunc) gst_pixbufscale_init, - }; - - pixbufscale_type = - g_type_register_static (GST_TYPE_ELEMENT, "GstPixbufScale", - &pixbufscale_info, 0); - } - return pixbufscale_type; -} +static gboolean parse_caps (GstCaps * caps, gint * width, gint * height); -static void -gst_pixbufscale_base_init (gpointer g_class) +GST_BOILERPLATE (GstPixbufScale, gst_pixbufscale, GstBaseTransform, + GST_TYPE_BASE_TRANSFORM) + + static void gst_pixbufscale_base_init (gpointer g_class) { GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); @@ -151,42 +139,110 @@ static void gst_pixbufscale_class_init (GstPixbufScaleClass * klass) { GObjectClass *gobject_class; - GstElementClass *gstelement_class; + GstBaseTransformClass *trans_class; gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; + trans_class = (GstBaseTransformClass *) klass; + + gobject_class->set_property = gst_pixbufscale_set_property; + gobject_class->get_property = gst_pixbufscale_get_property; - g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_METHOD, + g_object_class_install_property (gobject_class, + ARG_METHOD, g_param_spec_enum ("method", "method", "method", GST_TYPE_PIXBUFSCALE_METHOD, GST_PIXBUFSCALE_BILINEAR, G_PARAM_READWRITE)); - parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + trans_class->transform_caps = + GST_DEBUG_FUNCPTR (gst_pixbufscale_transform_caps); + trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_pixbufscale_set_caps); + trans_class->get_unit_size = + GST_DEBUG_FUNCPTR (gst_pixbufscale_get_unit_size); + trans_class->transform = GST_DEBUG_FUNCPTR (gst_pixbufscale_transform); + trans_class->fixate_caps = GST_DEBUG_FUNCPTR (gst_pixbufscale_fixate_caps); + trans_class->passthrough_on_same_caps = TRUE; - gobject_class->set_property = gst_pixbufscale_set_property; - gobject_class->get_property = gst_pixbufscale_get_property; + parent_class = g_type_class_peek_parent (klass); } +static void +gst_pixbufscale_init (GstPixbufScale * pixbufscale, + GstPixbufScaleClass * kclass) +{ + GST_DEBUG_OBJECT (pixbufscale, "_init"); + GstBaseTransform *trans = GST_BASE_TRANSFORM (pixbufscale); + + gst_pad_set_event_function (trans->srcpad, gst_pixbufscale_handle_src_event); + + pixbufscale->method = GST_PIXBUFSCALE_TILES; + pixbufscale->gdk_method = GDK_INTERP_TILES; +} + +static void +gst_pixbufscale_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstPixbufScale *src; + + g_return_if_fail (GST_IS_PIXBUFSCALE (object)); + src = GST_PIXBUFSCALE (object); + + switch (prop_id) { + case ARG_METHOD: + src->method = g_value_get_enum (value); + switch (src->method) { + case GST_PIXBUFSCALE_NEAREST: + src->gdk_method = GDK_INTERP_NEAREST; + break; + case GST_PIXBUFSCALE_TILES: + src->gdk_method = GDK_INTERP_TILES; + break; + case GST_PIXBUFSCALE_BILINEAR: + src->gdk_method = GDK_INTERP_BILINEAR; + break; + case GST_PIXBUFSCALE_HYPER: + src->gdk_method = GDK_INTERP_HYPER; + break; + } + break; + default: + break; + } +} + +static void +gst_pixbufscale_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstPixbufScale *src; + + g_return_if_fail (GST_IS_PIXBUFSCALE (object)); + src = GST_PIXBUFSCALE (object); + + switch (prop_id) { + case ARG_METHOD: + g_value_set_enum (value, src->method); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + static GstCaps * -gst_pixbufscale_getcaps (GstPad * pad) +gst_pixbufscale_transform_caps (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps) { GstPixbufScale *pixbufscale; - GstCaps *othercaps; - GstCaps *caps; - GstPad *otherpad; + GstCaps *ret; int i; - pixbufscale = GST_PIXBUFSCALE (gst_pad_get_parent (pad)); - - otherpad = (pad == pixbufscale->srcpad) ? pixbufscale->sinkpad : - pixbufscale->srcpad; - othercaps = gst_pad_get_allowed_caps (otherpad); + pixbufscale = GST_PIXBUFSCALE (trans); + ret = gst_caps_copy (caps); - caps = gst_caps_intersect (othercaps, gst_pad_get_pad_template_caps (pad)); - gst_caps_free (othercaps); - - for (i = 0; i < gst_caps_get_size (caps); i++) { - GstStructure *structure = gst_caps_get_structure (caps, i); + for (i = 0; i < gst_caps_get_size (ret); i++) { + GstStructure *structure = gst_caps_get_structure (ret, i); gst_structure_set (structure, "width", GST_TYPE_INT_RANGE, 16, 4096, @@ -194,288 +250,235 @@ gst_pixbufscale_getcaps (GstPad * pad) gst_structure_remove_field (structure, "pixel-aspect-ratio"); } - GST_DEBUG ("getcaps are: %" GST_PTR_FORMAT, caps); - return caps; + GST_DEBUG_OBJECT (trans, "returning caps: %", ret); + return ret; } -static GstPadLinkReturn -gst_pixbufscale_link (GstPad * pad, const GstCaps * caps) +static gboolean +parse_caps (GstCaps * caps, gint * width, gint * height) { - GstPixbufScale *pixbufscale; - GstPadLinkReturn ret; - GstPad *otherpad; + gboolean ret; GstStructure *structure; - int height, width; - gchar *caps_string; - caps_string = gst_caps_to_string (caps); - GST_DEBUG ("gst_pixbufscale_link %s\n", caps_string); - g_free (caps_string); + structure = gst_caps_get_structure (caps, 0); + ret = gst_structure_get_int (structure, "width", width); + ret &= gst_structure_get_int (structure, "height", height); - pixbufscale = GST_PIXBUFSCALE (gst_pad_get_parent (pad)); + return ret; +} - otherpad = (pad == pixbufscale->srcpad) ? pixbufscale->sinkpad : - pixbufscale->srcpad; +static gboolean +gst_pixbufscale_set_caps (GstBaseTransform * trans, GstCaps * in, GstCaps * out) +{ + GstPixbufScale *pixbufscale; + gboolean ret; - structure = gst_caps_get_structure (caps, 0); - ret = gst_structure_get_int (structure, "width", &width); - ret &= gst_structure_get_int (structure, "height", &height); + pixbufscale = GST_PIXBUFSCALE (trans); + ret = parse_caps (in, &pixbufscale->from_width, &pixbufscale->from_height); + ret &= parse_caps (out, &pixbufscale->to_width, &pixbufscale->to_height); + if (!ret) + goto done; - ret = gst_pad_try_set_caps (otherpad, caps); - if (ret == GST_PAD_LINK_OK) { - /* cool, we can use passthru */ + pixbufscale->from_stride = GST_ROUND_UP_4 (pixbufscale->from_width * 3); + pixbufscale->from_buf_size = + pixbufscale->from_stride * pixbufscale->from_height; - pixbufscale->to_width = width; - pixbufscale->to_height = height; - pixbufscale->from_width = width; - pixbufscale->from_height = height; + pixbufscale->to_stride = GST_ROUND_UP_4 (pixbufscale->to_width * 3); + pixbufscale->to_buf_size = pixbufscale->to_stride * pixbufscale->to_height; - pixbufscale->from_buf_size = GST_RGB24_SIZE (width, height); - pixbufscale->to_buf_size = GST_RGB24_SIZE (width, height); - pixbufscale->from_stride = GST_RGB24_ROWSTRIDE (width); - pixbufscale->to_stride = GST_RGB24_ROWSTRIDE (width); + GST_DEBUG_OBJECT (pixbufscale, "from=%dx%d, size %d -> to=%dx%d, size %d", + pixbufscale->from_width, pixbufscale->from_height, + pixbufscale->from_buf_size, pixbufscale->to_width, pixbufscale->to_height, + pixbufscale->to_buf_size); - pixbufscale->inited = TRUE; +done: + return ret; +} - return GST_PAD_LINK_OK; - } - if (gst_pad_is_negotiated (otherpad)) { - GstCaps *newcaps = gst_caps_copy (caps); +static gboolean +gst_pixbufscale_get_unit_size (GstBaseTransform * trans, + GstCaps * caps, guint * size) +{ + GstPixbufScale *pixbufscale; + gint width, height; - if (pad == pixbufscale->srcpad) { - gst_caps_set_simple (newcaps, - "width", G_TYPE_INT, pixbufscale->from_width, - "height", G_TYPE_INT, pixbufscale->from_height, NULL); - } else { - gst_caps_set_simple (newcaps, - "width", G_TYPE_INT, pixbufscale->to_width, - "height", G_TYPE_INT, pixbufscale->to_height, NULL); - } - ret = gst_pad_try_set_caps (otherpad, newcaps); - if (GST_PAD_LINK_FAILED (ret)) { - return GST_PAD_LINK_REFUSED; - } - } + g_return_val_if_fail (size, FALSE); - pixbufscale->passthru = FALSE; + pixbufscale = GST_PIXBUFSCALE (trans); - if (pad == pixbufscale->srcpad) { - pixbufscale->to_width = width; - pixbufscale->to_height = height; - } else { - pixbufscale->from_width = width; - pixbufscale->from_height = height; - } + if (!parse_caps (caps, &width, &height)) + return FALSE; - if (gst_pad_is_negotiated (otherpad)) { - pixbufscale->from_buf_size = - GST_RGB24_SIZE (pixbufscale->from_width, pixbufscale->from_height); - pixbufscale->to_buf_size = - GST_RGB24_SIZE (pixbufscale->to_width, pixbufscale->to_height); - pixbufscale->from_stride = GST_RGB24_ROWSTRIDE (pixbufscale->from_width); - pixbufscale->to_stride = GST_RGB24_ROWSTRIDE (pixbufscale->to_width); - pixbufscale->inited = TRUE; - } + *size = GST_ROUND_UP_4 (width * 3) * height; - return GST_PAD_LINK_OK; + return TRUE; } static void -gst_pixbufscale_init (GstPixbufScale * pixbufscale) +gst_pixbufscale_fixate_caps (GstBaseTransform * base, GstPadDirection direction, + GstCaps * caps, GstCaps * othercaps) { - GST_DEBUG_OBJECT (pixbufscale, "_init"); - pixbufscale->sinkpad = - gst_pad_new_from_template (gst_static_pad_template_get - (&gst_pixbufscale_sink_template), "sink"); - gst_element_add_pad (GST_ELEMENT (pixbufscale), pixbufscale->sinkpad); - gst_pad_set_chain_function (pixbufscale->sinkpad, gst_pixbufscale_chain); - gst_pad_set_link_function (pixbufscale->sinkpad, gst_pixbufscale_link); - gst_pad_set_getcaps_function (pixbufscale->sinkpad, gst_pixbufscale_getcaps); - - pixbufscale->srcpad = - gst_pad_new_from_template (gst_static_pad_template_get - (&gst_pixbufscale_src_template), "src"); - gst_element_add_pad (GST_ELEMENT (pixbufscale), pixbufscale->srcpad); - gst_pad_set_event_function (pixbufscale->srcpad, - gst_pixbufscale_handle_src_event); - gst_pad_set_link_function (pixbufscale->srcpad, gst_pixbufscale_link); - gst_pad_set_getcaps_function (pixbufscale->srcpad, gst_pixbufscale_getcaps); - - pixbufscale->inited = FALSE; - - pixbufscale->method = GST_PIXBUFSCALE_TILES; - pixbufscale->gdk_method = GDK_INTERP_TILES; -} - -static gboolean -gst_pixbufscale_handle_src_event (GstPad * pad, GstEvent * event) -{ - GstPixbufScale *pixbufscale; - double a; - GstStructure *structure; - GstEvent *new_event; + GstStructure *ins, *outs; + const GValue *from_par, *to_par; + + g_return_if_fail (gst_caps_is_fixed (caps)); + + GST_DEBUG_OBJECT (base, "trying to fixate othercaps %" GST_PTR_FORMAT + " based on caps %" GST_PTR_FORMAT, othercaps, caps); + + ins = gst_caps_get_structure (caps, 0); + outs = gst_caps_get_structure (othercaps, 0); + + from_par = gst_structure_get_value (ins, "pixel-aspect-ratio"); + to_par = gst_structure_get_value (outs, "pixel-aspect-ratio"); + + if (from_par && to_par) { + GValue to_ratio = { 0, }; /* w/h of output video */ + int from_w, from_h, from_par_n, from_par_d, to_par_n, to_par_d; + int count = 0, w = 0, h = 0, num, den; + + /* if both width and height are already fixed, we can't do anything + * * about it anymore */ + if (gst_structure_get_int (outs, "width", &w)) + ++count; + if (gst_structure_get_int (outs, "height", &h)) + ++count; + if (count == 2) { + GST_DEBUG_OBJECT (base, "dimensions already set to %dx%d, not fixating", + w, h); + return; + } - pixbufscale = GST_PIXBUFSCALE (gst_pad_get_parent (pad)); + gst_structure_get_int (ins, "width", &from_w); + gst_structure_get_int (ins, "height", &from_h); + from_par_n = gst_value_get_fraction_numerator (from_par); + from_par_d = gst_value_get_fraction_denominator (from_par); + to_par_n = gst_value_get_fraction_numerator (to_par); + to_par_d = gst_value_get_fraction_denominator (to_par); + + g_value_init (&to_ratio, GST_TYPE_FRACTION); + gst_value_set_fraction (&to_ratio, from_w * from_par_n * to_par_d, + from_h * from_par_d * to_par_n); + num = gst_value_get_fraction_numerator (&to_ratio); + den = gst_value_get_fraction_denominator (&to_ratio); + GST_DEBUG_OBJECT (base, + "scaling input with %dx%d and PAR %d/%d to output PAR %d/%d", + from_w, from_h, from_par_n, from_par_d, to_par_n, to_par_d); + GST_DEBUG_OBJECT (base, + "resulting output should respect ratio of %d/%d", num, den); + + /* now find a width x height that respects this display ratio. + * * prefer those that have one of w/h the same as the incoming video + * * using wd / hd = num / den */ + + /* start with same height, because of interlaced video */ + /* check hd / den is an integer scale factor, and scale wd with the PAR */ + if (from_h % den == 0) { + GST_DEBUG_OBJECT (base, "keeping video height"); + h = from_h; + w = h * num / den; + } else if (from_w % num == 0) { + GST_DEBUG_OBJECT (base, "keeping video width"); + w = from_w; + h = w * den / num; + } else { + GST_DEBUG_OBJECT (base, "approximating but keeping video height"); + h = from_h; + w = h * num / den; + } + GST_DEBUG_OBJECT (base, "scaling to %dx%d", w, h); + /* now fixate */ + gst_structure_fixate_field_nearest_int (outs, "width", w); + gst_structure_fixate_field_nearest_int (outs, "height", h); + } else { + gint width, height; - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_NAVIGATION: - structure = gst_structure_copy (event->event_data.structure.structure); - if (gst_structure_get_double (event->event_data.structure.structure, - "pointer_x", &a)) { - gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE, - a * pixbufscale->from_width / pixbufscale->to_width, NULL); + if (gst_structure_get_int (ins, "width", &width)) { + if (gst_structure_has_field (outs, "width")) { + gst_structure_fixate_field_nearest_int (outs, "width", width); } - if (gst_structure_get_double (event->event_data.structure.structure, - "pointer_y", &a)) { - gst_structure_set (structure, "pointer_y", G_TYPE_DOUBLE, - a * pixbufscale->from_height / pixbufscale->to_height, NULL); + } + if (gst_structure_get_int (ins, "height", &height)) { + if (gst_structure_has_field (outs, "height")) { + gst_structure_fixate_field_nearest_int (outs, "height", height); } - gst_event_unref (event); - new_event = gst_event_new (GST_EVENT_NAVIGATION); - new_event->event_data.structure.structure = structure; - return gst_pad_event_default (pad, new_event); - break; - default: - return gst_pad_event_default (pad, event); - break; + } } + + GST_DEBUG_OBJECT (base, "fixated othercaps to %" GST_PTR_FORMAT, othercaps); } -static void -pixbufscale_scale (GstPixbufScale * scale, unsigned char *dest, - unsigned char *src) +static GstFlowReturn +gst_pixbufscale_transform (GstBaseTransform * trans, + GstBuffer * in, GstBuffer * out) { + GstPixbufScale *scale; GdkPixbuf *src_pixbuf, *dest_pixbuf; - src_pixbuf = gdk_pixbuf_new_from_data - (src, GDK_COLORSPACE_RGB, FALSE, + scale = GST_PIXBUFSCALE (trans); + + src_pixbuf = + gdk_pixbuf_new_from_data (GST_BUFFER_DATA (in), GDK_COLORSPACE_RGB, FALSE, 8, scale->from_width, scale->from_height, GST_RGB24_ROWSTRIDE (scale->from_width), NULL, NULL); - dest_pixbuf = gdk_pixbuf_new_from_data - (dest, GDK_COLORSPACE_RGB, FALSE, - 8, scale->to_width, scale->to_height, + + dest_pixbuf = + gdk_pixbuf_new_from_data (GST_BUFFER_DATA (out), GDK_COLORSPACE_RGB, + FALSE, 8, scale->to_width, scale->to_height, GST_RGB24_ROWSTRIDE (scale->to_width), NULL, NULL); - gdk_pixbuf_scale (src_pixbuf, dest_pixbuf, 0, 0, scale->to_width, + + gdk_pixbuf_scale (src_pixbuf, dest_pixbuf, 0, 0, + scale->to_width, scale->to_height, 0, 0, (double) scale->to_width / scale->from_width, (double) scale->to_height / scale->from_height, scale->gdk_method); - dest_pixbuf = gdk_pixbuf_scale_simple - (src_pixbuf, scale->to_width, scale->to_height, scale->gdk_method); - g_object_unref (src_pixbuf); g_object_unref (dest_pixbuf); + + return GST_FLOW_OK; } -static void -gst_pixbufscale_chain (GstPad * pad, GstData * _data) +static gboolean +gst_pixbufscale_handle_src_event (GstPad * pad, GstEvent * event) { - GstBuffer *buf = GST_BUFFER (_data); GstPixbufScale *pixbufscale; - guchar *data; - gulong size; - GstBuffer *outbuf; - - g_return_if_fail (pad != NULL); - g_return_if_fail (GST_IS_PAD (pad)); - g_return_if_fail (buf != NULL); + gboolean ret; + double a; + GstStructure *structure; pixbufscale = GST_PIXBUFSCALE (gst_pad_get_parent (pad)); - g_return_if_fail (pixbufscale->inited); - - data = GST_BUFFER_DATA (buf); - size = GST_BUFFER_SIZE (buf); - - if (pixbufscale->passthru) { - GST_LOG_OBJECT (pixbufscale, "passing through buffer of %ld bytes in '%s'", - size, GST_OBJECT_NAME (pixbufscale)); - gst_pad_push (pixbufscale->srcpad, GST_DATA (buf)); - return; - } - - GST_LOG_OBJECT (pixbufscale, "got buffer of %ld bytes in '%s'", size, - GST_OBJECT_NAME (pixbufscale)); - GST_LOG_OBJECT (pixbufscale, - "size=%ld from=%dx%d to=%dx%d fromsize=%ld (should be %d) tosize=%d", - size, pixbufscale->from_width, pixbufscale->from_height, - pixbufscale->to_width, pixbufscale->to_height, size, - pixbufscale->from_buf_size, pixbufscale->to_buf_size); - - if (size != pixbufscale->from_buf_size) { - GST_ERROR ("Incoming RGB data is %d bytes (expected: %d bytes) (%dx%d)\n", - size, pixbufscale->from_buf_size, pixbufscale->from_width, - pixbufscale->from_height); - return; - } - - outbuf = gst_pad_alloc_buffer_and_set_caps (pixbufscale->srcpad, - GST_BUFFER_OFFSET_NONE, pixbufscale->to_buf_size); - - gst_buffer_stamp (outbuf, buf); - - pixbufscale_scale (pixbufscale, GST_BUFFER_DATA (outbuf), data); - - GST_DEBUG_OBJECT (pixbufscale, "pushing buffer of %d bytes in '%s'", - GST_BUFFER_SIZE (outbuf), GST_OBJECT_NAME (pixbufscale)); - gst_pad_push (pixbufscale->srcpad, GST_DATA (outbuf)); + GST_DEBUG_OBJECT (pixbufscale, "handling %s event", + GST_EVENT_TYPE_NAME (event)); - gst_buffer_unref (buf); -} - -static void -gst_pixbufscale_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstPixbufScale *src; - - g_return_if_fail (GST_IS_PIXBUFSCALE (object)); - src = GST_PIXBUFSCALE (object); + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_NAVIGATION: + event = + GST_EVENT (gst_mini_object_make_writable (GST_MINI_OBJECT (event))); - switch (prop_id) { - case ARG_METHOD: - src->method = g_value_get_enum (value); - switch (src->method) { - case GST_PIXBUFSCALE_NEAREST: - src->gdk_method = GDK_INTERP_NEAREST; - break; - case GST_PIXBUFSCALE_TILES: - src->gdk_method = GDK_INTERP_TILES; - break; - case GST_PIXBUFSCALE_BILINEAR: - src->gdk_method = GDK_INTERP_BILINEAR; - break; - case GST_PIXBUFSCALE_HYPER: - src->gdk_method = GDK_INTERP_HYPER; - break; + structure = (GstStructure *) gst_event_get_structure (event); + if (gst_structure_get_double (structure, "pointer_x", &a)) { + gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE, + a * pixbufscale->from_width / pixbufscale->to_width, NULL); + } + if (gst_structure_get_double (structure, "pointer_y", &a)) { + gst_structure_set (structure, "pointer_y", G_TYPE_DOUBLE, + a * pixbufscale->from_height / pixbufscale->to_height, NULL); } break; default: break; } -} -static void -gst_pixbufscale_get_property (GObject * object, guint prop_id, GValue * value, - GParamSpec * pspec) -{ - GstPixbufScale *src; + ret = gst_pad_event_default (pad, event); - g_return_if_fail (GST_IS_PIXBUFSCALE (object)); - src = GST_PIXBUFSCALE (object); + gst_object_unref (pixbufscale); - switch (prop_id) { - case ARG_METHOD: - g_value_set_enum (value, src->method); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } + return ret; } - gboolean pixbufscale_init (GstPlugin * plugin) { diff --git a/ext/gdk_pixbuf/pixbufscale.h b/ext/gdk_pixbuf/pixbufscale.h index 0d9b10fe..275a0b72 100644 --- a/ext/gdk_pixbuf/pixbufscale.h +++ b/ext/gdk_pixbuf/pixbufscale.h @@ -25,9 +25,21 @@ #include #include +#include G_BEGIN_DECLS +#define GST_TYPE_PIXBUFSCALE \ + (gst_pixbufscale_get_type()) +#define GST_PIXBUFSCALE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PIXBUFSCALE,GstPixbufScale)) +#define GST_PIXBUFSCALE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PIXBUFSCALE,GstPixbufScale)) +#define GST_IS_PIXBUFSCALE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PIXBUFSCALE)) +#define GST_IS_PIXBUFSCALE_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PIXBUFSCALE)) + typedef enum { GST_PIXBUFSCALE_NEAREST, GST_PIXBUFSCALE_TILES, @@ -35,27 +47,14 @@ typedef enum { GST_PIXBUFSCALE_HYPER } GstPixbufScaleMethod; -#define GST_TYPE_PIXBUFSCALE \ - (gst_pixbufscale_get_type()) -#define GST_PIXBUFSCALE(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PIXBUFSCALE,GstPixbufScale)) -#define GST_PIXBUFSCALE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PIXBUFSCALE,GstPixbufScale)) -#define GST_IS_PIXBUFSCALE(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PIXBUFSCALE)) -#define GST_IS_PIXBUFSCALE_CLASS(obj) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PIXBUFSCALE)) typedef struct _GstPixbufScale GstPixbufScale; typedef struct _GstPixbufScaleClass GstPixbufScaleClass; struct _GstPixbufScale { - GstElement element; - - GstPad *sinkpad,*srcpad; + GstBaseTransform element; /* video state */ - gboolean inited; gint to_width; gint to_height; gint from_width; @@ -73,7 +72,7 @@ struct _GstPixbufScale { }; struct _GstPixbufScaleClass { - GstElementClass parent_class; + GstBaseTransformClass parent_class; }; static GType gst_pixbufscale_get_type(void); -- cgit