static GstBin * kms_agnostic_bin2_create_bin_for_caps (KmsAgnosticBin2 * self, GstCaps * caps) { GstBin *dec_bin; KmsEncTreeBin *enc_bin; GstElement *input_element, *output_tee; dec_bin = kms_agnostic_bin2_get_or_create_dec_bin (self, caps); if (dec_bin == NULL) { return NULL; } if (is_raw_caps (caps)) { return dec_bin; } enc_bin = kms_enc_tree_bin_new (caps, self->priv->default_bitrate); if (enc_bin == NULL) { return NULL; } gst_bin_add (GST_BIN (self), GST_ELEMENT (enc_bin)); gst_element_sync_state_with_parent (GST_ELEMENT (enc_bin)); output_tee = kms_tree_bin_get_output_tee (KMS_TREE_BIN (dec_bin)); input_element = kms_tree_bin_get_input_element (KMS_TREE_BIN (enc_bin)); link_element_to_tee (output_tee, input_element); kms_agnostic_bin2_insert_bin (self, GST_BIN (enc_bin)); return GST_BIN (enc_bin); }
/** * 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 check_bin (KmsTreeBin * tree_bin, const GstCaps * caps) { gboolean ret = FALSE; GstElement *output_tee = kms_tree_bin_get_output_tee (tree_bin); GstPad *tee_sink = gst_element_get_static_pad (output_tee, "sink"); GstCaps *current_caps = kms_tree_bin_get_input_caps (tree_bin); if (current_caps == NULL) { current_caps = gst_pad_get_allowed_caps (tee_sink); GST_TRACE_OBJECT (tree_bin, "Allowed caps are: %" GST_PTR_FORMAT, current_caps); } else { gst_caps_ref (current_caps); GST_TRACE_OBJECT (tree_bin, "Current caps are: %" GST_PTR_FORMAT, current_caps); } if (current_caps != NULL) { if (gst_caps_can_intersect (caps, current_caps)) { ret = TRUE; } gst_caps_unref (current_caps); } g_object_unref (tee_sink); return ret; }
static GstBin * kms_agnostic_bin2_create_dec_bin (KmsAgnosticBin2 * self, const GstCaps * raw_caps) { KmsDecTreeBin *dec_bin; GstElement *output_tee, *input_element; GstCaps *caps = self->priv->input_bin_src_caps; if (caps == NULL || raw_caps == NULL) { return NULL; } dec_bin = kms_dec_tree_bin_new (caps, raw_caps); if (dec_bin == NULL) { return NULL; } gst_bin_add (GST_BIN (self), GST_ELEMENT (dec_bin)); gst_element_sync_state_with_parent (GST_ELEMENT (dec_bin)); output_tee = kms_tree_bin_get_output_tee (KMS_TREE_BIN (self->priv->input_bin)); input_element = kms_tree_bin_get_input_element (KMS_TREE_BIN (dec_bin)); link_element_to_tee (output_tee, input_element); return GST_BIN (dec_bin); }
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 GstBin * kms_agnostic_bin2_create_rtp_pay_bin (KmsAgnosticBin2 * self, GstCaps * caps) { KmsRtpPayTreeBin *bin; GstBin *enc_bin; GstElement *output_tee, *input_element; GstCaps *input_caps; GstPad *sink; bin = kms_rtp_pay_tree_bin_new (caps); if (bin == NULL) { return NULL; } gst_bin_add (GST_BIN (self), GST_ELEMENT (bin)); gst_element_sync_state_with_parent (GST_ELEMENT (bin)); input_element = kms_tree_bin_get_input_element (KMS_TREE_BIN (bin)); sink = gst_element_get_static_pad (input_element, "sink"); input_caps = gst_pad_query_caps (sink, NULL); g_object_unref (sink); enc_bin = kms_agnostic_bin2_find_or_create_bin_for_caps (self, input_caps); kms_agnostic_bin2_insert_bin (self, GST_BIN (bin)); gst_caps_unref (input_caps); output_tee = kms_tree_bin_get_output_tee (KMS_TREE_BIN (enc_bin)); gst_element_link (output_tee, input_element); return GST_BIN (bin); }
static gboolean check_bin (KmsTreeBin * tree_bin, const GstCaps * caps) { gboolean ret = FALSE; GstElement *output_tee = kms_tree_bin_get_output_tee (tree_bin); GstPad *tee_sink = gst_element_get_static_pad (output_tee, "sink"); GstCaps *current_caps = kms_tree_bin_get_input_caps (tree_bin); if (current_caps == NULL) { current_caps = gst_pad_get_allowed_caps (tee_sink); GST_TRACE_OBJECT (tree_bin, "Allowed caps are: %" GST_PTR_FORMAT, current_caps); } else { GST_TRACE_OBJECT (tree_bin, "Current caps are: %" GST_PTR_FORMAT, current_caps); } if (current_caps != NULL) { //TODO: Remove this when problem in negotiation with features will be //resolved GstCaps *caps_without_features = gst_caps_make_writable (current_caps); gst_caps_set_features (caps_without_features, 0, gst_caps_features_new_empty ()); if (gst_caps_can_intersect (caps, caps_without_features)) { ret = TRUE; } gst_caps_unref (caps_without_features); } g_object_unref (tee_sink); return ret; }
static void kms_parse_tree_bin_configure (KmsParseTreeBin * self, const GstCaps * caps) { KmsTreeBin *tree_bin = KMS_TREE_BIN (self); GstElement *output_tee; self->priv->parser = create_parser_for_caps (caps); gst_bin_add (GST_BIN (self), self->priv->parser); gst_element_sync_state_with_parent (self->priv->parser); kms_tree_bin_set_input_element (tree_bin, self->priv->parser); output_tee = kms_tree_bin_get_output_tee (tree_bin); gst_element_link_many (self->priv->parser, output_tee, NULL); }
static GstBin * kms_agnostic_bin2_create_bin_for_caps (KmsAgnosticBin2 * self, GstCaps * caps) { GstBin *dec_bin; KmsEncTreeBin *enc_bin; GstElement *input_element, *output_tee; if (kms_utils_caps_are_rtp (caps)) { return kms_agnostic_bin2_create_rtp_pay_bin (self, caps); } dec_bin = kms_agnostic_bin2_get_or_create_dec_bin (self, caps); if (dec_bin == NULL) { return NULL; } if (kms_utils_caps_are_raw (caps)) { return dec_bin; } enc_bin = kms_enc_tree_bin_new (caps, TARGET_BITRATE_DEFAULT, self->priv->min_bitrate, self->priv->max_bitrate, self->priv->codec_config); if (enc_bin == NULL) { return NULL; } gst_bin_add (GST_BIN (self), GST_ELEMENT (enc_bin)); gst_element_sync_state_with_parent (GST_ELEMENT (enc_bin)); output_tee = kms_tree_bin_get_output_tee (KMS_TREE_BIN (dec_bin)); input_element = kms_tree_bin_get_input_element (KMS_TREE_BIN (enc_bin)); gst_element_link (output_tee, input_element); kms_agnostic_bin2_insert_bin (self, GST_BIN (enc_bin)); return GST_BIN (enc_bin); }
static GstBin * kms_agnostic_bin2_find_bin_for_caps (KmsAgnosticBin2 * self, GstCaps * caps) { GList *bins, *l; GstBin *bin = NULL; if (gst_caps_is_any (caps)) { return self->priv->input_bin; } bins = g_hash_table_get_values (self->priv->bins); for (l = bins; l != NULL && bin == NULL; l = l->next) { GstElement *output_tee = kms_tree_bin_get_output_tee (KMS_TREE_BIN (l->data)); GstPad *tee_sink = gst_element_get_static_pad (output_tee, "sink"); GstCaps *current_caps = gst_pad_get_current_caps (tee_sink); if (current_caps == NULL) { current_caps = gst_pad_get_allowed_caps (tee_sink); GST_TRACE_OBJECT (l->data, "Allowed caps are: %" GST_PTR_FORMAT, current_caps); } else { GST_TRACE_OBJECT (l->data, "Current caps are: %" GST_PTR_FORMAT, current_caps); } if (current_caps != NULL) { if (gst_caps_can_intersect (caps, current_caps)) bin = l->data; gst_caps_unref (current_caps); } g_object_unref (tee_sink); } g_list_free (bins); return bin; }
static gboolean kms_enc_tree_bin_configure (KmsEncTreeBin * self, const GstCaps * caps, gint target_bitrate) { KmsTreeBin *tree_bin = KMS_TREE_BIN (self); GstElement *rate, *convert, *mediator, *output_tee, *capsfilter = NULL; self->priv->current_bitrate = target_bitrate; kms_enc_tree_bin_create_encoder_for_caps (self, caps, target_bitrate); if (self->priv->enc == NULL) { GST_WARNING_OBJECT (self, "Invalid encoder for caps: %" GST_PTR_FORMAT, caps); return FALSE; } GST_DEBUG_OBJECT (self, "Encoder found: %" GST_PTR_FORMAT, self->priv->enc); self->priv->enc_sink = gst_element_get_static_pad (self->priv->enc, "sink"); self->priv->remb_manager = kms_utils_remb_event_manager_create (self->priv->enc_sink); kms_utils_remb_event_manager_set_callback (self->priv->remb_manager, bitrate_callback, self, NULL); gst_pad_add_probe (self->priv->enc_sink, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, tag_event_probe, self, NULL); rate = kms_utils_create_rate_for_caps (caps); convert = kms_utils_create_convert_for_caps (caps); mediator = kms_utils_create_mediator_element (caps); gst_bin_add_many (GST_BIN (self), rate, convert, mediator, self->priv->enc, NULL); gst_element_sync_state_with_parent (self->priv->enc); gst_element_sync_state_with_parent (mediator); gst_element_sync_state_with_parent (convert); gst_element_sync_state_with_parent (rate); // FIXME: This is a hack to avoid an error on x264enc that does not work // properly with some raw formats, this should be fixed in gstreamer // but until this is done this hack makes it work if (self->priv->enc_type == X264) { GstCaps *filter_caps = gst_caps_from_string ("video/x-raw,format=I420"); GstPad *sink; capsfilter = gst_element_factory_make ("capsfilter", NULL); sink = gst_element_get_static_pad (capsfilter, "sink"); gst_pad_add_probe (sink, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, check_caps_probe, NULL, NULL); g_object_unref (sink); g_object_set (capsfilter, "caps", filter_caps, NULL); gst_caps_unref (filter_caps); gst_bin_add (GST_BIN (self), capsfilter); gst_element_sync_state_with_parent (capsfilter); } kms_tree_bin_set_input_element (tree_bin, rate); output_tee = kms_tree_bin_get_output_tee (tree_bin); if (self->priv->enc_type == X264) { gst_element_link_many (rate, convert, mediator, capsfilter, self->priv->enc, output_tee, NULL); } else { gst_element_link_many (rate, convert, mediator, self->priv->enc, output_tee, NULL); } return TRUE; }