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;
}
gboolean
fs_rtp_sub_stream_add_output_ghostpad_unlock (FsRtpSubStream *substream,
    GError **error)
{
  GstPad *valve_srcpad;
  gchar *padname = NULL;
  GstPad *ghostpad = NULL;
  FsCodec *codec = NULL;

  if (fs_rtp_sub_stream_has_stopped_enter (substream))
  {
    FS_RTP_SESSION_UNLOCK (substream->priv->session);
    return TRUE;
  }

  if (substream->priv->adding_output_ghostpad)
  {
    FS_RTP_SESSION_UNLOCK (substream->priv->session);
    goto out;
  }

  g_assert (substream->priv->output_ghostpad == NULL);

  substream->priv->adding_output_ghostpad = TRUE;

  padname = g_strdup_printf ("src_%u_%u_%d", substream->priv->session->id,
      substream->ssrc,
      substream->pt);

  FS_RTP_SESSION_UNLOCK (substream->priv->session);

  valve_srcpad = gst_element_get_static_pad (substream->priv->output_valve,
      "src");
  g_assert (valve_srcpad);

  ghostpad = gst_ghost_pad_new_from_template (padname, valve_srcpad,
      gst_element_class_get_pad_template (
          GST_ELEMENT_GET_CLASS (substream->priv->conference),
          "src_%d_%d_%d"));

  gst_object_unref (valve_srcpad);
  g_free (padname);

  if (!ghostpad)
  {
    g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
        "Could not build ghostpad src_%u_%u_%d", substream->priv->session->id,
        substream->ssrc, substream->pt);
    goto error;
  }

  if (!gst_pad_set_active (ghostpad, TRUE))
  {
    g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
        "Could not activate the src_%u_%u_%d", substream->priv->session->id,
        substream->ssrc, substream->pt);
    gst_object_unref (ghostpad);
    goto error;
  }

  if (!gst_element_add_pad (GST_ELEMENT (substream->priv->conference),
          ghostpad))
  {
    g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
        "Could add build ghostpad src_%u_%u_%d to the conference",
        substream->priv->session->id, substream->ssrc, substream->pt);
    gst_object_unref (ghostpad);
    goto error;
  }

  FS_RTP_SESSION_LOCK (substream->priv->session);
  substream->priv->output_ghostpad = ghostpad;

  GST_DEBUG ("Src pad added on substream for ssrc:%X pt:%u " FS_CODEC_FORMAT,
      substream->ssrc, substream->pt,
      FS_CODEC_ARGS (substream->codec));

  codec = fs_codec_copy (substream->codec);

  FS_RTP_SESSION_UNLOCK (substream->priv->session);

  g_signal_emit (substream, signals[SRC_PAD_ADDED], 0,
                 ghostpad, codec);
  g_signal_emit (substream, signals[CODEC_CHANGED], 0);

  fs_codec_destroy (codec);

  g_object_set (substream->priv->output_valve, "drop", FALSE, NULL);

 out:

  fs_rtp_sub_stream_has_stopped_exit (substream);
  return TRUE;

 error:

  substream->priv->adding_output_ghostpad = FALSE;
  fs_rtp_sub_stream_has_stopped_exit (substream);
  return FALSE;
}
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;
}