pidgin: 2096c40a: During a voice call, Pidgin now sends co...

rekkanoryo at pidgin.im rekkanoryo at pidgin.im
Sun Mar 13 15:11:02 EDT 2011


----------------------------------------------------------------------
Revision: 2096c40a83be57e3b90de8440dd125180b4bd4a3
Parent:   a385464438fbed9bb3e15bfb4e7a654b54542b4b
Author:   jakub.adam at ktknet.cz
Date:     03/13/11 14:00:58
Branch:   im.pidgin.pidgin
URL: http://d.pidgin.im/viewmtn/revision/info/2096c40a83be57e3b90de8440dd125180b4bd4a3

Changelog: 

During a voice call, Pidgin now sends constant audio traffic, even when there
is silence. Especially on slower connections, this can waste considerable amount
of bandwidth by transmitting nothing but ambient noise.

I used peak level data from GstLevel? in the input branch of media pipeline to
control a GstValve? put between audio source and Farsight confbin. Whenever the
peak drops below defined threshold, the valve gets closed, when sound level
reaches above the threshold, valve opens again. This effectively blocks sending
data over network in the silent periods and in my tests this simple method
worked quite well.

Silence threshold might need to be fine tuned (or switched off at all) depending
on microphone hardware and/or the noisiness of surrounding environment. I will
propose an user interface for this in a separate ticket.

Future improvement can be adding support for comfort noise (RFC3389), as the
line now stays completely mute when suppression is active, which can be a bit
distracting.

I made a tiny change in level parameter that is passed to PurpleMedia?'s "level"
signal handlers. The value converted from dB to percent was multiplied by five.
Searching through source code history seems this was done to make the value
variation displayed on call dialog level meter widgets look bigger. I think it
is better not to confuse future developers and pass the unmodified percent value
to the handler and multiply only in gtkmedia.c: level_message_cb() where it has
reason.

Changes against parent a385464438fbed9bb3e15bfb4e7a654b54542b4b

  patched  libpurple/media/backend-fs2.c
  patched  libpurple/mediamanager.c
  patched  pidgin/gtkmedia.c

-------------- next part --------------
============================================================
--- libpurple/mediamanager.c	c60fb3ce4321be346e203fcca008a0e75eed0a6e
+++ libpurple/mediamanager.c	26efd3b932f87ae93e7377aca001eb425dc34cc8
@@ -175,6 +175,7 @@ purple_media_manager_init (PurpleMediaMa
 
 	purple_prefs_add_none("/purple/media");
 	purple_prefs_add_none("/purple/media/audio");
+	purple_prefs_add_int("/purple/media/audio/silence_threshold", 5);
 	purple_prefs_add_none("/purple/media/audio/volume");
 	purple_prefs_add_int("/purple/media/audio/volume/input", 10);
 	purple_prefs_add_int("/purple/media/audio/volume/output", 10);
============================================================
--- pidgin/gtkmedia.c	5c7c1695c896d7ae5fb8b7ad7bf9a408d88aaf3c
+++ pidgin/gtkmedia.c	b6495fa912cd05774e057a762a822c681c23d9a4
@@ -363,7 +363,7 @@ level_message_cb(PurpleMedia *media, gch
 		progress = gtkmedia->priv->send_progress;
 	else
 		progress = gtkmedia->priv->recv_progress;
-	gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), level);
+	gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), level * 5);
 }
 
 
============================================================
--- libpurple/media/backend-fs2.c	e7589e51803be693d1682e3a00e89569f9515fe7
+++ libpurple/media/backend-fs2.c	365d32be4d10f4919d04bce39d4fc9b5abc9ad52
@@ -125,6 +125,7 @@ struct _PurpleMediaBackendFs2Session
 
 	GstElement *src;
 	GstElement *tee;
+	GstElement *srcvalve;
 
 	GstPad *srcpad;
 
@@ -142,6 +143,8 @@ struct _PurpleMediaBackendFs2Private
 	GHashTable *participants;
 
 	GList *streams;
