diff options
Diffstat (limited to 'gst/goom/gstgoom.c')
-rw-r--r-- | gst/goom/gstgoom.c | 279 |
1 files changed, 140 insertions, 139 deletions
diff --git a/gst/goom/gstgoom.c b/gst/goom/gstgoom.c index b05b8f370..86528355d 100644 --- a/gst/goom/gstgoom.c +++ b/gst/goom/gstgoom.c @@ -1,6 +1,7 @@ /* gstgoom.c: implementation of goom drawing element * Copyright (C) <2001> Richard Boulton <richard@tartarus.org> * (C) <2006> Wim Taymans <wim at fluendo dot com> + * (C) <2011> Wim Taymans <wim.taymans at gmail dot com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -28,7 +29,7 @@ * <refsect2> * <title>Example launch line</title> * |[ - * gst-launch -v audiotestsrc ! goom ! ffmpegcolorspace ! xvimagesink + * gst-launch -v audiotestsrc ! goom ! videoconvert ! xvimagesink * ]| * </refsect2> */ @@ -41,6 +42,7 @@ #include <gst/gst.h> #include "gstgoom.h" #include <gst/video/video.h> +#include <gst/audio/audio.h> #include "goom.h" #if HAVE_ORC @@ -71,76 +73,39 @@ enum static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_xRGB_HOST_ENDIAN) +#if G_BYTE_ORDER == G_BIG_ENDIAN + GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("xRGB")) +#else + GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("BGRx")) +#endif ); static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", /* the name of the pads */ GST_PAD_SINK, /* type of the pad */ GST_PAD_ALWAYS, /* ALWAYS/SOMETIMES */ - GST_STATIC_CAPS ("audio/x-raw-int, " - "endianness = (int) BYTE_ORDER, " - "signed = (boolean) TRUE, " - "width = (int) 16, " - "depth = (int) 16, " + GST_STATIC_CAPS ("audio/x-raw, " + "format = (string) " GST_AUDIO_NE (S16) ", " "rate = (int) [ 8000, 96000 ], " "channels = (int) { 1, 2 }") ); -static void gst_goom_class_init (GstGoomClass * klass); -static void gst_goom_base_init (GstGoomClass * klass); -static void gst_goom_init (GstGoom * goom); static void gst_goom_finalize (GObject * object); static GstStateChangeReturn gst_goom_change_state (GstElement * element, GstStateChange transition); -static GstFlowReturn gst_goom_chain (GstPad * pad, GstBuffer * buffer); -static gboolean gst_goom_src_event (GstPad * pad, GstEvent * event); -static gboolean gst_goom_sink_event (GstPad * pad, GstEvent * event); - -static gboolean gst_goom_src_query (GstPad * pad, GstQuery * query); +static GstFlowReturn gst_goom_chain (GstPad * pad, GstObject * parent, + GstBuffer * buffer); +static gboolean gst_goom_src_event (GstPad * pad, GstObject * parent, + GstEvent * event); +static gboolean gst_goom_sink_event (GstPad * pad, GstObject * parent, + GstEvent * event); -static gboolean gst_goom_sink_setcaps (GstPad * pad, GstCaps * caps); -static gboolean gst_goom_src_setcaps (GstPad * pad, GstCaps * caps); +static gboolean gst_goom_src_query (GstPad * pad, GstObject * parent, + GstQuery * query); -static GstElementClass *parent_class = NULL; - -GType -gst_goom_get_type (void) -{ - static GType type = 0; - - if (!type) { - static const GTypeInfo info = { - sizeof (GstGoomClass), - (GBaseInitFunc) gst_goom_base_init, - NULL, - (GClassInitFunc) gst_goom_class_init, - NULL, - NULL, - sizeof (GstGoom), - 0, - (GInstanceInitFunc) gst_goom_init, - }; - - type = g_type_register_static (GST_TYPE_ELEMENT, "GstGoom", &info, 0); - } - return type; -} - -static void -gst_goom_base_init (GstGoomClass * klass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - - gst_element_class_set_details_simple (element_class, "GOOM: what a GOOM!", - "Visualization", - "Takes frames of data and outputs video frames using the GOOM filter", - "Wim Taymans <wim@fluendo.com>"); - gst_element_class_add_static_pad_template (element_class, - &sink_template); - gst_element_class_add_static_pad_template (element_class, &src_template); -} +#define gst_goom_parent_class parent_class +G_DEFINE_TYPE (GstGoom, gst_goom, GST_TYPE_ELEMENT); static void gst_goom_class_init (GstGoomClass * klass) @@ -151,10 +116,17 @@ gst_goom_class_init (GstGoomClass * klass) gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; - parent_class = g_type_class_peek_parent (klass); - gobject_class->finalize = gst_goom_finalize; + gst_element_class_set_details_simple (gstelement_class, "GOOM: what a GOOM!", + "Visualization", + "Takes frames of data and outputs video frames using the GOOM filter", + "Wim Taymans <wim@fluendo.com>"); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&sink_template)); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&src_template)); + gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_goom_change_state); } @@ -167,13 +139,9 @@ gst_goom_init (GstGoom * goom) GST_DEBUG_FUNCPTR (gst_goom_chain)); gst_pad_set_event_function (goom->sinkpad, GST_DEBUG_FUNCPTR (gst_goom_sink_event)); - gst_pad_set_setcaps_function (goom->sinkpad, - GST_DEBUG_FUNCPTR (gst_goom_sink_setcaps)); gst_element_add_pad (GST_ELEMENT (goom), goom->sinkpad); goom->srcpad = gst_pad_new_from_static_template (&src_template, "src"); - gst_pad_set_setcaps_function (goom->srcpad, - GST_DEBUG_FUNCPTR (gst_goom_src_setcaps)); gst_pad_set_event_function (goom->srcpad, GST_DEBUG_FUNCPTR (gst_goom_src_event)); gst_pad_set_query_function (goom->srcpad, @@ -202,6 +170,8 @@ gst_goom_finalize (GObject * object) goom->plugin = NULL; g_object_unref (goom->adapter); + if (goom->pool) + gst_object_unref (goom->pool); G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -219,39 +189,32 @@ gst_goom_reset (GstGoom * goom) } static gboolean -gst_goom_sink_setcaps (GstPad * pad, GstCaps * caps) +gst_goom_sink_setcaps (GstGoom * goom, GstCaps * caps) { - GstGoom *goom; GstStructure *structure; - gboolean res; - - goom = GST_GOOM (GST_PAD_PARENT (pad)); structure = gst_caps_get_structure (caps, 0); - res = gst_structure_get_int (structure, "channels", &goom->channels); - res &= gst_structure_get_int (structure, "rate", &goom->rate); + gst_structure_get_int (structure, "channels", &goom->channels); + gst_structure_get_int (structure, "rate", &goom->rate); goom->bps = goom->channels * sizeof (gint16); - return res; + return TRUE; } static gboolean -gst_goom_src_setcaps (GstPad * pad, GstCaps * caps) +gst_goom_src_setcaps (GstGoom * goom, GstCaps * caps) { - GstGoom *goom; GstStructure *structure; - - goom = GST_GOOM (GST_PAD_PARENT (pad)); + gboolean res; structure = gst_caps_get_structure (caps, 0); - if (!gst_structure_get_int (structure, "width", &goom->width) || !gst_structure_get_int (structure, "height", &goom->height) || !gst_structure_get_fraction (structure, "framerate", &goom->fps_n, &goom->fps_d)) - return FALSE; + goto error; goom_set_resolution (goom->plugin, goom->width, goom->height); @@ -265,7 +228,16 @@ gst_goom_src_setcaps (GstPad * pad, GstCaps * caps) GST_DEBUG_OBJECT (goom, "dimension %dx%d, framerate %d/%d, spf %d", goom->width, goom->height, goom->fps_n, goom->fps_d, goom->spf); - return TRUE; + res = gst_pad_push_event (goom->srcpad, gst_event_new_caps (caps)); + + return res; + + /* ERRORS */ +error: + { + GST_DEBUG_OBJECT (goom, "error parsing caps"); + return FALSE; + } } static gboolean @@ -273,24 +245,28 @@ gst_goom_src_negotiate (GstGoom * goom) { GstCaps *othercaps, *target; GstStructure *structure; - const GstCaps *templ; + GstCaps *templ; + GstQuery *query; + GstBufferPool *pool = NULL; + guint size, min, max, prefix, alignment; templ = gst_pad_get_pad_template_caps (goom->srcpad); GST_DEBUG_OBJECT (goom, "performing negotiation"); /* see what the peer can do */ - othercaps = gst_pad_peer_get_caps (goom->srcpad); + othercaps = gst_pad_peer_query_caps (goom->srcpad, NULL); if (othercaps) { target = gst_caps_intersect (othercaps, templ); gst_caps_unref (othercaps); + gst_caps_unref (templ); if (gst_caps_is_empty (target)) goto no_format; gst_caps_truncate (target); } else { - target = gst_caps_ref ((GstCaps *) templ); + target = templ; } structure = gst_caps_get_structure (target, 0); @@ -299,7 +275,42 @@ gst_goom_src_negotiate (GstGoom * goom) gst_structure_fixate_field_nearest_fraction (structure, "framerate", DEFAULT_FPS_N, DEFAULT_FPS_D); - gst_pad_set_caps (goom->srcpad, target); + gst_goom_src_setcaps (goom, target); + + /* try to get a bufferpool now */ + /* find a pool for the negotiated caps now */ + query = gst_query_new_allocation (target, TRUE); + + if (gst_pad_peer_query (goom->srcpad, query)) { + /* we got configuration from our peer, parse them */ + gst_query_parse_allocation_params (query, &size, &min, &max, &prefix, + &alignment, &pool); + } else { + size = goom->outsize; + min = max = 0; + prefix = 0; + alignment = 0; + } + + if (pool == NULL) { + GstStructure *config; + + /* we did not get a pool, make one ourselves then */ + pool = gst_buffer_pool_new (); + + config = gst_buffer_pool_get_config (pool); + gst_buffer_pool_config_set (config, target, size, min, max, prefix, + alignment); + gst_buffer_pool_set_config (pool, config); + } + + if (goom->pool) + gst_object_unref (goom->pool); + goom->pool = pool; + + /* and activate */ + gst_buffer_pool_set_active (pool, TRUE); + gst_caps_unref (target); return TRUE; @@ -312,12 +323,12 @@ no_format: } static gboolean -gst_goom_src_event (GstPad * pad, GstEvent * event) +gst_goom_src_event (GstPad * pad, GstObject * parent, GstEvent * event) { gboolean res; GstGoom *goom; - goom = GST_GOOM (gst_pad_get_parent (pad)); + goom = GST_GOOM (parent); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_QOS: @@ -326,7 +337,7 @@ gst_goom_src_event (GstPad * pad, GstEvent * event) GstClockTimeDiff diff; GstClockTime timestamp; - gst_event_parse_qos (event, &proportion, &diff, ×tamp); + gst_event_parse_qos (event, NULL, &proportion, &diff, ×tamp); /* save stuff for the _chain() function */ GST_OBJECT_LOCK (goom); @@ -346,20 +357,27 @@ gst_goom_src_event (GstPad * pad, GstEvent * event) res = gst_pad_push_event (goom->sinkpad, event); break; } - gst_object_unref (goom); return res; } static gboolean -gst_goom_sink_event (GstPad * pad, GstEvent * event) +gst_goom_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) { gboolean res; GstGoom *goom; - goom = GST_GOOM (gst_pad_get_parent (pad)); + goom = GST_GOOM (parent); switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_CAPS: + { + GstCaps *caps; + + gst_event_parse_caps (event, &caps); + res = gst_goom_sink_setcaps (goom, caps); + break; + } case GST_EVENT_FLUSH_START: res = gst_pad_push_event (goom->srcpad, event); break; @@ -367,22 +385,12 @@ gst_goom_sink_event (GstPad * pad, GstEvent * event) gst_goom_reset (goom); res = gst_pad_push_event (goom->srcpad, event); break; - case GST_EVENT_NEWSEGMENT: + case GST_EVENT_SEGMENT: { - GstFormat format; - gdouble rate, arate; - gint64 start, stop, time; - gboolean update; - /* the newsegment values are used to clip the input samples * and to convert the incomming timestamps to running time so * we can do QoS */ - gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, - &start, &stop, &time); - - /* now configure the values */ - gst_segment_set_newsegment_full (&goom->segment, update, - rate, arate, format, start, stop, time); + gst_event_copy_segment (event, &goom->segment); res = gst_pad_push_event (goom->srcpad, event); break; @@ -391,18 +399,17 @@ gst_goom_sink_event (GstPad * pad, GstEvent * event) res = gst_pad_push_event (goom->srcpad, event); break; } - gst_object_unref (goom); return res; } static gboolean -gst_goom_src_query (GstPad * pad, GstQuery * query) +gst_goom_src_query (GstPad * pad, GstObject * parent, GstQuery * query) { gboolean res = FALSE; GstGoom *goom; - goom = GST_GOOM (gst_pad_get_parent (pad)); + goom = GST_GOOM (parent); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_LATENCY: @@ -447,59 +454,48 @@ gst_goom_src_query (GstPad * pad, GstQuery * query) break; } default: - res = gst_pad_peer_query (goom->sinkpad, query); + res = gst_pad_query_default (pad, parent, query); break; } - gst_object_unref (goom); - return res; } +/* make sure we are negotiated */ static GstFlowReturn -get_buffer (GstGoom * goom, GstBuffer ** outbuf) +ensure_negotiated (GstGoom * goom) { - GstFlowReturn ret; + gboolean reconfigure; - if (GST_PAD_CAPS (goom->srcpad) == NULL) { + reconfigure = gst_pad_check_reconfigure (goom->srcpad); + + /* we don't know an output format yet, pick one */ + if (reconfigure || !gst_pad_has_current_caps (goom->srcpad)) { if (!gst_goom_src_negotiate (goom)) return GST_FLOW_NOT_NEGOTIATED; } - - GST_DEBUG_OBJECT (goom, "allocating output buffer with caps %" - GST_PTR_FORMAT, GST_PAD_CAPS (goom->srcpad)); - - ret = - gst_pad_alloc_buffer_and_set_caps (goom->srcpad, - GST_BUFFER_OFFSET_NONE, goom->outsize, - GST_PAD_CAPS (goom->srcpad), outbuf); - if (ret != GST_FLOW_OK) - return ret; - return GST_FLOW_OK; } + static GstFlowReturn -gst_goom_chain (GstPad * pad, GstBuffer * buffer) +gst_goom_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) { GstGoom *goom; GstFlowReturn ret; GstBuffer *outbuf = NULL; - goom = GST_GOOM (gst_pad_get_parent (pad)); + goom = GST_GOOM (parent); if (goom->bps == 0) { ret = GST_FLOW_NOT_NEGOTIATED; goto beach; } - /* If we don't have an output format yet, preallocate a buffer to try and - * set one */ - if (GST_PAD_CAPS (goom->srcpad) == NULL) { - ret = get_buffer (goom, &outbuf); - if (ret != GST_FLOW_OK) { - gst_buffer_unref (buffer); - goto beach; - } + /* Make sure have an output format */ + ret = ensure_negotiated (goom); + if (ret != GST_FLOW_OK) { + gst_buffer_unref (buffer); + goto beach; } /* don't try to combine samples from discont buffer */ @@ -508,8 +504,8 @@ gst_goom_chain (GstPad * pad, GstBuffer * buffer) } GST_DEBUG_OBJECT (goom, - "Input buffer has %d samples, time=%" G_GUINT64_FORMAT, - GST_BUFFER_SIZE (buffer) / goom->bps, GST_BUFFER_TIMESTAMP (buffer)); + "Input buffer has %" G_GSIZE_FORMAT " samples, time=%" G_GUINT64_FORMAT, + gst_buffer_get_size (buffer) / goom->bps, GST_BUFFER_TIMESTAMP (buffer)); /* Collect samples until we have enough for an output frame */ gst_adapter_push (goom->adapter, buffer); @@ -518,7 +514,6 @@ gst_goom_chain (GstPad * pad, GstBuffer * buffer) while (TRUE) { const guint16 *data; - gboolean need_skip; guchar *out_frame; gint i; guint avail, to_flush; @@ -545,12 +540,12 @@ gst_goom_chain (GstPad * pad, GstBuffer * buffer) timestamp += gst_util_uint64_scale_int (dist, GST_SECOND, goom->rate); } - if (timestamp != -1) { + if (GST_CLOCK_TIME_IS_VALID (timestamp)) { gint64 qostime; + gboolean need_skip; qostime = gst_segment_to_running_time (&goom->segment, GST_FORMAT_TIME, - timestamp); - qostime += goom->duration; + timestamp) + goom->duration; GST_OBJECT_LOCK (goom); /* check for QoS, don't compute buffers that are known to be late */ @@ -567,7 +562,7 @@ gst_goom_chain (GstPad * pad, GstBuffer * buffer) /* get next GOOM_SAMPLES, we have at least this amount of samples */ data = - (const guint16 *) gst_adapter_peek (goom->adapter, + (const guint16 *) gst_adapter_map (goom->adapter, GOOM_SAMPLES * goom->bps); if (goom->channels == 2) { @@ -585,18 +580,21 @@ gst_goom_chain (GstPad * pad, GstBuffer * buffer) /* alloc a buffer if we don't have one yet, this happens * when we pushed a buffer in this while loop before */ if (outbuf == NULL) { - ret = get_buffer (goom, &outbuf); + GST_DEBUG_OBJECT (goom, "allocating output buffer"); + ret = gst_buffer_pool_acquire_buffer (goom->pool, &outbuf, NULL); if (ret != GST_FLOW_OK) { + gst_adapter_unmap (goom->adapter); goto beach; } } GST_BUFFER_TIMESTAMP (outbuf) = timestamp; GST_BUFFER_DURATION (outbuf) = goom->duration; - GST_BUFFER_SIZE (outbuf) = goom->outsize; out_frame = (guchar *) goom_update (goom->plugin, goom->datain, 0, 0); - memcpy (GST_BUFFER_DATA (outbuf), out_frame, goom->outsize); + gst_buffer_fill (outbuf, 0, out_frame, goom->outsize); + + gst_adapter_unmap (goom->adapter); GST_DEBUG ("Pushing frame with time=%" GST_TIME_FORMAT ", duration=%" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp), @@ -622,7 +620,6 @@ gst_goom_chain (GstPad * pad, GstBuffer * buffer) gst_buffer_unref (outbuf); beach: - gst_object_unref (goom); return ret; } @@ -647,6 +644,10 @@ gst_goom_change_state (GstElement * element, GstStateChange transition) switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: + if (goom->pool) { + gst_buffer_pool_set_active (goom->pool, FALSE); + gst_object_replace ((GstObject **) & goom->pool, NULL); + } break; case GST_STATE_CHANGE_READY_TO_NULL: break; |