[asterisk-commits] file: branch file/bridging r159895 - /team/file/bridging/bridges/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Sun Nov 30 15:09:37 CST 2008


Author: file
Date: Sun Nov 30 15:09:36 2008
New Revision: 159895

URL: http://svn.digium.com/view/asterisk?view=rev&rev=159895
Log:
Use the timing API so we get the best timing source available for mixing in bridge_softmix and doxygenify it a bit.

Modified:
    team/file/bridging/bridges/bridge_softmix.c

Modified: team/file/bridging/bridges/bridge_softmix.c
URL: http://svn.digium.com/view/asterisk/team/file/bridging/bridges/bridge_softmix.c?view=diff&rev=159895&r1=159894&r2=159895
==============================================================================
--- team/file/bridging/bridges/bridge_softmix.c (original)
+++ team/file/bridging/bridges/bridge_softmix.c Sun Nov 30 15:09:36 2008
@@ -24,10 +24,9 @@
  *
  * \ingroup bridges
  *
- * \todo This bridge operates in 16 kHz mode to support wideband conferencing.
- * However, in the case that there are not at least 2 channels on the bridge
- * that support 16 kHz audio, then this should be optimized to fall back to
- * operating in 8 kHz mode.
+ * \todo This bridge operates in 8 kHz mode unless a define is uncommented.
+ * This needs to be improved so the bridge moves between the dominant codec as needed depending
+ * on channels present in the bridge and transcoding capabilities.
  */
 
 #include "asterisk.h"
@@ -50,28 +49,44 @@
 #include "asterisk/logger.h"
 #include "asterisk/slinfactory.h"
 #include "asterisk/astobj2.h"
-
-#define SOFTMIX_INTERVAL 20 /* Valid options are 10, 20, and 30 */
-#define SOFTMIX_SAMPLES (320 * (SOFTMIX_INTERVAL / 10))
-
+#include "asterisk/timing.h"
+
+/*! \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_SAMPLES (160 * (SOFTMIX_INTERVAL / 10))
+
+/*! \brief Define used to turn on 16 kHz audio support */
+/* #define SOFTMIX_16_SUPPORT */
+
+/*! \brief Structure which contains per-channel mixing information */
 struct softmix_channel {
+	/*! Lock to protect this structure */
 	ast_mutex_t lock;
+	/*! Factory which contains audio read in from the channel */
 	struct ast_slinfactory factory;
+	/*! Frame that contains mixed audio to be written out to the channel */
 	struct ast_frame frame;
+	/*! Bit used to indicate that the channel provided audio for this mixing interval */
 	int have_audio:1;
+	/*! 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_SAMPLES];
+	/*! Buffer containing only the audio from the channel */
 	short our_buf[SOFTMIX_SAMPLES];
 };
 
-/* Called when a channel is joined to the bridge. We need to setup a smoother so that frames from all channels will be consistent */
+/*! \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;
 
 	/* Create a new softmix_channel structure and allocate various things on it */
-	if (!(sc = ast_calloc(1, sizeof(*sc))))
+	if (!(sc = ast_calloc(1, sizeof(*sc)))) {
 		return -1;
+	}
 
 	/* Can't forget the lock */
 	ast_mutex_init(&sc->lock);
@@ -81,10 +96,14 @@
 
 	/* Setup frame parameters */
 	sc->frame.frametype = AST_FRAME_VOICE;
+#ifdef SOFTMIX_16_SUPPORT
 	sc->frame.subclass = AST_FORMAT_SLINEAR16;
+#else
+	sc->frame.subclass = AST_FORMAT_SLINEAR;
+#endif
 	sc->frame.data.ptr = sc->final_buf;
-	sc->frame.datalen = sizeof(sc->final_buf);
-	sc->frame.samples = SOFTMIX_SAMPLES;
+	sc->frame.datalen = SOFTMIX_SAMPLES;
+	sc->frame.samples = SOFTMIX_SAMPLES / 2;
 
 	/* Can't forget to record our pvt structure within the bridged channel structure */
 	bridge_channel->bridge_pvt = sc;
@@ -92,7 +111,7 @@
 	return 0;
 }
 
