Sat Mar 10 01:54:47 2012

Asterisk developer's documentation


bridge_softmix.c File Reference

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 Structure which contains per-channel mixing information. 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 = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_bridge_technology softmix_bridge


Detailed Description

Multi-party software based channel mixing.

Author:
Joshua Colp <jcolp@digium.com>
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.

Definition in file bridge_softmix.c.


Define Documentation

#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().


Function Documentation

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, and softmix_bridge.

00309 {
00310    return ast_bridge_technology_register(&softmix_bridge);
00311 }

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.

00091 {
00092    struct ast_timer *timer;
00093 
00094    if (!(timer = ast_timer_open())) {
00095       return -1;
00096    }
00097 
00098    bridge->bridge_pvt = timer;
00099 
00100    return 0;
00101 }

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.

00105 {
00106    if (!bridge->bridge_pvt) {
00107       return -1;
00108    }
00109    ast_timer_close((struct ast_timer *) bridge->bridge_pvt);
00110 
00111    return 0;
00112 }

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, SOFTMIX_DATALEN, and SOFTMIX_SAMPLES.

00116 {
00117    struct softmix_channel *sc = NULL;
00118 
00119    /* Create a new softmix_channel structure and allocate various things on it */
00120    if (!(sc = ast_calloc(1, sizeof(*sc)))) {
00121       return -1;
00122    }
00123 
00124    /* Can't forget the lock */
00125    ast_mutex_init(&sc->lock);
00126 
00127    /* Setup smoother */
00128    ast_slinfactory_init(&sc->factory);
00129 
00130    /* Setup frame parameters */
00131    sc->frame.frametype = AST_FRAME_VOICE;
00132 #ifdef SOFTMIX_16_SUPPORT
00133    sc->frame.subclass.codec = AST_FORMAT_SLINEAR16;
00134 #else
00135    sc->frame.subclass.codec = AST_FORMAT_SLINEAR;
00136 #endif
00137    sc->frame.data.ptr = sc->final_buf;
00138    sc->frame.datalen = SOFTMIX_DATALEN;
00139    sc->frame.samples = SOFTMIX_SAMPLES;
00140 
00141    /* Can't forget to record our pvt structure within the bridged channel structure */
00142    bridge_channel->bridge_pvt = sc;
00143 
00144    return 0;
00145 }

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.

00149 {
00150    struct softmix_channel *sc = bridge_channel->bridge_pvt;
00151 
00152    /* Drop mutex lock */
00153    ast_mutex_destroy(&sc->lock);
00154 
00155    /* Drop the factory */
00156    ast_slinfactory_destroy(&sc->factory);
00157 
00158    /* Eep! drop ourselves */
00159    ast_free(sc);
00160 
00161    return 0;
00162 }

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.

00199 {
00200    struct softmix_channel *sc = bridge_channel->bridge_pvt;
00201 
00202    ast_mutex_lock(&sc->lock);
00203 
00204    if (sc->have_frame) {
00205       ast_write(bridge_channel->chan, &sc->frame);
00206       sc->have_frame = 0;
00207    }
00208 
00209    ast_mutex_unlock(&sc->lock);
00210 
00211    return 0;
00212 }

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, ast_bridge_channel::bridge_pvt, ast_bridge::bridge_pvt, 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.

