[svn-commits] file: branch file/bridging r159895 - /team/file/bridging/bridges/
SVN commits to the Digium repositories
svn-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 svn-commits
mailing list