-/* Called when a channel leaves the bridge */
+/*! \brief Function called when a channel leaves the bridge */
 static int softmix_bridge_leave(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 {
 	struct softmix_channel *sc = bridge_channel->bridge_pvt;
@@ -109,20 +128,26 @@
 	return 0;
 }
 
-/* Called when a frame comes from a channel and should go into the bridge */
+/*! \brief Function called when a channel writes a frame into the bridge */
 static enum ast_bridge_write_result softmix_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
 {
 	struct softmix_channel *sc = bridge_channel->bridge_pvt;
 
 	/* Only accept audio frames, all others are unsupported */
-	if (frame->frametype != AST_FRAME_VOICE)
+	if (frame->frametype != AST_FRAME_VOICE) {
 		return AST_BRIDGE_WRITE_UNSUPPORTED;
+	}
 
 	ast_mutex_lock(&sc->lock);
 
 	/* If a frame was provided add it to the smoother */
-	if (frame->frametype == AST_FRAME_VOICE && frame->subclass == AST_FORMAT_SLINEAR16)
+#ifdef SOFTMIX_16_SUPPORT
+	if (frame->frametype == AST_FRAME_VOICE && frame->subclass == AST_FORMAT_SLINEAR16) {
+#else
+	if (frame->frametype == AST_FRAME_VOICE && frame->subclass == AST_FORMAT_SLINEAR) {
+#endif	
 		ast_slinfactory_feed(&sc->factory, frame);
+	}
 	
 	/* If a frame is ready to be written out, do so */
 	if (sc->have_frame) {
@@ -136,7 +161,7 @@
 	return AST_BRIDGE_WRITE_SUCCESS;
 }
 
-/* Called when a bridged channel thread is interrupted */
+/*! \brief Function called when the channel's thread is poked */
 static int softmix_bridge_poke(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 {
 	struct softmix_channel *sc = bridge_channel->bridge_pvt;
@@ -153,22 +178,21 @@
 	return 0;
 }
 
-/* Main bridge thread function */
+/*! \brief Function which acts as the mixing thread */
 static int softmix_bridge_thread(struct ast_bridge *bridge)
 {
-	struct timeval base = ast_tvnow();
-	int skew = 0, previous_skew = 0, last_adjust = 0;
-	ast_cond_t cond;
-	ast_mutex_t lock;
-	
-	ast_cond_init(&cond, NULL);
-	ast_mutex_init(&lock);
+	int timingfd;
+
+	if ((timingfd = ast_timer_open()) < 0) {
+		return -1;
+	}
+
+	ast_timer_set_rate(timingfd, (1000 / SOFTMIX_INTERVAL));
 
 	while (!bridge->stop && !bridge->refresh && bridge->array_num) {
 		struct ast_bridge_channel *bridge_channel = NULL;
 		short buf[SOFTMIX_SAMPLES] = {0, };
-		struct timeval next_wakeup;
-		struct timespec ts = {0, };
+		int timeout = -1;
 
 		/* Go through pulling audio from each factory that has it available */
 		AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
@@ -215,40 +239,16 @@
 
 		ao2_unlock(bridge);
 
-		/* If there is a skew value incorporate it into the base time to adjust for timing */
-		if (previous_skew && skew) {
-			int adjust = abs(skew-previous_skew), new_adjust = 0;
-			if (adjust > 0)
-				new_adjust = abs(adjust-last_adjust);
-			base = ast_tvadd(base, ast_tv(0, ((SOFTMIX_INTERVAL - new_adjust) + SOFTMIX_INTERVAL) * 1000));
-			last_adjust = new_adjust;
-		} else {
-			base = ast_tvadd(base, ast_tv(0, (SOFTMIX_INTERVAL * 2) * 1000));
-		}
-
-		/* Calculate next time until we should wake up */
-		next_wakeup = ast_tvadd(ast_tvnow(), ast_tvsub(base, ast_tvnow()));
-
-		/* Apply this time to the timespec */
-		ts.tv_sec = next_wakeup.tv_sec;
-		ts.tv_nsec = next_wakeup.tv_usec * 1000;
-
-		/* Wait until then */
-		ast_mutex_lock(&lock);
-		ast_cond_timedwait(&cond, &lock, &ts);
-		ast_mutex_unlock(&lock);
-
-		/* Before we calculate the skew value... record the previous one */
-		previous_skew = skew;
-		
-		/* Calculate a skew value (what we wanted versus what we got) */
-		skew = ast_tvdiff_ms(ast_tvnow(), next_wakeup);
+		/* Wait for the timing source to tell us to wake up and get things done */
+		ast_waitfor_n_fd(&timingfd, 1, &timeout, NULL);
+
+		ast_timer_ack(timingfd, 1);
 
 		ao2_lock(bridge);
 	}
 
-	ast_mutex_destroy(&lock);
-	ast_cond_destroy(&cond);
+	ast_timer_set_rate(timingfd, 0);
+	ast_timer_close(timingfd);
 
 	return 0;
 }
@@ -257,7 +257,11 @@
 	.name = "softmix",
 	.capabilities = AST_BRIDGE_CAPABILITY_MULTIMIX | AST_BRIDGE_CAPABILITY_THREAD | AST_BRIDGE_CAPABILITY_MULTITHREADED,
 	.preference = AST_BRIDGE_PREFERENCE_LOW,
+#ifdef SOFTMIX_16_SUPPORT
 	.formats = AST_FORMAT_SLINEAR16,
+#else
+	.formats = AST_FORMAT_SLINEAR,
+#endif
 	.join = softmix_bridge_join,
 	.leave = softmix_bridge_leave,
 	.write = softmix_bridge_write,




More information about the asterisk-commits mailing list