コード例 #1
0
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;
}
コード例 #2
0
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;
}
コード例 #3
0
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;
}
コード例 #4
0
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;
}
コード例 #5
0
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;
}
コード例 #6
0
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;
}
コード例 #7
0
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;
}