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); }
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; }
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; }