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; }
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); if (kms_utils_caps_are_video (caps)) { g_object_set (queue, "leaky", 2, "max-size-time", LEAKY_TIME, NULL); } 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); }