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: 379091 $")
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 bridge->bridge_pvt = NULL;
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 if (!(bridge_channel->bridge_pvt)) {
00153 return 0;
00154 }
00155 bridge_channel->bridge_pvt = NULL;
00156
00157
00158 ast_mutex_destroy(&sc->lock);
00159
00160
00161 ast_slinfactory_destroy(&sc->factory);
00162
00163
00164 ast_free(sc);
00165
00166 return 0;
00167 }
00168
00169
00170 static enum ast_bridge_write_result softmix_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
00171 {
00172 struct softmix_channel *sc = bridge_channel->bridge_pvt;
00173
00174
00175 if (frame->frametype != AST_FRAME_VOICE) {
00176 return AST_BRIDGE_WRITE_UNSUPPORTED;
00177 }
00178
00179 ast_mutex_lock(&sc->lock);
00180
00181
00182 #ifdef SOFTMIX_16_SUPPORT
00183 if (frame->frametype == AST_FRAME_VOICE && frame->subclass.codec == AST_FORMAT_SLINEAR16) {
00184 #else
00185 if (frame->frametype == AST_FRAME_VOICE && frame->subclass.codec == AST_FORMAT_SLINEAR) {
00186 #endif
00187 ast_slinfactory_feed(&sc->factory, frame);
00188 }
00189
00190
00191 if (sc->have_frame) {
00192 ast_write(bridge_channel->chan, &sc->frame);
00193 sc->have_frame = 0;
00194 }
00195
00196
00197 ast_mutex_unlock(&sc->lock);
00198
00199 return AST_BRIDGE_WRITE_SUCCESS;
00200 }
00201
00202
00203 static int softmix_bridge_poke(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
00204 {
00205 struct softmix_channel *sc = bridge_channel->bridge_pvt;
00206
00207 ast_mutex_lock(&sc->lock);
00208
00209 if (sc->have_frame) {
00210 ast_write(bridge_channel->chan, &sc->frame);
00211 sc->have_frame = 0;
00212 }
00213
00214 ast_mutex_unlock(&sc->lock);
00215
00216 return 0;
00217 }
00218
00219
00220 static int softmix_bridge_thread(struct ast_bridge *bridge)
00221 {
00222 struct ast_timer *timer = (struct ast_timer *) bridge->bridge_pvt;
00223 int timingfd = ast_timer_fd(timer);
00224
00225 ast_timer_set_rate(timer, (1000 / SOFTMIX_INTERVAL));
00226
00227 while (!bridge->stop && !bridge->refresh && bridge->array_num) {
00228 struct ast_bridge_channel *bridge_channel = NULL;
00229 short buf[SOFTMIX_DATALEN] = {0, };
00230 int timeout = -1;
00231
00232
00233 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
00234 struct softmix_channel *sc = bridge_channel->bridge_pvt;
00235
00236 ast_mutex_lock(&sc->lock);
00237
00238
00239 if (ast_slinfactory_available(&sc->factory) >= SOFTMIX_SAMPLES && ast_slinfactory_read(&sc->factory, sc->our_buf, SOFTMIX_SAMPLES)) {
00240 short *data1, *data2;
00241 int i;
00242
00243
00244 for (i = 0, data1 = buf, data2 = sc->our_buf; i < SOFTMIX_DATALEN; i++, data1++, data2++)
00245 ast_slinear_saturated_add(data1, data2);
00246
00247 sc->have_audio = 1;
00248 } else {
00249
00250 sc->have_audio = 0;
00251 }
00252 ast_mutex_unlock(&sc->lock);
00253 }
00254
00255
00256 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
00257 struct softmix_channel *sc = bridge_channel->bridge_pvt;
00258 int i = 0;
00259
00260
00261 memcpy(sc->final_buf, buf, sizeof(sc->final_buf));
00262
00263
00264 if (sc->have_audio) {
00265 for (i = 0; i < SOFTMIX_DATALEN; i++) {
00266 ast_slinear_saturated_subtract(&sc->final_buf[i], &sc->our_buf[i]);
00267 }
00268 }
00269
00270
00271 sc->have_frame = 1;
00272
00273
00274 pthread_kill(bridge_channel->thread, SIGURG);
00275 }
00276
00277 ao2_unlock(bridge);
00278
00279
00280 ast_waitfor_n_fd(&timingfd, 1, &timeout, NULL);
00281
00282 if (ast_timer_ack(timer, 1) < 0) {
00283 ast_log(LOG_ERROR, "Failed to acknowledge timer in softmix bridge\n");
00284 ao2_lock(bridge);
00285 break;
00286 }
00287
00288 ao2_lock(bridge);
00289 }
00290
00291 return 0;
00292 }
00293
00294 static struct ast_bridge_technology softmix_bridge = {
00295 .name = "softmix",
00296 .capabilities = AST_BRIDGE_CAPABILITY_MULTIMIX | AST_BRIDGE_CAPABILITY_THREAD | AST_BRIDGE_CAPABILITY_MULTITHREADED,
00297 .preference = AST_BRIDGE_PREFERENCE_LOW,
00298 #ifdef SOFTMIX_16_SUPPORT
00299 .formats = AST_FORMAT_SLINEAR16,
00300 #else
00301 .formats = AST_FORMAT_SLINEAR,
00302 #endif
00303 .create = softmix_bridge_create,
00304 .destroy = softmix_bridge_destroy,
00305 .join = softmix_bridge_join,
00306 .leave = softmix_bridge_leave,
00307 .write = softmix_bridge_write,
00308 .thread = softmix_bridge_thread,
00309 .poke = softmix_bridge_poke,
00310 };
00311
00312 static int unload_module(void)
00313 {
00314 return ast_bridge_technology_unregister(&softmix_bridge);
00315 }
00316
00317 static int load_module(void)
00318 {
00319 return ast_bridge_technology_register(&softmix_bridge);
00320 }
00321
00322 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Multi-party software based channel mixing");