コード例 #1
0
static gboolean
match_send_codec_no_pt (CodecAssociation *old_ca, gpointer user_data)
{
  FsCodec *old_codec;
  FsCodec *tmpcodec = NULL;
  CodecAssociation *new_ca = user_data;
  gboolean ret;

  if (old_ca->disable || old_ca->reserved)
    return FALSE;

  if (new_ca->send_codec->id == old_ca->send_codec->id)
  {
    old_codec = old_ca->send_codec;
  }
  else
  {
    tmpcodec = old_codec = fs_codec_copy (old_ca->send_codec);
    old_codec->id = new_ca->codec->id;
  }

  ret = fs_codec_are_equal (old_codec, new_ca->codec);
  fs_codec_destroy (tmpcodec);

  return ret;
}
コード例 #2
0
GList *
finish_codec_negotiation (
    GList *old_codec_associations,
    GList *new_codec_associations)
{
  int i;
  GList *item;

  /* Now, lets fill all of the PTs that were previously used in the session
   * even if they are not currently used, so they can't be re-used
   */

  for (i=0; i < 128; i++)
  {
    CodecAssociation *local_ca = NULL;

    /* We can skip ids where something already exists */
    if (lookup_codec_association_by_pt_list (new_codec_associations, i, TRUE))
      continue;

    /* We check if our local table (our offer) and if we offered
     * something, we add it. Some broken implementation (like Tandberg's)
     * send packets on PTs that they did not put in their response
     */
    local_ca = lookup_codec_association_by_pt_list (old_codec_associations,
        i, FALSE);
    if (local_ca) {
      CodecAssociation *new_ca = codec_association_copy (local_ca);
      new_ca->recv_only = TRUE;
      new_codec_associations = g_list_append (new_codec_associations, new_ca);
    }
  }

  for (item = new_codec_associations; item; item = g_list_next (item))
  {
    CodecAssociation *new_ca = item->data;
    CodecAssociation *old_ca = NULL;

    if (new_ca->disable || new_ca->reserved || new_ca->recv_only)
    {
      new_ca->need_config = FALSE;
      continue;
    }

    old_ca = lookup_codec_association_custom_internal (old_codec_associations,
        TRUE, match_send_codec_no_pt, new_ca);
    if (old_ca && old_ca->send_codec &&
        fs_codec_are_equal (new_ca->send_codec, old_ca->send_codec))
      keep_config_from_old_codec (new_ca->codec, old_ca->codec);

    new_ca->need_config = codec_needs_config (new_ca->codec);
  }

  return new_codec_associations;
}
コード例 #3
0
ファイル: fs-rtp-stream.c プロジェクト: kakaroto/farstream
static gboolean
_codec_list_has_codec (GList *list, FsCodec *codec)
{
  for (; list; list = g_list_next (list))
  {
    FsCodec *listcodec = list->data;
    if (fs_codec_are_equal (codec, listcodec))
      return TRUE;
  }

  return FALSE;
}
コード例 #4
0
/**
 * fs_rtp_special_sources_remove:
 * @extra_sources: A pointer to the #GList returned by previous calls to this
 *  function
 * @negotiated_codec_associations: A pointer to the #GList of current negotiated
 * #CodecAssociation
 * @mutex: the mutex protecting the last two things
 * @send_codec: A pointer to the currently selected send codec
 *
 * This function removes any special source that are not compatible with the
 * currently selected send codec.
 *
 * Returns: %TRUE if a source was removed
 */
