Exemple #1
0
/**
 * fs_rtp_stream_set_negotiated_codecs_unlock
 * @stream: a #FsRtpStream
 * @codecs: The #GList of #FsCodec to set for the negotiated-codecs property
 *
 * This function sets the value of the FsStream:negotiated-codecs property.
 * Unlike most other functions in this element, it TAKES the reference to the
 * codecs, so you have to give it its own copy.
 *
 * You must enter this function with the session lock held and it will release
 * it.
 */
void
fs_rtp_stream_set_negotiated_codecs_unlock (FsRtpStream *stream,
    GList *codecs)
{
  FsRtpSession *session = fs_rtp_stream_get_session (stream, NULL);

  if (!session)
    return;

  if (fs_codec_list_are_equal (stream->negotiated_codecs, codecs))
  {
    fs_codec_list_destroy (codecs);
    FS_RTP_SESSION_UNLOCK (session);
    g_object_unref (session);
    return;
  }

  if (stream->negotiated_codecs)
    fs_codec_list_destroy (stream->negotiated_codecs);

  stream->negotiated_codecs = codecs;

  FS_RTP_SESSION_UNLOCK (session);

  g_object_notify (G_OBJECT (stream), "negotiated-codecs");

  g_object_unref (session);
}
static void
set_initial_codecs (
    struct SimpleTestConference *from,
    struct SimpleTestStream *to)
{
  GList *codecs = NULL;
  GList *filtered_codecs = NULL;
  GList *item = NULL;
  GList *rcodecs2 = NULL;
  GError *error = NULL;

  g_object_get (from->session, "codecs", &codecs, NULL);

  ts_fail_if (codecs == NULL, "Could not get the codecs");

  for (item = g_list_first (codecs); item; item = g_list_next (item))
  {
    FsCodec *codec = item->data;
    if (codec->id == 0 || codec->id == 8)
      filtered_codecs = g_list_append (filtered_codecs, codec);
  }

  ts_fail_if (filtered_codecs == NULL, "PCMA and PCMU are not in the codecs"
      " you must install gst-plugins-good");


  g_debug ("Setting initial remote codecs on %d:%d from %d",
      to->dat->id, to->target->id,
      from->id);

  if (!fs_stream_set_remote_codecs (to->stream, filtered_codecs, &error))
  {
    if (error)
      ts_fail ("Could not set the remote codecs on stream %d:%d (%d): %s",
          to->dat->id, to->target->id,
          error->code,
          error->message);
    else
      ts_fail ("Could not set the remote codecs on stream %d"
          " and we DID not get a GError!!", to->target->id);
  }
  g_object_get (to->stream, "remote-codecs", &rcodecs2, NULL);
  ts_fail_unless (_compare_codec_lists (rcodecs2, filtered_codecs),
      "Can not get remote codecs correctly");
  fs_codec_list_destroy (rcodecs2);


  if (select_last_codec)
    ts_fail_unless (
        fs_session_set_send_codec (to->dat->session,
            g_list_last (filtered_codecs)->data,
            &error),
        "Error setting the send codec to the last codec: %s",
        error ? error->message : "No GError");
  g_clear_error (&error);

