static GstElement * gst_switch_select (GstSwitch * swit, GstPadTemplate * templ, const gchar * name, const GstCaps * caps) { GList *item = GST_BIN_CHILDREN (GST_BIN (swit)); GstElement *swcase = NULL; for (; item; item = g_list_next (item)) { GList *paditem = GST_ELEMENT_PADS (GST_ELEMENT (item->data)); GstPad *basepad = NULL, *pad = NULL; for (; paditem; paditem = g_list_next (paditem)) { pad = GST_PAD (paditem->data); if (GST_PAD_IS_SINK (pad) && !gst_pad_is_linked (pad) && !GST_OBJECT_FLAG_IS_SET (GST_OBJECT (pad), GST_SWITCH_PAD_FLAG_GHOSTED)) { basepad = pad; break; } } if (basepad) { swcase = GST_ELEMENT (item->data); break; } } if (!swcase) { swcase = gst_switch_request_new_case (swit, templ, caps); } return swcase; }
/* generate queries to adaptive demux */ static gboolean testQueryCheckDataReceived (GstAdaptiveDemuxTestEngine * engine, GstAdaptiveDemuxTestOutputStream * stream, GstBuffer * buffer, gpointer user_data) { GList *pads; GstPad *pad; GstQuery *query; gboolean ret; gint64 duration; gboolean seekable; gint64 segment_start; gint64 segment_end; gchar *uri; gchar *redirect_uri; gboolean redirect_permanent; pads = GST_ELEMENT_PADS (stream->appsink); /* AppSink should have only 1 pad */ fail_unless (pads != NULL); fail_unless (g_list_length (pads) == 1); pad = GST_PAD (pads->data); query = gst_query_new_duration (GST_FORMAT_TIME); ret = gst_pad_peer_query (pad, query); fail_unless (ret == TRUE); gst_query_parse_duration (query, NULL, &duration); fail_unless (duration == 135743 * GST_MSECOND); gst_query_unref (query); query = gst_query_new_seeking (GST_FORMAT_TIME); ret = gst_pad_peer_query (pad, query); fail_unless (ret == TRUE); gst_query_parse_seeking (query, NULL, &seekable, &segment_start, &segment_end); fail_unless (seekable == TRUE); fail_unless (segment_start == 0); fail_unless (segment_end == duration); gst_query_unref (query); query = gst_query_new_uri (); ret = gst_pad_peer_query (pad, query); fail_unless (ret == TRUE); gst_query_parse_uri (query, &uri); gst_query_parse_uri_redirection (query, &redirect_uri); gst_query_parse_uri_redirection_permanent (query, &redirect_permanent); fail_unless (strcmp (uri, "http://unit.test/test.mpd") == 0); /* adaptive demux does not reply with redirect information */ fail_unless (redirect_uri == NULL); fail_unless (redirect_permanent == FALSE); g_free (uri); g_free (redirect_uri); gst_query_unref (query); return gst_adaptive_demux_test_check_received_data (engine, stream, buffer, user_data); }
static GstPad * gst_tcp_mix_src_request_new_pad (GstElement * element, GstPadTemplate * templ, const gchar * unused, const GstCaps * caps) { GstTCPMixSrc *src = GST_TCP_MIX_SRC (element); GstPad *srcpad; gchar *name; gboolean res; int num; //g_print ("%s:%d: %s\n", __FILE__, __LINE__, __FUNCTION__); GST_INFO_OBJECT (src, "Requesting new pad %s.%s (caps: %s)", GST_ELEMENT_NAME (src), GST_PAD_TEMPLATE_NAME_TEMPLATE (templ), gst_caps_to_string (caps)); GST_OBJECT_LOCK (src); num = g_list_length (GST_ELEMENT_PADS (src)); name = g_strdup_printf ("src_%u", num); srcpad = GST_PAD_CAST (g_object_new (GST_TYPE_TCP_MIX_SRC_PAD, "name", name, "direction", templ->direction, "template", templ, NULL)); g_free (name); GST_OBJECT_UNLOCK (src); // see: gst_tcp_mix_src_activate_push gst_pad_set_active (srcpad, TRUE); gst_pad_activate_mode (srcpad, GST_PAD_MODE_PUSH, TRUE); gst_pad_set_activatemode_function (srcpad, (GstPadActivateModeFunction) gst_tcp_mix_src_activate_mode); gst_pad_set_query_function (srcpad, gst_tcp_mix_src_query); gst_pad_set_event_function (srcpad, gst_tcp_mix_src_event); gst_pad_set_getrange_function (srcpad, gst_tcp_mix_src_getrange); //GST_OBJECT_FLAG_SET (srcpad, GST_PAD_FLAG_PROXY_CAPS); //INFO ("add-pad: %s.%s", GST_ELEMENT_NAME (src), GST_PAD_NAME (srcpad)); res = gst_element_add_pad (GST_ELEMENT_CAST (src), srcpad); gst_tcp_mix_src_start (src, GST_TCP_MIX_SRC_PAD (srcpad)); if (G_UNLIKELY (!res)) { GST_ERROR_OBJECT (src, "Failed to add new pad"); } return srcpad; }
static void gst_tee_dispose (GObject * object) { GList *item; restart: for (item = GST_ELEMENT_PADS (object); item; item = g_list_next (item)) { GstPad *pad = GST_PAD (item->data); if (GST_PAD_IS_SRC (pad)) { gst_element_release_request_pad (GST_ELEMENT (object), pad); goto restart; } } G_OBJECT_CLASS (parent_class)->dispose (object); }
static gboolean gst_base_adaptive_sink_request_first_fragments (GstBaseAdaptiveSink * sink) { GList *tmp; gint i; tmp = g_list_first (GST_ELEMENT_PADS (GST_ELEMENT (sink))); do { for (i = 0; i < sink->min_cache; i++) { gst_base_adaptive_sink_request_new_fragment (sink, (GstPad *) tmp->data); } tmp = g_list_next (tmp); } while (tmp != NULL); return TRUE; }
static void gst_rtp_mux_dispose (GObject * object) { GstRTPMux *rtp_mux = GST_RTP_MUX (object); GList *item; g_clear_object (&rtp_mux->last_pad); restart: for (item = GST_ELEMENT_PADS (object); item; item = g_list_next (item)) { GstPad *pad = GST_PAD (item->data); if (GST_PAD_IS_SINK (pad)) { gst_element_release_request_pad (GST_ELEMENT (object), pad); goto restart; } } G_OBJECT_CLASS (gst_rtp_mux_parent_class)->dispose (object); }
static void gst_funnel_dispose (GObject * object) { GstFunnel *funnel = GST_FUNNEL (object); GList *item; gst_object_replace ((GstObject **) & funnel->last_sinkpad, NULL); restart: for (item = GST_ELEMENT_PADS (object); item; item = g_list_next (item)) { GstPad *pad = GST_PAD (item->data); if (GST_PAD_IS_SINK (pad)) { gst_element_release_request_pad (GST_ELEMENT (object), pad); goto restart; } } G_OBJECT_CLASS (parent_class)->dispose (object); }
static gboolean gst_tcp_mix_src_stop (GstTCPMixSrc * src, GstTCPMixSrcPad * pad) { GError *err = NULL; GList *item; GST_OBJECT_LOCK (src); GST_DEBUG_OBJECT (src, "Closing client sockets"); for (item = GST_ELEMENT_PADS (src); item; item = g_list_next (item)) { GstPad *p = GST_PAD (item->data); if (GST_PAD_IS_SRC (p)) { gst_tcp_mix_src_pad_reset (GST_TCP_MIX_SRC_PAD (p)); } } GST_OBJECT_UNLOCK (src); if (src->server_socket) { GST_DEBUG_OBJECT (src, "Closing server socket"); if (!g_socket_close (src->server_socket, &err)) { GST_ERROR_OBJECT (src, "Failed to close socket: %s", err->message); g_clear_error (&err); } g_object_unref (src->server_socket); src->server_socket = NULL; gst_tcp_mix_src_stop_acceptor (src); g_atomic_int_set (&src->bound_port, 0); g_object_notify (G_OBJECT (src), "bound-port"); } GST_OBJECT_FLAG_UNSET (src, GST_TCP_MIX_SRC_OPEN); return TRUE; }
static void gst_tcp_mix_src_add_client (GstTCPMixSrc * src, GSocket * socket) { GstTCPMixSrcPad *pad, *p; GList *item; GError *err; pad = NULL; GST_OBJECT_LOCK (src); for (item = GST_ELEMENT_PADS (src); item; item = g_list_next (item)) { p = pad = GST_TCP_MIX_SRC_PAD (item->data); if (GST_PAD_IS_SRC (p)) { GST_OBJECT_LOCK (p); if (pad->client) { pad = NULL; } else { GST_TCP_MIX_SRC_PAD_CLIENT_LOCK (pad); pad->client = socket; GST_TCP_MIX_SRC_PAD_CLIENT_NOTIFY (pad); GST_TCP_MIX_SRC_PAD_CLIENT_UNLOCK (pad); } GST_OBJECT_UNLOCK (p); if (pad) break; } } GST_OBJECT_UNLOCK (src); if (!pad) { pad = GST_TCP_MIX_SRC_PAD (gst_element_get_request_pad (GST_ELEMENT (src), srctemplate.name_template)); GST_OBJECT_LOCK (pad); GST_TCP_MIX_SRC_PAD_CLIENT_LOCK (pad); pad->client = socket; GST_TCP_MIX_SRC_PAD_CLIENT_NOTIFY (pad); GST_TCP_MIX_SRC_PAD_CLIENT_UNLOCK (pad); GST_OBJECT_UNLOCK (pad); } if (pad) { GST_DEBUG_OBJECT (pad, "New client on %s.%s (%d srcpads)", GST_ELEMENT_NAME (src), GST_PAD_NAME (pad), GST_ELEMENT (src)->numsrcpads); gst_tcp_mix_src_request_link_pad (src, pad); if (!gst_pad_is_linked (GST_PAD (pad))) { GST_ERROR_OBJECT (src, "Pad %s.%s is not linked", GST_ELEMENT_NAME (src), GST_PAD_NAME (pad)); } if (!gst_pad_is_active (GST_PAD (pad))) gst_pad_set_active (GST_PAD (pad), TRUE); g_signal_emit (src, gst_tcpmixsrc_signals[SIGNAL_NEW_CLIENT], 0, pad); } else { GST_WARNING_OBJECT (src, "No pad for new client, closing.."); if (!g_socket_close (socket, &err)) { GST_ERROR_OBJECT (src, "Failed to close socket: %s", err->message); g_clear_error (&err); } g_object_unref (socket); } }
static void gst_tcp_mix_src_request_link_pad (GstTCPMixSrc * src, GstTCPMixSrcPad * pad) { GstTCPMixSrcPad *p; GstPad *pp; GList *item; gboolean linked = FALSE; GstBin *parent; GstElement *target; GstPadLinkReturn linkRet; if (gst_pad_is_linked (GST_PAD (pad))) { #if 1 pp = GST_PAD_PEER (pad); GST_WARNING_OBJECT (src, "Pad %s.%s already linked to %s.%s", GST_ELEMENT_NAME (src), GST_PAD_NAME (pad), GST_ELEMENT_NAME (GST_PAD_PARENT (pp)), GST_PAD_NAME (pp)); #endif return; } GST_LOG_OBJECT (src, "Linking pad '%s.%s'", GST_ELEMENT_NAME (src), GST_PAD_NAME (pad)); INFO ("link"); /** * Don't do GST_OBJECT_LOCK() here, it causes DEADLOCK. */ /* GST_OBJECT_LOCK (src); */ if (!src->autosink) goto find_sink; parent = GST_BIN (GST_ELEMENT_PARENT (src)); target = gst_bin_get_by_name (parent, src->autosink); INFO ("link"); if (!target) goto find_sink; pp = gst_element_get_request_pad (target, "sink_%u"); GST_DEBUG_OBJECT (src, "Link %s.%s-%s.%s", GST_ELEMENT_NAME (src), GST_PAD_NAME (pad), GST_ELEMENT_NAME (GST_PAD_PARENT (pp)), GST_PAD_NAME (pp)); INFO ("link"); linkRet = gst_pad_link (GST_PAD (pad), GST_PAD (pp)); if (GST_PAD_LINK_FAILED (linkRet)) { GST_ERROR_OBJECT (src, "can't link"); } return; find_sink: #if 1 for (item = GST_ELEMENT_PADS (src); item; item = g_list_next (item)) { p = GST_TCP_MIX_SRC_PAD (item->data); if (GST_PAD_IS_SRC (p)) { GST_OBJECT_LOCK (p); if ((pp = GST_PAD_PEER (p))) { GstElement *ele = GST_ELEMENT (GST_PAD_PARENT (pp)); // FIXME: pad name calculation pp = gst_element_get_request_pad (ele, "sink_%u"); GST_DEBUG_OBJECT (src, "Link %s.%s-%s.%s", GST_ELEMENT_NAME (src), GST_PAD_NAME (pad), GST_ELEMENT_NAME (GST_PAD_PARENT (pp)), GST_PAD_NAME (pp)); linkRet = gst_pad_link (GST_PAD (pad), GST_PAD (pp)); if (GST_PAD_LINK_FAILED (linkRet)) { GST_ERROR_OBJECT (src, "can't link"); } else { linked = TRUE; } } GST_OBJECT_UNLOCK (p); if (linked) break; } } #endif /* GST_OBJECT_UNLOCK (src); */ return; }