[svn-commits] dvossel: branch dvossel/hd_conferencing_ftw r307835 - in /team/dvossel/hd_con...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Mon Feb 14 17:11:18 CST 2011


Author: dvossel
Date: Mon Feb 14 17:11:14 2011
New Revision: 307835

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=307835
Log:
ConfBridge now dynamically jumps to the best sample rate as people join and leave

Supports 8khz-96khz.  I could not justify the audio buffer required for 192khz.

Modified:
    team/dvossel/hd_conferencing_ftw/bridges/bridge_multiplexed.c
    team/dvossel/hd_conferencing_ftw/bridges/bridge_softmix.c
    team/dvossel/hd_conferencing_ftw/include/asterisk/slinfactory.h
    team/dvossel/hd_conferencing_ftw/main/slinfactory.c

Modified: team/dvossel/hd_conferencing_ftw/bridges/bridge_multiplexed.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/hd_conferencing_ftw/bridges/bridge_multiplexed.c?view=diff&rev=307835&r1=307834&r2=307835
==============================================================================
--- team/dvossel/hd_conferencing_ftw/bridges/bridge_multiplexed.c (original)
+++ team/dvossel/hd_conferencing_ftw/bridges/bridge_multiplexed.c Mon Feb 14 17:11:14 2011
@@ -219,6 +219,9 @@
 		winner = ast_waitfor_nandfds(multiplexed_thread->chans, multiplexed_thread->service_count, &fds, 1, NULL, &outfd, &to);
 		multiplexed_thread->waiting = 0;
 		ao2_lock(multiplexed_thread);
+		if (multiplexed_thread->thread == AST_PTHREADT_STOP) {
+			break;
+		}
 
 		if (outfd > -1) {
 			int nudge;
@@ -230,7 +233,21 @@
 			}
 		}
 		if (winner && winner->bridge) {
-			ast_bridge_handle_trip(winner->bridge, NULL, winner, -1);
+			struct ast_bridge *bridge = winner->bridge;
+			int stop = 0;
+			ao2_unlock(multiplexed_thread);
+			while ((bridge = winner->bridge) && ao2_trylock(bridge)) {
+				sched_yield();
+				if (multiplexed_thread->thread == AST_PTHREADT_STOP) {
+					stop = 1;
+					break;
+				}
+			}
+			if (!stop && bridge) {
+				ast_bridge_handle_trip(bridge, NULL, winner, -1);
+				ao2_unlock(winner->bridge);
+			}
+			ao2_lock(multiplexed_thread);
 		}
 	}
 

Modified: team/dvossel/hd_conferencing_ftw/bridges/bridge_softmix.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/hd_conferencing_ftw/bridges/bridge_softmix.c?view=diff&rev=307835&r1=307834&r2=307835
==============================================================================
--- team/dvossel/hd_conferencing_ftw/bridges/bridge_softmix.c (original)
+++ team/dvossel/hd_conferencing_ftw/bridges/bridge_softmix.c Mon Feb 14 17:11:14 2011
@@ -52,14 +52,19 @@
 #include "asterisk/astobj2.h"
 #include "asterisk/timing.h"
 
+/*! Max sample rate */
+#define MAX_RATE 96000
+
+#define MAX_DATALEN 1920
+
 /*! \brief Interval at which mixing will take place. Valid options are 10, 20, and 40. */
 #define SOFTMIX_INTERVAL 20
 
 /*! \brief Size of the buffer used for sample manipulation */
-#define SOFTMIX_DATALEN (160 * (SOFTMIX_INTERVAL / 10))
+#define SOFTMIX_DATALEN(rate) ((rate/50) * (SOFTMIX_INTERVAL / 10))
 
 /*! \brief Number of samples we are dealing with */
-#define SOFTMIX_SAMPLES (SOFTMIX_DATALEN / 2)
+#define SOFTMIX_SAMPLES(rate) (SOFTMIX_DATALEN(rate) / 2)
 
 /*! \brief Define used to turn on 16 kHz audio support */
 /* #define SOFTMIX_16_SUPPORT */
@@ -77,40 +82,93 @@
 	/*! Bit used to indicate that a frame is available to be written out to the channel */
 	int have_frame:1;
 	/*! Buffer containing final mixed audio from all sources */
