maiku.vv: 33c389f2: Wait for Farsight 2's codecs-ready prope...

maiku at soc.pidgin.im maiku at soc.pidgin.im
Thu Sep 4 23:31:27 EDT 2008


-----------------------------------------------------------------
Revision: 33c389f28f8fbefb95f7cf1bc22730ffd1d92bcb
Ancestor: 1423c95edd2cc48f194d3574fc0798cd8249869e
Author: maiku at soc.pidgin.im
Date: 2008-09-05T02:18:15
Branch: im.pidgin.maiku.vv
URL: http://d.pidgin.im/viewmtn/revision/info/33c389f28f8fbefb95f7cf1bc22730ffd1d92bcb

Modified files:
        libpurple/media.c libpurple/media.h
        libpurple/protocols/jabber/jingle.c pidgin/gtkmedia.c

ChangeLog: 

Wait for Farsight 2's codecs-ready property to be TRUE before using codecs.
This will make codecs that need extra configuration, such as THEORA and 
H264, work consistently.

-------------- next part --------------
============================================================
--- libpurple/media.c	941cd561f2aa4fe43bbe9dd8cb0df1ac4d7d56e8
+++ libpurple/media.c	5c6fb6e8b18c47210149f378ad13362893ebd872
@@ -106,6 +106,7 @@ enum {
 	NEW_CANDIDATE,
 	CANDIDATES_PREPARED,
 	CANDIDATE_PAIR,
+	CODECS_READY,
 	LAST_SIGNAL
 };
 static guint purple_media_signals[LAST_SIGNAL] = {0};
@@ -215,6 +216,10 @@ purple_media_class_init (PurpleMediaClas
 					 G_SIGNAL_RUN_LAST, 0, NULL, NULL,
 					 purple_smarshal_VOID__BOXED_BOXED,
 					 G_TYPE_NONE, 2, FS_TYPE_CANDIDATE, FS_TYPE_CANDIDATE);
+	purple_media_signals[CODECS_READY] = g_signal_new("codecs-ready", G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST, 0, NULL, NULL,
+					 g_cclosure_marshal_VOID__STRING,
+					 G_TYPE_NONE, 1, G_TYPE_STRING);
 
 	g_type_class_add_private(klass, sizeof(PurpleMediaPrivate));
 }
@@ -663,6 +668,18 @@ media_bus_call(GstBus *bus, GstMessage *
 				
 			} else if (gst_structure_has_name(msg->structure,
 					"farsight-codecs-changed")) {
+				GList *sessions = g_hash_table_get_values(PURPLE_MEDIA(media)->priv->sessions);
+				FsSession *fssession = g_value_get_object(gst_structure_get_value(msg->structure, "session"));
+				for (; sessions; sessions = g_list_delete_link(sessions, sessions)) {
+					PurpleMediaSession *session = sessions->data;
+					if (session->session == fssession) {
+						g_signal_emit(session->media,
+								purple_media_signals[CODECS_READY],
+								0, &session->id);
+						g_list_free(sessions);
+						break;
+					}
+				}
 			}
 			break;
 		}
