#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_info * | ast_module_info = &__mod_info |
static struct ast_bridge_technology | softmix_bridge |
Definition in file bridge_softmix.c.
#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().
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 }
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] |