static void
_codec_association_destroy (CodecAssociation *ca)
{
  if (!ca)
    return;

  fs_codec_destroy (ca->codec);
  fs_codec_destroy (ca->send_codec);
  g_free (ca->send_profile);
  g_free (ca->recv_profile);
  g_slice_free (CodecAssociation, ca);
}
Exemplo n.º 2
0
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);
}
static void
fs_rtp_special_source_finalize (GObject *object)
{
  FsRtpSpecialSource *self = FS_RTP_SPECIAL_SOURCE (object);

  if (self->priv->rtpmuxer)
  {
    gst_object_unref (self->priv->rtpmuxer);
    self->priv->rtpmuxer = NULL;
  }

  if (self->priv->outer_bin)
  {
    gst_object_unref (self->priv->outer_bin);
    self->priv->outer_bin = NULL;
  }

  if (self->codec)
    fs_codec_destroy (self->codec);
  self->codec = NULL;

  if (self->priv->mutex)
    g_mutex_free (self->priv->mutex);
  self->priv->mutex = NULL;

  G_OBJECT_CLASS (fs_rtp_special_source_parent_class)->finalize (object);
}
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;
}
static void
negotiate_stream_codec (CodecAssociation *old_ca, FsCodec *remote_codec,
    gboolean multi_stream, FsCodec **nego_codec, FsCodec **nego_send_codec)
{
  if (multi_stream)
    *nego_codec = sdp_negotiate_codec (old_ca->codec, FS_PARAM_TYPE_ALL,
        remote_codec, FS_PARAM_TYPE_SEND | FS_PARAM_TYPE_SEND_AVOID_NEGO);
  else
    *nego_codec = sdp_negotiate_codec (old_ca->codec, FS_PARAM_TYPE_ALL,
        remote_codec, FS_PARAM_TYPE_SEND);

  if (*nego_codec)
  {
    if (multi_stream)
      *nego_send_codec = sdp_negotiate_codec (
          old_ca->send_codec,
          FS_PARAM_TYPE_BOTH | FS_PARAM_TYPE_SEND_AVOID_NEGO,
          remote_codec, FS_PARAM_TYPE_SEND | FS_PARAM_TYPE_SEND_AVOID_NEGO);
    else
      *nego_send_codec = sdp_negotiate_codec (
          old_ca->send_codec, FS_PARAM_TYPE_BOTH,
          remote_codec, FS_PARAM_TYPE_SEND | FS_PARAM_TYPE_SEND_AVOID_NEGO);

    /* If send codec can't be negotiated, try another one */
    if (!*nego_send_codec)
    {
      fs_codec_destroy (*nego_codec);
      *nego_codec = NULL;
    }
  }
}
Exemplo n.º 6
0
/**
 * fs_codec_list_destroy: (skip): 
 * @codec_list: a GList of #FsCodec to delete
 *
 * Deletes a list of #FsCodec structures and the list itself.
 * Does nothing on %NULL lists.
 */