  g_list_free (filtered_codecs);
  fs_codec_list_destroy (codecs);
}
static void
_negotiated_codecs_notify (GObject *object, GParamSpec *paramspec,
    gpointer user_data)
{
  struct SimpleTestConference *dat = user_data;
  FsSession *session = FS_SESSION (object);
  GList *codecs = NULL;
  GError *error = NULL;
  GList *item = NULL;

  g_debug ("%d: New negotiated codecs", dat->id);

  ts_fail_if (session != dat->session, "Got signal from the wrong object");

  g_object_get (dat->session, "codecs", &codecs, NULL);
  ts_fail_if (codecs == NULL, "Could not get the negotiated codecs");


  /* We have to find the stream from the target that points back to us */
  for (item = g_list_first (dat->streams); item; item = g_list_next (item))
  {
    struct SimpleTestStream *st = item->data;
    struct SimpleTestStream *st2 = find_pointback_stream (st->target, dat);
    GList *rcodecs2;

    g_debug ("Setting negotiated remote codecs on %d:%d from %d",st2->dat->id,
        st2->target->id, dat->id);
    if (!fs_stream_set_remote_codecs (st2->stream, codecs, &error))
    {
      if (error)
        ts_fail ("Could not set the remote codecs on stream %d:%d (%d): %s",
            st2->dat->id, st2->target->id,
            error->code,
            error->message);
      else
        ts_fail ("Could not set the remote codecs on stream %d:%d"
            " and we DID not get a GError!!",
            st2->dat->id, st2->target->id);
    }
    g_object_get (st2->stream, "remote-codecs", &rcodecs2, NULL);
    ts_fail_unless (_compare_codec_lists (rcodecs2, codecs),
        "Can not get remote codecs correctly");

    fs_codec_list_destroy (rcodecs2);

    if (select_last_codec)
      ts_fail_unless (
          fs_session_set_send_codec (st2->dat->session,
              g_list_last (codecs)->data,
              &error),
          "Error setting the send codec to the last codec: %s",
          error ? error->message : "No GError");

    g_clear_error (&error);
    break;
  }
  fs_codec_list_destroy (codecs);
}
Exemple #4
0
static void
fs_rtp_stream_finalize (GObject *object)
{
  FsRtpStream *self = FS_RTP_STREAM (object);

  fs_codec_list_destroy (self->remote_codecs);
  fs_codec_list_destroy (self->negotiated_codecs);

  g_mutex_clear (&self->priv->mutex);

  G_OBJECT_CLASS (fs_rtp_stream_parent_class)->finalize (object);
}
Exemple #5
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
empathy_call_handler_finalize (GObject *object)
{
  EmpathyCallHandlerPriv *priv = GET_PRIV (object);

  fs_codec_destroy (priv->send_audio_codec);
  fs_codec_destroy (priv->send_video_codec);
  fs_codec_list_destroy (priv->recv_audio_codecs);
  fs_codec_list_destroy (priv->recv_video_codecs);
  fs_candidate_destroy (priv->audio_remote_candidate);
  fs_candidate_destroy (priv->video_remote_candidate);
  fs_candidate_destroy (priv->audio_local_candidate);
  fs_candidate_destroy (priv->video_local_candidate);

  G_OBJECT_CLASS (empathy_call_handler_parent_class)->finalize (object);
}
Exemple #7
0
static void
set_codecs (struct SimpleTestConference *dat, FsStream *stream)
{
  GList *codecs = NULL;
  GList *filtered_codecs = NULL;
  GList *item = NULL;
  GError *error = NULL;
  FsCodec *dtmf_codec = NULL;

  g_object_get (dat->session, "codecs", &codecs, NULL);

  ts_fail_if (codecs == NULL, "Could not get the local codecs");

  for (item = g_list_first (codecs); item; item = g_list_next (item))
  {
    FsCodec *codec = item->data;
    if (codec->id == 0 || codec->id == 8)
    {
      filtered_codecs = g_list_append (filtered_codecs, codec);
    }
    else if (codec->clock_rate == 8000 &&
        !g_ascii_strcasecmp (codec->encoding_name, "telephone-event"))
    {
      ts_fail_unless (dtmf_codec == NULL,
          "More than one copy of telephone-event");
      dtmf_codec = codec;
      filtered_codecs = g_list_append (filtered_codecs, codec);
    }
  }

  ts_fail_if (filtered_codecs == NULL, "PCMA and PCMU are not in the codecs"
      " you must install gst-plugins-good");

  ts_fail_unless (dtmf_codec != NULL);
  dtmf_codec->id = dtmf_id;

  if (!fs_stream_set_remote_codecs (stream, filtered_codecs, &error))
  {
    if (error)
      ts_fail ("Could not set the remote codecs on stream (%d): %s",
          error->code,
          error->message);
    else
      ts_fail ("Could not set the remote codecs on stream"
          " and we did NOT get a GError!!");
  }

  g_list_free (filtered_codecs);
  fs_codec_list_destroy (codecs);
}
Exemple #8
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);

}
Exemple #9
0
static TestSession*
add_audio_session (GstElement *pipeline, FsConference *conf, guint id,
    FsParticipant *part, gchar *send_socket, gchar *recv_socket)
{
  TestSession *ses = g_slice_new0 (TestSession);
  GError *error = NULL;
  GstPad *pad = NULL, *pad2 = NULL;
  GstElement *src = NULL;
  GList *cands = NULL;
  GParameter param = {0};
  gboolean res;
  FsCandidate *cand;
  GList *codecs = NULL;

  ses->send_socket = send_socket;
  ses->recv_socket = recv_socket;

  ses->session = fs_conference_new_session (conf, FS_MEDIA_TYPE_AUDIO, &error);
  print_error (error);
  g_assert (ses->session);

  g_object_get (ses->session, "sink-pad", &pad, NULL);

  if (g_getenv ("AUDIOSRC"))
    src = gst_parse_bin_from_description (g_getenv ("AUDIOSRC"), TRUE,
        &error);
  else
    src = gst_parse_bin_from_description (DEFAULT_AUDIOSRC, TRUE,
        &error);
  print_error (error);
  g_assert (src);

  g_assert (gst_bin_add (GST_BIN (pipeline), src));

  pad2 = gst_element_get_static_pad (src, "src");
  g_assert (pad2);

  g_assert (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (pad2, pad)));

  gst_object_unref (pad2);
  gst_object_unref (pad);

  ses->stream = fs_session_new_stream (ses->session, part, FS_DIRECTION_BOTH,
      &error);
  print_error (error);
  g_assert (ses->stream);

  cand = fs_candidate_new ("", FS_COMPONENT_RTP,
      FS_CANDIDATE_TYPE_HOST, FS_NETWORK_PROTOCOL_UDP, send_socket, 0);
  cands = g_list_prepend (NULL, cand);

  param.name = "preferred-local-candidates";
  g_value_init (&param.value, FS_TYPE_CANDIDATE_LIST);
  g_value_take_boxed (&param.value, cands);

  res = fs_stream_set_transmitter (ses->stream, "shm", &param, 1, &error);
  print_error (error);
  g_value_unset (&param.value);

  g_signal_connect (ses->stream, "src-pad-added",
      G_CALLBACK (src_pad_added_cb), pipeline);

  codecs = g_list_prepend (NULL,
      fs_codec_new (FS_CODEC_ID_ANY, "PCMA", FS_MEDIA_TYPE_AUDIO, 0));
  codecs = g_list_prepend (codecs,
      fs_codec_new (FS_CODEC_ID_ANY, "PCMU", FS_MEDIA_TYPE_AUDIO, 0));

  res = fs_session_set_codec_preferences (ses->session, codecs, &error);
  print_error (error);
  fs_codec_list_destroy (codecs);


  g_object_get (ses->session, "codecs-without-config", &codecs, NULL);
  res = fs_stream_set_remote_codecs (ses->stream, codecs, &error);
  print_error (error);
  g_assert (res);


  return ses;
}
static void
_handoff_handler (GstElement *element, GstBuffer *buffer, GstPad *pad,
  gpointer user_data)
{
  struct SimpleTestStream *st = user_data;
  int i;
  gboolean stop = TRUE;
  GList *codecs = NULL;

  g_object_get (st->dat->session,
      "codecs", &codecs,
      NULL);

  ts_fail_if (codecs == NULL, "Could not get codecs");

  if (st->flags & WAITING_ON_LAST_CODEC)
  {
    if (fs_codec_are_equal (
        g_list_last (codecs)->data,
        g_object_get_data (G_OBJECT (element), "codec")))
    {
      st->flags &= ~WAITING_ON_LAST_CODEC;
      st->flags |= SHOULD_BE_LAST_CODEC;
      max_buffer_count += st->buffer_count;
      g_debug ("We HAVE last codec");
    }
    else
    {
      gchar *str = fs_codec_to_string (
          g_object_get_data (G_OBJECT (element), "codec"));
      gchar *str2 = fs_codec_to_string (g_list_last (codecs)->data);
      g_debug ("not yet the last codec, skipping (we have %s, we want %s)",
          str, str2);
      g_free (str);
      g_free (str2);
      fs_codec_list_destroy (codecs);
      return;
    }
  }


  if (select_last_codec || st->flags & SHOULD_BE_LAST_CODEC)
    ts_fail_unless (
        fs_codec_are_equal (
            g_list_last (codecs)->data,
            g_object_get_data (G_OBJECT (element), "codec")),
        "The handoff handler got a buffer from the wrong codec (last)");
  else
    ts_fail_unless (
        fs_codec_are_equal (
            g_list_first (codecs)->data,
            g_object_get_data (G_OBJECT (element), "codec")),
        "The handoff handler got a buffer from the wrong codec");

  fs_codec_list_destroy (codecs);


  st->buffer_count++;

  if (st->buffer_count % 10 == 0)
    g_debug ("%d:%d: Buffer %d", st->dat->id, st->target->id, st->buffer_count);

  /*
  ts_fail_if (dat->buffer_count > max_buffer_count,
    "Too many buffers %d > max_buffer_count", dat->buffer_count);
  */

  for (i = 0; i < count && !stop ; i++)
  {
    GList *item;


    for (item = g_list_first (dats[i]->streams);
         item;
         item = g_list_next (item))
    {
      struct SimpleTestStream *st2 = item->data;

      if (st2->buffer_count < max_buffer_count)
      {
        stop = FALSE;
        break;
      }
    }
  }

  if (stop)
  {
    if (reset_to_last_codec && !(st->flags & HAS_BEEN_RESET)) {
      GError *error = NULL;
      GList *nego_codecs = NULL;
      gchar *str = NULL;

      g_object_get (st->target->session,
          "codecs", &nego_codecs,
          NULL);

      ts_fail_if (nego_codecs == NULL, "No codecs");
      ts_fail_if (g_list_length (nego_codecs) < 2, "Only one negotiated codec");

      str = fs_codec_to_string (g_list_last (nego_codecs)->data);
      g_debug ("Setting codec to: %s", str);
      g_free (str);

      ts_fail_unless (fs_session_set_send_codec (st->target->session,
              g_list_last (nego_codecs)->data, &error),
          "Could not set the send codec: %s",
          error ? error->message : "NO GError!!!");
      g_clear_error (&error);

      fs_codec_list_destroy (nego_codecs);

      st->flags |= HAS_BEEN_RESET | WAITING_ON_LAST_CODEC;

      g_debug ("RESET TO LAST CODEC");

    } else {
      g_main_loop_quit (loop);
    }
  }
}
Exemple #11
0
static void
_substream_codec_changed (FsRtpSubStream *substream,
    FsRtpStream *stream)
{
  GList *substream_item = NULL;
  GList *codeclist = NULL;
  FsRtpSession *session = fs_rtp_stream_get_session (stream, NULL);

  if (!session)
    return;

  FS_RTP_SESSION_LOCK (session);

  if (!substream->codec)
  {
    FS_RTP_SESSION_UNLOCK (session);
    g_object_unref (session);
    return;
  }

  codeclist = g_list_prepend (NULL, fs_codec_copy (substream->codec));

  for (substream_item = stream->substreams;
       substream_item;
       substream_item = g_list_next (substream_item))
  {
    FsRtpSubStream *othersubstream = substream_item->data;

    if (othersubstream != substream)
    {
      if (othersubstream->codec)
      {
        if (fs_codec_are_equal (substream->codec, othersubstream->codec))
          break;

        if (!_codec_list_has_codec (codeclist, othersubstream->codec))
          codeclist = g_list_append (codeclist,
              fs_codec_copy (othersubstream->codec));
      }
    }
  }

  FS_RTP_SESSION_UNLOCK (session);

  if (substream_item == NULL)
  {
    GstElement *conf = NULL;

    g_object_notify (G_OBJECT (stream), "current-recv-codecs");

    g_object_get (session, "conference", &conf, NULL);

    gst_element_post_message (conf,
        gst_message_new_element (GST_OBJECT (conf),
            gst_structure_new ("farstream-recv-codecs-changed",
                "stream", FS_TYPE_STREAM, stream,
                "codecs", FS_TYPE_CODEC_LIST, codeclist,
                NULL)));

    gst_object_unref (conf);
  }

  fs_codec_list_destroy (codeclist);
  g_object_unref (session);
}
Exemple #12
0
/**
 * fs_rtp_stream_set_remote_codecs:
 * @stream: an #FsStream
 * @remote_codecs: a #GList of #FsCodec representing the remote codecs
 * @error: location of a #GError, or NULL if no error occured
 *
 * This function will set the list of remote codecs for this stream. If
 * the given remote codecs couldn't be negotiated with the list of local
 * codecs or already negotiated codecs for the corresponding #FsSession, @error
 * will be set and %FALSE will be returned. The @remote_codecs list will be
 * copied so it must be free'd using fs_codec_list_destroy() when done.
 *
 * Returns: %FALSE if the remote codecs couldn't be set.
 */
