Ejemplo n.º 1
0
static void
skype_audio_stream_update_codecs (SkypeBaseStream *stream,
    GList **codecs)
{
  SkypeAudioStreamPrivate *priv = SKYPE_AUDIO_STREAM (stream)->priv;
  FsCodec *codec;
  gchar *value;
  guint telephony_pt = priv->last_telephony_pt;

  if (codecs == NULL || *codecs == NULL || (*codecs)->data == NULL)
    {
      g_warning ("update_codecs should not be passed an empty codec list");
      return;
    }

  codec = (FsCodec *)((*codecs)->data);

  /* Add ptime value */
  value = g_strdup_printf ("%d", priv->ptime);
  fs_codec_add_optional_parameter (codec, "ptime", value);
  g_free (value);

  /* Add telephony codec if needed */
  if (priv->pending_telephony_pt != FS_CODEC_ID_DISABLE)
    telephony_pt = priv->pending_telephony_pt;

  if (telephony_pt != FS_CODEC_ID_DISABLE)
    {
      codec = fs_codec_new (telephony_pt, "telephone-event",
          FS_MEDIA_TYPE_AUDIO, 8000);
      fs_codec_add_optional_parameter (codec, "events", "0-11");
      *codecs = g_list_append (*codecs, codec);
    }
}
Ejemplo n.º 2
0
static FsCodec *
init_codec_with_three_params (void)
{
  FsCodec *codec = fs_codec_new (1, "aa", FS_MEDIA_TYPE_VIDEO, 650);

  fs_codec_add_optional_parameter (codec, "aa1", "bb1");
  fs_codec_add_optional_parameter (codec, "aa2", "bb2");
  fs_codec_add_optional_parameter (codec, "aa3", "bb3");

  fs_codec_add_feedback_parameter (codec, "aa1", "bb1", "cc1");
  fs_codec_add_feedback_parameter (codec, "aa2", "bb2", "cc2");
  fs_codec_add_feedback_parameter (codec, "aa3", "bb3", "cc3");

  return codec;
}
Ejemplo n.º 3
0
static void
caps_changed (GstPad *pad, GParamSpec *spec, FsStream *stream)
{
  GstCaps *caps;
  GstStructure *s;
  FsCodec *codec;
  GList *codecs;
  const gchar *config;
  GError *error = NULL;

  g_object_get (pad, "caps", &caps, NULL);

  if (!caps)
    return;

  s = gst_caps_get_structure (caps, 0);

  codec = fs_codec_new (96, "THEORA", FS_MEDIA_TYPE_VIDEO, 90000);

  config = gst_structure_get_string (s, "configuration");
  if (config)
    fs_codec_add_optional_parameter (codec, "configuration", config);

  codecs = g_list_prepend (NULL, codec);
  fail_unless (fs_stream_set_remote_codecs (stream, codecs, &error),
      "Unable to set remote codec: %s",
      error ? error->message : "UNKNOWN");
  fs_codec_list_destroy (codecs);
}
static void
keep_config_from_old_codec (FsCodec *new_codec, FsCodec *old_codec)
{
  GList *item;

  for (item = old_codec->optional_params; item; item = item->next)
  {
    FsCodecParameter *oldparam = item->data;
    if (!fs_codec_get_optional_parameter (new_codec, oldparam->name, NULL)
        && codec_has_config_data_named (new_codec, oldparam->name))
      fs_codec_add_optional_parameter (new_codec, oldparam->name,
          oldparam->value);
  }
}
Ejemplo n.º 5
0
static void
_simple_profile_init (struct SimpleTestStream *st, guint confid, guint streamid)
{
  GList *prefs = NULL;
  FsCodec *codec = NULL;
  gboolean ret;

  codec = fs_codec_new (0, "PCMU", FS_MEDIA_TYPE_AUDIO, 8000);
  fs_codec_add_optional_parameter (codec, "farstream-send-profile",
      "audioconvert ! audioresample ! audioconvert ! mulawenc ! rtppcmupay");
  prefs = g_list_append (NULL, codec);

  ret = fs_session_set_codec_preferences (st->dat->session, prefs,
      NULL);
  ts_fail_unless (ret, "set codec prefs");

  fs_codec_list_destroy (prefs);

}
Ejemplo n.º 6
0
static CodecBlueprint *
load_codec_blueprint (FsMediaType media_type, gchar **in, gsize *size) {
  CodecBlueprint *codec_blueprint = g_slice_new0 (CodecBlueprint);
  gchar *tmp;
  gint tmp_size;
  int i;
  gint id;
  gchar *encoding_name = NULL;
  guint clock_rate;

  READ_CHECK (read_codec_blueprint_int
      (in, size, &(id)));
  READ_CHECK (read_codec_blueprint_string
      (in, size, &(encoding_name)));
  READ_CHECK (read_codec_blueprint_uint
      (in, size, &(clock_rate)));
  codec_blueprint->codec = fs_codec_new (id, encoding_name, media_type,
      clock_rate);
  g_free (encoding_name);
  READ_CHECK (read_codec_blueprint_uint
      (in, size, &(codec_blueprint->codec->channels)));

  READ_CHECK (read_codec_blueprint_int (in, size, &tmp_size));
  for (i = 0; i < tmp_size; i++) {
    gchar *name, *value;
    READ_CHECK (read_codec_blueprint_string (in, size, &(name)));
    READ_CHECK (read_codec_blueprint_string (in, size, &(value)));
    fs_codec_add_optional_parameter (codec_blueprint->codec, name, value);
    g_free (name);
    g_free (value);
  }

  READ_CHECK (read_codec_blueprint_string (in, size, &tmp));
  codec_blueprint->media_caps = gst_caps_from_string (tmp);
  g_free (tmp);

  READ_CHECK (read_codec_blueprint_string (in, size, &tmp));
  codec_blueprint->rtp_caps = gst_caps_from_string (tmp);
  g_free (tmp);

  READ_CHECK (read_codec_blueprint_int (in, size, &tmp_size));
  for (i = 0; i < tmp_size; i++) {
    int j, tmp_size2;
    GList *tmplist = NULL;

    READ_CHECK (read_codec_blueprint_int (in, size, &tmp_size2));
    for (j = 0; j < tmp_size2; j++) {
      GstElementFactory *fact = NULL;
      READ_CHECK (read_codec_blueprint_string (in, size, &(tmp)));
      fact = gst_element_factory_find (tmp);
      g_free (tmp);
      if (!fact)
        goto error;
      tmplist = g_list_append (tmplist, fact);
    }
    codec_blueprint->send_pipeline_factory =
      g_list_append (codec_blueprint->send_pipeline_factory, tmplist);
  }

  READ_CHECK (read_codec_blueprint_int (in, size, &tmp_size));
  for (i = 0; i < tmp_size; i++) {
    int j, tmp_size2;
    GList *tmplist = NULL;

    READ_CHECK (read_codec_blueprint_int (in, size, &tmp_size2));
    for (j = 0; j < tmp_size2; j++) {
      GstElementFactory *fact = NULL;
      READ_CHECK (read_codec_blueprint_string (in, size, &(tmp)));
      fact = gst_element_factory_find (tmp);
      g_free (tmp);
      if (!fact)
        goto error;
      tmplist = g_list_append (tmplist, fact);
    }
    codec_blueprint->receive_pipeline_factory =
      g_list_append (codec_blueprint->receive_pipeline_factory, tmplist);
  }

  GST_DEBUG ("adding codec %s with pt %d, send_pipeline %p, receive_pipeline %p",
      codec_blueprint->codec->encoding_name, codec_blueprint->codec->id,
      codec_blueprint->send_pipeline_factory,
      codec_blueprint->receive_pipeline_factory);

  return codec_blueprint;

 error:
  codec_blueprint_destroy (codec_blueprint);

  return NULL;
}
GList *
create_local_codec_associations (
    GList *blueprints,
    GList *codec_prefs,
    GList *current_codec_associations)
{
  GList *codec_associations = NULL;
  GList *bp_e = NULL;
  GList *codec_pref_e = NULL;
  GList *lca_e = NULL;
  gboolean has_valid_codec = FALSE;
  CodecAssociation *oldca = NULL;

  if (blueprints == NULL)
    return NULL;

  GST_DEBUG ("Creating local codec associations");

  /* First, lets create the original table by looking at our preferred codecs */
  for (codec_pref_e = codec_prefs;
       codec_pref_e;
       codec_pref_e = g_list_next (codec_pref_e))
  {
    FsCodec *codec_pref = codec_pref_e->data;
    CodecBlueprint *bp = _find_matching_blueprint (codec_pref, blueprints);
    CodecAssociation *ca = NULL;
    GList *bp_param_e = NULL;

    /* If its a negative pref, ignore it in this stage */
    if (codec_pref->id == FS_CODEC_ID_DISABLE)
      continue;

    /* If we want to disable a codec ID, we just insert a reserved codec assoc
     * in the list
     */
    if (codec_pref->id >= 0 && codec_pref->id < 128 &&
        codec_pref->encoding_name &&
        !g_ascii_strcasecmp (codec_pref->encoding_name, "reserve-pt"))
    {
      CodecAssociation *ca = g_slice_new0 (CodecAssociation);
      ca->codec = fs_codec_copy (codec_pref);
      ca->reserved = TRUE;
      codec_associations = g_list_append (codec_associations, ca);
      continue;
    }

    /* No matching blueprint, can't use this codec */
    if (!bp &&
        !fs_codec_get_optional_parameter (codec_pref, RECV_PROFILE_ARG,
                NULL))
    {
      GST_LOG ("Could not find matching blueprint for preferred codec %s/%s",
          fs_media_type_to_string (codec_pref->media_type),
          codec_pref->encoding_name);
      continue;
    }

    /* Now lets see if there is an existing codec that matches this preference
     */

    if (codec_pref->id == FS_CODEC_ID_ANY)
    {
      oldca = lookup_codec_association_custom_internal (
          current_codec_associations, TRUE,
          match_original_codec_and_codec_pref, codec_pref);
    }
    else
    {
      oldca = lookup_codec_association_by_pt_list (current_codec_associations,
          codec_pref->id, FALSE);
      if (oldca && oldca->reserved)
        oldca = NULL;
    }

    /* In this case, we have a matching codec association, lets keep the
     * payload type from it
     */
    if (oldca)
    {
      FsCodec *codec = sdp_negotiate_codec (
          oldca->codec, FS_PARAM_TYPE_BOTH | FS_PARAM_TYPE_CONFIG,
          codec_pref, FS_PARAM_TYPE_ALL);
      FsCodec *send_codec;

      if (codec)
      {
        fs_codec_destroy (codec);

        send_codec = sdp_negotiate_codec (
            oldca->send_codec, FS_PARAM_TYPE_SEND,
            codec_pref, FS_PARAM_TYPE_SEND | FS_PARAM_TYPE_SEND_AVOID_NEGO);
        if (send_codec)
          fs_codec_destroy (send_codec);
        else
          oldca = NULL;
      }
      else
      {
        oldca = NULL;
      }
    }

    ca = g_slice_new0 (CodecAssociation);
    ca->blueprint = bp;
    ca->codec = fs_codec_copy (codec_pref);
    codec_remove_parameter (ca->codec, SEND_PROFILE_ARG);
    codec_remove_parameter (ca->codec, RECV_PROFILE_ARG);
    ca->send_codec = codec_copy_filtered (codec_pref, FS_PARAM_TYPE_CONFIG);
    codec_remove_parameter (ca->send_codec, SEND_PROFILE_ARG);
    codec_remove_parameter (ca->send_codec, RECV_PROFILE_ARG);
    if (oldca)
      ca->send_codec->id = ca->codec->id = oldca->codec->id;
    ca->send_profile = dup_param_value (codec_pref, SEND_PROFILE_ARG);
    ca->recv_profile = dup_param_value (codec_pref, RECV_PROFILE_ARG);

    if (bp)
    {
      /* Codec pref does not come with a number, but
       * The blueprint has its own id, lets use it */
      if (ca->codec->id == FS_CODEC_ID_ANY &&
          (bp->codec->id >= 0 || bp->codec->id < 128))
      {
        ca->send_codec->id = ca->codec->id = bp->codec->id;
      }

      if (ca->codec->clock_rate == 0)
        ca->codec->clock_rate = bp->codec->clock_rate;

      if (ca->codec->channels == 0)
        ca->codec->channels = bp->codec->channels;

      for (bp_param_e = bp->codec->optional_params;
           bp_param_e;
           bp_param_e = g_list_next (bp_param_e))
      {
        FsCodecParameter *bp_param = bp_param_e->data;

        if (fs_codec_get_optional_parameter (ca->codec, bp_param->name, NULL))
          fs_codec_add_optional_parameter (ca->codec, bp_param->name,
              bp_param->value);
      }
    }

    {
      gchar *tmp = fs_codec_to_string (ca->codec);
      GST_LOG ("Added preferred codec %s", tmp);
      g_free (tmp);
    }

    codec_associations = list_insert_local_ca (codec_associations, ca);
  }

  /* Now, only codecs with specified ids are here,
   * the rest are dynamic
   * Lets attribute them here */
  for (lca_e = codec_associations;
       lca_e;
       lca_e = g_list_next (lca_e))
  {
    CodecAssociation *lca = lca_e->data;

    if (lca->reserved)
      continue;

    if (lca->codec->id < 0)
    {
      lca->send_codec->id = lca->codec->id = _find_first_empty_dynamic_entry (
          current_codec_associations, codec_associations);
      if (lca->codec->id < 0)
      {
        GST_ERROR ("We've run out of dynamic payload types");
        goto error;
      }
    }
  }

  /* Now, lets add all other codecs from the blueprints */
  for (bp_e = g_list_first (blueprints); bp_e; bp_e = g_list_next (bp_e)) {
    CodecBlueprint *bp = bp_e->data;
    CodecAssociation *ca = NULL;
    GList *tmpca_e = NULL;
    gboolean next = FALSE;
    FsCodec *codec;

    /* Lets skip codecs that dont have all of the required informations */
    if (bp->codec->clock_rate == 0)
      continue;

    /* Check if its already used */
    for (tmpca_e = codec_associations;
         tmpca_e;
         tmpca_e = g_list_next (tmpca_e))
    {
      CodecAssociation *tmpca = tmpca_e->data;
      if (tmpca->blueprint == bp)
        break;
    }
    if (tmpca_e)
      continue;

    /* Check if it is disabled in the list of preferred codecs */
    if (_is_disabled (codec_prefs, bp))
    {
      gchar *tmp = fs_codec_to_string (bp->codec);
      GST_DEBUG ("Codec %s disabled by config", tmp);
      g_free (tmp);
      continue;
    }

    /* Re-use already existing codec associations with this blueprint
     * if any, we only keep the PT from the old assoc
     * (the rest will be regenerated by the renegotiation)
     */
    for (tmpca_e = current_codec_associations;
         tmpca_e;
         tmpca_e = g_list_next (tmpca_e))
    {
      CodecAssociation *tmpca = tmpca_e->data;

      if (tmpca->blueprint == bp)
      {
        /* Ignore reserved (we've just regenerated them )*/
        if (tmpca->reserved)
          continue;

        /* Ignore it if there is already something for this PT */
        if (lookup_codec_association_by_pt_list (codec_associations,
                tmpca->codec->id, TRUE))
          continue;

        /* Can't keep this codec, for some reason its wrong */
        codec = sdp_negotiate_codec (tmpca->codec, FS_PARAM_TYPE_CONFIG,
            bp->codec, FS_PARAM_TYPE_ALL);
        if (!codec)
          continue;
        fs_codec_destroy (codec);

        ca = g_slice_new0 (CodecAssociation);
        ca->blueprint = bp;
        ca->codec = fs_codec_copy (bp->codec);
        ca->send_codec = codec_copy_filtered (bp->codec, FS_PARAM_TYPE_CONFIG);
        ca->codec->id = ca->send_codec->id = tmpca->codec->id;

        codec_associations = list_insert_local_ca (codec_associations, ca);
        next = TRUE;
      }
    }
    if (next)
      continue;

    codec = sdp_negotiate_codec (bp->codec, FS_PARAM_TYPE_ALL,
        bp->codec, FS_PARAM_TYPE_ALL);

    /* If it does not negotiate against itself, there must be something wrong */
    if (!codec)
      continue;
    fs_codec_destroy (codec);

    ca = g_slice_new0 (CodecAssociation);
    ca->blueprint = bp;
    ca->codec = fs_codec_copy (bp->codec);

    if (ca->codec->id < 0)
    {
      ca->codec->id = _find_first_empty_dynamic_entry (
          current_codec_associations, codec_associations);
      if (ca->codec->id < 0)
      {
        GST_WARNING ("We've run out of dynamic payload types");
        goto error;
      }
    }

    ca->send_codec = codec_copy_filtered (ca->codec, FS_PARAM_TYPE_CONFIG);

    codec_associations = list_insert_local_ca (codec_associations, ca);
  }

  for (lca_e = codec_associations;
       lca_e;
       lca_e = g_list_next (lca_e))
  {
    CodecAssociation *ca = lca_e->data;

    if (codec_association_is_valid_for_sending (ca, TRUE))
      has_valid_codec = TRUE;
  }

  if (!has_valid_codec)
  {
    GST_WARNING ("All codecs disabled by preferences");
    goto error;
  }

  return codec_associations;

 error:
  codec_association_list_destroy (codec_associations);

  return NULL;
}
/**
 *  fill FarsightCodec fields based on payloader capabilities
 *  TODO: optimise using quarks
 */