00216 {
00217    struct ast_timer *timer = (struct ast_timer *) bridge->bridge_pvt;
00218    int timingfd = ast_timer_fd(timer);
00219 
00220    ast_timer_set_rate(timer, (1000 / SOFTMIX_INTERVAL));
00221 
00222    while (!bridge->stop && !bridge->refresh && bridge->array_num) {
00223       struct ast_bridge_channel *bridge_channel = NULL;
00224       short buf[SOFTMIX_DATALEN] = {0, };
00225       int timeout = -1;
00226 
00227       /* Go through pulling audio from each factory that has it available */
00228       AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
00229          struct softmix_channel *sc = bridge_channel->bridge_pvt;
00230 
00231          ast_mutex_lock(&sc->lock);
00232 
00233          /* Try to get audio from the factory if available */
00234          if (ast_slinfactory_available(&sc->factory) >= SOFTMIX_SAMPLES && ast_slinfactory_read(&sc->factory, sc->our_buf, SOFTMIX_SAMPLES)) {
00235             short *data1, *data2;
00236             int i;
00237 
00238             /* Put into the local final buffer */
00239             for (i = 0, data1 = buf, data2 = sc->our_buf; i < SOFTMIX_DATALEN; i++, data1++, data2++)
00240                ast_slinear_saturated_add(data1, data2);
00241             /* Yay we have our own audio */
00242             sc->have_audio = 1;
00243          } else {
00244             /* Awww we don't have audio ;( */
00245             sc->have_audio = 0;
00246          }
00247          ast_mutex_unlock(&sc->lock);
00248       }
00249 
00250       /* Next step go through removing the channel's own audio and creating a good frame... */
00251       AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
00252          struct softmix_channel *sc = bridge_channel->bridge_pvt;
00253          int i = 0;
00254 
00255          /* Copy from local final buffer to our final buffer */
00256          memcpy(sc->final_buf, buf, sizeof(sc->final_buf));
00257 
00258          /* If we provided audio then take it out */
00259          if (sc->have_audio) {
00260             for (i = 0; i < SOFTMIX_DATALEN; i++) {
00261                ast_slinear_saturated_subtract(&sc->final_buf[i], &sc->our_buf[i]);
00262             }
00263          }
00264 
00265          /* The frame is now ready for use... */
00266          sc->have_frame = 1;
00267 
00268          /* Poke bridged channel thread just in case */
00269          pthread_kill(bridge_channel->thread, SIGURG);
00270       }
00271 
00272       ao2_unlock(bridge);
00273 
00274       /* Wait for the timing source to tell us to wake up and get things done */
00275       ast_waitfor_n_fd(&timingfd, 1, &timeout, NULL);
00276 
00277       ast_timer_ack(timer, 1);
00278 
00279       ao2_lock(bridge);
00280    }
00281 
00282    return 0;
00283 }

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.

00166 {
00167    struct softmix_channel *sc = bridge_channel->bridge_pvt;
00168 
00169    /* Only accept audio frames, all others are unsupported */
00170    if (frame->frametype != AST_FRAME_VOICE) {
00171       return AST_BRIDGE_WRITE_UNSUPPORTED;
00172    }
00173 
00174    ast_mutex_lock(&sc->lock);
00175 
00176    /* If a frame was provided add it to the smoother */
00177 #ifdef SOFTMIX_16_SUPPORT
00178    if (frame->frametype == AST_FRAME_VOICE && frame->subclass.codec == AST_FORMAT_SLINEAR16) {
00179 #else
00180    if (frame->frametype == AST_FRAME_VOICE && frame->subclass.codec == AST_FORMAT_SLINEAR) {
00181 #endif
00182       ast_slinfactory_feed(&sc->factory, frame);
00183    }
00184 
00185    /* If a frame is ready to be written out, do so */
00186    if (sc->have_frame) {
00187       ast_write(bridge_channel->chan, &sc->frame);
00188       sc->have_frame = 0;
00189    }
00190 
00191    /* Alllll done */
00192    ast_mutex_unlock(&sc->lock);
00193 
00194    return AST_BRIDGE_WRITE_SUCCESS;
00195 }

static int unload_module ( void   )  [static]

Definition at line 303 of file bridge_softmix.c.

References ast_bridge_technology_unregister(), and softmix_bridge.

00304 {
00305    return ast_bridge_technology_unregister(&softmix_bridge);
00306 }


Variable Documentation

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 = "88eaa8f5c1bd988bedd71113385e0886" , .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.

Referenced by load_module(), and unload_module().


Generated on Sat Mar 10 01:54:47 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7