static GstPad * kms_hub_port_generate_sink_pad (GstElement * element, GstPadTemplate * templ, const gchar * name, const GstCaps * caps, GstElement * output) { GstPad *output_pad, *pad; output_pad = gst_element_get_static_pad (output, "sink"); pad = gst_ghost_pad_new_from_template (name, output_pad, templ); g_object_unref (output_pad); if (GST_STATE (element) >= GST_STATE_PAUSED || GST_STATE_PENDING (element) >= GST_STATE_PAUSED || GST_STATE_TARGET (element) >= GST_STATE_PAUSED) { gst_pad_set_active (pad, TRUE); } if (gst_element_add_pad (element, pad)) return pad; GST_ERROR_OBJECT (element, "Cannot add pad %" GST_PTR_FORMAT, pad); g_object_unref (pad); return NULL; }
//FIXME this should be part of the library void shmdata_base_reader_clean_element (GstElement *element) { if (element != NULL && GST_IS_ELEMENT(element) && GST_STATE_CHANGE_FAILURE != GST_STATE_RETURN(element)) { { // unlinking pads GstIterator *pad_iter = gst_element_iterate_pads(element); gst_iterator_foreach(pad_iter, (GFunc) shmdata_base_reader_unlink_pad, NULL); gst_iterator_free(pad_iter); } { // releasing request pads GstIterator *pad_iter = gst_element_iterate_pads(element); gst_iterator_foreach(pad_iter, (GFunc) shmdata_base_reader_release_request_pad, element); gst_iterator_free(pad_iter); } GstState state = GST_STATE_TARGET(element); if (state != GST_STATE_NULL) { if (GST_STATE_CHANGE_ASYNC == gst_element_set_state(element, GST_STATE_NULL)) { while (GST_STATE(element) != GST_STATE_NULL) { // warning this may be blocking gst_element_get_state(element, NULL, NULL, GST_CLOCK_TIME_NONE); } } } if (GST_IS_BIN(gst_element_get_parent(element))) gst_bin_remove(GST_BIN(gst_element_get_parent(element)), element); else gst_object_unref(element); } }
static gboolean kms_base_hub_create_and_link_ghost_pad (KmsBaseHub * mixer, GstPad * src_pad, const gchar * gp_name, const gchar * gp_template_name, GstPad * target) { GstPadTemplate *templ; GstPad *gp; gboolean ret; templ = gst_element_class_get_pad_template (GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (mixer)), gp_template_name); gp = gst_ghost_pad_new_from_template (gp_name, target, templ); if (GST_STATE (mixer) >= GST_STATE_PAUSED || GST_STATE_PENDING (mixer) >= GST_STATE_PAUSED || GST_STATE_TARGET (mixer) >= GST_STATE_PAUSED) { gst_pad_set_active (gp, TRUE); } ret = gst_element_add_pad (GST_ELEMENT (mixer), gp); if (ret) { gst_pad_link (src_pad, gp); } else { g_object_unref (gp); } return ret; }
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 kms_hub_port_start_media_type (KmsElement * self, KmsElementPadType type, GstPadTemplate * templ, const gchar * pad_name) { GstElement *capsfilter = gst_element_factory_make ("capsfilter", NULL); GstPad *src = gst_element_get_static_pad (capsfilter, "src"); GstPad *internal_src; gst_bin_add (GST_BIN (self), capsfilter); gst_element_sync_state_with_parent (capsfilter); internal_src = gst_ghost_pad_new_from_template (pad_name, src, templ); g_object_set_qdata_full (G_OBJECT (internal_src), key_elem_data_quark (), g_object_ref (capsfilter), g_object_unref); g_object_set_qdata (G_OBJECT (internal_src), key_type_data_quark (), GINT_TO_POINTER (type)); g_signal_connect (internal_src, "linked", G_CALLBACK (kms_hub_port_internal_src_pad_linked), 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 (internal_src, TRUE); } gst_element_add_pad (GST_ELEMENT (self), internal_src); g_object_unref (src); }
static void type_found (GstElement * typefind, guint probability, GstCaps * caps, GstSplitMuxPartReader * reader) { GstElement *demux; GST_INFO_OBJECT (reader, "Got type %" GST_PTR_FORMAT, caps); /* typefind found a type. Look for the demuxer to handle it */ demux = reader->demux = find_demuxer (caps); if (reader->demux == NULL) { GST_ERROR_OBJECT (reader, "Failed to create demuxer element"); return; } /* Connect to demux signals */ g_signal_connect (demux, "pad-added", G_CALLBACK (new_decoded_pad_added_cb), reader); g_signal_connect (demux, "no-more-pads", G_CALLBACK (no_more_pads), reader); gst_element_set_locked_state (demux, TRUE); gst_bin_add (GST_BIN_CAST (reader), demux); gst_element_link_pads (reader->typefind, "src", demux, NULL); gst_element_set_state (reader->demux, GST_STATE_TARGET (reader)); gst_element_set_locked_state (demux, FALSE); }
void GstUtils::sync_state_with_parent(GstElement *element) { if (!GST_IS_ELEMENT(element)) { g_debug("GstUtils::sync_state_with_parent, arg is not an element"); return; } GstElement *parent = GST_ELEMENT(GST_ELEMENT_PARENT(element)); if (GST_IS_ELEMENT(parent)) { if (GST_STATE(parent) != GST_STATE_TARGET(parent)) gst_element_set_state(element, GST_STATE_TARGET(parent)); else gst_element_sync_state_with_parent(element); } else g_warning ("GstUtils::sync_state_with_parent, cannot sync an orphan element"); }
static gboolean kms_base_hub_link_src_pad (KmsBaseHub * mixer, const gchar * gp_name, const gchar * template_name, GstElement * internal_element, const gchar * pad_name, gboolean remove_on_unlink) { GstPad *gp, *target; gboolean ret; if (GST_OBJECT_PARENT (internal_element) != GST_OBJECT (mixer)) { GST_ERROR_OBJECT (mixer, "Cannot link %" GST_PTR_FORMAT " wrong hierarchy", internal_element); return FALSE; } target = gst_element_get_static_pad (internal_element, pad_name); if (target == NULL) { target = gst_element_get_request_pad (internal_element, pad_name); if (target != NULL && remove_on_unlink) { g_signal_connect (G_OBJECT (target), "unlinked", G_CALLBACK (remove_unlinked_pad), NULL); } } if (target == NULL) { GST_ERROR_OBJECT (mixer, "Cannot get target pad"); return FALSE; } gp = gst_element_get_static_pad (GST_ELEMENT (mixer), gp_name); if (gp == NULL) { GstPadTemplate *templ; templ = gst_element_class_get_pad_template (GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (mixer)), template_name); gp = gst_ghost_pad_new_from_template (gp_name, target, templ); if (GST_STATE (mixer) >= GST_STATE_PAUSED || GST_STATE_PENDING (mixer) >= GST_STATE_PAUSED || GST_STATE_TARGET (mixer) >= GST_STATE_PAUSED) { gst_pad_set_active (gp, TRUE); } ret = gst_element_add_pad (GST_ELEMENT (mixer), gp); if (!ret) { g_object_unref (gp); } } else { ret = set_target (gp, target); g_object_unref (gp); } g_object_unref (target); return ret; }
void GstUtils::wait_state_changed(GstElement *bin) { if (!GST_IS_BIN(bin)) { g_warning("GstUtils::wait_state_changed not a bin"); return; } GValue val = G_VALUE_INIT; g_value_init(&val, G_TYPE_BOOLEAN); g_object_get_property(G_OBJECT(bin), "async-handling", &val); if (g_value_get_boolean(&val) == FALSE) while (GST_STATE(bin) != GST_STATE_TARGET(bin)) { g_debug("GstUtils::wait_state_changed, from %s to %s", gst_element_state_get_name(GST_STATE(bin)), gst_element_state_get_name(GST_STATE_TARGET(bin))); // warning this may be blocking gst_element_get_state(bin, nullptr, nullptr, GST_CLOCK_TIME_NONE); } g_value_unset(&val); return; }
static void gst_decklink_video_sink_state_changed (GstElement * element, GstState old_state, GstState new_state, GstState pending_state) { GstDecklinkVideoSink *self = GST_DECKLINK_VIDEO_SINK_CAST (element); // Aka gst_element_lost_state() if (old_state == GST_STATE_PAUSED && new_state == GST_STATE_PAUSED && pending_state == GST_STATE_PAUSED && GST_STATE_TARGET (element) == GST_STATE_PLAYING) { gst_decklink_video_sink_stop_scheduled_playback (self); } }
GstPad * kms_element_connect_sink_target_full (KmsElement * self, GstPad * target, KmsElementPadType type, const gchar * description) { GstPad *pad; gchar *pad_name; GstPadTemplate *templ; templ = gst_static_pad_template_get (&sink_factory); pad_name = get_pad_name (type, description); pad = gst_ghost_pad_new_from_template (pad_name, target, templ); g_free (pad_name); g_object_unref (templ); if (type == KMS_ELEMENT_PAD_TYPE_VIDEO) { kms_utils_drop_until_keyframe (pad, TRUE); kms_utils_manage_gaps (pad); } gst_pad_set_query_function (pad, kms_element_pad_query); gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM | GST_PAD_PROBE_TYPE_EVENT_FLUSH, accept_eos_probe, self, NULL); g_signal_connect (G_OBJECT (pad), "unlinked", G_CALLBACK (send_flush_on_unlink), 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 (pad, TRUE); } if (gst_element_add_pad (GST_ELEMENT (self), pad)) { kms_element_set_sink_input_stats (self, pad, type); return pad; } g_object_unref (pad); return NULL; }
gboolean gst_element_sync_state_with_parent_target_state (GstElement * element) { GstElement *parent; GstState target; GstStateChangeReturn ret; g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); parent = GST_ELEMENT_CAST (gst_element_get_parent (element)); if (parent == NULL) { GST_DEBUG_OBJECT (element, "element has no parent"); return FALSE; } GST_OBJECT_LOCK (parent); target = GST_STATE_TARGET (parent); GST_OBJECT_UNLOCK (parent); GST_DEBUG_OBJECT (element, "setting parent (%s) target state %s", GST_ELEMENT_NAME (parent), gst_element_state_get_name (target)); gst_object_unref (parent); ret = gst_element_set_state (element, target); if (ret == GST_STATE_CHANGE_FAILURE) { GST_DEBUG_OBJECT (element, "setting target state failed (%s)", gst_element_state_change_return_get_name (ret)); return FALSE; } return TRUE; }
static void kms_element_add_src_pad (KmsElement * self, GstElement * element, const gchar * pad_name, const gchar * templ_name) { GstPad *srcpad; srcpad = gst_ghost_pad_new_no_target_from_template (pad_name, gst_element_class_get_pad_template (GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (self)), templ_name)); 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 (srcpad, TRUE); g_signal_connect (srcpad, "linked", G_CALLBACK (kms_element_set_target_on_linked), element); g_signal_connect (srcpad, "unlinked", G_CALLBACK (kms_element_remove_target_on_unlinked), element); gst_element_add_pad (GST_ELEMENT (self), srcpad); }
gboolean shmdata_base_reader_attach (shmdata_base_reader_t *reader) { g_mutex_lock (&reader->mutex_); if (reader->attached_) { g_mutex_unlock (&reader->mutex_); return FALSE; } reader->attached_ = TRUE; reader->source_ = gst_element_factory_make ("shmsrc", NULL); reader->deserializer_ = gst_element_factory_make ("gdpdepay", NULL); GstPad *pad = gst_element_get_static_pad(reader->deserializer_, "src"); gst_pad_add_data_probe (pad, G_CALLBACK (shmdata_base_reader_reset_time), reader); gst_object_unref(pad); reader->typefind_ = gst_element_factory_make ("typefind", NULL); if (NULL == reader->typefind_) { g_warning ("no typefind !"); g_mutex_unlock (&reader->mutex_); return FALSE; } reader->have_type_handler_id_ = g_signal_connect (reader->typefind_, "have-type", G_CALLBACK (shmdata_base_reader_on_type_found), reader); if (reader->do_absolute_) reader->timereset_ = FALSE; if (!reader->source_) { g_critical ("Reader: \"shmsrc\" element could not be created"); g_mutex_unlock (&reader->mutex_); return FALSE; } if (!reader->deserializer_) { g_critical ("Reader: \"gdpdepay\" element could not be created."); g_mutex_unlock (&reader->mutex_); return FALSE; } if (!reader->typefind_) { g_critical ("Reader: \"typefind\" element could not be created."); g_mutex_unlock (&reader->mutex_); return FALSE; } g_object_set_data (G_OBJECT (reader->source_), "shmdata_base_reader", (gpointer)reader); g_object_set_data (G_OBJECT (reader->deserializer_), "shmdata_base_reader", (gpointer)reader); g_object_set (G_OBJECT (reader->source_), "socket-path", reader->socket_name_, NULL); gst_bin_add_many (GST_BIN (reader->bin_), reader->source_, reader->deserializer_, reader->typefind_, NULL); GstPad *src_pad = gst_element_get_static_pad (reader->typefind_, "src"); GstPad *sink_pad = gst_element_get_compatible_pad (reader->sink_, src_pad, GST_PAD_CAPS(src_pad)); gst_element_link_many (reader->source_, reader->deserializer_, reader->typefind_, NULL); gst_pad_link (src_pad, sink_pad); gst_object_unref(sink_pad); gst_object_unref(src_pad); gst_element_set_state (reader->typefind_,GST_STATE_TARGET(reader->bin_)); gst_element_set_state (reader->deserializer_,GST_STATE_TARGET(reader->bin_)); gst_element_set_state (reader->source_,GST_STATE_TARGET(reader->bin_)); g_mutex_unlock (&reader->mutex_); return FALSE; //for g_idle_add }
static GstPad * kms_element_request_new_pad (GstElement * element, GstPadTemplate * templ, const gchar * name, const GstCaps * caps) { GstPad *ret_pad = NULL; gchar *pad_name; gboolean added; KMS_ELEMENT_LOCK (element); if (templ == gst_element_class_get_pad_template (GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (element)), "audio_src_%u")) { pad_name = g_strdup_printf ("audio_src_%d", KMS_ELEMENT (element)->priv->audio_pad_count++); ret_pad = kms_element_generate_src_pad (KMS_ELEMENT (element), pad_name, KMS_ELEMENT (element)->priv->audio_agnosticbin, templ); if (ret_pad == NULL) KMS_ELEMENT (element)->priv->audio_pad_count--; g_free (pad_name); } else if (templ == gst_element_class_get_pad_template (GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (element)), "video_src_%u")) { pad_name = g_strdup_printf ("video_src_%d", KMS_ELEMENT (element)->priv->video_pad_count++); ret_pad = kms_element_generate_src_pad (KMS_ELEMENT (element), pad_name, KMS_ELEMENT (element)->priv->video_agnosticbin, templ); if (ret_pad == NULL) KMS_ELEMENT (element)->priv->video_pad_count--; g_free (pad_name); } else if (templ == gst_element_class_get_pad_template (GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (element)), AUDIO_SINK_PAD)) { ret_pad = kms_element_generate_sink_pad (KMS_ELEMENT (element), AUDIO_SINK_PAD, &KMS_ELEMENT (element)->priv->audio_valve, templ); gst_pad_add_probe (ret_pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, accept_eos_probe, element, NULL); g_signal_connect (G_OBJECT (ret_pad), "unlinked", G_CALLBACK (send_flush_on_unlink), NULL); } else if (templ == gst_element_class_get_pad_template (GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (element)), VIDEO_SINK_PAD)) { ret_pad = kms_element_generate_sink_pad (KMS_ELEMENT (element), VIDEO_SINK_PAD, &KMS_ELEMENT (element)->priv->video_valve, templ); gst_pad_add_probe (ret_pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, accept_eos_probe, element, NULL); g_signal_connect (G_OBJECT (ret_pad), "unlinked", G_CALLBACK (send_flush_on_unlink), NULL); } if (ret_pad == NULL) { KMS_ELEMENT_UNLOCK (element); GST_WARNING ("No pad created"); return NULL; } if (GST_STATE (element) >= GST_STATE_PAUSED || GST_STATE_PENDING (element) >= GST_STATE_PAUSED || GST_STATE_TARGET (element) >= GST_STATE_PAUSED) gst_pad_set_active (ret_pad, TRUE); added = gst_element_add_pad (element, ret_pad); KMS_ELEMENT_UNLOCK (element); if (added) return ret_pad; if (gst_pad_get_direction (ret_pad) == GST_PAD_SRC) { GstPad *target = gst_ghost_pad_get_target (GST_GHOST_PAD (ret_pad)); if (target != NULL) { GstElement *agnostic = gst_pad_get_parent_element (target); gst_element_release_request_pad (agnostic, target); g_object_unref (target); g_object_unref (agnostic); } } g_object_unref (ret_pad); return NULL; }
static GstPad * gst_sctp_base_sink_request_new_pad (GstElement * element, GstPadTemplate * templ, const gchar * name, const GstCaps * caps) { GstSCTPBaseSink *self = GST_SCTP_BASE_SINK (element); GstPad *sinkpad, *ghostpad; GstElement *sctpclientsink; gchar *padname; gchar *pad_id; gint64 val; guint16 id; GST_SCTP_BASE_SINK_LOCK (self); if (self->priv->num_ostreams < self->priv->streams) { GST_SCTP_BASE_SINK_UNLOCK (self); GST_WARNING ("No more available streams"); return NULL; } pad_id = get_stream_id_from_padname (name); if (pad_id == NULL) { GST_SCTP_BASE_SINK_UNLOCK (self); GST_WARNING ("Link of elements without using pad names is not yet supported"); return NULL; } val = g_ascii_strtoll (pad_id, NULL, 10); g_free (pad_id); if (val > G_MAXUINT32) { GST_SCTP_BASE_SINK_UNLOCK (self); GST_ERROR ("SCTP stream id %" G_GINT64_FORMAT " is not valid", val); return NULL; } id = val; sctpclientsink = gst_element_factory_make ("sctpclientsink", NULL); sinkpad = gst_element_get_static_pad (sctpclientsink, "sink"); if (sinkpad == NULL) { GST_SCTP_BASE_SINK_UNLOCK (self); GST_ERROR_OBJECT (sctpclientsink, "Can not get sink pad"); gst_object_unref (sctpclientsink); return NULL; } g_object_set (sctpclientsink, "stream-id", id, "socket", self->priv->socket, NULL); gst_bin_add (GST_BIN (element), sctpclientsink); gst_element_sync_state_with_parent (sctpclientsink); padname = g_strdup_printf ("sink_%u", id); ghostpad = gst_ghost_pad_new_from_template (padname, sinkpad, templ); g_object_unref (sinkpad); g_free (padname); if (GST_STATE (element) >= GST_STATE_PAUSED || GST_STATE_PENDING (element) >= GST_STATE_PAUSED || GST_STATE_TARGET (element) >= GST_STATE_PAUSED) gst_pad_set_active (ghostpad, TRUE); gst_element_add_pad (element, ghostpad); self->priv->streams++; GST_SCTP_BASE_SINK_UNLOCK (self); return ghostpad; }
/* GstElement vfuncs */ static GstPad * gst_stream_synchronizer_request_new_pad (GstElement * element, GstPadTemplate * temp, const gchar * name, const GstCaps * caps) { GstStreamSynchronizer *self = GST_STREAM_SYNCHRONIZER (element); GstStream *stream; gchar *tmp; GST_STREAM_SYNCHRONIZER_LOCK (self); GST_DEBUG_OBJECT (self, "Requesting new pad for stream %d", self->current_stream_number); stream = g_slice_new0 (GstStream); stream->transform = self; stream->stream_number = self->current_stream_number; g_cond_init (&stream->stream_finish_cond); stream->stream_start_seqnum = G_MAXUINT32; stream->segment_seqnum = G_MAXUINT32; tmp = g_strdup_printf ("sink_%u", self->current_stream_number); stream->sinkpad = gst_pad_new_from_static_template (&sinktemplate, tmp); g_free (tmp); gst_pad_set_element_private (stream->sinkpad, stream); gst_pad_set_iterate_internal_links_function (stream->sinkpad, GST_DEBUG_FUNCPTR (gst_stream_synchronizer_iterate_internal_links)); gst_pad_set_query_function (stream->sinkpad, GST_DEBUG_FUNCPTR (gst_stream_synchronizer_query)); gst_pad_set_event_function (stream->sinkpad, GST_DEBUG_FUNCPTR (gst_stream_synchronizer_sink_event)); gst_pad_set_chain_function (stream->sinkpad, GST_DEBUG_FUNCPTR (gst_stream_synchronizer_sink_chain)); tmp = g_strdup_printf ("src_%u", self->current_stream_number); stream->srcpad = gst_pad_new_from_static_template (&srctemplate, tmp); g_free (tmp); gst_pad_set_element_private (stream->srcpad, stream); gst_pad_set_iterate_internal_links_function (stream->srcpad, GST_DEBUG_FUNCPTR (gst_stream_synchronizer_iterate_internal_links)); gst_pad_set_query_function (stream->srcpad, GST_DEBUG_FUNCPTR (gst_stream_synchronizer_query)); gst_pad_set_event_function (stream->srcpad, GST_DEBUG_FUNCPTR (gst_stream_synchronizer_src_event)); gst_segment_init (&stream->segment, GST_FORMAT_UNDEFINED); self->streams = g_list_prepend (self->streams, stream); self->current_stream_number++; GST_STREAM_SYNCHRONIZER_UNLOCK (self); /* Add pads and activate unless we're going to NULL */ g_rec_mutex_lock (GST_STATE_GET_LOCK (self)); if (GST_STATE_TARGET (self) != GST_STATE_NULL) { gst_pad_set_active (stream->srcpad, TRUE); gst_pad_set_active (stream->sinkpad, TRUE); } gst_element_add_pad (GST_ELEMENT_CAST (self), stream->srcpad); gst_element_add_pad (GST_ELEMENT_CAST (self), stream->sinkpad); g_rec_mutex_unlock (GST_STATE_GET_LOCK (self)); return stream->sinkpad; }