[asterisk-commits] dvossel: branch dvossel/hd_conferencing_ftw r307835 - in /team/dvossel/hd_con...
SVN commits to the Asterisk project
asterisk-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 asterisk-commits
mailing list