[farsight2/master] Release locks while modifying the recv pipeline
Olivier Crête
olivier.crete at collabora.co.uk
Mon Dec 22 18:07:47 PST 2008
---
gst/fsrtpconference/fs-rtp-session.c | 5 +-
gst/fsrtpconference/fs-rtp-substream.c | 113 +++++++++++++++++++++++++-------
2 files changed, 93 insertions(+), 25 deletions(-)
diff --git a/gst/fsrtpconference/fs-rtp-session.c b/gst/fsrtpconference/fs-rtp-session.c
index 69a4f5f..7961a5e 100644
--- a/gst/fsrtpconference/fs-rtp-session.c
+++ b/gst/fsrtpconference/fs-rtp-session.c
@@ -2795,8 +2795,9 @@ fs_rtp_session_substream_set_codec_bin_unlock (FsRtpSession *session,
if (!codecbin)
goto out;
- return fs_rtp_sub_stream_set_codecbin_unlock (substream, ca->codec, codecbin,
- error);
+
+ return fs_rtp_sub_stream_set_codecbin_unlock (substream,
+ fs_codec_copy (ca->codec), codecbin, error);
out:
FS_RTP_SESSION_UNLOCK (session);
diff --git a/gst/fsrtpconference/fs-rtp-substream.c b/gst/fsrtpconference/fs-rtp-substream.c
index 10e543e..eb4a6a5 100644
--- a/gst/fsrtpconference/fs-rtp-substream.c
+++ b/gst/fsrtpconference/fs-rtp-substream.c
@@ -103,8 +103,17 @@ struct _FsRtpSubStreamPrivate {
*/
gulong blocking_id;
+ /* This is protected by the session lock... the caller takes the lock
+ * before updating the property.. yea nasty I know
+ */
gboolean receiving;
+ /* Both of these are session mutex protected */
+ /* This is TRUE while someone is modifying the recv pipeline */
+ gboolean modifying;
+ /* This becomes true when the substream is stopped */
+ gboolean stopped;
+
/* Protected by the this mutex */
GMutex *mutex;
GstClockID no_rtcp_timeout_id;
@@ -149,6 +158,10 @@ fs_rtp_sub_stream_emit_error (FsRtpSubStream *substream,
gchar *debug_msg);
static void
+fs_rtp_sub_stream_try_stop (FsRtpSubStream *substream);
+
+
+static void
fs_rtp_sub_stream_class_init (FsRtpSubStreamClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
@@ -764,7 +777,7 @@ fs_rtp_sub_stream_get_property (GObject *object,
* Add and links the rtpbin for a given substream.
* Removes any codecbin that was previously there.
*
- * This function will swallow one ref to the codecbin
+ * This function will swallow one ref to the codecbin and the codec.x
*
* You must enter this function with the session lock held and it will release
* it.
@@ -784,6 +797,16 @@ fs_rtp_sub_stream_set_codecbin_unlock (FsRtpSubStream *substream,
GstPad *pad;
gboolean codec_changed = TRUE;
+ if (substream->priv->stopped)
+ {
+ 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;
+
if (substream->codec)
{
if (!fs_codec_are_equal (codec, substream->codec))
@@ -792,6 +815,10 @@ fs_rtp_sub_stream_set_codecbin_unlock (FsRtpSubStream *substream,
if (substream->priv->codecbin)
{
+ FsCodec *saved_codec = substream->codec;
+
+ FS_RTP_SESSION_UNLOCK (substream->priv->session);
+
gst_element_set_locked_state (substream->priv->codecbin, TRUE);
if (gst_element_set_state (substream->priv->codecbin, GST_STATE_NULL) !=
GST_STATE_CHANGE_SUCCESS)
@@ -801,7 +828,11 @@ fs_rtp_sub_stream_set_codecbin_unlock (FsRtpSubStream *substream,
"Could not set the codec bin for ssrc %u"
" and payload type %d to the state NULL", substream->ssrc,
substream->pt);
+ substream->priv->modifying = FALSE;
FS_RTP_SESSION_UNLOCK (substream->priv->session);
+ gst_object_unref (codecbin);
+ fs_codec_destroy (codec);
+ fs_rtp_sub_stream_try_stop (substream);
return FALSE;
}
@@ -809,19 +840,29 @@ fs_rtp_sub_stream_set_codecbin_unlock (FsRtpSubStream *substream,
substream->priv->codecbin);
substream->priv->codecbin = NULL;
- fs_codec_destroy (substream->codec);
- substream->codec = NULL;
+ 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_SESSION_UNLOCK (substream->priv->session);
+ substream->priv->modifying = FALSE;
+ fs_rtp_sub_stream_try_stop (substream);
return FALSE;
}
@@ -830,7 +871,7 @@ fs_rtp_sub_stream_set_codecbin_unlock (FsRtpSubStream *substream,
{
g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
"Could not set the codec bin to the playing state");
- goto error_locked;
+ goto error;
}
if (!gst_element_link_pads (codecbin, "src",
@@ -838,7 +879,7 @@ fs_rtp_sub_stream_set_codecbin_unlock (FsRtpSubStream *substream,
{
g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
"Could not link the codec bin to the valve");
- goto error_locked;
+ goto error;
}
if (!gst_element_link_pads (substream->priv->capsfilter, "src",
@@ -847,7 +888,7 @@ fs_rtp_sub_stream_set_codecbin_unlock (FsRtpSubStream *substream,
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_locked;
+ goto error;
}
caps = fs_codec_to_gst_caps (codec);
@@ -861,7 +902,7 @@ fs_rtp_sub_stream_set_codecbin_unlock (FsRtpSubStream *substream,
{
g_set_error (error, FS_ERROR, FS_ERROR_INTERNAL, "Could not get sink pad"
" from codecbin");
- goto error_locked;
+ goto error;
}
/* This is a non-error error
@@ -878,14 +919,16 @@ fs_rtp_sub_stream_set_codecbin_unlock (FsRtpSubStream *substream,
/* We call this to drop all buffers until something comes up */
fs_rtp_sub_stream_add_probe_locked (substream);
- goto error_locked;
+ goto error;
}
gst_object_unref (pad);
+ FS_RTP_SESSION_LOCK (substream->priv->session);
substream->priv->caps = caps;
substream->priv->codecbin = codecbin;
- substream->codec = fs_codec_copy (codec);
+ substream->codec = codec;
+ substream->priv->modifying = FALSE;
if (substream->priv->stream && !substream->priv->output_ghostpad)
{
@@ -899,18 +942,26 @@ fs_rtp_sub_stream_set_codecbin_unlock (FsRtpSubStream *substream,
g_signal_emit (substream, signals[CODEC_CHANGED], 0);
}
- return TRUE;
+ gst_object_unref (codecbin);
- error_locked:
- FS_RTP_SESSION_UNLOCK (substream->priv->session);
+ fs_rtp_sub_stream_try_stop (substream);
+
+ return TRUE;
error:
+ substream->priv->modifying = FALSE;
+
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;
}
@@ -941,15 +992,17 @@ fs_rtp_sub_stream_new (FsRtpConference *conference,
return substream;
}
-/**
- * fs_rtp_sub_stream_stop:
- *
- * Stops all of the elements on a #FsRtpSubstream
- */
-
-void
-fs_rtp_sub_stream_stop (FsRtpSubStream *substream)
+static void
+fs_rtp_sub_stream_try_stop (FsRtpSubStream *substream)
{
+ FS_RTP_SESSION_LOCK (substream->priv->session);
+ if (!substream->priv->stopped || substream->priv->modifying)
+ {
+ FS_RTP_SESSION_UNLOCK (substream->priv->session);
+ return;
+ }
+ FS_RTP_SESSION_UNLOCK (substream->priv->session);
+
if (substream->priv->output_ghostpad)
gst_pad_set_active (substream->priv->output_ghostpad, FALSE);
@@ -959,13 +1012,11 @@ fs_rtp_sub_stream_stop (FsRtpSubStream *substream)
gst_element_set_state (substream->priv->valve, GST_STATE_NULL);
}
- FS_RTP_SESSION_LOCK (substream->priv->session);
if (substream->priv->codecbin)
{
gst_element_set_locked_state (substream->priv->codecbin, TRUE);
gst_element_set_state (substream->priv->codecbin, GST_STATE_NULL);
}
- FS_RTP_SESSION_UNLOCK (substream->priv->session);
if (substream->priv->capsfilter)
{
@@ -974,6 +1025,22 @@ fs_rtp_sub_stream_stop (FsRtpSubStream *substream)
}
}
+/**
+ * fs_rtp_sub_stream_stop:
+ *
+ * Stops all of the elements on a #FsRtpSubstream
+ */
+
+void
+fs_rtp_sub_stream_stop (FsRtpSubStream *substream)
+{
+ FS_RTP_SESSION_LOCK (substream->priv->session);
+ substream->priv->stopped = TRUE;
+ FS_RTP_SESSION_UNLOCK (substream->priv->session);
+
+ fs_rtp_sub_stream_try_stop (substream);
+}
+
/**
* fs_rtp_sub_stream_add_output_ghostpad_unlock:
--
1.5.6.5
More information about the farsight-commits
mailing list