00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "asterisk.h"
00037
00038 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 328209 $")
00039
00040 #include <stdio.h>
00041 #include <stdlib.h>
00042 #include <string.h>
00043 #include <sys/time.h>
00044 #include <signal.h>
00045 #include <errno.h>
00046 #include <unistd.h>
00047
00048 #include "asterisk/module.h"
00049 #include "asterisk/channel.h"
00050 #include "asterisk/bridging.h"
00051 #include "asterisk/bridging_technology.h"
00052 #include "asterisk/frame.h"
00053 #include "asterisk/options.h"
00054 #include "asterisk/logger.h"
00055 #include "asterisk/slinfactory.h"
00056 #include "asterisk/astobj2.h"
00057 #include "asterisk/timing.h"
00058
00059
00060 #define SOFTMIX_INTERVAL 20
00061
00062
00063 #define SOFTMIX_DATALEN (160 * (SOFTMIX_INTERVAL / 10))
00064
00065
00066 #define SOFTMIX_SAMPLES (SOFTMIX_DATALEN / 2)
00067
00068
00069
00070
00071
00072 struct softmix_channel {
00073
00074 ast_mutex_t lock;
00075
00076 struct ast_slinfactory factory;
00077
00078 struct ast_frame frame;
00079
00080 int have_audio:1;
00081
00082 int have_frame:1;
00083
00084 short final_buf[SOFTMIX_DATALEN];
00085
00086 short our_buf[SOFTMIX_DATALEN];
00087 };
00088
00089
00090 static int softmix_bridge_create(struct ast_bridge *bridge)
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 }
00102
00103
00104 static int softmix_bridge_destroy(struct ast_bridge *bridge)
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 }
00113
00114
00115 static int softmix_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
00116 {
00117 struct softmix_channel *sc = NULL;
00118
00119
00120 if (!(sc = ast_calloc(1, sizeof(*sc)))) {
00121 return -1;
00122 }
00123
00124
00125 ast_mutex_init(&sc->lock);
00126
00127
00128 ast_slinfactory_init(&sc->factory);
00129
00130
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
00142 bridge_channel->bridge_pvt = sc;
00143
00144 return 0;
00145 }
00146
00147
00148 static int softmix_bridge_leave(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
00149 {
00150 struct softmix_channel *sc = bridge_channel->bridge_pvt;
00151
00152
00153 ast_mutex_destroy(&sc->lock);
00154
00155
00156 ast_slinfactory_destroy(&sc->factory);
00157
00158
00159 ast_free(sc);
00160
00161 return 0;
00162 }
00163
00164
00165 static enum ast_bridge_write_result softmix_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
00166 {
00167 struct softmix_channel *sc = bridge_channel->bridge_pvt;
00168
00169
00170 if (frame->frametype != AST_FRAME_VOICE) {
00171 return AST_BRIDGE_WRITE_UNSUPPORTED;
00172 }
00173
00174 ast_mutex_lock(&sc->lock);
00175
00176
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
00186 if (sc->have_frame) {
00187 ast_write(bridge_channel->chan, &sc->frame);
00188 sc->have_frame = 0;
00189 }
00190
00191
00192 ast_mutex_unlock(&sc->lock);
00193
00194 return AST_BRIDGE_WRITE_SUCCESS;
00195 }
00196
00197
00198 static int softmix_bridge_poke(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
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 }
00213
00214
00215 static int softmix_bridge_thread(struct ast_bridge *bridge)
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
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
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
00239 for (i = 0, data1 = buf, data2 = sc->our_buf; i < SOFTMIX_DATALEN; i++, data1++, data2++)
00240 ast_slinear_saturated_add(data1, data2);
00241
00242 sc->have_audio = 1;
00243 } else {
00244
00245 sc->have_audio = 0;
00246 }
00247 ast_mutex_unlock(&sc->lock);
00248 }
00249
00250
00251 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
00252 struct softmix_channel *sc = bridge_channel->bridge_pvt;
00253 int i = 0;
00254
00255
00256 memcpy(sc->final_buf, buf, sizeof(sc->final_buf));
00257
00258
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
00266 sc->have_frame = 1;
00267
00268
00269 pthread_kill(bridge_channel->thread, SIGURG);
00270 }
00271
00272 ao2_unlock(bridge);
00273
00274
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 }
00284
00285 static struct ast_bridge_technology softmix_bridge = {
00286 .name = "softmix",
00287 .capabilities = AST_BRIDGE_CAPABILITY_MULTIMIX | AST_BRIDGE_CAPABILITY_THREAD | AST_BRIDGE_CAPABILITY_MULTITHREADED,
00288 .preference = AST_BRIDGE_PREFERENCE_LOW,
00289 #ifdef SOFTMIX_16_SUPPORT
00290 .formats = AST_FORMAT_SLINEAR16,
00291 #else
00292 .formats = AST_FORMAT_SLINEAR,
00293 #endif
00294 .create = softmix_bridge_create,
00295 .destroy = softmix_bridge_destroy,
00296 .join = softmix_bridge_join,
00297 .leave = softmix_bridge_leave,
00298 .write = softmix_bridge_write,
00299 .thread = softmix_bridge_thread,
00300 .poke = softmix_bridge_poke,
00301 };
00302
00303 static int unload_module(void)
00304 {
00305 return ast_bridge_technology_unregister(&softmix_bridge);
00306 }
00307
00308 static int load_module(void)
00309 {
00310 return ast_bridge_technology_register(&softmix_bridge);
00311 }
00312
00313 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Multi-party software based channel mixing");