static gboolean
extract_field_data (GQuark field_id,
                    const GValue *value,
                    gpointer user_data)
{
  /* TODO : This can be called several times from different rtp caps for the
   * same codec, it would be good to make sure any duplicate values are the
   * same, if not then we have several rtp elements that are giving different
   * caps information, therefore they need to be fixed */

  FsCodec *codec = (FsCodec *) user_data;
  GType type = G_VALUE_TYPE (value);
  const gchar *field_name = g_quark_to_string (field_id);
  const gchar *tmp;

  if (0 == strcmp (field_name, "media"))
  {
    if (type != G_TYPE_STRING)
    {
      return FALSE;
    }
    tmp = g_value_get_string (value);
    if (strcmp (tmp, "audio") == 0)
    {
      codec->media_type = FS_MEDIA_TYPE_AUDIO;
    }
    else if (strcmp (tmp, "video") == 0)
    {
      codec->media_type = FS_MEDIA_TYPE_VIDEO;
    }

  }
  else if (0 == strcmp (field_name, "payload"))
  {
    if (type == GST_TYPE_INT_RANGE)
    {
      if (gst_value_get_int_range_min (value) < 96 ||
          gst_value_get_int_range_max (value) > 255)
      {
        return FALSE;
      }
    }
    else if (type == G_TYPE_INT)
    {
      int id;
      id = g_value_get_int (value);
      if (id > 96)
      {
        /* Dynamic id that was explicitelly set ?? shouldn't happen */
        return FALSE;
      }
      codec->id = id;
    }
    else
    {
      return FALSE;
    }
  }
  else if (0 == strcmp (field_name, "clock-rate"))
  {
    if (type == GST_TYPE_INT_RANGE)
    {
      /* set to 0, this should be checked by the optional parameters code later
       * in Farsight */
      codec->clock_rate = 0;
      return TRUE;
    }
    else if (type != G_TYPE_INT)
    {
      return FALSE;
    }
    codec->clock_rate = g_value_get_int (value);
  }
  else if (0 == strcmp (field_name, "ssrc") ||
      0 == strcmp (field_name, "clock-base") ||
      0 == strcmp (field_name, "seqnum-base"))
  {
    // ignore these fields for now
    ;
  }
  else if (0 == strcmp (field_name, "encoding-name"))
  {
    if (type != G_TYPE_STRING)
    {
      return FALSE;
    }
    if (!codec->encoding_name)
    {
      codec->encoding_name = g_value_dup_string (value);
    }
  }
  else if (0 == strcmp (field_name, "encoding-params"))
  {
    if (type != G_TYPE_STRING)
    {
      return FALSE;
    }
    codec->channels = (guint) g_ascii_strtoull (
                                       g_value_get_string (value), NULL, 10);
  }
  else
  {
    if (type == G_TYPE_STRING)
      fs_codec_add_optional_parameter (codec, field_name,
          g_value_get_string (value));
  }

  return TRUE;
}
Ejemplo n.º 9
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;
}