@@ -880,7 +897,7 @@ purple_media_video_init_src(GstElement *
 	src = gst_element_factory_make(video_plugin, "purplevideosource");
 	gst_bin_add(GST_BIN(*sendbin), src);
 
-	tee = gst_element_factory_make("tee", NULL);
+	tee = gst_element_factory_make("tee", "purplevideosrctee");
 	gst_bin_add(GST_BIN(*sendbin), tee);
 	gst_element_link(src, tee);
 
@@ -893,13 +910,14 @@ purple_media_video_init_src(GstElement *
 		g_object_set (G_OBJECT(src), "is-live", TRUE, NULL);
 	}
 
-	pad = gst_element_get_pad(queue, "src");
+	pad = gst_element_get_static_pad(queue, "src");
 	ghost = gst_ghost_pad_new("ghostsrc", pad);
+	gst_object_unref(pad);
 	gst_element_add_pad(*sendbin, ghost);
 
-	queue = gst_element_factory_make("queue", NULL);
+	queue = gst_element_factory_make("queue", "purplelocalvideoqueue");
 	gst_bin_add(GST_BIN(*sendbin), queue);
-	gst_element_link(tee, queue);
+	/* The queue is linked later, when the local video is ready to be shown */
 
 	local_sink = gst_element_factory_make("autovideosink", "purplelocalvideosink");
 	gst_bin_add(GST_BIN(*sendbin), local_sink);
@@ -1316,6 +1334,15 @@ purple_media_set_send_codec(PurpleMedia 
 	return TRUE;
 }
 
+gboolean
+purple_media_codecs_ready(PurpleMedia *media, const gchar *sess_id)
+{
+	PurpleMediaSession *session = purple_media_get_session(media, sess_id);
+	gboolean ret;
+	g_object_get(session->session, "codecs-ready", &ret, NULL);
+	return ret;
+}
+
 void purple_media_mute(PurpleMedia *media, gboolean active)
 {
 	GList *sessions = g_hash_table_get_values(media->priv->sessions);
============================================================
--- libpurple/media.h	359360edf6edcbcd4d69e7da23e83f2565a76870
+++ libpurple/media.h	6f2ed391b1ff575ec8d6be06c724c9f607c8ffa6
@@ -472,6 +472,16 @@ gboolean purple_media_set_send_codec(Pur
 gboolean purple_media_set_send_codec(PurpleMedia *media, const gchar *sess_id, FsCodec *codec);
 
 /**
+ * Gets whether a session's codecs are ready to be used.
+ *
+ * @param media The media object to find the session in.
+ * @param sess_id The session id of the session to check.
+ *
+ * @return @c TRUE The codecs are ready, or @c FALSE otherwise.
+ */
+gboolean purple_media_codecs_ready(PurpleMedia *media, const gchar *sess_id);
+
+/**
  * Mutes or unmutes all the audio local audio sources.
  *
  * @param media The media object to mute or unmute
============================================================
--- libpurple/protocols/jabber/jingle.c	c341efe0614b9574529bd2bc864ceb9d386923e8
+++ libpurple/protocols/jabber/jingle.c	670d4292cd432fdf0bbee6dae2a1b999a3868915
@@ -814,7 +814,22 @@ jabber_jingle_session_send_content_accep
 	jabber_iq_send(result);
 }
 #endif
+
 static void
+jabber_jingle_session_accept(JingleSession *session)
+{
+	if (jabber_jingle_session_get_state(session) == ACCEPTED &&
+			purple_media_candidates_prepared(
+				jabber_jingle_session_get_media(session),
+				jabber_jingle_session_get_remote_jid(session))) {
+		jabber_iq_send(jabber_jingle_session_create_session_accept(session));
+		
+		purple_debug_info("jingle", "Sent session accept.\n");
+		jabber_jingle_session_set_state(session, ACTIVE);
+	}
+}
+
+static void
 jabber_jingle_session_send_session_accept(JingleSession *session)
 {
 	/* create transport-info packages */
@@ -843,13 +858,8 @@ jabber_jingle_session_send_session_accep
 				jabber_jingle_session_content_get_name(jsc))));
 	}
 
-	if (purple_media_candidates_prepared(media, remote_jid)) {
-		jabber_iq_send(jabber_jingle_session_create_session_accept(session));
-
-		purple_debug_info("jingle", "Sent session accept.\n");
-		jabber_jingle_session_set_state(session, ACTIVE);
-	} else
-		jabber_jingle_session_set_state(session, ACCEPTED);
+	jabber_jingle_session_set_state(session, ACCEPTED);
+	jabber_jingle_session_accept(session);
 }
 
 static void