void
fs_codec_list_destroy (GList *codec_list)
{
  GList *lp;
  FsCodec *codec;

  for (lp = codec_list; lp; lp = g_list_next (lp)) {
    codec = (FsCodec *) lp->data;
    fs_codec_destroy (codec);
    lp->data = NULL;
  }
  g_list_free (codec_list);
}
static gboolean
codec_sdp_compare (FsCodec *local_codec, FsCodec *remote_codec)
{
  FsCodec *nego_codec = sdp_negotiate_codec (
      local_codec, FS_PARAM_TYPE_ALL & ~FS_PARAM_TYPE_CONFIG,
      remote_codec, FS_PARAM_TYPE_ALL & ~FS_PARAM_TYPE_CONFIG);

  if (!nego_codec)
    return FALSE;

  fs_codec_destroy (nego_codec);
  return TRUE;
}
Exemplo n.º 8
0
static void
fs_rtp_sub_stream_finalize (GObject *object)
{
  FsRtpSubStream *self = FS_RTP_SUB_STREAM (object);

  if (self->codec)
    fs_codec_destroy (self->codec);

  if (self->priv->caps)
    gst_caps_unref (self->priv->caps);

  if (self->priv->mutex)
    g_mutex_free (self->priv->mutex);

  G_OBJECT_CLASS (fs_rtp_sub_stream_parent_class)->finalize (object);
}
void
codec_blueprint_destroy (CodecBlueprint *codec_blueprint)
{
  GList *walk;

  if (codec_blueprint->codec)
  {
    fs_codec_destroy (codec_blueprint->codec);
  }

  if (codec_blueprint->media_caps)
  {
    gst_caps_unref (codec_blueprint->media_caps);
  }

  if (codec_blueprint->rtp_caps)
  {
    gst_caps_unref (codec_blueprint->rtp_caps);
  }

  for (walk = codec_blueprint->send_pipeline_factory;
      walk; walk = g_list_next (walk))
  {
    if (walk->data)
    {
      g_list_foreach (walk->data, (GFunc) gst_object_unref, NULL);
      g_list_free (walk->data);
    }
  }
  for (walk = codec_blueprint->receive_pipeline_factory;
      walk; walk = g_list_next (walk))
  {
    if (walk->data)
    {
      g_list_foreach (walk->data, (GFunc) gst_object_unref, NULL);
      g_list_free (walk->data);
    }
  }
  g_list_free (codec_blueprint->send_pipeline_factory);
  g_list_free (codec_blueprint->receive_pipeline_factory);


  g_slice_free (CodecBlueprint, codec_blueprint);
}
Exemplo n.º 10
0
static void
_connected (
    FsMsnConnection *connection,
    guint fd,
    gpointer user_data)
{
  FsMsnStream *self = FS_MSN_STREAM (user_data);
  GError *error = NULL;
  GstPad *pad;
  GstElement *fdelem;
  int checkfd;
  FsMsnConference *conference = fs_msn_stream_get_conference (self, NULL);
  GstElement *codecbin = NULL;
  GstElement *recv_valve = NULL;
  GstElement *send_valve = NULL;
  gboolean drop;

  if (!conference)
    goto error;

  GST_DEBUG ("******** CONNECTED %d**********", fd);

  gst_element_post_message (GST_ELEMENT (conference),
      gst_message_new_element (GST_OBJECT (conference),
          gst_structure_new ("farstream-component-state-changed",
              "stream", FS_TYPE_STREAM, self,
              "component", G_TYPE_UINT, 1,
              "state", FS_TYPE_STREAM_STATE, FS_STREAM_STATE_READY,
              NULL)));

  if (self->priv->conference->max_direction == FS_DIRECTION_RECV)
    codecbin = gst_parse_bin_from_description (
        "fdsrc name=fdsrc do-timestamp=true ! mimdec ! valve name=recv_valve", TRUE, &error);
  else
    codecbin = gst_parse_bin_from_description (
        "videoconvert ! videoscale ! mimenc name=enc !"
        " fdsink name=fdsink sync=false async=false",
        TRUE, &error);

  if (!codecbin)
  {
    g_prefix_error (&error, "Error creating codecbin: ");
    fs_stream_emit_error (FS_STREAM (self), FS_ERROR_CONSTRUCTION,
        error->message);
    g_clear_error (&error);
    goto error;
  }

  /* So we don't require an unlreased gst-plugins-bad mimenc */
  if (self->priv->conference->max_direction == FS_DIRECTION_SEND)
  {
    GstElement *mimenc = gst_bin_get_by_name (GST_BIN (codecbin), "enc");
    if (g_object_class_find_property (
            G_OBJECT_GET_CLASS (mimenc), "paused-mode"))
      g_object_set (mimenc, "paused-mode", TRUE, NULL);
    gst_object_unref (mimenc);
  }

  if (self->priv->conference->max_direction == FS_DIRECTION_RECV)
  {
    fdelem = gst_bin_get_by_name (GST_BIN (codecbin), "fdsrc");
    gst_base_src_set_format (GST_BASE_SRC (fdelem), GST_FORMAT_TIME);
  }
  else
  {
    fdelem = gst_bin_get_by_name (GST_BIN (codecbin), "fdsink");
  }

  if (!fdelem)
  {
    fs_stream_emit_error (FS_STREAM (self), FS_ERROR_CONSTRUCTION,
        "Could not get fd element");
    goto error;
  }

  g_object_set (fdelem, "fd", fd, NULL);
  g_object_get (fdelem, "fd", &checkfd, NULL);
  gst_object_unref (fdelem);

  if (fd != checkfd)
  {
    fs_stream_emit_error (FS_STREAM (self), FS_ERROR_INTERNAL,
        "Could not set file descriptor");
    goto error;
  }


  if (self->priv->conference->max_direction == FS_DIRECTION_RECV)
    pad = gst_element_get_static_pad (codecbin, "src");
  else
    pad = gst_element_get_static_pad (codecbin, "sink");

  if (!pad)
  {
    fs_stream_emit_error (FS_STREAM (self), FS_ERROR_CONSTRUCTION,
        "Could not get codecbin pad");
    goto error;
  }

  if (!gst_bin_add (GST_BIN (conference), codecbin))
  {
    gst_object_unref (pad);
    fs_stream_emit_error (FS_STREAM (self), FS_ERROR_CONSTRUCTION,
        "Could not add codecbin to the conference");
    goto error;
  }

  GST_OBJECT_LOCK (conference);
  self->priv->fd = fd;
  self->priv->codecbin = gst_object_ref (codecbin);
  GST_OBJECT_UNLOCK (conference);

  if (self->priv->conference->max_direction == FS_DIRECTION_RECV)
  {
    FsCodec *mimic_codec;
    GstPad *src_pad;

    src_pad = gst_ghost_pad_new ("src_1_1_1", pad);
    gst_object_unref (pad);

    GST_OBJECT_LOCK (conference);
    self->priv->src_pad =  gst_object_ref (src_pad);
    GST_OBJECT_UNLOCK (conference);

    gst_pad_set_active (src_pad, TRUE);
    if (!gst_element_add_pad (GST_ELEMENT (conference), src_pad))
    {
      fs_stream_emit_error (FS_STREAM (self), FS_ERROR_CONSTRUCTION,
          "Could not add src_1_1_1 pad");
      gst_object_unref (src_pad);
      goto error;
    }

    recv_valve = gst_bin_get_by_name (GST_BIN (codecbin), "recv_valve");

    if (!recv_valve)
    {
       fs_stream_emit_error (FS_STREAM (self), FS_ERROR_CONSTRUCTION,
           "Could not get recv_valve");
       gst_object_unref (src_pad);
       goto error;
    }

    GST_OBJECT_LOCK (conference);
    self->priv->recv_valve = gst_object_ref (recv_valve);
    drop = !(self->priv->direction & FS_DIRECTION_RECV);
    GST_OBJECT_UNLOCK (conference);

    g_object_set (recv_valve, "drop", drop, NULL);


    mimic_codec = fs_codec_new (0, "mimic",
        FS_MEDIA_TYPE_VIDEO, 0);
    fs_stream_emit_src_pad_added (FS_STREAM (self), src_pad, mimic_codec);
    fs_codec_destroy (mimic_codec);
    gst_object_unref (src_pad);

  }
  else
  {
    GstPad *valvepad;

    GST_OBJECT_LOCK (conference);
    if (self->priv->session->valve)
      send_valve = gst_object_ref (self->priv->session->valve);
    GST_OBJECT_UNLOCK (conference);

    if (!send_valve)
    {
      fs_stream_emit_error (FS_STREAM (self), FS_ERROR_DISPOSED,
          "Session was disposed");
      goto error;
    }

    valvepad = gst_element_get_static_pad (send_valve, "src");

    if (!valvepad)
    {
      gst_object_unref (pad);
      fs_stream_emit_error (FS_STREAM (self), FS_ERROR_CONSTRUCTION,
          "Could not get valve sink pad");
      goto error;
    }

    if (GST_PAD_LINK_FAILED (gst_pad_link (valvepad, pad)))
    {
      gst_object_unref (valvepad);
      gst_object_unref (pad);
      fs_stream_emit_error (FS_STREAM (self), FS_ERROR_CONSTRUCTION,
          "Could not link valve to codec bin");
      goto error;
    }
    gst_object_unref (valvepad);
    gst_object_unref (pad);
  }

  if (!gst_element_sync_state_with_parent (codecbin))
  {
    fs_stream_emit_error (FS_STREAM (self), FS_ERROR_CONSTRUCTION,
        "Could not start codec bin");
    goto error;
  }

  if (self->priv->conference->max_direction == FS_DIRECTION_SEND)
  {
    GST_OBJECT_LOCK (conference);
    fs_msn_stream_set_tos_locked (self, self->priv->tos);
    drop = !(self->priv->direction & FS_DIRECTION_SEND);
    GST_OBJECT_UNLOCK (conference);
    g_object_set (send_valve, "drop", drop, NULL);
  }

 error:

  if (send_valve)
    gst_object_unref (send_valve);
  if (recv_valve)
    gst_object_unref (recv_valve);
  if (codecbin)
    gst_object_unref (codecbin);
  if (conference)
    gst_object_unref (conference);
}
Exemplo n.º 11
0
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;
}
Exemplo n.º 12
0
gboolean
skype_audio_stream_send_dtmf (SkypeAudioStream *self,
    int event,
    int type)
{
  SkypeAudioStreamPrivate *priv = self->priv;
  FsuSession *session;
  FsSession *fssession;
  FsDTMFMethod method;
  gboolean ret = TRUE;
  GstStructure *structure;
  GstEvent *gstevent;

  g_debug ("Sending telephony event: %d, type: %d", event, type);

  structure = gst_structure_new ("dtmf-event",
      "type", G_TYPE_INT, 1,
      "number", G_TYPE_INT, event,
      "volume", G_TYPE_INT, 8,
      "start", G_TYPE_BOOLEAN, TRUE,
      NULL);
  gstevent = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, structure);

  if (!gst_element_send_event (priv->dtmfsrc, gstevent))
    g_warning ("DTMF start event wasn't applied");

  structure = gst_structure_new ("dtmf-event",
      "type", G_TYPE_INT, 1,
      "number", G_TYPE_INT, event,
      "volume", G_TYPE_INT, 8,
      "start", G_TYPE_BOOLEAN, FALSE,
      NULL);
  gstevent = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, structure);

  if (!gst_element_send_event (priv->dtmfsrc, gstevent))
    g_warning ("DTMF start event wasn't applied");

  if (g_queue_is_empty (priv->event_queue))
    {
      /* The type argument doubles as both the type of event
       * (RTP or in-band) as well as the PT to use if it's RTP */
      if (type == SKYPE_DTMF_EVENT_TYPE_IN_BAND)
        {
          method = FS_DTMF_METHOD_IN_BAND;
        }
      else if (type == priv->last_telephony_pt)
        {
          /* Play now only if the current PT matches the desired one */
          method = FS_DTMF_METHOD_RTP_RFC4733;
        }
      else
        {
          FsCodec *codec;

          /* Can't play the DTMF event now, queue the event and update codecs */
          DTMFQueueEvent *dtmf_event = g_slice_new0 (DTMFQueueEvent);
          dtmf_event->event_nr = event;
          dtmf_event->rtp_type = type;
          g_queue_push_tail (priv->event_queue, dtmf_event);

          priv->pending_telephony_pt = type;

          /* Trigger a codec update */
          g_object_get (self, "codec", &codec, NULL);
          g_object_set (self, "codec", codec, NULL);
          fs_codec_destroy (codec);
          return ret;
        }
    }
  else
    {
      /* Other events are pending, queue this one */
      DTMFQueueEvent *dtmf_event = g_slice_new0 (DTMFQueueEvent);
      dtmf_event->event_nr = event;
      dtmf_event->rtp_type = type;
      g_queue_push_tail (priv->event_queue, dtmf_event);
      return ret;
    }

  g_object_get (priv->stream, "fsu-session", &session, NULL);

  if (session == NULL)
    {
      g_warning ("SendDTMF: session == NULL");
      return FALSE;
    }

  g_object_get (session, "fs-session", &fssession, NULL);

  g_object_unref (session);

  if (fssession == NULL)
    {
      g_warning ("SendDTMF: fssession == NULL");
      return FALSE;
    }

  /* Play the event */
  if (!fs_session_start_telephony_event (fssession, event, 0, method))
    {
      g_warning ("Telephony event type not supported");
      ret = FALSE;
    }
  else
    {
      fs_session_stop_telephony_event (fssession, method);
    }

  g_object_unref (fssession);
  return ret;
}
Exemplo n.º 13
0
/**
 * validate_codecs_configuration:
 * @media_type: The #FsMediaType these codecs should be for
 * @blueprints: A #GList of #CodecBlueprints to validate the codecs agsint
 * @codecs: a #GList of #FsCodec that represent the preferences
 *
 * This function validates a GList of passed FarsightCodec structures
 * against the valid discovered payloaders
 * It removes all "invalid" codecs from the list, it modifies the list
 * passed in as an argument.
 *
 * Returns: the #GList of #FsCodec minus the invalid ones
 */
