diff options
Diffstat (limited to 'plugins/elements/gstinputselector.c')
-rw-r--r-- | plugins/elements/gstinputselector.c | 240 |
1 files changed, 76 insertions, 164 deletions
diff --git a/plugins/elements/gstinputselector.c b/plugins/elements/gstinputselector.c index 7235a47..564e721 100644 --- a/plugins/elements/gstinputselector.c +++ b/plugins/elements/gstinputselector.c @@ -59,28 +59,13 @@ #include "gstinputselector.h" +#include "gst/glib-compat-private.h" + GST_DEBUG_CATEGORY_STATIC (input_selector_debug); #define GST_CAT_DEFAULT input_selector_debug -#if GLIB_CHECK_VERSION(2, 26, 0) -#define NOTIFY_MUTEX_LOCK() -#define NOTIFY_MUTEX_UNLOCK() -#else -static GStaticRecMutex notify_mutex = G_STATIC_REC_MUTEX_INIT; -#define NOTIFY_MUTEX_LOCK() g_static_rec_mutex_lock (¬ify_mutex) -#define NOTIFY_MUTEX_UNLOCK() g_static_rec_mutex_unlock (¬ify_mutex) -#endif - -#define GST_INPUT_SELECTOR_GET_LOCK(sel) (((GstInputSelector*)(sel))->lock) -#define GST_INPUT_SELECTOR_GET_COND(sel) (((GstInputSelector*)(sel))->cond) -#define GST_INPUT_SELECTOR_LOCK(sel) (g_mutex_lock (GST_INPUT_SELECTOR_GET_LOCK(sel))) -#define GST_INPUT_SELECTOR_UNLOCK(sel) (g_mutex_unlock (GST_INPUT_SELECTOR_GET_LOCK(sel))) -#define GST_INPUT_SELECTOR_WAIT(sel) (g_cond_wait (GST_INPUT_SELECTOR_GET_COND(sel), \ - GST_INPUT_SELECTOR_GET_LOCK(sel))) -#define GST_INPUT_SELECTOR_BROADCAST(sel) (g_cond_broadcast (GST_INPUT_SELECTOR_GET_COND(sel))) - static GstStaticPadTemplate gst_input_selector_sink_factory = -GST_STATIC_PAD_TEMPLATE ("sink%d", +GST_STATIC_PAD_TEMPLATE ("sink_%u", GST_PAD_SINK, GST_PAD_REQUEST, GST_STATIC_CAPS_ANY); @@ -99,7 +84,7 @@ enum PROP_SYNC_STREAMS }; -#define DEFAULT_SYNC_STREAMS FALSE +#define DEFAULT_SYNC_STREAMS TRUE #define DEFAULT_PAD_ALWAYS_OK TRUE @@ -178,11 +163,14 @@ static void gst_selector_pad_set_property (GObject * object, static gint64 gst_selector_pad_get_running_time (GstSelectorPad * pad); static void gst_selector_pad_reset (GstSelectorPad * pad); -static gboolean gst_selector_pad_event (GstPad * pad, GstEvent * event); -static GstCaps *gst_selector_pad_getcaps (GstPad * pad, GstCaps * filter); -static gboolean gst_selector_pad_acceptcaps (GstPad * pad, GstCaps * caps); -static GstIterator *gst_selector_pad_iterate_linked_pads (GstPad * pad); -static GstFlowReturn gst_selector_pad_chain (GstPad * pad, GstBuffer * buf); +static gboolean gst_selector_pad_event (GstPad * pad, GstObject * parent, + GstEvent * event); +static gboolean gst_selector_pad_query (GstPad * pad, GstObject * parent, + GstQuery * query); +static GstIterator *gst_selector_pad_iterate_linked_pads (GstPad * pad, + GstObject * parent); +static GstFlowReturn gst_selector_pad_chain (GstPad * pad, GstObject * parent, + GstBuffer * buf); G_DEFINE_TYPE (GstSelectorPad, gst_selector_pad, GST_TYPE_PAD); @@ -330,16 +318,14 @@ gst_selector_pad_reset (GstSelectorPad * pad) /* strictly get the linked pad from the sinkpad. If the pad is active we return * the srcpad else we return NULL */ static GstIterator * -gst_selector_pad_iterate_linked_pads (GstPad * pad) +gst_selector_pad_iterate_linked_pads (GstPad * pad, GstObject * parent) { GstInputSelector *sel; GstPad *otherpad; GstIterator *it = NULL; GValue val = { 0, }; - sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); - if (G_UNLIKELY (sel == NULL)) - return NULL; + sel = GST_INPUT_SELECTOR (parent); otherpad = gst_input_selector_get_linked_pad (sel, pad, TRUE); if (otherpad) { @@ -349,13 +335,12 @@ gst_selector_pad_iterate_linked_pads (GstPad * pad) g_value_unset (&val); gst_object_unref (otherpad); } - gst_object_unref (sel); return it; } static gboolean -gst_selector_pad_event (GstPad * pad, GstEvent * event) +gst_selector_pad_event (GstPad * pad, GstObject * parent, GstEvent * event) { gboolean res = TRUE; gboolean forward; @@ -364,11 +349,7 @@ gst_selector_pad_event (GstPad * pad, GstEvent * event) GstPad *prev_active_sinkpad; GstPad *active_sinkpad; - sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); - if (G_UNLIKELY (sel == NULL)) { - gst_event_unref (event); - return FALSE; - } + sel = GST_INPUT_SELECTOR (parent); selpad = GST_SELECTOR_PAD_CAST (pad); GST_INPUT_SELECTOR_LOCK (sel); @@ -380,9 +361,7 @@ gst_selector_pad_event (GstPad * pad, GstEvent * event) GST_INPUT_SELECTOR_UNLOCK (sel); if (prev_active_sinkpad != active_sinkpad && pad == active_sinkpad) { - NOTIFY_MUTEX_LOCK (); g_object_notify (G_OBJECT (sel), "active-pad"); - NOTIFY_MUTEX_UNLOCK (); } switch (GST_EVENT_TYPE (event)) { @@ -486,44 +465,19 @@ gst_selector_pad_event (GstPad * pad, GstEvent * event) } else gst_event_unref (event); - gst_object_unref (sel); - return res; } -static GstCaps * -gst_selector_pad_getcaps (GstPad * pad, GstCaps * filter) -{ - GstInputSelector *sel; - GstCaps *caps; - - sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); - if (G_UNLIKELY (sel == NULL)) - return (filter ? gst_caps_ref (filter) : gst_caps_new_any ()); - - GST_DEBUG_OBJECT (sel, "Getting caps of srcpad peer"); - caps = gst_pad_peer_get_caps (sel->srcpad, filter); - if (caps == NULL) - caps = (filter ? gst_caps_ref (filter) : gst_caps_new_any ()); - - gst_object_unref (sel); - - return caps; -} - static gboolean -gst_selector_pad_acceptcaps (GstPad * pad, GstCaps * caps) +gst_selector_pad_query (GstPad * pad, GstObject * parent, GstQuery * query) { - GstInputSelector *sel; - gboolean res; - - sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); - if (G_UNLIKELY (sel == NULL)) - return FALSE; + gboolean res = FALSE; - GST_DEBUG_OBJECT (sel, "Checking acceptcaps of srcpad peer"); - res = gst_pad_peer_accept_caps (sel->srcpad, caps); - gst_object_unref (sel); + switch (GST_QUERY_TYPE (query)) { + default: + res = gst_pad_query_default (pad, parent, query); + break; + } return res; } @@ -550,7 +504,7 @@ gst_input_selector_wait_running_time (GstInputSelector * sel, GstPad *active_sinkpad; GstSelectorPad *active_selpad; GstSegment *seg, *active_seg; - GstClockTime running_time, active_running_time = -1; + GstClockTime running_time, active_running_time = GST_CLOCK_TIME_NONE; seg = &pad->segment; @@ -595,9 +549,10 @@ gst_input_selector_wait_running_time (GstInputSelector * sel, * d) the active pad has no running time or the active * pad's running time is before this running time * e) the active pad has a non-time segment + * f) the active pad changed and has not pushed anything */ - while (pad != active_selpad && !sel->flushing && !pad->flushing && - (sel->blocked || active_running_time == -1 + while (pad != active_selpad && !sel->flushing && !pad->flushing + && active_selpad->pushed && (sel->blocked || active_running_time == -1 || running_time >= active_running_time)) { if (!sel->blocked) GST_DEBUG_OBJECT (pad, @@ -641,7 +596,7 @@ gst_input_selector_wait_running_time (GstInputSelector * sel, static GstFlowReturn -gst_selector_pad_chain (GstPad * pad, GstBuffer * buf) +gst_selector_pad_chain (GstPad * pad, GstObject * parent, GstBuffer * buf) { GstInputSelector *sel; GstFlowReturn res; @@ -652,7 +607,7 @@ gst_selector_pad_chain (GstPad * pad, GstBuffer * buf) GstSegment *seg; GstEvent *start_event = NULL; - sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); + sel = GST_INPUT_SELECTOR (parent); selpad = GST_SELECTOR_PAD_CAST (pad); seg = &selpad->segment; @@ -701,23 +656,24 @@ gst_selector_pad_chain (GstPad * pad, GstBuffer * buf) /* if we have a pending segment, push it out now */ if (G_UNLIKELY (prev_active_sinkpad != active_sinkpad || selpad->segment_pending)) { - GST_DEBUG_OBJECT (pad, - "pushing pending NEWSEGMENT update %d, rate %lf, applied rate %lf, " - "format %d, " "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %" - G_GINT64_FORMAT, FALSE, seg->rate, seg->applied_rate, seg->format, - seg->start, seg->stop, seg->time); - - start_event = gst_event_new_segment (seg); - gst_event_set_seqnum (start_event, selpad->segment_seqnum); - - selpad->segment_pending = FALSE; + if (G_UNLIKELY (seg->format == GST_FORMAT_UNDEFINED)) { + GST_ERROR_OBJECT (pad, "Buffers arrived before NEWSEGMENT event"); + } else { + GST_DEBUG_OBJECT (pad, + "pushing pending NEWSEGMENT update %d, rate %lf, applied rate %lf, " + "format %d, " "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %" + G_GINT64_FORMAT, FALSE, seg->rate, seg->applied_rate, seg->format, + seg->start, seg->stop, seg->time); + + start_event = gst_event_new_segment (seg); + gst_event_set_seqnum (start_event, selpad->segment_seqnum); + selpad->segment_pending = FALSE; + } } GST_INPUT_SELECTOR_UNLOCK (sel); if (prev_active_sinkpad != active_sinkpad && pad == active_sinkpad) { - NOTIFY_MUTEX_LOCK (); g_object_notify (G_OBJECT (sel), "active-pad"); - NOTIFY_MUTEX_UNLOCK (); } if (start_event) @@ -738,7 +694,6 @@ gst_selector_pad_chain (GstPad * pad, GstBuffer * buf) selpad->pushed = TRUE; done: - gst_object_unref (sel); return res; /* dropped buffers */ @@ -767,12 +722,13 @@ flushing: GST_DEBUG_OBJECT (pad, "We are flushing, discard buffer %p", buf); GST_INPUT_SELECTOR_UNLOCK (sel); gst_buffer_unref (buf); - res = GST_FLOW_WRONG_STATE; + res = GST_FLOW_FLUSHING; goto done; } } static void gst_input_selector_dispose (GObject * object); +static void gst_input_selector_finalize (GObject * object); static void gst_input_selector_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); @@ -786,9 +742,10 @@ static void gst_input_selector_release_pad (GstElement * element, GstPad * pad); static GstStateChangeReturn gst_input_selector_change_state (GstElement * element, GstStateChange transition); -static GstCaps *gst_input_selector_getcaps (GstPad * pad, GstCaps * filter); -static gboolean gst_input_selector_event (GstPad * pad, GstEvent * event); -static gboolean gst_input_selector_query (GstPad * pad, GstQuery * query); +static gboolean gst_input_selector_event (GstPad * pad, GstObject * parent, + GstEvent * event); +static gboolean gst_input_selector_query (GstPad * pad, GstObject * parent, + GstQuery * query); static gint64 gst_input_selector_block (GstInputSelector * self); /* FIXME: create these marshallers using glib-genmarshal */ @@ -837,6 +794,7 @@ gst_input_selector_class_init (GstInputSelectorClass * klass) GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); gobject_class->dispose = gst_input_selector_dispose; + gobject_class->finalize = gst_input_selector_finalize; gobject_class->set_property = gst_input_selector_set_property; gobject_class->get_property = gst_input_selector_get_property; @@ -859,7 +817,7 @@ gst_input_selector_class_init (GstInputSelectorClass * klass) * buffers are dropped by input-selector that might be needed * when switching the active pad. * - * Since: 0.10.35 + * Since: 0.10.36 */ g_object_class_install_property (gobject_class, PROP_SYNC_STREAMS, g_param_spec_boolean ("sync-streams", "Sync Streams", @@ -880,7 +838,7 @@ gst_input_selector_class_init (GstInputSelectorClass * klass) G_STRUCT_OFFSET (GstInputSelectorClass, block), NULL, NULL, gst_input_selector_marshal_INT64__VOID, G_TYPE_INT64, 0); - gst_element_class_set_details_simple (gstelement_class, "Input selector", + gst_element_class_set_static_metadata (gstelement_class, "Input selector", "Generic", "N-to-1 input stream selector", "Julien Moutte <julien@moutte.net>, " "Jan Schmidt <thaytan@mad.scientist.com>, " @@ -903,20 +861,19 @@ gst_input_selector_init (GstInputSelector * sel) sel->srcpad = gst_pad_new ("src", GST_PAD_SRC); gst_pad_set_iterate_internal_links_function (sel->srcpad, GST_DEBUG_FUNCPTR (gst_selector_pad_iterate_linked_pads)); - gst_pad_set_getcaps_function (sel->srcpad, - GST_DEBUG_FUNCPTR (gst_input_selector_getcaps)); gst_pad_set_query_function (sel->srcpad, GST_DEBUG_FUNCPTR (gst_input_selector_query)); gst_pad_set_event_function (sel->srcpad, GST_DEBUG_FUNCPTR (gst_input_selector_event)); + GST_OBJECT_FLAG_SET (sel->srcpad, GST_PAD_FLAG_PROXY_CAPS); gst_element_add_pad (GST_ELEMENT (sel), sel->srcpad); /* sinkpad management */ sel->active_sinkpad = NULL; sel->padcount = 0; sel->sync_streams = DEFAULT_SYNC_STREAMS; - sel->lock = g_mutex_new (); - sel->cond = g_cond_new (); + g_mutex_init (&sel->lock); + g_cond_init (&sel->cond); sel->blocked = FALSE; } @@ -929,18 +886,20 @@ gst_input_selector_dispose (GObject * object) gst_object_unref (sel->active_sinkpad); sel->active_sinkpad = NULL; } - if (sel->lock) { - g_mutex_free (sel->lock); - sel->lock = NULL; - } - if (sel->cond) { - g_cond_free (sel->cond); - sel->cond = NULL; - } - G_OBJECT_CLASS (parent_class)->dispose (object); } +static void +gst_input_selector_finalize (GObject * object) +{ + GstInputSelector *sel = GST_INPUT_SELECTOR (object); + + g_mutex_clear (&sel->lock); + g_cond_clear (&sel->cond); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + /* this function must be called with the SELECTOR_LOCK. It returns TRUE when the * active pad changed. */ static gboolean @@ -1059,7 +1018,7 @@ gst_input_selector_get_linked_pad (GstInputSelector * sel, GstPad * pad, } static gboolean -gst_input_selector_event (GstPad * pad, GstEvent * event) +gst_input_selector_event (GstPad * pad, GstObject * parent, GstEvent * event) { GstInputSelector *sel; gboolean result = FALSE; @@ -1069,12 +1028,7 @@ gst_input_selector_event (GstPad * pad, GstEvent * event) GstPad *eventpad; GList *pushed_pads = NULL; - sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); - if (G_UNLIKELY (sel == NULL)) { - gst_event_unref (event); - return FALSE; - } - + sel = GST_INPUT_SELECTOR (parent); /* Send upstream events to all sinkpads */ iter = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (sel)); @@ -1124,17 +1078,12 @@ gst_input_selector_event (GstPad * pad, GstEvent * event) /* query on the srcpad. We override this function because by default it will * only forward the query to one random sinkpad */ static gboolean -gst_input_selector_query (GstPad * pad, GstQuery * query) +gst_input_selector_query (GstPad * pad, GstObject * parent, GstQuery * query) { - gboolean res = TRUE; + gboolean res = FALSE; GstInputSelector *sel; - GstPad *otherpad; - - sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); - if (G_UNLIKELY (sel == NULL)) - return FALSE; - otherpad = gst_input_selector_get_linked_pad (sel, pad, TRUE); + sel = GST_INPUT_SELECTOR (parent); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_LATENCY: @@ -1147,9 +1096,6 @@ gst_input_selector_query (GstPad * pad, GstQuery * query) resmax = -1; reslive = FALSE; - /* assume FALSE, we become TRUE if one query succeeds */ - res = FALSE; - /* perform the query on all sinkpads and combine the results. We take the * max of min and the min of max for the result latency. */ GST_INPUT_SELECTOR_LOCK (sel); @@ -1195,47 +1141,13 @@ gst_input_selector_query (GstPad * pad, GstQuery * query) break; } default: - if (otherpad) - res = gst_pad_peer_query (otherpad, query); + res = gst_pad_query_default (pad, parent, query); break; } - if (otherpad) - gst_object_unref (otherpad); - gst_object_unref (sel); return res; } -static GstCaps * -gst_input_selector_getcaps (GstPad * pad, GstCaps * filter) -{ - GstPad *otherpad; - GstInputSelector *sel; - GstCaps *caps; - - sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); - if (G_UNLIKELY (sel == NULL)) - return (filter ? gst_caps_ref (filter) : gst_caps_new_any ()); - - otherpad = gst_input_selector_get_linked_pad (sel, pad, FALSE); - - if (!otherpad) { - GST_DEBUG_OBJECT (pad, "Pad not linked, returning ANY"); - caps = (filter ? gst_caps_ref (filter) : gst_caps_new_any ()); - } else { - GST_DEBUG_OBJECT (pad, "Pad is linked (to %s:%s), returning peer caps", - GST_DEBUG_PAD_NAME (otherpad)); - /* if the peer has caps, use those. If the pad is not linked, this function - * returns NULL and we return ANY */ - if (!(caps = gst_pad_peer_get_caps (otherpad, filter))) - caps = (filter ? gst_caps_ref (filter) : gst_caps_new_any ()); - gst_object_unref (otherpad); - } - - gst_object_unref (sel); - return caps; -} - /* check if the pad is the active sinkpad */ static inline gboolean gst_input_selector_is_active_sinkpad (GstInputSelector * sel, GstPad * pad) @@ -1286,7 +1198,7 @@ gst_input_selector_request_new_pad (GstElement * element, GST_INPUT_SELECTOR_LOCK (sel); GST_LOG_OBJECT (sel, "Creating new pad %d", sel->padcount); - name = g_strdup_printf ("sink%d", sel->padcount++); + name = g_strdup_printf ("sink_%u", sel->padcount++); sinkpad = g_object_new (GST_TYPE_SELECTOR_PAD, "name", name, "direction", templ->direction, "template", templ, NULL); g_free (name); @@ -1295,15 +1207,15 @@ gst_input_selector_request_new_pad (GstElement * element, gst_pad_set_event_function (sinkpad, GST_DEBUG_FUNCPTR (gst_selector_pad_event)); - gst_pad_set_getcaps_function (sinkpad, - GST_DEBUG_FUNCPTR (gst_selector_pad_getcaps)); - gst_pad_set_acceptcaps_function (sinkpad, - GST_DEBUG_FUNCPTR (gst_selector_pad_acceptcaps)); + gst_pad_set_query_function (sinkpad, + GST_DEBUG_FUNCPTR (gst_selector_pad_query)); gst_pad_set_chain_function (sinkpad, GST_DEBUG_FUNCPTR (gst_selector_pad_chain)); gst_pad_set_iterate_internal_links_function (sinkpad, GST_DEBUG_FUNCPTR (gst_selector_pad_iterate_linked_pads)); + GST_OBJECT_FLAG_SET (sinkpad, GST_PAD_FLAG_PROXY_CAPS); + GST_OBJECT_FLAG_SET (sinkpad, GST_PAD_FLAG_PROXY_ALLOCATION); gst_pad_set_active (sinkpad, TRUE); gst_element_add_pad (GST_ELEMENT (sel), sinkpad); GST_INPUT_SELECTOR_UNLOCK (sel); |