@@ -942,17 +952,93 @@ jabber_jingle_session_candidate_pair_est
 						    FsCandidate *remote_candidate,
 						    JingleSession *session)
 {
-	if (!jabber_jingle_session_is_initiator(session) &&
-			jabber_jingle_session_get_state(session) == ACCEPTED &&
-			purple_media_candidates_prepared(media,
-				jabber_jingle_session_get_remote_jid(session))) {
-		jabber_iq_send(jabber_jingle_session_create_session_accept(session));
-		
-		purple_debug_info("jingle", "Sent session accept.\n");
-		jabber_jingle_session_set_state(session, ACTIVE);
+	if (!jabber_jingle_session_is_initiator(session)) {
+		jabber_jingle_session_accept(session);
 	}
 }
 
+static void
+jabber_jingle_session_initiate_result_cb(JabberStream *js, xmlnode *packet, gpointer data)
+{
+	const char *from = xmlnode_get_attrib(packet, "from");
+	JingleSession *session = jabber_jingle_session_find_by_jid(js, from);
+	PurpleMedia *media;
+	GList *contents;
+
+	if (!session) {
+		/* respond with an error here */
+		purple_debug_error("jingle", "Received session-initiate ack"
+				   " to nonexistent session\n");
+		return;
+	}
+
+	media = session->media;
+
+	if (!strcmp(xmlnode_get_attrib(packet, "type"), "error")) {
+		purple_media_got_hangup(media);
+		return;
+	}
+
+	/* catch errors */
+	if (xmlnode_get_child(packet, "error")) {
+		purple_media_got_hangup(media);
+		return;
+	}
+
+	/* create transport-info packages */
+	contents = jabber_jingle_session_get_contents(session);
+	for (; contents; contents = contents->next) {
+		JingleSessionContent *jsc = contents->data;
+		GList *candidates = purple_media_get_local_candidates(
+				jabber_jingle_session_get_media(session),
+				jabber_jingle_session_content_get_name(jsc),
+				jabber_jingle_session_get_remote_jid(session));
+		purple_debug_info("jingle",
+				  "jabber_session_candidates_prepared: %d candidates\n",
+				  g_list_length(candidates));
+		for (; candidates; candidates = candidates->next) {
+			FsCandidate *candidate = candidates->data;
+			JabberIq *result = jabber_jingle_session_create_transport_info(jsc,
+					candidate);
+			jabber_iq_send(result);
+		}
+		fs_candidate_list_destroy(candidates);
+	}
+
+	jabber_jingle_session_set_state(session, GOT_ACK);
+}
+
+static void
+jabber_jingle_session_codecs_ready_cb(PurpleMedia *media,
+				      const gchar *sess_id,
+				      JingleSession *session)
+{
+	GList *contents = jabber_jingle_session_get_contents(session);
+	for (; contents; contents = g_list_delete_link(contents, contents)) {
+		JingleSessionContent *jsc = contents->data;
+		if (!purple_media_codecs_ready(media,
+				jabber_jingle_session_content_get_name(jsc))) {
+			break;
+		}
+	}
+
+	if (contents != NULL)
+		g_list_free(contents);
+	else if (jabber_jingle_session_is_initiator(session)
+			&& jabber_jingle_session_get_state(session) == PENDING) {
+		JabberIq *request;
+
+		/* create request */
+		request = jabber_jingle_session_create_session_initiate(session);
+		jabber_iq_set_callback(request, jabber_jingle_session_initiate_result_cb, NULL);
+
+		/* send request to other part */	
+		jabber_iq_send(request);
+	} else {
+		jabber_jingle_session_accept(session);
+	}
+}
+
 static gboolean
 jabber_jingle_session_initiate_media_internal(JingleSession *session,
 					      const char *initiator,
@@ -1027,69 +1113,19 @@ jabber_jingle_session_initiate_media_int
 				 G_CALLBACK(jabber_jingle_session_new_candidate_cb), session);
 	g_signal_connect(G_OBJECT(media), "candidate-pair", 
 				 G_CALLBACK(jabber_jingle_session_candidate_pair_established_cb), session);
+	g_signal_connect(G_OBJECT(media), "codecs-ready", 
+				 G_CALLBACK(jabber_jingle_session_codecs_ready_cb), session);
 
 	purple_media_ready(media);
 
 	return TRUE;
 }
 