-	short final_buf[SOFTMIX_DATALEN];
+	short final_buf[MAX_DATALEN];
 	/*! Buffer containing only the audio from the channel */
-	short our_buf[SOFTMIX_DATALEN];
+	short our_buf[MAX_DATALEN];
+};
+
+struct softmix_bridge_data {
+	struct ast_timer *timer;
+	int internal_rate;
 };
 
 /*! \brief Function called when a bridge is created */
 static int softmix_bridge_create(struct ast_bridge *bridge)
 {
-	struct ast_timer *timer;
-
-	if (!(timer = ast_timer_open())) {
+	struct softmix_bridge_data *bridge_data;
+
+	if (!(bridge_data = ast_calloc(1, sizeof(struct softmix_bridge_data)))) {
 		return -1;
 	}
-
-	bridge->bridge_pvt = timer;
-
+	if (!(bridge_data->timer = ast_timer_open())) {
+		ast_free(bridge_data);
+		return -1;
+	}
+
+	/* start at 8khz, let it grow from there */
+	bridge_data->internal_rate = 8000;
+
+	bridge->bridge_pvt = bridge_data;
 	return 0;
 }
 
 /*! \brief Function called when a bridge is destroyed */
 static int softmix_bridge_destroy(struct ast_bridge *bridge)
 {
+	struct softmix_bridge_data *bridge_data = bridge->bridge_pvt;
 	if (!bridge->bridge_pvt) {
 		return -1;
 	}
-	ast_timer_close((struct ast_timer *) bridge->bridge_pvt);
-
-	return 0;
+	ast_timer_close(bridge_data->timer);
+	ast_free(bridge_data);
+	return 0;
+}
+
+static enum ast_format_id slin_by_rate(int rate) {
+	if (rate >= 96000) {
+		return AST_FORMAT_SLINEAR96;
+	} else if (rate >= 48000) {
+		return AST_FORMAT_SLINEAR48;
+	} else if (rate >= 44100) {
+		return AST_FORMAT_SLINEAR44;
+	} else if (rate >= 32000) {
+		return AST_FORMAT_SLINEAR32;
+	} else if (rate >= 24000) {
+		return AST_FORMAT_SLINEAR24;
+	} else if (rate >= 16000) {
+		return AST_FORMAT_SLINEAR16;
+	} else if (rate >= 12000) {
+		return AST_FORMAT_SLINEAR12;
+	}
+	return AST_FORMAT_SLINEAR;
+}
+
+static void set_softmix_bridge_data(int rate, struct ast_bridge_channel *bridge_channel, int reset)
+{
+	struct softmix_channel *sc = bridge_channel->bridge_pvt;
+	if (reset) {
+		ast_slinfactory_destroy(&sc->factory);
+	}
+	/* Setup frame parameters */
+	sc->frame.frametype = AST_FRAME_VOICE;
+
+	ast_format_set(&sc->frame.subclass.format, slin_by_rate(rate), 0);
+	sc->frame.data.ptr = sc->final_buf;
+	sc->frame.datalen = SOFTMIX_DATALEN(rate);
+	sc->frame.samples = SOFTMIX_SAMPLES(rate);
+
+	/* Setup smoother */
+	ast_slinfactory_init_with_format(&sc->factory, &sc->frame.subclass.format);
+
+	ast_set_read_format(bridge_channel->chan, &sc->frame.subclass.format);
+	ast_set_write_format(bridge_channel->chan, &sc->frame.subclass.format);
 }
 
 /*! \brief Function called when a channel is joined into the bridge */
 static int softmix_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 {
 	struct softmix_channel *sc = NULL;
+	struct softmix_bridge_data *bridge_data = bridge->bridge_pvt;
 
 	/* Create a new softmix_channel structure and allocate various things on it */
 	if (!(sc = ast_calloc(1, sizeof(*sc)))) {
@@ -120,22 +178,10 @@
 	/* Can't forget the lock */
 	ast_mutex_init(&sc->lock);
 
-	/* Setup smoother */
-	ast_slinfactory_init(&sc->factory);
-
-	/* Setup frame parameters */
-	sc->frame.frametype = AST_FRAME_VOICE;
-#ifdef SOFTMIX_16_SUPPORT
-	ast_format_set(&sc->frame.subclass.format, AST_FORMAT_SLINEAR16, 0);
-#else
-	ast_format_set(&sc->frame.subclass.format, AST_FORMAT_SLINEAR, 0);
-#endif
-	sc->frame.data.ptr = sc->final_buf;
-	sc->frame.datalen = SOFTMIX_DATALEN;
-	sc->frame.samples = SOFTMIX_SAMPLES;
-
 	/* Can't forget to record our pvt structure within the bridged channel structure */
 	bridge_channel->bridge_pvt = sc;
+
+	set_softmix_bridge_data(bridge_data->internal_rate, bridge_channel, 0);
 
 	return 0;
 }
@@ -170,11 +216,7 @@
 	ast_mutex_lock(&sc->lock);
 
 	/* If a frame was provided add it to the smoother */
-#ifdef SOFTMIX_16_SUPPORT
-	if (frame->frametype == AST_FRAME_VOICE && frame->subclass.format.id == AST_FORMAT_SLINEAR16) {
-#else
-	if (frame->frametype == AST_FRAME_VOICE && frame->subclass.format.id == AST_FORMAT_SLINEAR) {
-#endif
+	if (frame->frametype == AST_FRAME_VOICE && ast_format_is_slinear(&frame->subclass.format)) {
 		ast_slinfactory_feed(&sc->factory, frame);
 	}
 
@@ -210,29 +252,43 @@
 /*! \brief Function which acts as the mixing thread */
 static int softmix_bridge_thread(struct ast_bridge *bridge)
 {
-	struct ast_timer *timer = (struct ast_timer *) bridge->bridge_pvt;
+	struct softmix_bridge_data *bridge_data = bridge->bridge_pvt;
+	struct ast_timer *timer = bridge_data->timer;
 	int timingfd = ast_timer_fd(timer);
+	int update_all_rates = 0; /* set this when the internal sample rate has changed */
 
 	ast_timer_set_rate(timer, (1000 / SOFTMIX_INTERVAL));
 
 	while (!bridge->stop && !bridge->refresh && bridge->array_num) {
 		struct ast_bridge_channel *bridge_channel = NULL;
-		short buf[SOFTMIX_DATALEN] = {0, };
+		short buf[MAX_DATALEN] = {0, };
 		int timeout = -1;
+
+		/* these variables help determine if a rate change is required */
+		int highest_supported_rate = 8000;
+		int num_above_internal_rate = 0;
+		int num_below_internal_rate = 0;
+		int num_at_internal_rate = 0;
 
 		/* Go through pulling audio from each factory that has it available */
 		AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
 			struct softmix_channel *sc = bridge_channel->bridge_pvt;
+			int channel_native_rate;
 
 			ast_mutex_lock(&sc->lock);
 
+			if (update_all_rates) {
+				set_softmix_bridge_data(bridge_data->internal_rate, bridge_channel, 1);
+			}
+
 			/* Try to get audio from the factory if available */
-			if (ast_slinfactory_available(&sc->factory) >= SOFTMIX_SAMPLES && ast_slinfactory_read(&sc->factory, sc->our_buf, SOFTMIX_SAMPLES)) {
+			if (ast_slinfactory_available(&sc->factory) >= SOFTMIX_SAMPLES(bridge_data->internal_rate) &&
+				ast_slinfactory_read(&sc->factory, sc->our_buf, SOFTMIX_SAMPLES(bridge_data->internal_rate))) {
 				short *data1, *data2;
 				int i;
 
 				/* Put into the local final buffer */
-				for (i = 0, data1 = buf, data2 = sc->our_buf; i < SOFTMIX_DATALEN; i++, data1++, data2++)
+				for (i = 0, data1 = buf, data2 = sc->our_buf; i < SOFTMIX_DATALEN(bridge_data->internal_rate); i++, data1++, data2++)
 					ast_slinear_saturated_add(data1, data2);
 				/* Yay we have our own audio */
 				sc->have_audio = 1;
@@ -240,6 +296,21 @@
 				/* Awww we don't have audio ;( */
 				sc->have_audio = 0;
 			}
+
+			/* Gather stats about channel sample rates.  */
+			channel_native_rate = MAX(ast_format_rate(&bridge_channel->chan->rawwriteformat),
+				ast_format_rate(&bridge_channel->chan->rawreadformat));
+			if (channel_native_rate > highest_supported_rate) {
+				highest_supported_rate = channel_native_rate;
+			}
+			if (channel_native_rate > bridge_data->internal_rate) {
+				num_above_internal_rate++;
+			} else if (channel_native_rate == bridge_data->internal_rate) {
+				num_at_internal_rate++;
+			} else if (channel_native_rate < bridge_data->internal_rate) {
+				num_below_internal_rate++;
+			}
+
 			ast_mutex_unlock(&sc->lock);
 		}
 
@@ -253,7 +324,7 @@
 
 			/* If we provided audio then take it out */
 			if (sc->have_audio) {
-				for (i = 0; i < SOFTMIX_DATALEN; i++) {
+				for (i = 0; i < SOFTMIX_DATALEN(bridge_data->internal_rate); i++) {
 					ast_slinear_saturated_subtract(&sc->final_buf[i], &sc->our_buf[i]);
 				}
 			}
@@ -265,6 +336,18 @@
 			pthread_kill(bridge_channel->thread, SIGURG);
 		}
 
+		/* Re-adjust the internal bridge sample rate if
+		 * 1. two or more channels support a higher sample rate
+		 * 2. no channels support the current sample rate or a higher rate
+		 */
+		if ((num_above_internal_rate >= 2) ||
+			(!num_at_internal_rate && !num_above_internal_rate)) {
+			update_all_rates = 1;
+			ast_log(LOG_NOTICE, " UPDATED FROM %d to %d\n", bridge_data->internal_rate, highest_supported_rate);
+			bridge_data->internal_rate = highest_supported_rate;
+		} else {
+			update_all_rates = 0;
+		}
 		ao2_unlock(bridge);
 
 		/* Wait for the timing source to tell us to wake up and get things done */

Modified: team/dvossel/hd_conferencing_ftw/include/asterisk/slinfactory.h
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/hd_conferencing_ftw/include/asterisk/slinfactory.h?view=diff&rev=307835&r1=307834&r2=307835
==============================================================================
--- team/dvossel/hd_conferencing_ftw/include/asterisk/slinfactory.h (original)
+++ team/dvossel/hd_conferencing_ftw/include/asterisk/slinfactory.h Mon Feb 14 17:11:14 2011
@@ -56,11 +56,11 @@
  * \brief Initialize a slinfactory
  *
  * \param sf The slinfactory to initialize
- * \param sample_rate The output sample rate desired
+ * \param slin_out the slinear output format desired.
  *
  * \return 0 on success, non-zero on failure
  */
-int ast_slinfactory_init_rate(struct ast_slinfactory *sf, unsigned int sample_rate);
+int ast_slinfactory_init_with_format(struct ast_slinfactory *sf, const struct ast_format *slin_out);
 
 /*!
  * \brief Destroy the contents of a slinfactory

Modified: team/dvossel/hd_conferencing_ftw/main/slinfactory.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/hd_conferencing_ftw/main/slinfactory.c?view=diff&rev=307835&r1=307834&r2=307835
==============================================================================
--- team/dvossel/hd_conferencing_ftw/main/slinfactory.c (original)
+++ team/dvossel/hd_conferencing_ftw/main/slinfactory.c Mon Feb 14 17:11:14 2011
@@ -39,20 +39,14 @@
 	ast_format_set(&sf->output_format, AST_FORMAT_SLINEAR, 0);
 }
 
-int ast_slinfactory_init_rate(struct ast_slinfactory *sf, unsigned int sample_rate) 
+int ast_slinfactory_init_with_format(struct ast_slinfactory *sf, const struct ast_format *slin_out)
 {
 	memset(sf, 0, sizeof(*sf));
 	sf->offset = sf->hold;
-	switch (sample_rate) {
-	case 8000:
-		ast_format_set(&sf->output_format, AST_FORMAT_SLINEAR, 0);
-		break;
-	case 16000:
-		ast_format_set(&sf->output_format, AST_FORMAT_SLINEAR16, 0);
-		break;
-	default:
+	if (!ast_format_is_slinear(slin_out)) {
 		return -1;
 	}
+	ast_format_copy(&sf->output_format, slin_out);
 
 	return 0;
 }




More information about the svn-commits mailing list