Exemple #1
0
void
fs_rtp_sub_stream_stop (FsRtpSubStream *substream)
{
  FS_RTP_SUB_STREAM_LOCK (substream);
  substream->priv->stopped = TRUE;
  FS_RTP_SUB_STREAM_UNLOCK (substream);

  fs_rtp_sub_stream_try_stop (substream);
}
static gpointer
no_rtcp_timeout_func (gpointer user_data)
{
  FsRtpSubStream *self = FS_RTP_SUB_STREAM (user_data);
  GstClock *sysclock = NULL;
  GstClockID id;
  gboolean emit = TRUE;

  sysclock = gst_system_clock_obtain ();
  if (sysclock == NULL)
    goto no_sysclock;

  FS_RTP_SUB_STREAM_LOCK(self);
  id = self->priv->no_rtcp_timeout_id = gst_clock_new_single_shot_id (sysclock,
      self->priv->next_no_rtcp_timeout);

  FS_RTP_SUB_STREAM_UNLOCK(self);
  gst_clock_id_wait (id, NULL);
  FS_RTP_SUB_STREAM_LOCK(self);

  gst_clock_id_unref (id);
  self->priv->no_rtcp_timeout_id = NULL;

  if (self->priv->next_no_rtcp_timeout == 0)
    emit = FALSE;

  FS_RTP_SUB_STREAM_UNLOCK(self);

  gst_object_unref (sysclock);

  if (emit)
    g_signal_emit (self, signals[NO_RTCP_TIMEDOUT], 0);

  return NULL;

 no_sysclock:
  {
    fs_rtp_sub_stream_emit_error (self, FS_ERROR_INTERNAL,
        "Could not get system clock",
        "Could not get system clock");
    return NULL;
  }
}
static void
fs_rtp_sub_stream_stop_no_rtcp_timeout_thread (FsRtpSubStream *self)
{
  FS_RTP_SUB_STREAM_LOCK(self);
  self->priv->next_no_rtcp_timeout = 0;
  if (self->priv->no_rtcp_timeout_id)
    gst_clock_id_unschedule (self->priv->no_rtcp_timeout_id);

  if (self->priv->no_rtcp_timeout_thread == NULL)
  {
    FS_RTP_SUB_STREAM_UNLOCK(self);
    return;
  }
  else
  {
    FS_RTP_SUB_STREAM_UNLOCK(self);
  }

  g_thread_join (self->priv->no_rtcp_timeout_thread);

  FS_RTP_SUB_STREAM_LOCK(self);
  self->priv->no_rtcp_timeout_thread = NULL;
  FS_RTP_SUB_STREAM_UNLOCK(self);
}
Exemple #4
0
static void
fs_rtp_sub_stream_try_stop (FsRtpSubStream *substream)
{
  FS_RTP_SUB_STREAM_LOCK (substream);
  if (!substream->priv->stopped || substream->priv->modifying)
  {
    FS_RTP_SUB_STREAM_UNLOCK (substream);
    return;
  }
  FS_RTP_SUB_STREAM_UNLOCK (substream);

  if (substream->priv->rtpbin_unlinked_sig) {
    g_signal_handler_disconnect (substream->priv->rtpbin_pad,
        substream->priv->rtpbin_unlinked_sig);
    substream->priv->rtpbin_unlinked_sig = 0;
  }

  gst_pad_set_blocked_async (substream->priv->rtpbin_pad, FALSE,
      do_nothing_blocked_callback, NULL);

  if (substream->priv->output_ghostpad)
    gst_pad_set_active (substream->priv->output_ghostpad, FALSE);

  if (substream->priv->output_valve)
  {
    gst_element_set_locked_state (substream->priv->output_valve, TRUE);
    gst_element_set_state (substream->priv->output_valve, GST_STATE_NULL);
  }

  if (substream->priv->codecbin)
  {
    gst_element_set_locked_state (substream->priv->codecbin, TRUE);
    gst_element_set_state (substream->priv->codecbin, GST_STATE_NULL);
  }

  if (substream->priv->capsfilter)
  {
    gst_element_set_locked_state (substream->priv->capsfilter, TRUE);
    gst_element_set_state (substream->priv->capsfilter, GST_STATE_NULL);
  }

  if (substream->priv->input_valve)
  {
    gst_element_set_locked_state (substream->priv->input_valve, TRUE);
    gst_element_set_state (substream->priv->input_valve, GST_STATE_NULL);
  }
}
static gboolean
fs_rtp_sub_stream_start_no_rtcp_timeout_thread (FsRtpSubStream *self,
    GError **error)
{
  gboolean res = TRUE;
  GstClock *sysclock = NULL;

  sysclock = gst_system_clock_obtain ();
  if (sysclock == NULL)
  {
    g_set_error (error, FS_ERROR, FS_ERROR_INTERNAL,
        "Could not obtain gst system clock");
    return FALSE;
  }

  FS_RTP_SESSION_LOCK (self->priv->session);
  FS_RTP_SUB_STREAM_LOCK(self);

  self->priv->next_no_rtcp_timeout = gst_clock_get_time (sysclock) +
    (self->no_rtcp_timeout * GST_MSECOND);

  gst_object_unref (sysclock);

  if (self->priv->no_rtcp_timeout_thread == NULL) {
    /* only create a new thread if the old one was stopped. Otherwise we can
     * just reuse the currently running one. */
    self->priv->no_rtcp_timeout_thread =
      g_thread_create (no_rtcp_timeout_func, self, TRUE, error);
  }

  res = (self->priv->no_rtcp_timeout_thread != NULL);

  if (res == FALSE && error && *error == NULL)
    g_set_error (error, FS_ERROR, FS_ERROR_INTERNAL, "Unknown error creating"
        " thread");

  FS_RTP_SUB_STREAM_UNLOCK(self);
  FS_RTP_SESSION_UNLOCK (self->priv->session);

  return res;
}
Exemple #6
0
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;
}