+
+	gdouble silence_threshold;
 };
 
 enum {
@@ -153,6 +156,11 @@ purple_media_backend_fs2_init(PurpleMedi
 static void
 purple_media_backend_fs2_init(PurpleMediaBackendFs2 *self)
 {
+	PurpleMediaBackendFs2Private *priv =
+			PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self);
+
+	priv->silence_threshold = purple_prefs_get_int(
+			"/purple/media/audio/silence_threshold") / 100.0;
 }
 
 static gboolean
@@ -766,6 +774,22 @@ get_session_from_fs_stream(PurpleMediaBa
 	return NULL;
 }
 
+static gdouble
+gst_msg_db_to_percent(GstMessage *msg, gchar *value_name)
+{
+	const GValue *list;
+	const GValue *value;
+	gdouble value_db;
+	gdouble percent;
+
+	list = gst_structure_get_value(
+				gst_message_get_structure(msg), value_name);
+	value = gst_value_list_get_value(list, 0);
+	value_db = g_value_get_double(value);
+	percent = pow(10, value_db / 20);
+	return (percent > 1.0) ? 1.0 : percent;
+}
+
 static void
 gst_handle_message_element(GstBus *bus, GstMessage *msg,
 		PurpleMediaBackendFs2 *self)
@@ -778,17 +802,12 @@ gst_handle_message_element(GstBus *bus, 
 	if (level_id == 0)
 		level_id = g_signal_lookup("level", PURPLE_TYPE_MEDIA);
 
-	if (g_signal_has_handler_pending(priv->media, level_id, 0, FALSE)
-			&& gst_structure_has_name(
-			gst_message_get_structure(msg), "level")) {
+	if (gst_structure_has_name(msg->structure, "level")) {
 		GstElement *src = GST_ELEMENT(GST_MESSAGE_SRC(msg));
 		gchar *name;
 		gchar *participant = NULL;
 		PurpleMediaBackendFs2Session *session = NULL;
-		gdouble rms_db;
 		gdouble percent;
-		const GValue *list;
-		const GValue *value;
 
 		if (!PURPLE_IS_MEDIA(priv->media) ||
 				GST_ELEMENT_PARENT(src) != priv->confbin)
@@ -798,7 +817,17 @@ gst_handle_message_element(GstBus *bus, 
 
 		if (!strncmp(name, "sendlevel_", 10)) {
 			session = get_session(self, name+10);
-		} else {
+			percent = gst_msg_db_to_percent(msg, "decay");
+			g_object_set(session->srcvalve,
+					"drop", (percent < priv->silence_threshold), NULL);
+		}
+
+		g_free(name);
+
+		if (!g_signal_has_handler_pending(priv->media, level_id, 0, FALSE))
+			return;
+
+		if (!session) {
 			GList *iter = priv->streams;
 			PurpleMediaBackendFs2Stream *stream;
 			for (; iter; iter = g_list_next(iter)) {
@@ -811,20 +840,11 @@ gst_handle_message_element(GstBus *bus, 
 			}
 		}
 
-		g_free(name);
-
 		if (!session)
 			return;
 
-		list = gst_structure_get_value(
-				gst_message_get_structure(msg), "rms");
-		value = gst_value_list_get_value(list, 0);
-		rms_db = g_value_get_double(value);
-		percent = pow(10, rms_db / 20) * 5;
+		percent = gst_msg_db_to_percent(msg, "rms");
 
-		if(percent > 1.0)
-			percent = 1.0;
-
 		g_signal_emit(priv->media, level_id, 0,
 				session->id, participant, percent);
 		return;
@@ -1376,13 +1396,17 @@ create_src(PurpleMediaBackendFs2 *self, 
 		name = g_strdup_printf("sendlevel_%s", session->id);
 		level = gst_element_factory_make("level", name);
 		g_free(name);
+		session->srcvalve = gst_element_factory_make("valve", NULL);
 		gst_bin_add(GST_BIN(priv->confbin), volume);
 		gst_bin_add(GST_BIN(priv->confbin), level);
+		gst_bin_add(GST_BIN(priv->confbin), session->srcvalve);
 		gst_element_set_state(level, GST_STATE_PLAYING);
 		gst_element_set_state(volume, GST_STATE_PLAYING);
+		gst_element_set_state(session->srcvalve, GST_STATE_PLAYING);
+		gst_element_link(level, session->srcvalve);
 		gst_element_link(volume, level);
 		gst_element_link(session->tee, volume);
-		srcpad = gst_element_get_static_pad(level, "src");
+		srcpad = gst_element_get_static_pad(session->srcvalve, "src");
 		g_object_set(volume, "volume", input_volume, NULL);
 	} else {
 		srcpad = gst_element_get_request_pad(session->tee, "src%d");


More information about the Commits mailing list