Mon Jun 27 16:51:03 2011

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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .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 59 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 56 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 62 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 309 of file bridge_softmix.c.

static void __unreg_module ( void   )  [static]

Definition at line 309 of file bridge_softmix.c.

static int load_module ( void   )  [static]

Definition at line 304 of file bridge_softmix.c.

References ast_bridge_technology_register, and softmix_bridge.

00305 {
00306    return ast_bridge_technology_register(&softmix_bridge);
00307 }

static int softmix_bridge_create ( struct ast_bridge bridge  )  [static]

Function called when a bridge is created.

Definition at line 86 of file bridge_softmix.c.

References ast_timer_open(), ast_bridge::bridge_pvt, and timer.

00087 {
00088    struct ast_timer *timer;
00089 
00090    if (!(timer = ast_timer_open())) {
00091       return -1;
00092    }
00093 
00094    bridge->bridge_pvt = timer;
00095 
00096    return 0;
00097 }

static int softmix_bridge_destroy ( struct ast_bridge bridge  )  [static]

Function called when a bridge is destroyed.

Definition at line 100 of file bridge_softmix.c.

References ast_timer_close(), and ast_bridge::bridge_pvt.

00101 {
00102    if (!bridge->bridge_pvt) {
00103       return -1;
00104    }
00105    ast_timer_close((struct ast_timer *) bridge->bridge_pvt);
00106 
00107    return 0;
00108 }

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 111 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.

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

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 144 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.

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

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 194 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.

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

static int softmix_bridge_thread ( struct ast_bridge bridge  )  [static]

Function which acts as the mixing thread.

Definition at line 211 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.

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

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 161 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.

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

static int unload_module ( void   )  [static]

Definition at line 299 of file bridge_softmix.c.

References ast_bridge_technology_unregister(), and softmix_bridge.

00300 {
00301    return ast_bridge_technology_unregister(&softmix_bridge);
00302 }


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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static]

Definition at line 309 of file bridge_softmix.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 309 of file bridge_softmix.c.

struct ast_bridge_technology softmix_bridge [static]

Definition at line 281 of file bridge_softmix.c.

Referenced by load_module(), and unload_module().


Generated on Mon Jun 27 16:51:03 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7