static gboolean src_query_func (GstPad * pad, GstObject * parent, GstQuery * query) { GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (parent); return klass->src_query (GST_AGGREGATOR (parent), query); }
static gboolean aggregate_func (GstAggregator * self) { GstAggregatorPrivate *priv = self->priv; GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (self); GST_LOG_OBJECT (self, "Checking aggregate"); while (priv->send_eos && gst_aggregator_iterate_sinkpads (self, (GstAggregatorPadForeachFunc) _check_all_pads_with_data_or_eos, NULL) && priv->running) { GST_TRACE_OBJECT (self, "Actually aggregating!"); priv->flow_return = klass->aggregate (self); if (priv->flow_return == GST_FLOW_EOS) { g_main_context_wakeup (self->priv->mcontext); _remove_all_sources (self); _push_eos (self); } if (priv->flow_return == GST_FLOW_FLUSHING && g_atomic_int_get (&priv->flush_seeking)) priv->flow_return = GST_FLOW_OK; GST_LOG_OBJECT (self, "flow return is %s", gst_flow_get_name (priv->flow_return)); if (priv->flow_return != GST_FLOW_OK) break; } return G_SOURCE_REMOVE; }
static gboolean src_event_func (GstPad * pad, GstObject * parent, GstEvent * event) { GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (parent); return klass->src_event (GST_AGGREGATOR (parent), event); }
static gboolean src_activate_mode (GstPad * pad, GstObject * parent, GstPadMode mode, gboolean active) { GstAggregator *self = GST_AGGREGATOR (parent); GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (parent); if (klass->src_activate) { if (klass->src_activate (self, mode, active) == FALSE) { return FALSE; } } if (active == TRUE) { switch (mode) { case GST_PAD_MODE_PUSH: { GST_INFO_OBJECT (pad, "Activating pad!"); _start_srcpad_task (self); return TRUE; } default: { GST_ERROR_OBJECT (pad, "Only supported mode is PUSH"); return FALSE; } } } /* deactivating */ GST_INFO_OBJECT (self, "Deactivating srcpad"); _stop_srcpad_task (self, FALSE); return TRUE; }
static GstFlowReturn _chain (GstPad * pad, GstObject * object, GstBuffer * buffer) { GstBuffer *actual_buf = buffer; GstAggregator *self = GST_AGGREGATOR (object); GstAggregatorPrivate *priv = self->priv; GstAggregatorPad *aggpad = GST_AGGREGATOR_PAD (pad); GstAggregatorClass *aggclass = GST_AGGREGATOR_GET_CLASS (object); GST_DEBUG_OBJECT (aggpad, "Start chaining a buffer %" GST_PTR_FORMAT, buffer); if (g_atomic_int_get (&aggpad->priv->flushing) == TRUE) goto flushing; if (g_atomic_int_get (&aggpad->priv->pending_eos) == TRUE) goto eos; PAD_LOCK_EVENT (aggpad); if (aggpad->buffer) { GST_DEBUG_OBJECT (aggpad, "Waiting for buffer to be consumed"); PAD_WAIT_EVENT (aggpad); } PAD_UNLOCK_EVENT (aggpad); if (g_atomic_int_get (&aggpad->priv->flushing) == TRUE) goto flushing; if (aggclass->clip) { aggclass->clip (self, aggpad, buffer, &actual_buf); } PAD_LOCK_EVENT (aggpad); if (aggpad->buffer) gst_buffer_unref (aggpad->buffer); aggpad->buffer = actual_buf; PAD_UNLOCK_EVENT (aggpad); _add_aggregate_gsource (self); GST_DEBUG_OBJECT (aggpad, "Done chaining"); return priv->flow_return; flushing: gst_buffer_unref (buffer); GST_DEBUG_OBJECT (aggpad, "We are flushing"); return GST_FLOW_FLUSHING; eos: gst_buffer_unref (buffer); GST_DEBUG_OBJECT (pad, "We are EOS already..."); return GST_FLOW_EOS; }
static GstPad * _request_new_pad (GstElement * element, GstPadTemplate * templ, const gchar * req_name, const GstCaps * caps) { GstAggregator *self; GstAggregatorPad *agg_pad; GstElementClass *klass = GST_ELEMENT_GET_CLASS (element); GstAggregatorPrivate *priv = GST_AGGREGATOR (element)->priv; self = GST_AGGREGATOR (element); if (templ == gst_element_class_get_pad_template (klass, "sink_%u")) { gint serial = 0; gchar *name = NULL; GST_OBJECT_LOCK (element); if (req_name == NULL || strlen (req_name) < 6 || !g_str_has_prefix (req_name, "sink_")) { /* no name given when requesting the pad, use next available int */ priv->padcount++; } else { /* parse serial number from requested padname */ serial = g_ascii_strtoull (&req_name[5], NULL, 10); if (serial >= priv->padcount) priv->padcount = serial; } name = g_strdup_printf ("sink_%u", priv->padcount); agg_pad = g_object_new (GST_AGGREGATOR_GET_CLASS (self)->sinkpads_type, "name", name, "direction", GST_PAD_SINK, "template", templ, NULL); g_free (name); GST_OBJECT_UNLOCK (element); } else { return NULL; } GST_DEBUG_OBJECT (element, "Adding pad %s", GST_PAD_NAME (agg_pad)); if (priv->running) gst_pad_set_active (GST_PAD (agg_pad), TRUE); /* add the pad to the element */ gst_element_add_pad (element, GST_PAD (agg_pad)); return GST_PAD (agg_pad); }
static GstFlowReturn _flush (GstAggregator * self) { GstFlowReturn ret = GST_FLOW_OK; GstAggregatorPrivate *priv = self->priv; GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (self); GST_DEBUG_OBJECT (self, "Flushing everything"); g_atomic_int_set (&priv->send_segment, TRUE); g_atomic_int_set (&priv->flush_seeking, FALSE); g_atomic_int_set (&priv->tags_changed, FALSE); if (klass->flush) ret = klass->flush (self); return ret; }
static void aggregate_func (GstAggregator * self) { GstAggregatorPrivate *priv = self->priv; GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (self); if (self->priv->running == FALSE) { GST_DEBUG_OBJECT (self, "Not running anymore"); return; } QUEUE_POP (self); GST_LOG_OBJECT (self, "Checking aggregate"); while (priv->send_eos && gst_aggregator_iterate_sinkpads (self, (GstAggregatorPadForeachFunc) _check_all_pads_with_data_or_eos_or_timeout, NULL) && priv->running) { GST_TRACE_OBJECT (self, "Actually aggregating!"); priv->flow_return = klass->aggregate (self); if (priv->flow_return == GST_FLOW_EOS) { QUEUE_FLUSH (self); _push_eos (self); } if (priv->flow_return == GST_FLOW_FLUSHING && g_atomic_int_get (&priv->flush_seeking)) priv->flow_return = GST_FLOW_OK; GST_LOG_OBJECT (self, "flow return is %s", gst_flow_get_name (priv->flow_return)); if (priv->flow_return != GST_FLOW_OK) break; } }
/* GstElement vmethods implementations */ static GstStateChangeReturn _change_state (GstElement * element, GstStateChange transition) { GstStateChangeReturn ret; GstAggregator *self = GST_AGGREGATOR (element); GstAggregatorClass *agg_class = GST_AGGREGATOR_GET_CLASS (self); switch (transition) { case GST_STATE_CHANGE_READY_TO_PAUSED: agg_class->start (self); break; default: break; } if ((ret = GST_ELEMENT_CLASS (aggregator_parent_class)->change_state (element, transition)) == GST_STATE_CHANGE_FAILURE) goto failure; switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: agg_class->stop (self); break; default: break; } return ret; failure: { GST_ERROR_OBJECT (element, "parent failed state change"); return ret; } }
static GstFlowReturn _chain (GstPad * pad, GstObject * object, GstBuffer * buffer) { GstBuffer *actual_buf = buffer; GstAggregator *self = GST_AGGREGATOR (object); GstAggregatorPrivate *priv = self->priv; GstAggregatorPad *aggpad = GST_AGGREGATOR_PAD (pad); GstAggregatorClass *aggclass = GST_AGGREGATOR_GET_CLASS (object); GstClockTime timeout = gst_aggregator_get_timeout (self); GstClockTime now; GST_DEBUG_OBJECT (aggpad, "Start chaining a buffer %" GST_PTR_FORMAT, buffer); if (aggpad->priv->timeout_id) { gst_clock_id_unschedule (aggpad->priv->timeout_id); gst_clock_id_unref (aggpad->priv->timeout_id); aggpad->priv->timeout_id = NULL; } g_atomic_int_set (&aggpad->unresponsive, FALSE); PAD_STREAM_LOCK (aggpad); if (g_atomic_int_get (&aggpad->priv->flushing) == TRUE) goto flushing; if (g_atomic_int_get (&aggpad->priv->pending_eos) == TRUE) goto eos; PAD_LOCK_EVENT (aggpad); if (aggpad->buffer) { GST_DEBUG_OBJECT (aggpad, "Waiting for buffer to be consumed"); PAD_WAIT_EVENT (aggpad); } PAD_UNLOCK_EVENT (aggpad); if (g_atomic_int_get (&aggpad->priv->flushing) == TRUE) goto flushing; if (aggclass->clip) { aggclass->clip (self, aggpad, buffer, &actual_buf); } PAD_LOCK_EVENT (aggpad); if (aggpad->buffer) gst_buffer_unref (aggpad->buffer); aggpad->buffer = actual_buf; PAD_UNLOCK_EVENT (aggpad); PAD_STREAM_UNLOCK (aggpad); QUEUE_PUSH (self); if (GST_CLOCK_TIME_IS_VALID (timeout)) { now = gst_clock_get_time (self->clock); aggpad->priv->timeout_id = gst_clock_new_single_shot_id (self->clock, now + timeout); gst_clock_id_wait_async (aggpad->priv->timeout_id, _unresponsive_timeout, gst_object_ref (aggpad), gst_object_unref); } GST_DEBUG_OBJECT (aggpad, "Done chaining"); return priv->flow_return; flushing: PAD_STREAM_UNLOCK (aggpad); gst_buffer_unref (buffer); GST_DEBUG_OBJECT (aggpad, "We are flushing"); return GST_FLOW_FLUSHING; eos: PAD_STREAM_UNLOCK (aggpad); gst_buffer_unref (buffer); GST_DEBUG_OBJECT (pad, "We are EOS already..."); return GST_FLOW_EOS; }