static GstPad * _get_peer_pad (GstPad * pad) { GstPad *peer = gst_pad_get_peer (pad); if (!peer) return NULL; while (GST_IS_PROXY_PAD (peer)) { GstPad *next_pad; if (GST_IS_GHOST_PAD (peer)) { next_pad = gst_pad_get_peer (peer); if (next_pad == pad) next_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (peer)); } else { next_pad = GST_PAD (gst_proxy_pad_get_internal (GST_PROXY_PAD (peer))); } if (!next_pad) return NULL; gst_object_unref (peer); peer = next_pad; } return peer; }
static void kms_audio_mixer_remove_sometimes_src_pad (KmsAudioMixer * self, GstElement * adder) { GstProxyPad *internal; GstPad *srcpad, *peer; srcpad = gst_element_get_static_pad (adder, "src"); peer = gst_pad_get_peer (srcpad); if (peer == NULL) goto end_phase_1; internal = gst_proxy_pad_get_internal ((GstProxyPad *) peer); if (internal == NULL) goto end_phase_2; gst_ghost_pad_set_target (GST_GHOST_PAD (internal), NULL); if (GST_STATE (self) < GST_STATE_PAUSED || GST_STATE_PENDING (self) < GST_STATE_PAUSED || GST_STATE_TARGET (self) < GST_STATE_PAUSED) { gst_pad_set_active (GST_PAD (internal), FALSE); } GST_DEBUG ("Removing source pad %" GST_PTR_FORMAT, internal); gst_element_remove_pad (GST_ELEMENT (self), GST_PAD (internal)); gst_object_unref (internal); end_phase_2: gst_object_unref (peer); end_phase_1: gst_object_unref (srcpad); }
static void gst_play_sink_video_convert_init (GstPlaySinkVideoConvert * self) { GstPadTemplate *templ; self->lock = g_mutex_new (); gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED); templ = gst_static_pad_template_get (&sinktemplate); self->sinkpad = gst_ghost_pad_new_no_target_from_template ("sink", templ); gst_pad_set_event_function (self->sinkpad, GST_DEBUG_FUNCPTR (gst_play_sink_video_convert_sink_event)); gst_pad_set_setcaps_function (self->sinkpad, GST_DEBUG_FUNCPTR (gst_play_sink_video_convert_sink_setcaps)); gst_pad_set_getcaps_function (self->sinkpad, GST_DEBUG_FUNCPTR (gst_play_sink_video_convert_getcaps)); self->sink_proxypad = GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD (self->sinkpad))); gst_element_add_pad (GST_ELEMENT_CAST (self), self->sinkpad); gst_object_unref (templ); templ = gst_static_pad_template_get (&srctemplate); self->srcpad = gst_ghost_pad_new_no_target_from_template ("src", templ); gst_pad_set_getcaps_function (self->srcpad, GST_DEBUG_FUNCPTR (gst_play_sink_video_convert_getcaps)); gst_element_add_pad (GST_ELEMENT_CAST (self), self->srcpad); gst_object_unref (templ); gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->srcpad), self->sink_proxypad); }
static void gst_play_sink_convert_bin_init (GstPlaySinkConvertBin * self) { GstPadTemplate *templ; g_mutex_init (&self->lock); templ = gst_static_pad_template_get (&sinktemplate); self->sinkpad = gst_ghost_pad_new_no_target_from_template ("sink", templ); gst_pad_set_event_function (self->sinkpad, GST_DEBUG_FUNCPTR (gst_play_sink_convert_bin_sink_event)); gst_pad_set_query_function (self->sinkpad, GST_DEBUG_FUNCPTR (gst_play_sink_convert_bin_query)); self->sink_proxypad = GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD (self->sinkpad))); gst_element_add_pad (GST_ELEMENT_CAST (self), self->sinkpad); gst_object_unref (templ); templ = gst_static_pad_template_get (&srctemplate); self->srcpad = gst_ghost_pad_new_no_target_from_template ("src", templ); gst_pad_set_query_function (self->srcpad, GST_DEBUG_FUNCPTR (gst_play_sink_convert_bin_query)); gst_element_add_pad (GST_ELEMENT_CAST (self), self->srcpad); gst_object_unref (templ); gst_play_sink_convert_bin_add_identity (self); }
void kms_tree_bin_unlink_input_element_from_tee (KmsTreeBin * self) { GstPad *queue_sink, *peer, *tee_src; GstElement *tee; queue_sink = gst_element_get_static_pad (self->priv->input_element, "sink"); peer = gst_pad_get_peer (queue_sink); if (GST_IS_PROXY_PAD (peer)) { GstProxyPad *ghost; ghost = gst_proxy_pad_get_internal (GST_PROXY_PAD (peer)); tee_src = gst_pad_get_peer (GST_PAD (ghost)); g_object_unref (peer); g_object_unref (ghost); } else { tee_src = peer; } gst_pad_unlink (tee_src, queue_sink); tee = gst_pad_get_parent_element (tee_src); if (tee != NULL) { gst_element_release_request_pad (tee, tee_src); g_object_unref (tee); } g_object_unref (tee_src); g_object_unref (queue_sink); }
static void kms_agnostic_bin2_link_to_tee (KmsAgnosticBin2 * self, GstPad * pad, GstElement * tee, GstCaps * caps) { GstElement *queue = gst_element_factory_make ("queue", NULL); GstPad *target; GstProxyPad *proxy; gst_bin_add (GST_BIN (self), queue); gst_element_sync_state_with_parent (queue); if (!(gst_caps_is_any (caps) || gst_caps_is_empty (caps)) && kms_utils_caps_are_raw (caps)) { GstElement *convert = kms_utils_create_convert_for_caps (caps); GstElement *rate = kms_utils_create_rate_for_caps (caps); GstElement *mediator = kms_utils_create_mediator_element (caps); remove_element_on_unlinked (convert, "src", "sink"); if (rate) { remove_element_on_unlinked (rate, "src", "sink"); } remove_element_on_unlinked (mediator, "src", "sink"); if (rate) { gst_bin_add (GST_BIN (self), rate); } gst_bin_add_many (GST_BIN (self), convert, mediator, NULL); gst_element_sync_state_with_parent (mediator); gst_element_sync_state_with_parent (convert); if (rate) { gst_element_sync_state_with_parent (rate); } if (rate) { gst_element_link_many (queue, rate, mediator, NULL); } else { gst_element_link (queue, mediator); } gst_element_link_many (mediator, convert, NULL); target = gst_element_get_static_pad (convert, "src"); } else { target = gst_element_get_static_pad (queue, "src"); } gst_ghost_pad_set_target (GST_GHOST_PAD (pad), target); proxy = gst_proxy_pad_get_internal (GST_PROXY_PAD (pad)); gst_pad_set_query_function (GST_PAD_CAST (proxy), proxy_src_pad_query_function); g_object_unref (proxy); g_object_unref (target); link_element_to_tee (tee, queue); }
static void gst_play_sink_audio_convert_init (GstPlaySinkAudioConvert * self) { GstPadTemplate *templ; self->lock = g_mutex_new (); gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED); templ = gst_static_pad_template_get (&sinktemplate); self->sinkpad = gst_ghost_pad_new_no_target_from_template ("sink", templ); gst_pad_set_event_function (self->sinkpad, GST_DEBUG_FUNCPTR (gst_play_sink_audio_convert_sink_event)); gst_pad_set_setcaps_function (self->sinkpad, GST_DEBUG_FUNCPTR (gst_play_sink_audio_convert_sink_setcaps)); gst_pad_set_getcaps_function (self->sinkpad, GST_DEBUG_FUNCPTR (gst_play_sink_audio_convert_getcaps)); self->sink_proxypad = GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD (self->sinkpad))); gst_element_add_pad (GST_ELEMENT_CAST (self), self->sinkpad); gst_object_unref (templ); templ = gst_static_pad_template_get (&srctemplate); self->srcpad = gst_ghost_pad_new_no_target_from_template ("src", templ); gst_pad_set_getcaps_function (self->srcpad, GST_DEBUG_FUNCPTR (gst_play_sink_audio_convert_getcaps)); gst_element_add_pad (GST_ELEMENT_CAST (self), self->srcpad); gst_object_unref (templ); gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->srcpad), self->sink_proxypad); /* FIXME: Only create this on demand but for now we need * it to always exist because of playsink's volume proxying * logic. */ self->volume = gst_element_factory_make ("volume", "volume"); if (self->volume) gst_object_ref_sink (self->volume); }
static void gst_insert_bin_init (GstInsertBin * self) { GstProxyPad *internal; self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GST_TYPE_INSERT_BIN, GstInsertBinPrivate); g_queue_init (&self->priv->change_queue); self->priv->sinkpad = gst_ghost_pad_new_no_target_from_template ("sink", gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (self), "sink")); gst_element_add_pad (GST_ELEMENT (self), self->priv->sinkpad); internal = gst_proxy_pad_get_internal (GST_PROXY_PAD (self->priv->sinkpad)); self->priv->srcpad = gst_ghost_pad_new_from_template ("src", GST_PAD (internal), gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (self), "src")); gst_object_unref (internal); gst_element_add_pad (GST_ELEMENT (self), self->priv->srcpad); }
static gboolean proxy_src_pad_query_function (GstPad * pad, GstObject * parent, GstQuery * query) { gboolean ret = gst_pad_query_default (pad, parent, query); if (!ret) { return ret; } if (GST_QUERY_TYPE (query) == GST_QUERY_ACCEPT_CAPS) { gboolean accepted; gst_query_parse_accept_caps_result (query, &accepted); if (!accepted) { GstProxyPad *gp = gst_proxy_pad_get_internal (GST_PROXY_PAD (pad)); KmsAgnosticBin2 *self = NULL; GST_ERROR_OBJECT (pad, "Caps not accepted: %" GST_PTR_FORMAT, query); if (gp) { self = KMS_AGNOSTIC_BIN2 (GST_OBJECT_PARENT (gp)); } if (self) { KMS_AGNOSTIC_BIN2_LOCK (self); remove_target_pad (GST_PAD_CAST (gp)); kms_agnostic_bin2_process_pad (self, GST_PAD_CAST (gp)); KMS_AGNOSTIC_BIN2_UNLOCK (self); } g_object_unref (gp); } } return ret; }
static void gst_insert_bin_block_pad_unlock (GstInsertBin * self) { struct ChangeData *data; GstPad *pad; GstPadProbeType probetype; again: data = g_queue_peek_head (&self->priv->change_queue); if (!data) { GST_OBJECT_UNLOCK (self); return; } if (data->action == GST_INSERT_BIN_ACTION_ADD && !validate_element (self, data->element)) goto error; if (data->action == GST_INSERT_BIN_ACTION_ADD) { if (data->sibling) { if (data->direction == DIRECTION_BEFORE) pad = get_single_pad (data->sibling, GST_PAD_SINK); else pad = get_single_pad (data->sibling, GST_PAD_SRC); } else { if (data->direction == DIRECTION_BEFORE) pad = (GstPad *) gst_proxy_pad_get_internal (GST_PROXY_PAD (self->priv->srcpad)); else pad = (GstPad *) gst_proxy_pad_get_internal (GST_PROXY_PAD (self->priv->sinkpad)); } if (!pad) { GST_WARNING_OBJECT (self, "Can not obtain a sibling pad to block" " before adding"); goto error; } if (!is_right_direction_for_block (pad)) { GstPad *peer = gst_pad_get_peer (pad); if (peer) { gst_object_unref (pad); pad = peer; } } } else { GstPad *element_pad; element_pad = get_single_pad (data->element, GST_PAD_SINK); if (!element_pad) { GST_WARNING_OBJECT (self, "Can not obtain the element's sink pad"); goto error; } if (!is_right_direction_for_block (element_pad)) { pad = gst_pad_get_peer (element_pad); } else { gst_object_unref (element_pad); element_pad = get_single_pad (data->element, GST_PAD_SRC); if (!element_pad) { GST_WARNING_OBJECT (self, "Can not obtain the element's src pad"); goto error; } pad = gst_pad_get_peer (element_pad); } gst_object_unref (element_pad); if (!pad) { GST_WARNING_OBJECT (self, "Can not obtain a sibling pad for removing"); goto error; } } if (GST_PAD_IS_SRC (pad)) probetype = GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM; else probetype = GST_PAD_PROBE_TYPE_BLOCK_UPSTREAM; GST_OBJECT_UNLOCK (self); gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_IDLE | probetype, pad_blocked_cb, self, NULL); gst_object_unref (pad); return; error: g_queue_pop_head (&self->priv->change_queue); gst_insert_bin_change_data_complete (self, data, FALSE); goto again; }