static CodecBlueprint * _find_matching_blueprint (FsCodec *codec, GList *blueprints) { GList *item = NULL; GstCaps *caps = NULL; caps = fs_codec_to_gst_caps (codec); if (!caps) { gchar *tmp = fs_codec_to_string (codec); GST_WARNING ("Could not transform codec into caps: %s", tmp); g_free (tmp); return NULL; } for (item = g_list_first (blueprints); item; item = g_list_next (item)) { CodecBlueprint *bp = item->data; if (gst_caps_can_intersect (caps, bp->rtp_caps)) break; } gst_caps_unref (caps); if (item) return item->data; else return NULL; }
static gboolean _is_disabled (GList *codec_prefs, CodecBlueprint *bp) { GList *item = NULL; for (item = g_list_first (codec_prefs); item; item = g_list_next (item)) { FsCodec *codec = item->data; GstCaps *caps = NULL; gboolean ok = FALSE; /* Only check for DISABLE entries */ if (codec->id != FS_CODEC_ID_DISABLE) continue; caps = fs_codec_to_gst_caps (codec); if (!caps) continue; if (gst_caps_can_intersect (caps, bp->rtp_caps)) ok = TRUE; gst_caps_unref (caps); if (ok) return TRUE; } return FALSE; }
static gboolean validate_codec_profile (FsCodec *codec,const gchar *bin_description, gboolean is_send) { GError *error = NULL; GstElement *bin = NULL; guint src_pad_count = 0, sink_pad_count = 0; GstCaps *caps; gpointer matching_pad = NULL; GstIterator *iter; bin = parse_bin_from_description_all_linked (bin_description, &src_pad_count, &sink_pad_count, &error); /* if could not build bin, fail */ if (!bin) { GST_WARNING ("Could not build profile (%s): %s", bin_description, error->message); g_clear_error (&error); return FALSE; } g_clear_error (&error); caps = fs_codec_to_gst_caps (codec); if (is_send) iter = gst_element_iterate_src_pads (bin); else iter = gst_element_iterate_sink_pads (bin); matching_pad = gst_iterator_find_custom (iter, find_matching_pad, caps); gst_iterator_free (iter); if (!matching_pad) { GST_WARNING ("Invalid profile (%s), has no %s pad that matches the codec" " details", is_send ? "src" : "sink", bin_description); gst_caps_unref (caps); gst_object_unref (bin); return FALSE; } gst_caps_unref (caps); gst_object_unref (bin); if (is_send) { if (src_pad_count == 0) { GST_WARNING ("Invalid profile (%s), has 0 src pad", bin_description); return FALSE; } } else { if (src_pad_count != 1) { GST_WARNING ("Invalid profile (%s), has %u src pads, should have one", bin_description, src_pad_count); return FALSE; } } if (sink_pad_count != 1) { GST_WARNING ("Invalid profile (%s), has %u sink pads, should have one", bin_description, sink_pad_count); return FALSE; } return TRUE; }
static gboolean fs_rtp_sub_stream_set_codecbin (FsRtpSubStream *substream, FsCodec *codec, GstElement *codecbin, GError **error) { GstCaps *caps = NULL; gchar *tmp; gboolean ret = FALSE; GstPad *pad; if (substream->priv->codecbin) { gst_element_set_locked_state (substream->priv->codecbin, TRUE); if (gst_element_set_state (substream->priv->codecbin, GST_STATE_NULL) != GST_STATE_CHANGE_SUCCESS) { gst_element_set_locked_state (substream->priv->codecbin, FALSE); g_set_error (error, FS_ERROR, FS_ERROR_INTERNAL, "Could not set the codec bin for ssrc %u" " and payload type %d to the state NULL", substream->ssrc, substream->pt); gst_object_unref (codecbin); fs_codec_destroy (codec); return FALSE; } gst_bin_remove (GST_BIN (substream->priv->conference), substream->priv->codecbin); FS_RTP_SESSION_LOCK (substream->priv->session); substream->priv->codecbin = NULL; if (substream->codec) { fs_codec_destroy (substream->codec); substream->codec = NULL; } if (substream->priv->caps) gst_caps_unref (substream->priv->caps); substream->priv->caps = NULL; FS_RTP_SESSION_UNLOCK (substream->priv->session); } if (!gst_bin_add (GST_BIN (substream->priv->conference), codecbin)) { gst_object_unref (codecbin); fs_codec_destroy (codec); g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION, "Could not add the codec bin to the conference"); return FALSE; } if (gst_element_set_state (codecbin, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION, "Could not set the codec bin to the playing state"); goto error; } if (!gst_element_link_pads (codecbin, "src", substream->priv->output_valve, "sink")) { g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION, "Could not link the codec bin to the output_valve"); goto error; } if (!gst_element_link_pads (substream->priv->capsfilter, "src", codecbin, "sink")) { g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION, "Could not link the receive capsfilter and the codecbin for pt %d", substream->pt); goto error; } caps = fs_codec_to_gst_caps (codec); tmp = gst_caps_to_string (caps); GST_DEBUG ("Setting caps %s on recv substream", tmp); g_free (tmp); g_object_set (substream->priv->capsfilter, "caps", caps, NULL); pad = gst_element_get_static_pad (codecbin, "sink"); if (!pad) { g_set_error (error, FS_ERROR, FS_ERROR_INTERNAL, "Could not get sink pad" " from codecbin"); goto error; } /* This is a non-error error * Some codecs require config data to start.. so we should just ignore them */ if (!gst_pad_set_caps (pad, caps)) { ret = TRUE; gst_object_unref (pad); gst_caps_unref (caps); GST_DEBUG ("Could not set the caps on the codecbin, waiting on config-data" " for SSRC:%x pt:%d", substream->ssrc, substream->pt); /* We call this to drop all buffers until something comes up */ fs_rtp_sub_stream_add_probe_locked (substream); goto error; } GST_DEBUG ("New recv codec accepted"); gst_object_unref (pad); FS_RTP_SESSION_LOCK (substream->priv->session); substream->priv->caps = caps; substream->priv->codecbin = codecbin; substream->codec = codec; codec = NULL; if (substream->priv->stream && !substream->priv->output_ghostpad) { if (!fs_rtp_sub_stream_add_output_ghostpad_unlock (substream, error)) goto error; } else { FS_RTP_SESSION_UNLOCK (substream->priv->session); g_signal_emit (substream, signals[CODEC_CHANGED], 0); } return TRUE; error: gst_element_set_locked_state (codecbin, TRUE); gst_element_set_state (codecbin, GST_STATE_NULL); gst_bin_remove (GST_BIN (substream->priv->conference), codecbin); fs_codec_destroy (codec); return ret; }
static GstElement * fs_rtp_dtmf_sound_source_build (FsRtpSpecialSource *source, GList *negotiated_codecs, FsCodec *selected_codec) { FsCodec *telephony_codec = NULL; GstCaps *caps = NULL; GstPad *pad = NULL; GstElement *dtmfsrc = NULL; GstElement *capsfilter = NULL; GstPad *ghostpad = NULL; GstElement *bin = NULL; GstElement *encoder = NULL; GstElement *payloader = NULL; gchar *encoder_name = NULL; gchar *payloader_name = NULL; telephony_codec = get_pcm_law_sound_codec (negotiated_codecs, &encoder_name, &payloader_name); g_return_val_if_fail (telephony_codec, NULL); source->codec = fs_codec_copy (telephony_codec); GST_DEBUG ("Creating dtmf sound source for " FS_CODEC_FORMAT, FS_CODEC_ARGS (telephony_codec)); bin = gst_bin_new (NULL); dtmfsrc = gst_element_factory_make ("dtmfsrc", NULL); if (!dtmfsrc) { GST_ERROR ("Could not make rtpdtmfsrc"); goto error; } if (!gst_bin_add (GST_BIN (bin), dtmfsrc)) { GST_ERROR ("Could not add rtpdtmfsrc to bin"); gst_object_unref (dtmfsrc); goto error; } encoder = gst_element_factory_make (encoder_name, NULL); if (!encoder) { GST_ERROR ("Could not make %s", encoder_name); goto error; } if (!gst_bin_add (GST_BIN (bin), encoder)) { GST_ERROR ("Could not add %s to bin", encoder_name); gst_object_unref (dtmfsrc); goto error; } if (!gst_element_link_pads (dtmfsrc, "src", encoder, "sink")) { GST_ERROR ("Could not link the rtpdtmfsrc and %s", encoder_name); goto error; } payloader = gst_element_factory_make (payloader_name, NULL); if (!payloader) { GST_ERROR ("Could not make %s", payloader_name); goto error; } if (!gst_bin_add (GST_BIN (bin), payloader)) { GST_ERROR ("Could not add %s to bin", payloader_name); gst_object_unref (dtmfsrc); goto error; } if (!gst_element_link_pads (encoder, "src", payloader, "sink")) { GST_ERROR ("Could not link the %s and %s", encoder_name, payloader_name); goto error; } capsfilter = gst_element_factory_make ("capsfilter", NULL); if (!capsfilter) { GST_ERROR ("Could not make capsfilter"); goto error; } if (!gst_bin_add (GST_BIN (bin), capsfilter)) { GST_ERROR ("Could not add capsfilter to bin"); gst_object_unref (capsfilter); goto error; } caps = fs_codec_to_gst_caps (telephony_codec); g_object_set (capsfilter, "caps", caps, NULL); { gchar *str = gst_caps_to_string (caps); GST_DEBUG ("Using caps %s for dtmf", str); g_free (str); } gst_caps_unref (caps); if (!gst_element_link_pads (payloader, "src", capsfilter, "sink")) { GST_ERROR ("Could not link the %s and its capsfilter", payloader_name); goto error; } pad = gst_element_get_static_pad (capsfilter, "src"); if (!pad) { GST_ERROR ("Could not get \"src\" pad from capsfilter"); goto error; } ghostpad = gst_ghost_pad_new ("src", pad); if (!ghostpad) { GST_ERROR ("Could not create a ghostpad for capsfilter src pad" " for dtmfsrc"); goto error; } if (!gst_element_add_pad (bin, ghostpad)) { GST_ERROR ("Could not get \"src\" ghostpad to dtmf sound source bin"); gst_object_unref (pad); goto error; } gst_object_unref (pad); return bin; error: gst_object_unref (bin); return NULL; }
static GstElement * fs_rtp_dtmf_event_source_build (FsRtpSpecialSource *source, GList *negotiated_codec_associations, FsCodec *selected_codec) { FsCodec *telephony_codec = NULL; GstCaps *caps = NULL; GstPad *pad = NULL; GstElement *dtmfsrc = NULL; GstElement *capsfilter = NULL; GstPad *ghostpad = NULL; GstElement *bin = NULL; telephony_codec = fs_rtp_dtmf_event_source_get_codec ( FS_RTP_SPECIAL_SOURCE_GET_CLASS(source), negotiated_codec_associations, selected_codec); g_return_val_if_fail (telephony_codec, NULL); source->codec = fs_codec_copy (telephony_codec); bin = gst_bin_new (NULL); GST_DEBUG ("Creating telephone-event source for " FS_CODEC_FORMAT, FS_CODEC_ARGS (telephony_codec)); dtmfsrc = gst_element_factory_make ("rtpdtmfsrc", NULL); if (!dtmfsrc) { GST_ERROR ("Could not make rtpdtmfsrc"); goto error; } if (!gst_bin_add (GST_BIN (bin), dtmfsrc)) { GST_ERROR ("Could not add rtpdtmfsrc to bin"); gst_object_unref (dtmfsrc); goto error; } capsfilter = gst_element_factory_make ("capsfilter", NULL); if (!capsfilter) { GST_ERROR ("Could not make capsfilter"); goto error; } if (!gst_bin_add (GST_BIN (bin), capsfilter)) { GST_ERROR ("Could not add capsfilter to bin"); gst_object_unref (capsfilter); goto error; } caps = fs_codec_to_gst_caps (telephony_codec); g_object_set (capsfilter, "caps", caps, NULL); { gchar *str = gst_caps_to_string (caps); GST_DEBUG ("Using caps %s for dtmf", str); g_free (str); } gst_caps_unref (caps); if (!gst_element_link_pads (dtmfsrc, "src", capsfilter, "sink")) { GST_ERROR ("Could not link the rtpdtmfsrc and its capsfilter"); goto error; } pad = gst_element_get_static_pad (capsfilter, "src"); if (!pad) { GST_ERROR ("Could not get \"src\" pad from capsfilter"); goto error; } ghostpad = gst_ghost_pad_new ("src", pad); if (!ghostpad) { GST_ERROR ("Could not create a ghostpad for capsfilter src pad for" " rtpdtmfsrc"); goto error; } if (!gst_element_add_pad (bin, ghostpad)) { GST_ERROR ("Could not get \"src\" ghostpad to dtmf source bin"); gst_object_unref (pad); goto error; } gst_object_unref (pad); return bin; error: gst_object_unref (bin); return NULL; }
static GList* fs_rtp_dtmf_event_source_class_add_blueprint (FsRtpSpecialSourceClass *klass, GList *blueprints) { GList *item; GList *already_done = NULL; GstElementFactory *fact = NULL; GList *new_blueprints = NULL; fact = gst_element_factory_find ("rtpdtmfsrc"); if (fact) { gst_object_unref (fact); } else { GST_CAT_WARNING (fsrtpconference_disco, "Could not find rtpdtmfsrc, will not offer DTMF events"); return blueprints; } fact = gst_element_factory_find ("rtpdtmfdepay"); if (!fact) GST_CAT_WARNING (fsrtpconference_disco, "Could not find rtpdtmfdepay, will not be able to receive DTMF events"); for (item = g_list_first (blueprints); item; item = g_list_next (item)) { CodecBlueprint *bp = item->data; GList *done_item = NULL; gboolean skip = FALSE; CodecBlueprint *new_bp = NULL; if (bp->codec->media_type != FS_MEDIA_TYPE_AUDIO) continue; if (!g_ascii_strcasecmp (bp->codec->encoding_name, "telephone-event")) continue; if (bp->codec->clock_rate == 0) continue; for (done_item = g_list_first (already_done); done_item; done_item = g_list_next (done_item)) { if (GPOINTER_TO_UINT (done_item->data) == bp->codec->clock_rate) { skip = TRUE; break; } } if (skip) continue; new_bp = g_slice_new0 (CodecBlueprint); new_bp->codec = fs_codec_new (FS_CODEC_ID_ANY, "telephone-event", FS_MEDIA_TYPE_AUDIO, bp->codec->clock_rate); fs_codec_add_optional_parameter (new_bp->codec, "events", "0-15"); new_bp->rtp_caps = fs_codec_to_gst_caps (new_bp->codec); new_bp->media_caps = gst_caps_new_any (); if (fact) new_bp->receive_pipeline_factory = g_list_prepend (NULL, g_list_prepend (NULL, gst_object_ref (fact))); new_blueprints = g_list_append (new_blueprints, new_bp); already_done = g_list_prepend (already_done, GUINT_TO_POINTER (bp->codec->clock_rate)); } if (fact) gst_object_unref (fact); g_list_free (already_done); blueprints = g_list_concat (blueprints, new_blueprints); return blueprints; }