#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 = "ac1f6a56484a8820659555499174e588" , .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 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, 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 }
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 = "ac1f6a56484a8820659555499174e588" , .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] |