GList *
validate_codecs_configuration (FsMediaType media_type, GList *blueprints,
  GList *codecs)
{
  GList *codec_e = codecs;

  while (codec_e)
  {
    FsCodec *codec = codec_e->data;
    GList *blueprint_e = NULL;
    FsCodecParameter *param;

    /* Check if codec is for the wrong media_type.. this would be wrong
     */
    if (media_type != codec->media_type)
      goto remove_this_codec;

    if (codec->id >= 0 && codec->id < 128 && codec->encoding_name &&
        !g_ascii_strcasecmp (codec->encoding_name, "reserve-pt"))
      goto accept_codec;

    for (blueprint_e = g_list_first (blueprints);
         blueprint_e;
         blueprint_e = g_list_next (blueprint_e))
    {
      CodecBlueprint *blueprint = blueprint_e->data;

      /* First, lets check the encoding name */
      if (g_ascii_strcasecmp (blueprint->codec->encoding_name,
              codec->encoding_name))
        continue;
      /* If both have a clock_rate, it must be the same */
      if (blueprint->codec->clock_rate && codec->clock_rate &&
          blueprint->codec->clock_rate != codec->clock_rate)
        continue;
        /* At least one needs to have a clockrate */
      else if (!blueprint->codec->clock_rate && !codec->clock_rate)
        continue;

      if (codec_sdp_compare (blueprint->codec, codec))
        break;
    }

    /* If there are send and/or recv profiles, lets test them */
    param = fs_codec_get_optional_parameter (codec, RECV_PROFILE_ARG, NULL);
    if (param && !validate_codec_profile (codec, param->value, FALSE))
        goto remove_this_codec;

    param = fs_codec_get_optional_parameter (codec, SEND_PROFILE_ARG, NULL);
    if (param && !validate_codec_profile (codec, param->value, TRUE))
      goto remove_this_codec;

    /* If no blueprint was found */
    if (blueprint_e == NULL)
    {
      /* Accept codecs with no blueprints if they have a valid profile */
      if (fs_codec_get_optional_parameter (codec, RECV_PROFILE_ARG, NULL) &&
          codec->encoding_name && codec->clock_rate)
        goto accept_codec;

      goto remove_this_codec;
    }

  accept_codec:
    codec_e = g_list_next (codec_e);

    continue;
  remove_this_codec:
    {
      GList *nextcodec_e = g_list_next (codec_e);
      gchar *tmp = fs_codec_to_string (codec);
      GST_DEBUG ("Preferred codec %s could not be matched with a blueprint",
          tmp);
      g_free (tmp);
      fs_codec_destroy (codec);
      codecs = g_list_delete_link (codecs, codec_e);
      codec_e = nextcodec_e;
    }
  }

  return codecs;
}
Exemplo n.º 14
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;
}
Exemplo n.º 15
0
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;
}
Exemplo n.º 16
0
/**
 * fs_codec_list_from_keyfile
 * @filename: Name of the #GKeyFile to read the codecs parameters from
 * @error: location of a #GError, or NULL if no error occured
 *
 * Reads the content of a #GKeyFile of the following format into
 * a #GList of #FsCodec structures.
 *
 *
 * Example:
 * |[
 * [audio/codec1]
 * clock-rate=8000
 *
 * [audio/codec1:1]
 * clock-rate=16000
 *
 * [audio/codec2]
 * one_param=QCIF
 * another_param=WOW
 * ]|
 *
 * Return value: The #GList of #FsCodec or %NULL if the keyfile was empty
 *  or an error occured.
 */
