diff options
author | Olivier CrĂȘte <olivier.crete@collabora.com> | 2012-09-12 16:03:06 -0400 |
---|---|---|
committer | Olivier CrĂȘte <olivier.crete@collabora.com> | 2012-09-12 16:03:13 -0400 |
commit | 5111a6ed209a59906f06984191b0322230666523 (patch) | |
tree | b8d669198c777b3552f9d46f45c7eed38eb95883 | |
parent | 27cd08ad9552eabfec8bb070e465a1edd6a7657e (diff) | |
download | gstreamer-plugins-bad-5111a6ed209a59906f06984191b0322230666523.tar.gz |
liveadder: port to 1.0 API
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | gst/liveadder/liveadder.c | 429 | ||||
-rw-r--r-- | gst/liveadder/liveadder.h | 23 |
3 files changed, 227 insertions, 227 deletions
diff --git a/configure.ac b/configure.ac index 7ef5f3571..83bebf9ec 100644 --- a/configure.ac +++ b/configure.ac @@ -315,7 +315,7 @@ GST_PLUGINS_NONPORTED=" aiff \ dccp faceoverlay \ fieldanalysis freeverb freeze frei0r \ hdvparse inter ivfparse jp2kdecimator \ - kate liveadder librfb \ + kate librfb \ mpegpsmux mve mxf mythtv nsf nuvdemux \ patchdetect pnm real \ sdi speed subenc stereo tta videofilters \ diff --git a/gst/liveadder/liveadder.c b/gst/liveadder/liveadder.c index 5cdced4d0..fc6d54ba8 100644 --- a/gst/liveadder/liveadder.c +++ b/gst/liveadder/liveadder.c @@ -1,7 +1,7 @@ /* - * Farsight Voice+Video library + * GStreamer * - * Copyright 2008 Collabora Ltd + * Copyright 2012 Collabora Ltd * Copyright 2008 Nokia Corporation * @author: Olivier Crete <olivier.crete@collabora.co.uk> * @@ -55,19 +55,23 @@ GST_DEBUG_CATEGORY_STATIC (live_adder_debug); #define GST_CAT_DEFAULT (live_adder_debug) static GstStaticPadTemplate gst_live_adder_sink_template = - GST_STATIC_PAD_TEMPLATE ("sink_%u", +GST_STATIC_PAD_TEMPLATE ("sink_%u", GST_PAD_SINK, GST_PAD_REQUEST, - GST_STATIC_CAPS (GST_AUDIO_INT_PAD_TEMPLATE_CAPS "; " - GST_AUDIO_FLOAT_PAD_TEMPLATE_CAPS) + GST_STATIC_CAPS (GST_AUDIO_CAPS_MAKE ("{ S8, U8, " + GST_AUDIO_NE (S16) "," GST_AUDIO_NE (U16) "," + GST_AUDIO_NE (S32) "," GST_AUDIO_NE (U32) "," + GST_AUDIO_NE (F32) "," GST_AUDIO_NE (F64) "}")) ); static GstStaticPadTemplate gst_live_adder_src_template = - GST_STATIC_PAD_TEMPLATE ("src", +GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_AUDIO_INT_PAD_TEMPLATE_CAPS "; " - GST_AUDIO_FLOAT_PAD_TEMPLATE_CAPS) + GST_STATIC_CAPS (GST_AUDIO_CAPS_MAKE ("{ S8, U8, " + GST_AUDIO_NE (S16) "," GST_AUDIO_NE (U16) "," + GST_AUDIO_NE (S32) "," GST_AUDIO_NE (U32) "," + GST_AUDIO_NE (F32) "," GST_AUDIO_NE (F64) "}")) ); /* Valve signals and args */ @@ -92,12 +96,7 @@ typedef struct _GstLiveAdderPadPrivate } GstLiveAdderPadPrivate; -#define _do_init(bla) \ - GST_DEBUG_CATEGORY_INIT (live_adder_debug, "liveadder", 0, "Live Adder"); - -GST_BOILERPLATE_FULL (GstLiveAdder, gst_live_adder, GstElement, - GST_TYPE_ELEMENT, _do_init); - +G_DEFINE_TYPE (GstLiveAdder, gst_live_adder, GST_TYPE_ELEMENT); static void gst_live_adder_finalize (GObject * object); static void @@ -108,20 +107,27 @@ gst_live_adder_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); static GstPad *gst_live_adder_request_new_pad (GstElement * element, - GstPadTemplate * templ, const gchar * unused); + GstPadTemplate * templ, const gchar * name, const GstCaps * caps); static void gst_live_adder_release_pad (GstElement * element, GstPad * pad); static GstStateChangeReturn gst_live_adder_change_state (GstElement * element, GstStateChange transition); -static gboolean gst_live_adder_setcaps (GstPad * pad, GstCaps * caps); -static GstCaps *gst_live_adder_sink_getcaps (GstPad * pad); -static gboolean -gst_live_adder_src_activate_push (GstPad * pad, gboolean active); -static gboolean gst_live_adder_src_event (GstPad * pad, GstEvent * event); +static gboolean gst_live_adder_setcaps (GstLiveAdder * adder, GstPad * pad, + GstCaps * caps); +static GstCaps *gst_live_adder_sink_getcaps (GstLiveAdder * adder, GstPad * pad, + GstCaps * filter); +static gboolean gst_live_adder_src_activate_mode (GstPad * pad, + GstObject * parent, GstPadMode mode, gboolean active); +static gboolean gst_live_adder_src_event (GstPad * pad, GstObject * parent, + GstEvent * event); static void gst_live_adder_loop (gpointer data); -static gboolean gst_live_adder_query (GstPad * pad, GstQuery * query); -static gboolean gst_live_adder_sink_event (GstPad * pad, GstEvent * event); +static gboolean gst_live_adder_src_query (GstPad * pad, GstObject * parent, + GstQuery * query); +static gboolean gst_live_adder_sink_query (GstPad * pad, GstObject * parent, + GstQuery * query); +static gboolean gst_live_adder_sink_event (GstPad * pad, GstObject * parent, + GstEvent * event); static void reset_pad_private (GstPad * pad); @@ -155,10 +161,13 @@ MAKE_FUNC_NC (add_float32, gfloat, gfloat) static void -gst_live_adder_base_init (gpointer klass) +gst_live_adder_class_init (GstLiveAdderClass * klass) { + GObjectClass *gobject_class = (GObjectClass *) klass; GstElementClass *gstelement_class = (GstElementClass *) klass; + GST_DEBUG_CATEGORY_INIT (live_adder_debug, "liveadder", 0, "Live Adder"); + gst_element_class_add_pad_template (gstelement_class, gst_static_pad_template_get (&gst_live_adder_src_template)); gst_element_class_add_pad_template (gstelement_class, @@ -167,13 +176,6 @@ gst_live_adder_base_init (gpointer klass) "Generic/Audio", "Mixes live/discontinuous audio streams", "Olivier Crete <olivier.crete@collabora.co.uk>"); -} - -static void -gst_live_adder_class_init (GstLiveAdderClass * klass) -{ - GObjectClass *gobject_class = (GObjectClass *) klass; - GstElementClass *gstelement_class = (GstElementClass *) klass; gobject_class->finalize = gst_live_adder_finalize; gobject_class->set_property = gst_live_adder_set_property; @@ -190,23 +192,18 @@ gst_live_adder_class_init (GstLiveAdderClass * klass) } static void -gst_live_adder_init (GstLiveAdder * adder, GstLiveAdderClass * klass) +gst_live_adder_init (GstLiveAdder * adder) { adder->srcpad = gst_pad_new_from_static_template (&gst_live_adder_src_template, "src"); - gst_pad_set_getcaps_function (adder->srcpad, - GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps)); - gst_pad_set_setcaps_function (adder->srcpad, - GST_DEBUG_FUNCPTR (gst_live_adder_setcaps)); gst_pad_set_query_function (adder->srcpad, - GST_DEBUG_FUNCPTR (gst_live_adder_query)); + GST_DEBUG_FUNCPTR (gst_live_adder_src_query)); gst_pad_set_event_function (adder->srcpad, GST_DEBUG_FUNCPTR (gst_live_adder_src_event)); - gst_pad_set_activatepush_function (adder->srcpad, - GST_DEBUG_FUNCPTR (gst_live_adder_src_activate_push)); + gst_pad_set_activatemode_function (adder->srcpad, + GST_DEBUG_FUNCPTR (gst_live_adder_src_activate_mode)); gst_element_add_pad (GST_ELEMENT (adder), adder->srcpad); - adder->format = GST_LIVE_ADDER_FORMAT_UNSET; adder->padcount = 0; adder->func = NULL; adder->not_empty_cond = g_cond_new (); @@ -233,7 +230,7 @@ gst_live_adder_finalize (GObject * object) g_list_free (adder->sinkpads); - G_OBJECT_CLASS (parent_class)->finalize (object); + G_OBJECT_CLASS (gst_live_adder_parent_class)->finalize (object); } @@ -294,24 +291,24 @@ gst_live_adder_get_property (GObject * object, /* we can only accept caps that we and downstream can handle. */ static GstCaps * -gst_live_adder_sink_getcaps (GstPad * pad) +gst_live_adder_sink_getcaps (GstLiveAdder * adder, GstPad * pad, + GstCaps * filter) { - GstLiveAdder *adder; GstCaps *result, *peercaps, *sinkcaps; - adder = GST_LIVE_ADDER (GST_PAD_PARENT (pad)); - /* get the downstream possible caps */ - peercaps = gst_pad_peer_get_caps (adder->srcpad); + peercaps = gst_pad_peer_query_caps (adder->srcpad, filter); /* get the allowed caps on this sinkpad, we use the fixed caps function so * that it does not call recursively in this function. */ - sinkcaps = gst_pad_get_fixed_caps_func (pad); + sinkcaps = gst_pad_get_current_caps (pad); + if (!sinkcaps) + sinkcaps = gst_pad_get_pad_template_caps (pad); if (peercaps) { /* if the peer has caps, intersect */ GST_DEBUG_OBJECT (adder, "intersecting peer and template caps"); result = gst_caps_intersect (peercaps, sinkcaps); - gst_caps_unref (peercaps); gst_caps_unref (sinkcaps); + gst_caps_unref (peercaps); } else { /* the peer has no caps (or there is no peer), just use the allowed caps * of this sinkpad. */ @@ -322,73 +319,111 @@ gst_live_adder_sink_getcaps (GstPad * pad) return result; } +struct SetCapsIterCtx +{ + GstPad *pad; + GstCaps *caps; + gboolean all_valid; +}; + +static void +check_other_caps (const GValue * item, gpointer user_data) +{ + GstPad *otherpad = GST_PAD (g_value_get_object (item)); + struct SetCapsIterCtx *ctx = user_data; + + if (otherpad == ctx->pad) + return; + + if (!gst_pad_peer_query_accept_caps (otherpad, ctx->caps)) + ctx->all_valid = FALSE; +} + +static void +set_other_caps (const GValue * item, gpointer user_data) +{ + GstPad *otherpad = GST_PAD (g_value_get_object (item)); + struct SetCapsIterCtx *ctx = user_data; + + if (otherpad == ctx->pad) + return; + + if (!gst_pad_set_caps (otherpad, ctx->caps)) + ctx->all_valid = FALSE; +} + /* the first caps we receive on any of the sinkpads will define the caps for all * the other sinkpads because we can only mix streams with the same caps. * */ static gboolean -gst_live_adder_setcaps (GstPad * pad, GstCaps * caps) +gst_live_adder_setcaps (GstLiveAdder * adder, GstPad * pad, GstCaps * caps) { - GstLiveAdder *adder; - GList *pads; - GstStructure *structure; - const char *media_type; - - adder = GST_LIVE_ADDER (GST_PAD_PARENT (pad)); + GstIterator *iter; + struct SetCapsIterCtx ctx; GST_LOG_OBJECT (adder, "setting caps on pad %p,%s to %" GST_PTR_FORMAT, pad, GST_PAD_NAME (pad), caps); /* FIXME, see if the other pads can accept the format. Also lock the * format on the other pads to this new format. */ - GST_OBJECT_LOCK (adder); - pads = GST_ELEMENT (adder)->pads; - while (pads) { - GstPad *otherpad = GST_PAD (pads->data); + iter = gst_element_iterate_sink_pads (GST_ELEMENT (adder)); + ctx.pad = pad; + ctx.caps = caps; + ctx.all_valid = TRUE; + while (gst_iterator_foreach (iter, check_other_caps, &ctx) == + GST_ITERATOR_RESYNC) { + ctx.all_valid = TRUE; + gst_iterator_resync (iter); + } + if (!ctx.all_valid) { + GST_WARNING_OBJECT (adder, "Caps are not acceptable by other sinkpads"); + gst_iterator_free (iter); + return FALSE; + } - if (otherpad != pad) - gst_caps_replace (&GST_PAD_CAPS (otherpad), caps); + while (gst_iterator_foreach (iter, set_other_caps, &ctx) == + GST_ITERATOR_RESYNC) { + ctx.all_valid = TRUE; + gst_iterator_resync (iter); + } + gst_iterator_free (iter); + + if (!ctx.all_valid) { + GST_WARNING_OBJECT (adder, "Could not set caps on the other sink pads"); + return FALSE; + } - pads = g_list_next (pads); + if (!gst_pad_set_caps (adder->srcpad, caps)) { + GST_WARNING_OBJECT (adder, "Could not set caps downstream"); + return FALSE; } + GST_OBJECT_LOCK (adder); /* parse caps now */ - structure = gst_caps_get_structure (caps, 0); - media_type = gst_structure_get_name (structure); - if (strcmp (media_type, "audio/x-raw-int") == 0) { - GST_DEBUG_OBJECT (adder, "parse_caps sets adder to format int"); - adder->format = GST_LIVE_ADDER_FORMAT_INT; - gst_structure_get_int (structure, "width", &adder->width); - gst_structure_get_int (structure, "depth", &adder->depth); - gst_structure_get_int (structure, "endianness", &adder->endianness); - gst_structure_get_boolean (structure, "signed", &adder->is_signed); - - if (adder->endianness != G_BYTE_ORDER) - goto not_supported; - - switch (adder->width) { + if (!gst_audio_info_from_caps (&adder->info, caps)) + goto not_supported; + + if (GST_AUDIO_INFO_IS_INTEGER (&adder->info)) { + switch (GST_AUDIO_INFO_WIDTH (&adder->info)) { case 8: - adder->func = (adder->is_signed ? - (GstLiveAdderFunction) add_int8 : (GstLiveAdderFunction) add_uint8); + adder->func = GST_AUDIO_INFO_IS_SIGNED (&adder->info) ? + (GstLiveAdderFunction) add_int8 : (GstLiveAdderFunction) add_uint8; break; case 16: - adder->func = (adder->is_signed ? + adder->func = GST_AUDIO_INFO_IS_SIGNED (&adder->info) ? (GstLiveAdderFunction) add_int16 : (GstLiveAdderFunction) - add_uint16); + add_uint16; break; case 32: - adder->func = (adder->is_signed ? + adder->func = GST_AUDIO_INFO_IS_SIGNED (&adder->info) ? (GstLiveAdderFunction) add_int32 : (GstLiveAdderFunction) - add_uint32); + add_uint32; break; default: goto not_supported; } - } else if (strcmp (media_type, "audio/x-raw-float") == 0) { - GST_DEBUG_OBJECT (adder, "parse_caps sets adder to format float"); - adder->format = GST_LIVE_ADDER_FORMAT_FLOAT; - gst_structure_get_int (structure, "width", &adder->width); - - switch (adder->width) { + } else if (GST_AUDIO_INFO_IS_FLOAT (&adder->info)) { + switch (GST_AUDIO_INFO_WIDTH (&adder->info)) { case 32: adder->func = (GstLiveAdderFunction) add_float32; break; @@ -402,11 +437,6 @@ gst_live_adder_setcaps (GstPad * pad, GstCaps * caps) goto not_supported; } - gst_structure_get_int (structure, "channels", &adder->channels); - gst_structure_get_int (structure, "rate", &adder->rate); - /* precalc bps */ - adder->bps = (adder->width / 8) * adder->channels; - GST_OBJECT_UNLOCK (adder); return TRUE; @@ -442,12 +472,14 @@ gst_live_adder_flush_start (GstLiveAdder * adder) } static gboolean -gst_live_adder_src_activate_push (GstPad * pad, gboolean active) +gst_live_adder_src_activate_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active) { + GstLiveAdder *adder = GST_LIVE_ADDER (parent); gboolean result = TRUE; - GstLiveAdder *adder = NULL; - adder = GST_LIVE_ADDER (gst_pad_get_parent (pad)); + if (mode == GST_PAD_MODE_PULL) + return FALSE; if (active) { /* Mark as non flushing */ @@ -469,19 +501,15 @@ gst_live_adder_src_activate_push (GstPad * pad, gboolean active) result = gst_pad_stop_task (pad); } - gst_object_unref (adder); - return result; } static gboolean -gst_live_adder_sink_event (GstPad * pad, GstEvent * event) +gst_live_adder_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) { - gboolean ret = TRUE; - GstLiveAdder *adder = NULL; + GstLiveAdder *adder = GST_LIVE_ADDER (parent); GstLiveAdderPadPrivate *padprivate = NULL; - - adder = GST_LIVE_ADDER (gst_pad_get_parent (pad)); + gboolean ret = TRUE; padprivate = gst_pad_get_element_private (pad); @@ -491,34 +519,35 @@ gst_live_adder_sink_event (GstPad * pad, GstEvent * event) GST_LOG_OBJECT (adder, "received %s", GST_EVENT_TYPE_NAME (event)); switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_NEWSEGMENT: + case GST_EVENT_CAPS: { - GstFormat format; - gdouble rate, arate; - gint64 start, stop, time; - gboolean update; - - gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, - &start, &stop, &time); + GstCaps *caps; + gst_event_parse_caps (event, &caps); + ret = gst_live_adder_setcaps (adder, pad, caps); gst_event_unref (event); + break; + } + case GST_EVENT_SEGMENT: + { + const GstSegment *segment; + GstSegment livesegment; + + gst_event_parse_segment (event, &segment); /* we need time for now */ - if (format != GST_FORMAT_TIME) + if (segment->format != GST_FORMAT_TIME) goto newseg_wrong_format; - GST_DEBUG_OBJECT (adder, - "newsegment: update %d, rate %g, arate %g, start %" GST_TIME_FORMAT - ", stop %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, - update, rate, arate, GST_TIME_ARGS (start), GST_TIME_ARGS (stop), - GST_TIME_ARGS (time)); - /* now configure the values, we need these to time the release of the * buffers on the srcpad. */ GST_OBJECT_LOCK (adder); - gst_segment_set_newsegment_full (&padprivate->segment, update, - rate, arate, format, start, stop, time); + gst_segment_copy_into (segment, &padprivate->segment); GST_OBJECT_UNLOCK (adder); + gst_event_unref (event); + + gst_segment_init (&livesegment, GST_FORMAT_TIME); + gst_pad_push_event (adder->srcpad, gst_event_new_segment (&livesegment)); break; } case GST_EVENT_FLUSH_START: @@ -527,13 +556,12 @@ gst_live_adder_sink_event (GstPad * pad, GstEvent * event) break; case GST_EVENT_FLUSH_STOP: GST_OBJECT_LOCK (adder); - adder->segment_pending = TRUE; adder->next_timestamp = GST_CLOCK_TIME_NONE; reset_pad_private (pad); - adder->segment_pending = TRUE; GST_OBJECT_UNLOCK (adder); ret = gst_pad_push_event (adder->srcpad, event); - ret = gst_live_adder_src_activate_push (adder->srcpad, TRUE); + ret = gst_live_adder_src_activate_mode (adder->srcpad, GST_OBJECT (adder), + GST_PAD_MODE_PUSH, TRUE); break; case GST_EVENT_EOS: { @@ -562,21 +590,20 @@ gst_live_adder_sink_event (GstPad * pad, GstEvent * event) } done: - gst_object_unref (adder); return ret; /* ERRORS */ newseg_wrong_format: { - GST_DEBUG_OBJECT (adder, "received non TIME newsegment"); + GST_DEBUG_OBJECT (adder, "received non TIME segment"); ret = FALSE; goto done; } } static gboolean -gst_live_adder_query_pos_dur (GstLiveAdder * adder, GstFormat informat, +gst_live_adder_query_pos_dur (GstLiveAdder * adder, GstFormat format, gboolean position, gint64 * outvalue) { gint64 max = G_MININT64; @@ -588,8 +615,7 @@ gst_live_adder_query_pos_dur (GstLiveAdder * adder, GstFormat informat, it = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (adder)); while (!done) { GstIteratorResult ires; - gpointer item; - GstFormat format = informat; + GValue item = { 0 }; ires = gst_iterator_next (it, &item); switch (ires) { @@ -598,21 +624,21 @@ gst_live_adder_query_pos_dur (GstLiveAdder * adder, GstFormat informat, break; case GST_ITERATOR_OK: { - GstPad *pad = GST_PAD_CAST (item); + GstPad *pad = GST_PAD_CAST (g_value_get_object (&item)); gint64 value; gboolean curres; /* ask sink peer for duration */ if (position) - curres = gst_pad_query_peer_position (pad, &format, &value); + curres = gst_pad_peer_query_position (pad, format, &value); else - curres = gst_pad_query_peer_duration (pad, &format, &value); + curres = gst_pad_peer_query_duration (pad, format, &value); /* take max from all valid return values */ /* Only if the format is the one we requested, otherwise ignore it ? */ - if (curres && format == informat) { + if (curres) { res &= curres; /* valid unknown length, stop searching */ @@ -694,20 +720,18 @@ gst_live_adder_query_position (GstLiveAdder * adder, GstQuery * query) static gboolean -gst_live_adder_query (GstPad * pad, GstQuery * query) +gst_live_adder_src_query (GstPad * pad, GstObject * parent, GstQuery * query) { - GstLiveAdder *adder; + GstLiveAdder *adder = GST_LIVE_ADDER (parent); gboolean res = FALSE; - adder = GST_LIVE_ADDER (gst_pad_get_parent (pad)); - switch (GST_QUERY_TYPE (query)) { case GST_QUERY_LATENCY: { /* We need to send the query upstream and add the returned latency to our * own */ GstClockTime min_latency = 0, max_latency = G_MAXUINT64; - gpointer item; + GValue item = { 0 }; GstIterator *iter = NULL; gboolean done = FALSE; @@ -717,7 +741,7 @@ gst_live_adder_query (GstPad * pad, GstQuery * query) switch (gst_iterator_next (iter, &item)) { case GST_ITERATOR_OK: { - GstPad *sinkpad = item; + GstPad *sinkpad = GST_PAD (g_value_get_object (&item)); GstClockTime pad_min_latency, pad_max_latency; gboolean pad_us_live; @@ -736,7 +760,6 @@ gst_live_adder_query (GstPad * pad, GstQuery * query) min_latency = MAX (pad_min_latency, min_latency); max_latency = MIN (pad_max_latency, max_latency); } - gst_object_unref (item); } break; case GST_ITERATOR_RESYNC: @@ -782,18 +805,45 @@ gst_live_adder_query (GstPad * pad, GstQuery * query) res = gst_live_adder_query_position (adder, query); break; default: - res = gst_pad_query_default (pad, query); + res = gst_pad_query_default (pad, parent, query); break; } - gst_object_unref (adder); + return res; +} + +static gboolean +gst_live_adder_sink_query (GstPad * pad, GstObject * parent, GstQuery * query) +{ + GstLiveAdder *adder = GST_LIVE_ADDER (parent); + gboolean res; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_CAPS: + { + GstCaps *filter; + GstCaps *result; + + gst_query_parse_caps (query, &filter); + result = gst_live_adder_sink_getcaps (adder, pad, filter); + gst_query_set_caps_result (query, result); + res = TRUE; + break; + } + default: + res = gst_pad_query_default (pad, parent, query); + break; + } return res; } static gboolean -forward_event_func (GstPad * pad, GValue * ret, GstEvent * event) +forward_event_func (const GValue * item, GValue * ret, gpointer user_data) { + GstPad *pad = GST_PAD (g_value_get_object (item)); + GstEvent *event = user_data; + gst_event_ref (event); GST_LOG_OBJECT (pad, "About to send event %s", GST_EVENT_TYPE_NAME (event)); if (!gst_pad_push_event (pad, event)) { @@ -804,11 +854,6 @@ forward_event_func (GstPad * pad, GValue * ret, GstEvent * event) GST_LOG_OBJECT (pad, "Sent event %p (%s).", event, GST_EVENT_TYPE_NAME (event)); } - - /* unref the pad because of a FIXME in gst_iterator_unfold - * it does a gst_iterator_next which refs the pad, but it never unrefs it - */ - gst_object_unref (pad); return TRUE; } @@ -833,8 +878,7 @@ forward_event (GstLiveAdder * adder, GstEvent * event) g_value_init (&vret, G_TYPE_BOOLEAN); g_value_set_boolean (&vret, TRUE); it = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (adder)); - gst_iterator_fold (it, (GstIteratorFoldFunction) forward_event_func, &vret, - event); + gst_iterator_fold (it, forward_event_func, &vret, event); gst_iterator_free (it); ret = g_value_get_boolean (&vret); @@ -844,13 +888,11 @@ forward_event (GstLiveAdder * adder, GstEvent * event) static gboolean -gst_live_adder_src_event (GstPad * pad, GstEvent * event) +gst_live_adder_src_event (GstPad * pad, GstObject * parent, GstEvent * event) { - GstLiveAdder *adder; + GstLiveAdder *adder = GST_LIVE_ADDER (parent); gboolean result; - adder = GST_LIVE_ADDER (gst_pad_get_parent (pad)); - switch (GST_EVENT_TYPE (event)) { case GST_EVENT_QOS: /* TODO : QoS might be tricky */ @@ -867,7 +909,6 @@ gst_live_adder_src_event (GstPad * pad, GstEvent * event) } gst_event_unref (event); - gst_object_unref (adder); return result; } @@ -876,15 +917,16 @@ static guint gst_live_adder_length_from_duration (GstLiveAdder * adder, GstClockTime duration) { - guint64 ret = (duration * adder->rate / GST_SECOND) * adder->bps; + guint64 ret = GST_AUDIO_INFO_BPF (&adder->info) * + (duration * GST_AUDIO_INFO_RATE (&adder->info) / GST_SECOND); return (guint) ret; } static GstFlowReturn -gst_live_live_adder_chain (GstPad * pad, GstBuffer * buffer) +gst_live_live_adder_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) { - GstLiveAdder *adder = GST_LIVE_ADDER (gst_pad_get_parent_element (pad)); + GstLiveAdder *adder = GST_LIVE_ADDER (parent); GstLiveAdderPadPrivate *padprivate = NULL; GstFlowReturn ret = GST_FLOW_OK; GList *item = NULL; @@ -916,7 +958,7 @@ gst_live_live_adder_chain (GstPad * pad, GstBuffer * buffer) if (padprivate->eos) { GST_DEBUG_OBJECT (adder, "Received buffer after EOS"); - ret = GST_FLOW_UNEXPECTED; + ret = GST_FLOW_EOS; gst_buffer_unref (buffer); goto out; } @@ -928,14 +970,9 @@ gst_live_live_adder_chain (GstPad * pad, GstBuffer * buffer) GST_WARNING_OBJECT (adder, "No new-segment received," " initializing segment with time 0..-1"); gst_segment_init (&padprivate->segment, GST_FORMAT_TIME); - gst_segment_set_newsegment (&padprivate->segment, - FALSE, 1.0, GST_FORMAT_TIME, 0, -1, 0); } - if (padprivate->segment.format != GST_FORMAT_TIME) - goto invalid_segment; - - buffer = gst_buffer_make_metadata_writable (buffer); + buffer = gst_buffer_make_writable (buffer); drift = GST_BUFFER_TIMESTAMP (buffer) - padprivate->expected_timestamp; @@ -960,8 +997,9 @@ gst_live_live_adder_chain (GstPad * pad, GstBuffer * buffer) /* If there is no duration, lets set one */ if (!GST_BUFFER_DURATION_IS_VALID (buffer)) { - GST_BUFFER_DURATION (buffer) = - gst_audio_duration_from_pad_buffer (pad, buffer); + GST_BUFFER_DURATION (buffer) = (gst_buffer_get_size (buffer) * GST_SECOND) / + (GST_AUDIO_INFO_BPF (&adder->info) * + GST_AUDIO_INFO_RATE (&adder->info)); padprivate->expected_timestamp = GST_CLOCK_TIME_NONE; } else { padprivate->expected_timestamp = GST_BUFFER_TIMESTAMP (buffer) + @@ -976,8 +1014,8 @@ gst_live_live_adder_chain (GstPad * pad, GstBuffer * buffer) * durations afterwards */ - buffer = gst_audio_buffer_clip (buffer, &padprivate->segment, adder->rate, - adder->bps); + buffer = gst_audio_buffer_clip (buffer, &padprivate->segment, + GST_AUDIO_INFO_RATE (&adder->info), GST_AUDIO_INFO_BPF (&adder->info)); /* buffer can be NULL if it's completely outside of the segment */ if (!buffer) { @@ -1026,6 +1064,7 @@ gst_live_live_adder_chain (GstPad * pad, GstBuffer * buffer) GstClockTime mix_duration = 0; GstClockTime mix_start = 0; GstClockTime mix_end = 0; + GstMapInfo oldmap, map; /* We haven't reached our place yet */ if (GST_BUFFER_TIMESTAMP (buffer) + skip >= @@ -1045,7 +1084,7 @@ gst_live_live_adder_chain (GstPad * pad, GstBuffer * buffer) GstClockTime subbuffer_duration = GST_BUFFER_TIMESTAMP (oldbuffer) - (GST_BUFFER_TIMESTAMP (buffer) + skip); - subbuffer = gst_buffer_create_sub (buffer, + subbuffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, gst_live_adder_length_from_duration (adder, skip), gst_live_adder_length_from_duration (adder, subbuffer_duration)); @@ -1075,12 +1114,15 @@ gst_live_live_adder_chain (GstPad * pad, GstBuffer * buffer) mix_duration = mix_end - mix_start; - adder->func (GST_BUFFER_DATA (oldbuffer) + + gst_buffer_map (oldbuffer, &oldmap, GST_MAP_WRITE); + gst_buffer_map (buffer, &map, GST_MAP_READ); + adder->func (oldmap.data + gst_live_adder_length_from_duration (adder, old_skip), - GST_BUFFER_DATA (buffer) + + map.data + gst_live_adder_length_from_duration (adder, skip), gst_live_adder_length_from_duration (adder, mix_duration)); - + gst_buffer_unmap (oldbuffer, &oldmap); + gst_buffer_unmap (buffer, &map); skip += mix_duration; } @@ -1092,12 +1134,13 @@ gst_live_live_adder_chain (GstPad * pad, GstBuffer * buffer) if (skip) { GstClockTime subbuffer_duration = GST_BUFFER_DURATION (buffer) - skip; GstClockTime subbuffer_ts = GST_BUFFER_TIMESTAMP (buffer) + skip; - GstBuffer *new_buffer = gst_buffer_create_sub (buffer, + GstBuffer *new_buffer = gst_buffer_copy_region (buffer, + GST_BUFFER_COPY_ALL, gst_live_adder_length_from_duration (adder, skip), gst_live_adder_length_from_duration (adder, subbuffer_duration)); gst_buffer_unref (buffer); buffer = new_buffer; - GST_BUFFER_TIMESTAMP (buffer) = subbuffer_ts; + GST_BUFFER_PTS (buffer) = subbuffer_ts; GST_BUFFER_DURATION (buffer) = subbuffer_duration; } @@ -1110,7 +1153,6 @@ gst_live_live_adder_chain (GstPad * pad, GstBuffer * buffer) out: GST_OBJECT_UNLOCK (adder); - gst_object_unref (adder); return ret; @@ -1123,19 +1165,6 @@ invalid_timestamp: ("Invalid timestamp received on buffer")); return GST_FLOW_ERROR; - -invalid_segment: - { - const gchar *format = gst_format_get_name (padprivate->segment.format); - GST_OBJECT_UNLOCK (adder); - gst_buffer_unref (buffer); - GST_ELEMENT_ERROR (adder, STREAM, FAILED, - ("This element only supports TIME segments, received other type"), - ("Received a segment of type %s, only support time segment", format)); - - return GST_FLOW_ERROR; - } - } /* @@ -1257,7 +1286,7 @@ push_buffer: if (diff < 0) diff = -diff; - if (diff < GST_SECOND / adder->rate) { + if (diff < GST_SECOND / GST_AUDIO_INFO_RATE (&adder->info)) { GST_BUFFER_TIMESTAMP (buffer) = adder->next_timestamp; GST_DEBUG_OBJECT (adder, "Correcting slight skew"); GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DISCONT); @@ -1280,17 +1309,6 @@ push_buffer: GST_BUFFER_DURATION (buffer); else adder->next_timestamp = GST_CLOCK_TIME_NONE; - - if (adder->segment_pending) { - /* - * We set the start at 0, because we re-timestamps to the running time - */ - newseg_event = gst_event_new_new_segment_full (FALSE, 1.0, 1.0, - GST_FORMAT_TIME, 0, -1, 0); - - adder->segment_pending = FALSE; - } - GST_OBJECT_UNLOCK (adder); if (newseg_event) @@ -1355,7 +1373,7 @@ eos: { /* store result, we are flushing now */ GST_DEBUG_OBJECT (adder, "We are EOS, pushing EOS downstream"); - adder->srcresult = GST_FLOW_UNEXPECTED; + adder->srcresult = GST_FLOW_EOS; gst_pad_pause_task (adder->srcpad); GST_OBJECT_UNLOCK (adder); gst_pad_push_event (adder->srcpad, gst_event_new_eos ()); @@ -1365,7 +1383,7 @@ eos: static GstPad * gst_live_adder_request_new_pad (GstElement * element, GstPadTemplate * templ, - const gchar * unused) + const gchar * ignored_name, const GstCaps * caps) { gchar *name; GstLiveAdder *adder; @@ -1390,12 +1408,10 @@ gst_live_adder_request_new_pad (GstElement * element, GstPadTemplate * templ, GST_DEBUG_OBJECT (adder, "request new pad %s", name); g_free (name); - gst_pad_set_getcaps_function (newpad, - GST_DEBUG_FUNCPTR (gst_live_adder_sink_getcaps)); - gst_pad_set_setcaps_function (newpad, - GST_DEBUG_FUNCPTR (gst_live_adder_setcaps)); gst_pad_set_event_function (newpad, GST_DEBUG_FUNCPTR (gst_live_adder_sink_event)); + gst_pad_set_query_function (newpad, + GST_DEBUG_FUNCPTR (gst_live_adder_sink_query)); padprivate = g_new0 (GstLiveAdderPadPrivate, 1); @@ -1506,7 +1522,8 @@ gst_live_adder_change_state (GstElement * element, GstStateChange transition) break; } - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + ret = GST_ELEMENT_CLASS (gst_live_adder_parent_class)->change_state (element, + transition); switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_PLAYING: diff --git a/gst/liveadder/liveadder.h b/gst/liveadder/liveadder.h index 7448601f9..136ac3ec0 100644 --- a/gst/liveadder/liveadder.h +++ b/gst/liveadder/liveadder.h @@ -1,5 +1,5 @@ /* - * Farsight Voice+Video library + * GStreamer * * Copyright 2008 Collabora Ltd * Copyright 2008 Nokia Corporation @@ -28,6 +28,7 @@ #define __GST_LIVE_ADDER_H__ #include <gst/gst.h> +#include <gst/audio/audio.h> G_BEGIN_DECLS #define GST_TYPE_LIVE_ADDER (gst_live_adder_get_type()) @@ -39,13 +40,6 @@ G_BEGIN_DECLS typedef struct _GstLiveAdder GstLiveAdder; typedef struct _GstLiveAdderClass GstLiveAdderClass; -typedef enum -{ - GST_LIVE_ADDER_FORMAT_UNSET, - GST_LIVE_ADDER_FORMAT_INT, - GST_LIVE_ADDER_FORMAT_FLOAT -} GstLiveAdderFormat; - typedef void (*GstLiveAdderFunction) (gpointer out, gpointer in, guint size); /** @@ -73,18 +67,7 @@ struct _GstLiveAdder GstClockTime next_timestamp; /* the next are valid for both int and float */ - GstLiveAdderFormat format; - gint rate; - gint channels; - gint width; - gint endianness; - - /* the next are valid only for format == GST_LIVE_ADDER_FORMAT_INT */ - gint depth; - gboolean is_signed; - - /* number of bytes per sample, actually width/8 * channels */ - gint bps; + GstAudioInfo info; /* function to add samples */ GstLiveAdderFunction func; |