static gboolean
fs_rtp_stream_set_remote_codecs (FsStream *stream,
                                 GList *remote_codecs, GError **error)
{
  FsRtpStream *self = FS_RTP_STREAM (stream);
  GList *item = NULL;
  FsMediaType media_type;
  FsRtpSession *session = fs_rtp_stream_get_session (self, error);

  if (!session)
    return FALSE;

  if (remote_codecs == NULL) {
    g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
      "You can not set NULL remote codecs");
    goto error;
  }

  g_object_get (session, "media-type", &media_type, NULL);

  for (item = g_list_first (remote_codecs); item; item = g_list_next (item))
  {
    FsCodec *codec = item->data;

    if (!codec->encoding_name)
    {
      g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
          "The codec must have an encoding name");
      goto error;
    }
    if (codec->id < 0 || codec->id > 128)
    {
      g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
          "The codec id must be between 0 ans 128 for %s",
          codec->encoding_name);
      goto error;
    }
    if (codec->media_type != media_type)
    {
      g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
          "The media type for codec %s is not %s", codec->encoding_name,
          fs_media_type_to_string (media_type));
      goto error;
    }
  }

  if (self->priv->new_remote_codecs_cb (self, remote_codecs, error,
          self->priv->user_data_for_cb))
  {
    gboolean is_new = TRUE;

    FS_RTP_SESSION_LOCK (session);
    if (self->remote_codecs)
    {
      is_new = !fs_codec_list_are_equal (self->remote_codecs, remote_codecs);
      fs_codec_list_destroy (self->remote_codecs);
    }
    self->remote_codecs = fs_codec_list_copy (remote_codecs);
    FS_RTP_SESSION_UNLOCK (session);

    if (is_new)
      g_object_notify (G_OBJECT (stream), "remote-codecs");
  } else {
    goto error;
  }

  g_object_unref (session);
  return TRUE;

 error:

  g_object_unref (session);
  return FALSE;
}
gboolean
skype_audio_stream_handle_message (SkypeBaseStream *self, GstMessage *message)
{
  SkypeAudioStreamPrivate *priv = SKYPE_AUDIO_STREAM (self)->priv;
  GstStructure *structure;
  FsSession *session = NULL;
  GList *secondary_codecs = NULL;
  GList *iter;

  if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT)
    return FALSE;

  structure = (GstStructure *)gst_message_get_structure (message);

  if (!gst_structure_has_name (structure, "farsight-send-codec-changed"))
    return FALSE;

  gst_structure_get (structure,
      "session", FS_TYPE_SESSION, &session,
      "secondary-codecs", FS_TYPE_CODEC_LIST, &secondary_codecs,
      NULL);

  /* Update the current telephony PT */
  for (iter = secondary_codecs; iter != NULL; iter = g_list_next (iter))
    {
      FsCodec *codec = (FsCodec *)iter->data;

      if (codec != NULL && !g_strcmp0 (codec->encoding_name, "telephone-event"))
        {
          priv->last_telephony_pt = codec->id;
          if (priv->pending_telephony_pt != FS_CODEC_ID_DISABLE &&
              priv->pending_telephony_pt == priv->last_telephony_pt)
            priv->pending_telephony_pt = FS_CODEC_ID_DISABLE;
          break;
        }
    }

  while (!g_queue_is_empty (priv->event_queue))
    {
      DTMFQueueEvent *event = (DTMFQueueEvent *)
          g_queue_pop_head (priv->event_queue);
      FsDTMFMethod method = FS_DTMF_METHOD_AUTO;

      if (event->rtp_type == SKYPE_DTMF_EVENT_TYPE_IN_BAND)
        {
          method = FS_DTMF_METHOD_IN_BAND;
        }
      else if (event->rtp_type == priv->last_telephony_pt)
        {
          method = FS_DTMF_METHOD_RTP_RFC4733;
        }
      else
        {
          /* New PT needed. Update codecs */
          FsCodec *codec;

          g_queue_push_head (priv->event_queue, event);

          priv->pending_telephony_pt = event->rtp_type;

          /* Trigger a codec update */
          g_object_get (self, "codec", &codec, NULL);
          g_object_set (self, "codec", codec, NULL);
          fs_codec_destroy (codec);

          break;
        }

      if (!fs_session_start_telephony_event (session,
          event->event_nr, 0, method))
        {
          g_warning ("Telephony event type not supported");
          g_queue_push_head (priv->event_queue, event);
        }
      else
        {
          fs_session_stop_telephony_event (session, method);
        }

      g_slice_free (DTMFQueueEvent, event);
    }

  g_object_unref (session);
  fs_codec_list_destroy (secondary_codecs);

  return TRUE;
}