GList *
fs_codec_list_from_keyfile (const gchar *filename, GError **error)
{
  GKeyFile *keyfile = NULL;
  GList *codecs = NULL;
  GError *gerror = NULL;
  gchar **groups = NULL;
  gsize groups_count = 0;
  int i;

  g_assert (filename);

  keyfile = g_key_file_new ();

  if (!g_key_file_load_from_file (keyfile, filename,
          G_KEY_FILE_NONE, error)) {
    goto out;
  }

  groups = g_key_file_get_groups (keyfile, &groups_count);

  if (!groups)
    goto out;

  for (i=0; i < groups_count && groups[i]; i++) {
    FsCodec *codec = g_slice_new0 (FsCodec);
    gchar **keys = NULL;
    gsize keys_count;
    int j;
    gchar *encoding_name = NULL;
    gchar *next_tok = NULL;

    codec->id = FS_CODEC_ID_ANY;

    keys = g_key_file_get_keys (keyfile, groups[i], &keys_count, &gerror);

    if (!keys || gerror) {
      if (gerror) {
        GST_WARNING ("Unable to read parameters for %s: %s\n",
            groups[i], gerror->message);

      } else {
        GST_WARNING ("Unknown errors while reading parameters for %s",
            groups[i]);
      }
      g_clear_error (&gerror);

      goto next_codec;
    }

    next_tok = strchr (groups[i], '/');
    if (!next_tok) {
      GST_WARNING ("Invalid codec name: %s", groups[i]);
      goto next_codec;
    }

    if ((next_tok - groups[i]) == 5 /* strlen ("audio") */ &&
        !g_ascii_strncasecmp ("audio", groups[i], 5))
      codec->media_type = FS_MEDIA_TYPE_AUDIO;
    else if ((next_tok - groups[i]) == 5 /* strlen ("video") */ &&
        !g_ascii_strncasecmp ("video", groups[i], 5))
      codec->media_type = FS_MEDIA_TYPE_VIDEO;
    else {
      GST_WARNING ("Invalid media type in codec name name %s", groups[i]);
      goto next_codec;
    }

    encoding_name = next_tok+1;

    next_tok = strchr (groups[i], ':');

    if (next_tok) {
      codec->encoding_name = g_strndup (encoding_name,
          next_tok - encoding_name);
    } else {
      codec->encoding_name = g_strdup (encoding_name);
    }

    if (!codec->encoding_name || codec->encoding_name[0] == 0) {
      goto next_codec;
    }

    for (j = 0; j < keys_count && keys[j]; j++) {
      if (!strcmp ("clock-rate", keys[j])) {
        codec->clock_rate = g_key_file_get_integer (keyfile, groups[i], keys[j],
            &gerror);
        if (gerror) {
          codec->clock_rate = 0;
          goto keyerror;
        }

      } else if (!strcmp ("id", keys[j])) {
         codec->id = g_key_file_get_integer (keyfile, groups[i], keys[j],
            &gerror);
        if (gerror) {
          codec->id = FS_CODEC_ID_ANY;
          goto keyerror;
        }

        if (codec->id < 0)
          codec->id = FS_CODEC_ID_DISABLE;

      } else if (!strcmp ("channels", keys[j])) {
         codec->channels = g_key_file_get_integer (keyfile, groups[i], keys[j],
            &gerror);
        if (gerror) {
          codec->channels = 0;
          goto keyerror;
        }

      } else {
        FsCodecParameter *param = g_slice_new (FsCodecParameter);

        param->name = g_strdup (keys[j]);
        param->value = g_key_file_get_string (keyfile, groups[i], keys[j],
            &gerror);
        if (gerror) {
          g_free (param->name);
          g_free (param->value);
          g_slice_free (FsCodecParameter, param);
          goto keyerror;
        }

        if (!param->name || !param->value) {
          g_free (param->name);
          g_free (param->value);
          g_slice_free (FsCodecParameter, param);
        } else {
          codec->optional_params = g_list_append (codec->optional_params,
              param);
        }
      }
      continue;
    keyerror:
      GST_WARNING ("Error reading key %s codec %s: %s", keys[j], groups[i],
          gerror->message);
      g_clear_error (&gerror);

    }

    codecs = g_list_append (codecs, codec);

    g_strfreev (keys);
    continue;
  next_codec:
    fs_codec_destroy (codec);
    g_strfreev (keys);

  }


 out:

  g_strfreev (groups);
  g_key_file_free (keyfile);

  return codecs;
}
/* insert given codec_cap list into list_codecs and list_codec_blueprints */
static void
parse_codec_cap_list (GList *list, FsMediaType media_type)
{
  GList *walk;
  CodecCap *codec_cap;
  FsCodec *codec;
  CodecBlueprint *codec_blueprint;
  gint i;
  gchar *tmp;
  GstElementFactory *tmpfact;

  /* go thru all common caps */
  for (walk = list; walk; walk = g_list_next (walk))
  {
    codec_cap = (CodecCap *)(walk->data);

    codec = g_slice_new0 (FsCodec);
    codec->id = FS_CODEC_ID_ANY;
    codec->clock_rate = 0;

    for (i = 0; i < gst_caps_get_size (codec_cap->rtp_caps); i++)
    {
      GstStructure *structure = gst_caps_get_structure (codec_cap->rtp_caps, i);

      gst_structure_foreach (structure, extract_field_data,
            (gpointer) codec);
    }

    if (!codec->encoding_name)
    {
      GstStructure *caps = gst_caps_get_structure (codec_cap->rtp_caps, 0);
      const gchar *encoding_name = codec->encoding_name ? codec->encoding_name
        : gst_structure_get_string (caps, "encoding-name");

      GST_DEBUG ("skipping codec %s/%s, no encoding name specified"
          " (pt: %d clock_rate:%u",
          media_type == FS_MEDIA_TYPE_AUDIO ? "audio" : "video",
          encoding_name ? encoding_name : "unknown", codec->id,
          codec->clock_rate);

      encoding_name = NULL;
      fs_codec_destroy (codec);
      continue;
    }

    switch (codec->media_type) {
      case FS_MEDIA_TYPE_VIDEO:
        if (!validate_h263_codecs (codec_cap)) {
          fs_codec_destroy (codec);
          continue;
        }
        break;
      case FS_MEDIA_TYPE_AUDIO:
        if (!validate_amr_codecs (codec_cap)) {
          fs_codec_destroy (codec);
          continue;
        }
        break;
      default:
        break;
    }

  another:

    codec_blueprint = g_slice_new0 (CodecBlueprint);
    codec_blueprint->codec = codec;
    codec_blueprint->media_caps = gst_caps_copy (codec_cap->caps);
    codec_blueprint->rtp_caps = gst_caps_copy (codec_cap->rtp_caps);

    codec_blueprint->send_pipeline_factory =
      copy_element_list (codec_cap->element_list2);
    codec_blueprint->receive_pipeline_factory =
      copy_element_list (codec_cap->element_list1);

    /* Lets add the converters at the beginning of the encoding pipelines */
    if (media_type == FS_MEDIA_TYPE_VIDEO)
    {
      tmpfact = gst_element_factory_find ("ffmpegcolorspace");
      if (tmpfact)
      {
        codec_blueprint->send_pipeline_factory = g_list_append (
            codec_blueprint->send_pipeline_factory,
            g_list_append (NULL, tmpfact));
      }
      tmpfact = gst_element_factory_find ("videoscale");
      if (tmpfact)
      {
        codec_blueprint->send_pipeline_factory = g_list_append (
            codec_blueprint->send_pipeline_factory,
            g_list_append (NULL, tmpfact));
      }
    }
    else if (media_type == FS_MEDIA_TYPE_AUDIO)
    {
      tmpfact = gst_element_factory_find ("audioconvert");
      if (tmpfact)
      {
        codec_blueprint->send_pipeline_factory = g_list_append (
            codec_blueprint->send_pipeline_factory,
            g_list_append (NULL, tmpfact));
      }
      tmpfact = gst_element_factory_find ("audioresample");
      if (tmpfact)
      {
        codec_blueprint->send_pipeline_factory = g_list_append (
            codec_blueprint->send_pipeline_factory,
            g_list_append (NULL, tmpfact));
      }
      tmpfact = gst_element_factory_find ("audioconvert");
      if (tmpfact)
      {
        codec_blueprint->send_pipeline_factory = g_list_append (
            codec_blueprint->send_pipeline_factory,
            g_list_append (NULL, tmpfact));
      }
    }

    /* insert new information into tables */
    list_codec_blueprints[media_type] = g_list_append (
        list_codec_blueprints[media_type], codec_blueprint);
    GST_DEBUG ("adding codec %s with pt %d, send_pipeline %p, receive_pipeline %p",
        codec->encoding_name, codec->id,
        codec_blueprint->send_pipeline_factory,
        codec_blueprint->receive_pipeline_factory);
    tmp = gst_caps_to_string (codec_blueprint->media_caps);
    GST_DEBUG ("media_caps: %s", tmp);
    g_free (tmp);
    tmp = gst_caps_to_string (codec_blueprint->rtp_caps);
    GST_DEBUG ("rtp_caps: %s", tmp);
    g_free (tmp);
    debug_pipeline (codec_blueprint->send_pipeline_factory);
    debug_pipeline (codec_blueprint->receive_pipeline_factory);

    if (!g_ascii_strcasecmp (codec->encoding_name, "H263-1998")) {
      codec = fs_codec_copy (codec);
      g_free (codec->encoding_name);
      codec->encoding_name = g_strdup ("H263-N800");
      goto another;
    }
  }
}
Exemplo n.º 18
0
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;
}
Exemplo n.º 19
0
static void
skype_audio_stream_set_property (GObject *object, guint property_id,
    const GValue *value, GParamSpec *pspec)
{
  SkypeAudioStreamPrivate *priv = SKYPE_AUDIO_STREAM (object)->priv;

  switch (property_id)
    {
      case PROP_BITRATE:
        skype_dynamic_properties_set (priv->properties, "bitrate",
            g_value_get_uint (value));
        break;
      case PROP_CHANNEL_ID:
        priv->channel_id = g_value_get_uint (value);
        break;
      case PROP_CONVERSATION_ID:
        priv->conversation_id = g_value_get_uint (value);
        break;
      case PROP_CALL_MEMBER_ID:
        priv->call_member_id = g_value_get_uint (value);
        break;
      case PROP_PTIME:
        {
          FsCodec *codec = NULL;

          priv->ptime = g_value_get_uint (value);

          /* Trigger a codec update */
          g_object_get (object, "codec", &codec, NULL);
          g_object_set (object, "codec", codec, NULL);
          fs_codec_destroy (codec);
        }
        break;
      case PROP_VOLUME:
        {
          priv->volume = g_value_get_double (value);

          if (priv->volume_id != NULL)
            {
              FsuFilterManager *manager;

              g_object_get (G_OBJECT (priv->stream),
                  "filter-manager", &manager, NULL);

              if (manager == NULL)
                {
                  g_warning ("Error fetching FsuFilterManager");
                }
              else
                {
                  FsuFilter *filter;

                  filter = fsu_filter_manager_get_filter_by_id (manager,
                      priv->volume_id);

                  if (filter == NULL)
                    {
                      g_warning ("Error retrieving volume filter");
                    }
                  else
                    {
                      g_object_set (filter, "volume", priv->volume, NULL);
                      g_object_unref (filter);
                    }

                  g_object_unref (manager);
                }
            }
        }
        break;
      default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
    }
}