/** * Link a pad internally * * @self: The #KmsAgnosticBin2 owner of the pad * @pad: (transfer full): The pad to be linked * @peer: (transfer full): The peer pad */ static void kms_agnostic_bin2_link_pad (KmsAgnosticBin2 * self, GstPad * pad, GstPad * peer) { GstCaps *caps; GstBin *bin; GST_INFO_OBJECT (self, "Linking: %" GST_PTR_FORMAT, pad); caps = gst_pad_query_caps (peer, NULL); if (caps == NULL) { goto end; } GST_DEBUG ("Query caps are: %" GST_PTR_FORMAT, caps); bin = kms_agnostic_bin2_find_bin_for_caps (self, caps); if (bin == NULL) { bin = kms_agnostic_bin2_create_bin_for_caps (self, caps); GST_DEBUG_OBJECT (self, "Created bin: %" GST_PTR_FORMAT, bin); } if (bin != NULL) { GstElement *tee = kms_tree_bin_get_output_tee (KMS_TREE_BIN (bin)); kms_utils_drop_until_keyframe (pad, TRUE); kms_agnostic_bin2_link_to_tee (self, pad, tee, caps); } gst_caps_unref (caps); end: g_object_unref (peer); }
static gboolean kms_rtp_pay_tree_bin_configure (KmsRtpPayTreeBin * self, const GstCaps * caps) { KmsTreeBin *tree_bin = KMS_TREE_BIN (self); GstElement *pay, *output_tee; GstPad *pad; pay = create_payloader_for_caps (caps); if (pay == NULL) { GST_WARNING_OBJECT (self, "Cannot find payloader for caps %" GST_PTR_FORMAT, caps); return FALSE; } GST_DEBUG_OBJECT (self, "Payloader found: %" GST_PTR_FORMAT, pay); pad = gst_element_get_static_pad (pay, "sink"); kms_utils_drop_until_keyframe (pad, TRUE); gst_object_unref (pad); gst_bin_add (GST_BIN (self), pay); gst_element_sync_state_with_parent (pay); kms_tree_bin_set_input_element (tree_bin, pay); output_tee = kms_tree_bin_get_output_tee (tree_bin); gst_element_link (pay, output_tee); return TRUE; }
static GstPadProbeReturn tee_src_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) { if (GST_PAD_PROBE_INFO_TYPE (info) & GST_PAD_PROBE_TYPE_EVENT_UPSTREAM) { GstEvent *event = gst_pad_probe_info_get_event (info); if (GST_EVENT_TYPE (event) == GST_EVENT_RECONFIGURE) { // Request key frame to upstream elements kms_utils_drop_until_keyframe (pad, TRUE); return GST_PAD_PROBE_DROP; } } return GST_PAD_PROBE_OK; }
static GstPadProbeReturn discont_detection_probe (GstPad * pad, GstPadProbeInfo * info, gpointer data) { GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER (info); if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) { if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT)) { GST_WARNING_OBJECT (pad, "Discont detected"); kms_utils_drop_until_keyframe (pad, FALSE); return GST_PAD_PROBE_DROP; } } return GST_PAD_PROBE_OK; }
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; }