Multi-party software based channel mixing. More...
#include "asterisk.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/time.h>#include <signal.h>#include <errno.h>#include <unistd.h>#include "asterisk/module.h"#include "asterisk/channel.h"#include "asterisk/bridging.h"#include "asterisk/bridging_technology.h"#include "asterisk/frame.h"#include "asterisk/options.h"#include "asterisk/logger.h"#include "asterisk/slinfactory.h"#include "asterisk/astobj2.h"#include "asterisk/timing.h"
Go to the source code of this file.
Data Structures | |
| struct | softmix_channel |
| Define used to turn on 16 kHz audio support. More... | |
Defines | |
| #define | SOFTMIX_DATALEN (160 * (SOFTMIX_INTERVAL / 10)) |
| Size of the buffer used for sample manipulation. | |
| #define | SOFTMIX_INTERVAL 20 |
| Interval at which mixing will take place. Valid options are 10, 20, and 40. | |
| #define | SOFTMIX_SAMPLES (SOFTMIX_DATALEN / 2) |
| Number of samples we are dealing with. | |
Functions | |
| static void | __reg_module (void) |
| static void | __unreg_module (void) |
| static int | load_module (void) |
| static int | softmix_bridge_create (struct ast_bridge *bridge) |
| Function called when a bridge is created. | |
| static int | softmix_bridge_destroy (struct ast_bridge *bridge) |
| Function called when a bridge is destroyed. | |
| static int | softmix_bridge_join (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel) |
| Function called when a channel is joined into the bridge. | |
| static int | softmix_bridge_leave (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel) |
| Function called when a channel leaves the bridge. | |
| static int | softmix_bridge_poke (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel) |
| Function called when the channel's thread is poked. | |
| static int | softmix_bridge_thread (struct ast_bridge *bridge) |
| Function which acts as the mixing thread. | |
| static enum ast_bridge_write_result | softmix_bridge_write (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame) |
| Function called when a channel writes a frame into the bridge. | |
| static int | unload_module (void) |
Variables | |
| static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Multi-party software based channel mixing" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| static struct ast_bridge_technology | softmix_bridge |
Multi-party software based channel mixing.
Definition in file bridge_softmix.c.
| #define SOFTMIX_DATALEN (160 * (SOFTMIX_INTERVAL / 10)) |
Size of the buffer used for sample manipulation.
Definition at line 63 of file bridge_softmix.c.
Referenced by softmix_bridge_join(), and softmix_bridge_thread().
| #define SOFTMIX_INTERVAL 20 |
Interval at which mixing will take place. Valid options are 10, 20, and 40.
Definition at line 60 of file bridge_softmix.c.
Referenced by softmix_bridge_thread().
| #define SOFTMIX_SAMPLES (SOFTMIX_DATALEN / 2) |
Number of samples we are dealing with.
Definition at line 66 of file bridge_softmix.c.
Referenced by softmix_bridge_join(), and softmix_bridge_thread().
| static void __reg_module | ( | void | ) | [static] |
Definition at line 313 of file bridge_softmix.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 313 of file bridge_softmix.c.
| static int load_module | ( | void | ) | [static] |
Definition at line 308 of file bridge_softmix.c.
References ast_bridge_technology_register.
{
return ast_bridge_technology_register(&softmix_bridge);
}
| static int softmix_bridge_create | ( | struct ast_bridge * | bridge | ) | [static] |
Function called when a bridge is created.
Definition at line 90 of file bridge_softmix.c.
References ast_timer_open(), ast_bridge::bridge_pvt, and timer.
{
struct ast_timer *timer;
if (!(timer = ast_timer_open())) {
return -1;
}
bridge->bridge_pvt = timer;
return 0;
}
| static int softmix_bridge_destroy | ( | struct ast_bridge * | bridge | ) | [static] |
Function called when a bridge is destroyed.
Definition at line 104 of file bridge_softmix.c.
References ast_timer_close(), and ast_bridge::bridge_pvt.
{
if (!bridge->bridge_pvt) {
return -1;
}
ast_timer_close((struct ast_timer *) bridge->bridge_pvt);
return 0;
}
| static int softmix_bridge_join | ( | struct ast_bridge * | bridge, |
| struct ast_bridge_channel * | bridge_channel | ||
| ) | [static] |
Function called when a channel is joined into the bridge.
Definition at line 115 of file bridge_softmix.c.
References ast_calloc, AST_FORMAT_SLINEAR, AST_FORMAT_SLINEAR16, AST_FRAME_VOICE, ast_mutex_init, ast_slinfactory_init(), ast_bridge_channel::bridge_pvt, ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, softmix_channel::factory, softmix_channel::final_buf, softmix_channel::frame, ast_frame::frametype, softmix_channel::lock, ast_frame::ptr, ast_frame::samples, SOFTMIX_DATALEN, SOFTMIX_SAMPLES, and ast_frame::subclass.
{
struct softmix_channel *sc = NULL;
/* Create a new softmix_channel structure and allocate various things on it */
if (!(sc = ast_calloc(1, sizeof(*sc)))) {
return -1;
}
/* 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
sc->frame.subclass.codec = AST_FORMAT_SLINEAR16;
#else
sc->frame.subclass.codec = AST_FORMAT_SLINEAR;
#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;
return 0;
}
| static int softmix_bridge_leave | ( | struct ast_bridge * | bridge, |
| struct ast_bridge_channel * | bridge_channel | ||
| ) | [static] |
Function called when a channel leaves the bridge.
Definition at line 148 of file bridge_softmix.c.
References ast_free, ast_mutex_destroy, ast_slinfactory_destroy(), ast_bridge_channel::bridge_pvt, softmix_channel::factory, and softmix_channel::lock.
{
struct softmix_channel *sc = bridge_channel->bridge_pvt;
/* Drop mutex lock */
ast_mutex_destroy(&sc->lock);
/* Drop the factory */
ast_slinfactory_destroy(&sc->factory);
/* Eep! drop ourselves */
ast_free(sc);
return 0;
}
| static int softmix_bridge_poke | ( | struct ast_bridge * | bridge, |
| struct ast_bridge_channel * | bridge_channel | ||
| ) | [static] |
Function called when the channel's thread is poked.
Definition at line 198 of file bridge_softmix.c.
References ast_mutex_lock, ast_mutex_unlock, ast_write(), ast_bridge_channel::bridge_pvt, ast_bridge_channel::chan, softmix_channel::frame, softmix_channel::have_frame, and softmix_channel::lock.
{
struct softmix_channel *sc = bridge_channel->bridge_pvt;
ast_mutex_lock(&sc->lock);
if (sc->have_frame) {
ast_write(bridge_channel->chan, &sc->frame);
sc->have_frame = 0;
}
ast_mutex_unlock(&sc->lock);
return 0;
}
| static int softmix_bridge_thread | ( | struct ast_bridge * | bridge | ) | [static] |
Function which acts as the mixing thread.
Definition at line 215 of file bridge_softmix.c.
References ao2_lock, ao2_unlock, ast_bridge::array_num, AST_LIST_TRAVERSE, ast_mutex_lock, ast_mutex_unlock, ast_slinear_saturated_add(), ast_slinear_saturated_subtract(), ast_slinfactory_available(), ast_slinfactory_read(), ast_timer_ack(), ast_timer_fd(), ast_timer_set_rate(), ast_waitfor_n_fd(), ast_bridge_channel::bridge_pvt, ast_bridge::bridge_pvt, ast_bridge::channels, ast_bridge_channel::entry, softmix_channel::factory, softmix_channel::final_buf, softmix_channel::have_audio, softmix_channel::have_frame, softmix_channel::lock, softmix_channel::our_buf, ast_bridge::refresh, SOFTMIX_DATALEN, SOFTMIX_INTERVAL, SOFTMIX_SAMPLES, ast_bridge::stop, ast_bridge_channel::thread, and timer.
{
struct ast_timer *timer = (struct ast_timer *) bridge->bridge_pvt;
int timingfd = ast_timer_fd(timer);
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, };
int timeout = -1;
/* 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;
ast_mutex_lock(&sc->lock);
/* 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)) {
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++)
ast_slinear_saturated_add(data1, data2);
/* Yay we have our own audio */
sc->have_audio = 1;
} else {
/* Awww we don't have audio ;( */
sc->have_audio = 0;
}
ast_mutex_unlock(&sc->lock);
}
/* Next step go through removing the channel's own audio and creating a good frame... */
AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
struct softmix_channel *sc = bridge_channel->bridge_pvt;
int i = 0;
/* Copy from local final buffer to our final buffer */
memcpy(sc->final_buf, buf, sizeof(sc->final_buf));
/* If we provided audio then take it out */
if (sc->have_audio) {
for (i = 0; i < SOFTMIX_DATALEN; i++) {
ast_slinear_saturated_subtract(&sc->final_buf[i], &sc->our_buf[i]);
}
}
/* The frame is now ready for use... */
sc->have_frame = 1;
/* Poke bridged channel thread just in case */
pthread_kill(bridge_channel->thread, SIGURG);
}
ao2_unlock(bridge);
/* 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(timer, 1);
ao2_lock(bridge);
}
return 0;
}
| static enum ast_bridge_write_result softmix_bridge_write | ( | struct ast_bridge * | bridge, |
| struct ast_bridge_channel * | bridge_channel, | ||
| struct ast_frame * | frame | ||
| ) | [static] |
Function called when a channel writes a frame into the bridge.
Definition at line 165 of file bridge_softmix.c.
References AST_BRIDGE_WRITE_SUCCESS, AST_BRIDGE_WRITE_UNSUPPORTED, AST_FORMAT_SLINEAR, AST_FORMAT_SLINEAR16, AST_FRAME_VOICE, ast_mutex_lock, ast_mutex_unlock, ast_slinfactory_feed(), ast_write(), ast_bridge_channel::bridge_pvt, ast_bridge_channel::chan, ast_frame_subclass::codec, softmix_channel::factory, softmix_channel::frame, ast_frame::frametype, softmix_channel::have_frame, softmix_channel::lock, and ast_frame::subclass.
{
struct softmix_channel *sc = bridge_channel->bridge_pvt;
/* Only accept audio frames, all others are unsupported */
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 */
#ifdef SOFTMIX_16_SUPPORT
if (frame->frametype == AST_FRAME_VOICE && frame->subclass.codec == AST_FORMAT_SLINEAR16) {
#else
if (frame->frametype == AST_FRAME_VOICE && frame->subclass.codec == 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) {
ast_write(bridge_channel->chan, &sc->frame);
sc->have_frame = 0;
}
/* Alllll done */
ast_mutex_unlock(&sc->lock);
return AST_BRIDGE_WRITE_SUCCESS;
}
| static int unload_module | ( | void | ) | [static] |
Definition at line 303 of file bridge_softmix.c.
References ast_bridge_technology_unregister().
{
return ast_bridge_technology_unregister(&softmix_bridge);
}
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Multi-party software based channel mixing" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static] |
Definition at line 313 of file bridge_softmix.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 313 of file bridge_softmix.c.
struct ast_bridge_technology softmix_bridge [static] |
Definition at line 285 of file bridge_softmix.c.