-static void
-jabber_jingle_session_initiate_result_cb(JabberStream *js, xmlnode *packet, gpointer data)
-{
-	const char *from = xmlnode_get_attrib(packet, "from");
-	JingleSession *session = jabber_jingle_session_find_by_jid(js, from);
-	PurpleMedia *media;
-	GList *contents;
-
-	if (!session) {
-		/* respond with an error here */
-		purple_debug_error("jingle", "Received session-initiate ack"
-				   " to nonexistent session\n");
-		return;
-	}
-
-	media = session->media;
-
-	if (!strcmp(xmlnode_get_attrib(packet, "type"), "error")) {
-		purple_media_got_hangup(media);
-		return;
-	}
-
-	/* catch errors */
-	if (xmlnode_get_child(packet, "error")) {
-		purple_media_got_hangup(media);
-		return;
-	}
-
-	/* create transport-info packages */
-	contents = jabber_jingle_session_get_contents(session);
-	for (; contents; contents = contents->next) {
-		JingleSessionContent *jsc = contents->data;
-		GList *candidates = purple_media_get_local_candidates(
-				jabber_jingle_session_get_media(session),
-				jabber_jingle_session_content_get_name(jsc),
-				jabber_jingle_session_get_remote_jid(session));
-		purple_debug_info("jingle",
-				  "jabber_session_candidates_prepared: %d candidates\n",
-				  g_list_length(candidates));
-		for (; candidates; candidates = candidates->next) {
-			FsCandidate *candidate = candidates->data;
-			JabberIq *result = jabber_jingle_session_create_transport_info(jsc,
-					candidate);
-			jabber_iq_send(result);
-		}
-		fs_candidate_list_destroy(candidates);
-	}
-
-	jabber_jingle_session_set_state(session, GOT_ACK);
-}
-
 PurpleMedia *
 jabber_jingle_session_initiate_media(JabberStream *js, const char *who, 
 				     PurpleMediaSessionType type)
 {
 	/* create content negotiation */
-	JabberIq *request;
 	JingleSession *session;
 	JabberBuddy *jb;
 	JabberBuddyResource *jbr;
@@ -1129,13 +1165,6 @@ jabber_jingle_session_initiate_media(Jab
 	g_free(jid);
 	g_free(me);
 
-	/* create request */
-	request = jabber_jingle_session_create_session_initiate(session);
-	jabber_iq_set_callback(request, jabber_jingle_session_initiate_result_cb, NULL);
-
-	/* send request to other part */	
-	jabber_iq_send(request);
-
 	return session->media;
 }
 
============================================================
--- pidgin/gtkmedia.c	fc5dafd0e42a74ca0411894d4cc2b2029a4d2619
+++ pidgin/gtkmedia.c	e6bdc85a826b2957d8bffc0e428f9e3f20b442a6
@@ -314,18 +314,18 @@ pidgin_media_ready_cb(PurpleMedia *media
 			if (!audiosendbin && (type & PURPLE_MEDIA_SEND_AUDIO)) {
 				purple_media_audio_init_src(&audiosendbin, &audiosendlevel);
 				purple_media_set_src(media, sessions->data, audiosendbin);
-				gst_element_set_state(audiosendbin, GST_STATE_READY);
+				gst_element_set_state(audiosendbin, GST_STATE_PLAYING);
 			}
 			if (!audiorecvbin && (type & PURPLE_MEDIA_RECV_AUDIO)) {
 				purple_media_audio_init_recv(&audiorecvbin, &audiorecvlevel);
 				purple_media_set_sink(media, sessions->data, audiorecvbin);
 				gst_element_set_state(audiorecvbin, GST_STATE_READY);
 			}
-		} else if (purple_media_get_session_type(media, sessions->data) & PURPLE_MEDIA_VIDEO) {
+		} else if (type & PURPLE_MEDIA_VIDEO) {
 			if (!videosendbin && (type & PURPLE_MEDIA_SEND_VIDEO)) {
 				purple_media_video_init_src(&videosendbin);
 				purple_media_set_src(media, sessions->data, videosendbin);
-				gst_element_set_state(videosendbin, GST_STATE_READY);
+				gst_element_set_state(videosendbin, GST_STATE_PLAYING);
 			}
 			if (!videorecvbin && (type & PURPLE_MEDIA_RECV_VIDEO)) {
 				purple_media_video_init_recv(&videorecvbin);
@@ -401,6 +401,7 @@ pidgin_media_accept_cb(PurpleMedia *medi
 	if (videosendbin) {
 		GtkWidget *aspect;
 		GtkWidget *local_video;
+		GstElement *tee, *queue;
 
 		aspect = gtk_aspect_frame_new(NULL, 0.5, 0.5, 4.0/3.0, FALSE);
 		gtk_frame_set_shadow_type(GTK_FRAME(aspect), GTK_SHADOW_IN);
@@ -414,7 +415,11 @@ pidgin_media_accept_cb(PurpleMedia *medi
 
 		gtkmedia->priv->local_video = local_video;
 
-		gst_element_set_state(videosendbin, GST_STATE_PLAYING);
+		tee = gst_bin_get_by_name(GST_BIN(videosendbin), "purplevideosrctee");
+		queue = gst_bin_get_by_name(GST_BIN(videosendbin), "purplelocalvideoqueue");
+		gst_element_link(tee, queue);
+		gst_object_unref(tee);
+		gst_object_unref(queue);
 	}
 
 	if (audiorecvbin) {
@@ -435,7 +440,6 @@ pidgin_media_accept_cb(PurpleMedia *medi
 		gtk_box_pack_end(GTK_BOX(send_widget),
 				   gtkmedia->priv->send_progress, FALSE, FALSE, 0);
 		gtk_widget_show(gtkmedia->priv->send_progress);
-		gst_element_set_state(audiosendbin, GST_STATE_PLAYING);
 
 		gtk_widget_show(gtkmedia->priv->mute);
 	}


More information about the Commits mailing list