diff options
author | Edgard Lima <edgard.lima@indt.org.br> | 2006-02-24 19:51:29 +0000 |
---|---|---|
committer | Edgard Lima <edgard.lima@indt.org.br> | 2006-02-24 19:51:29 +0000 |
commit | 73a6055bdf16990ff6abaed612b8527db439a9f8 (patch) | |
tree | 3debfbff45726f289fcb709da89881795d1aa790 /ext/gdk_pixbuf/gstgdkpixbuf.c | |
parent | 96c1cd6e0a6c1328eed7bbf680ecfbad82c92c72 (diff) |
I'm too lazy to comment this
Original commit message from CVS:
Gdkpixbuf ported from 0.8 to 0.10 by Renato Filho <renato.filho@indt.org.br>. gst_loader and gdkpixbufanimation still need port.
Diffstat (limited to 'ext/gdk_pixbuf/gstgdkpixbuf.c')
-rw-r--r-- | ext/gdk_pixbuf/gstgdkpixbuf.c | 332 |
1 files changed, 173 insertions, 159 deletions
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 <ds@schleef.org>", + "David A. Schleef <ds@schleef.org>, Renato Filho <renato.filho@indt.org.br>", }; /* 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) |