[farsight2/master] Use thread instead of g_timeout for no-rtcp-timeout
Olivier Crête
olivier.crete at collabora.co.uk
Tue Dec 23 15:21:59 PST 2008
---
gst/fsrtpconference/fs-rtp-substream.c | 138 +++++++++++++++++++++++++++-----
1 files changed, 118 insertions(+), 20 deletions(-)
diff --git a/gst/fsrtpconference/fs-rtp-substream.c b/gst/fsrtpconference/fs-rtp-substream.c
index 165fd81..008b597 100644
--- a/gst/fsrtpconference/fs-rtp-substream.c
+++ b/gst/fsrtpconference/fs-rtp-substream.c
@@ -105,10 +105,14 @@ struct _FsRtpSubStreamPrivate {
gboolean receiving;
- gint no_rtcp_timeout;
+ /* Protected by the this mutex */
+ GMutex *mutex;
+ GstClockID no_rtcp_timeout_id;
+ GstClockTime next_no_rtcp_timeout;
+ GThread *no_rtcp_timeout_thread;
- /* Protected by the session mutex */
- gint no_rtcp_timeout_id;
+ /* Protected by the session mutex*/
+ gint no_rtcp_timeout;
GError *construction_error;
};
@@ -122,6 +126,13 @@ G_DEFINE_TYPE(FsRtpSubStream, fs_rtp_sub_stream, G_TYPE_OBJECT);
(G_TYPE_INSTANCE_GET_PRIVATE ((o), FS_TYPE_RTP_SUB_STREAM, \
FsRtpSubStreamPrivate))
+
+#define FS_RTP_SUB_STREAM_LOCK(substream) \
+ g_mutex_lock (substream->priv->mutex)
+#define FS_RTP_SUB_STREAM_UNLOCK(substream) \
+ g_mutex_unlock (substream->priv->mutex)
+
+
static void fs_rtp_sub_stream_dispose (GObject *object);
static void fs_rtp_sub_stream_finalize (GObject *object);
static void fs_rtp_sub_stream_constructed (GObject *object);
@@ -328,23 +339,114 @@ fs_rtp_sub_stream_init (FsRtpSubStream *self)
self->priv = FS_RTP_SUB_STREAM_GET_PRIVATE (self);
self->priv->disposed = FALSE;
self->priv->receiving = TRUE;
+ self->priv->mutex = g_mutex_new ();
}
-static gboolean
-_no_rtcp_timeout (gpointer user_data)
+
+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 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);
- if (self->priv->no_rtcp_timeout_id)
- self->priv->no_rtcp_timeout_id = 0;
+ self->priv->next_no_rtcp_timeout = gst_clock_get_time (sysclock) +
+ (self->priv->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);
- g_signal_emit (self, signals[NO_RTCP_TIMEDOUT], 0);
+ return res;
+}
- return FALSE;
+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)
+ return;
+
+ 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
@@ -395,8 +497,9 @@ fs_rtp_sub_stream_constructed (GObject *object)
}
if (self->priv->no_rtcp_timeout > 0)
- self->priv->no_rtcp_timeout_id = g_timeout_add (self->priv->no_rtcp_timeout,
- _no_rtcp_timeout, self);
+ if (!fs_rtp_sub_stream_start_no_rtcp_timeout_thread (self,
+ &self->priv->construction_error))
+ return;
GST_CALL_PARENT (G_OBJECT_CLASS, constructed, (object));
}
@@ -410,15 +513,7 @@ fs_rtp_sub_stream_dispose (GObject *object)
if (self->priv->disposed)
return;
-
- FS_RTP_SESSION_LOCK (self->priv->session);
- if (self->priv->no_rtcp_timeout_id)
- {
- g_source_remove (self->priv->no_rtcp_timeout_id);
- self->priv->no_rtcp_timeout_id = 0;
- }
- FS_RTP_SESSION_UNLOCK (self->priv->session);
-
+ fs_rtp_sub_stream_stop_no_rtcp_timeout_thread (self);
if (self->priv->output_ghostpad) {
gst_element_remove_pad (GST_ELEMENT (self->priv->conference),
@@ -474,6 +569,9 @@ fs_rtp_sub_stream_finalize (GObject *object)
if (self->priv->codec)
fs_codec_destroy (self->priv->codec);
+ if (self->priv->mutex)
+ g_mutex_free (self->priv->mutex);
+
G_OBJECT_CLASS (fs_rtp_sub_stream_parent_class)->finalize (object);
}
--
1.5.6.5
More information about the farsight-commits
mailing list