changeset 31105:0485aed45f5b

This patch fixes #12758. If the user starts two parallel video calls, then ends one of them some time later, the user can still see and hear the participant from the non-ended call, but the other participant no longer receives the user's video or audio. The problem lies in purple_media_backend_fs2_dispose(), which calls gst_element_set_state() in such a way that the media sources stop sending data. Additional reference information is mentioned on #12758, comment 6 (http://developer.pidgin.im/ticket/12758#comment:6). committer: John Bailey <rekkanoryo@rekkanoryo.org>
author jakub.adam@ktknet.cz
date Sat, 08 Jan 2011 02:13:40 +0000
parents 43ab38a1f55c
children a063e2a804ff
files libpurple/media/backend-fs2.c libpurple/mediamanager.c
diffstat 2 files changed, 24 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/media/backend-fs2.c	Fri Jan 07 11:42:13 2011 +0000
+++ b/libpurple/media/backend-fs2.c	Sat Jan 08 02:13:40 2011 +0000
@@ -126,6 +126,8 @@
 	GstElement *src;
 	GstElement *tee;
 
+	GstPad *srcpad;
+
 	PurpleMediaSessionType type;
 };
 
@@ -168,6 +170,22 @@
 		pipeline = purple_media_manager_get_pipeline(
 				purple_media_get_manager(priv->media));
 
+		/* All connections to media sources should be blocked before confbin is
+		 * removed, to prevent freezing of any other simultaneously running
+		 * media calls. */
+		if (priv->sessions) {
+			GList *sessions = g_hash_table_get_values(priv->sessions);
+			for (; sessions; sessions =
+					g_list_delete_link(sessions, sessions)) {
+				PurpleMediaBackendFs2Session *session = sessions->data;
+				if (session->srcpad) {
+					gst_pad_set_blocked(session->srcpad, TRUE);
+					gst_object_unref(session->srcpad);
+					session->srcpad = NULL;
+				}
+			}
+		}
+
 		gst_element_set_locked_state(priv->confbin, TRUE);
 		gst_element_set_state(GST_ELEMENT(priv->confbin),
 				GST_STATE_NULL);
@@ -1258,6 +1276,7 @@
 			session_type_to_fs_stream_direction(type);
 	GstElement *src;
 	GstPad *sinkpad, *srcpad;
+	GstPad *ghost = NULL;
 
 	if ((type_direction & FS_DIRECTION_SEND) == 0)
 		return TRUE;
@@ -1297,7 +1316,7 @@
 	if (GST_ELEMENT_PARENT(priv->confbin)
 			== GST_ELEMENT_PARENT(session->src)) {
 		GstPad *pad = gst_element_get_static_pad(session->tee, "sink");
-		GstPad *ghost = gst_ghost_pad_new(NULL, pad);
+		ghost = gst_ghost_pad_new(NULL, pad);
 		gst_object_unref(pad);
 		gst_pad_set_active(ghost, TRUE);
 		gst_element_add_pad(priv->confbin, ghost);
@@ -1305,6 +1324,8 @@
 
 	gst_element_set_state(session->tee, GST_STATE_PLAYING);
 	gst_element_link(session->src, priv->confbin);
+	if (ghost)
+		session->srcpad = gst_pad_get_peer(ghost);
 
 	g_object_get(session->session, "sink-pad", &sinkpad, NULL);
 	if (session->type & PURPLE_MEDIA_SEND_AUDIO) {
--- a/libpurple/mediamanager.c	Fri Jan 07 11:42:13 2011 +0000
+++ b/libpurple/mediamanager.c	Sat Jan 08 02:13:40 2011 +0000
@@ -400,6 +400,8 @@
 	GstIteratorResult result;
 
 	gst_element_release_request_pad(GST_ELEMENT_PARENT(pad), pad);
+	gst_pad_set_blocked(pad, FALSE);
+
 	iter = gst_element_iterate_src_pads(parent);
 
 	result = gst_iterator_next(iter, (gpointer)&remaining_pad);