# HG changeset patch # User jakub.adam@ktknet.cz # Date 1294452820 0 # Node ID 0485aed45f5bac2bbc32218ecc8ddbe299720a66 # Parent 43ab38a1f55c5b8168d0fa783ab3e6e57b92d27d 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 diff -r 43ab38a1f55c -r 0485aed45f5b libpurple/media/backend-fs2.c --- 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) { diff -r 43ab38a1f55c -r 0485aed45f5b libpurple/mediamanager.c --- 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);