gboolean
fs_rtp_special_sources_remove (
    GList **extra_sources,
    GList **negotiated_codec_associations,
    GMutex *mutex,
    FsCodec *send_codec)
{
  GList *klass_item = NULL;
  gboolean changed = FALSE;

  fs_rtp_special_sources_init ();

  for (klass_item = g_list_first (classes);
       klass_item;
       klass_item = g_list_next (klass_item))
  {
    FsRtpSpecialSourceClass *klass = klass_item->data;
    GList *obj_item;
    FsRtpSpecialSource *obj = NULL;

  restart:
    g_mutex_lock (mutex);

    /* Check if we already have an object for this type */
    for (obj_item = g_list_first (*extra_sources);
         obj_item;
         obj_item = g_list_next (obj_item))
    {
      obj = obj_item->data;
      if (G_OBJECT_TYPE(obj) == G_OBJECT_CLASS_TYPE(klass))
        break;
    }

    if (obj_item)
    {
      FsCodec *telephony_codec =  fs_rtp_special_source_class_get_codec (klass,
          *negotiated_codec_associations, send_codec);

      if (!telephony_codec || !fs_codec_are_equal (telephony_codec, obj->codec))
      {
        *extra_sources = g_list_remove (*extra_sources, obj);
        changed = TRUE;
        g_mutex_unlock (mutex);
        g_object_unref (obj);
        goto restart;
      }
    }

    g_mutex_unlock (mutex);
  }

  return changed;
}
コード例 #5
0
static gboolean
_compare_codec_lists (GList *list1, GList *list2)
{
  for (; list1 && list2;
       list1 = g_list_next (list1),
       list2 = g_list_next (list2)) {
    if (!fs_codec_are_equal (list1->data, list2->data))
      return FALSE;
  }

  if (list1 == NULL && list2 == NULL)
    return TRUE;
  else
    return FALSE;
}
コード例 #6
0
CodecAssociation *
lookup_codec_association_by_codec (GList *codec_associations, FsCodec *codec)
{
  while (codec_associations)
  {
    if (codec_associations->data)
    {
      CodecAssociation *ca = codec_associations->data;
      if (fs_codec_are_equal (ca->codec, codec))
        return ca;
    }
    codec_associations = g_list_next (codec_associations);
  }

  return NULL;
}
コード例 #7
0
CodecAssociation *
lookup_codec_association_by_codec_for_sending (GList *codec_associations,
    FsCodec *codec)
{
  GList *item;

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

    if (codec_association_is_valid_for_sending (ca, FALSE) &&
        fs_codec_are_equal (ca->codec, codec))
      return ca;
  }

  return NULL;
}
コード例 #8
0
gboolean
codec_associations_list_are_equal (GList *list1, GList *list2)
{
  for (;list1 && list2;
       list1 = g_list_next (list1), list2 = g_list_next (list2))
  {
    CodecAssociation *ca1 = NULL;
    CodecAssociation *ca2 = NULL;

    /* Skip disabled codecs */
    while (list1) {
      ca1 = list1->data;
      if (!ca1->disable || !ca1->reserved)
        break;
      list1 = g_list_next (list1);
    }
    while (list2) {
      ca2 = list2->data;
      if (!ca2->disable || !ca2->reserved)
        break;
      list2 = g_list_next (list2);
    }

    if (list1 == NULL || list2 == NULL)
      break;

    /* We must emit the notification if the recv-only status
     * of a codec has changed
     */
    if (ca1->recv_only != ca2->recv_only)
      return FALSE;

    if (!fs_codec_are_equal (ca1->codec, ca2->codec))
      return FALSE;
  }

  if (list1 == NULL && list2 == NULL)
    return TRUE;
  else
    return FALSE;
}
コード例 #9
0
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);
    }
  }
}
コード例 #10
0
ファイル: fs-rtp-stream.c プロジェクト: kakaroto/farstream
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);
}
コード例 #11
0
ファイル: fs-rtp-substream.c プロジェクト: zsx/ossbuild
gboolean
fs_rtp_sub_stream_set_codecbin_unlock (FsRtpSubStream *substream,
    FsCodec *codec,
    GstElement *codecbin,
    GError **error)
{
  GstCaps *caps = NULL;
  gchar *tmp;
  gboolean ret = FALSE;
  GstPad *pad;
  gboolean codec_changed = TRUE;

  FS_RTP_SUB_STREAM_LOCK (substream);

  if (substream->priv->stopped)
  {
    FS_RTP_SUB_STREAM_UNLOCK (substream);
    FS_RTP_SESSION_UNLOCK (substream->priv->session);
    gst_object_unref (codecbin);
    fs_codec_destroy (codec);
    fs_rtp_sub_stream_try_stop (substream);
    return TRUE;
  }
  substream->priv->modifying = TRUE;
  FS_RTP_SUB_STREAM_UNLOCK (substream);

  if (substream->codec)
  {
    if (!fs_codec_are_equal (codec, substream->codec))
      codec_changed = FALSE;
  }

  if (substream->priv->codecbin)
  {
    FsCodec *saved_codec = substream->codec;
    GstElement *old_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);
      FS_RTP_SUB_STREAM_LOCK (substream);
      substream->priv->modifying = FALSE;
      FS_RTP_SUB_STREAM_UNLOCK (substream);
      FS_RTP_SESSION_UNLOCK (substream->priv->session);
      gst_object_unref (codecbin);
      fs_codec_destroy (codec);
      fs_rtp_sub_stream_try_stop (substream);
      return FALSE;
    }

    old_codecbin = substream->priv->codecbin;
    substream->priv->codecbin = NULL;
    FS_RTP_SESSION_UNLOCK (substream->priv->session);

    gst_bin_remove (GST_BIN (substream->priv->conference), old_codecbin);

    FS_RTP_SESSION_LOCK (substream->priv->session);
    if (substream->codec == saved_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);

  gst_object_ref (codecbin);

  if (!gst_bin_add (GST_BIN (substream->priv->conference), codecbin))
  {
    gst_object_unref (codecbin);
    g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
      "Could not add the codec bin to the conference");
    FS_RTP_SUB_STREAM_LOCK (substream);
    substream->priv->modifying = FALSE;
    FS_RTP_SUB_STREAM_UNLOCK (substream);
    fs_rtp_sub_stream_try_stop (substream);
    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_object_unref (pad);

  FS_RTP_SESSION_LOCK (substream->priv->session);
  substream->priv->caps = caps;
  substream->priv->codecbin = codecbin;
  substream->codec = codec;
  FS_RTP_SUB_STREAM_LOCK (substream);
  substream->priv->modifying = FALSE;
  FS_RTP_SUB_STREAM_UNLOCK (substream);

  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);
    if (codec_changed)
      g_signal_emit (substream, signals[CODEC_CHANGED], 0);
  }

  gst_object_unref (codecbin);

  fs_rtp_sub_stream_try_stop (substream);

  return TRUE;

 error:
  FS_RTP_SUB_STREAM_LOCK (substream);
  substream->priv->modifying = FALSE;
  FS_RTP_SUB_STREAM_UNLOCK (substream);


  gst_element_set_locked_state (codecbin, TRUE);
  gst_element_set_state (codecbin, GST_STATE_NULL);
  gst_object_ref (codecbin);
  gst_bin_remove (GST_BIN (substream->priv->conference), codecbin);

  gst_object_unref (codecbin);
  fs_codec_destroy (codec);

  fs_rtp_sub_stream_try_stop (substream);

  return ret;
}