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 #include "asterisk.h"
00033
00034 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 247776 $")
00035
00036 #include <stdio.h>
00037 #include <stdlib.h>
00038 #include <string.h>
00039 #include <sys/time.h>
00040 #include <signal.h>
00041 #include <errno.h>
00042 #include <unistd.h>
00043
00044 #include "asterisk/module.h"
00045 #include "asterisk/channel.h"
00046 #include "asterisk/bridging.h"
00047 #include "asterisk/bridging_technology.h"
00048 #include "asterisk/frame.h"
00049 #include "asterisk/options.h"
00050 #include "asterisk/logger.h"
00051 #include "asterisk/slinfactory.h"
00052 #include "asterisk/astobj2.h"
00053 #include "asterisk/timing.h"
00054
00055
00056 #define SOFTMIX_INTERVAL 20
00057
00058
00059 #define SOFTMIX_DATALEN (160 * (SOFTMIX_INTERVAL / 10))
00060
00061
00062 #define SOFTMIX_SAMPLES (SOFTMIX_DATALEN / 2)
00063
00064
00065
00066
00067
00068 struct softmix_channel {
00069
00070 ast_mutex_t lock;
00071
00072 struct ast_slinfactory factory;
00073
00074 struct ast_frame frame;
00075
00076 int have_audio:1;
00077
00078 int have_frame:1;
00079
00080 short final_buf[SOFTMIX_DATALEN];
00081
00082 short our_buf[SOFTMIX_DATALEN];
00083 };
00084
00085
00086 static int softmix_bridge_create(struct ast_bridge *bridge)
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 }
00098
00099
00100 static int softmix_bridge_destroy(struct ast_bridge *bridge)
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 }
00109
00110
00111 static int softmix_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
00112 {
00113 struct softmix_channel *sc = NULL;
00114
00115
00116 if (!(sc = ast_calloc(1, sizeof(*sc)))) {
00117 return -1;
00118 }
00119
00120
00121 ast_mutex_init(&sc->lock);
00122
00123
00124 ast_slinfactory_init(&sc->factory);
00125
00126
00127 sc->frame.frametype = AST_FRAME_VOICE;
00128 #ifdef SOFTMIX_16_SUPPORT
00129 sc->frame.subclass = AST_FORMAT_SLINEAR16;
00130 #else
00131 sc->frame.subclass = 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
00138 bridge_channel->bridge_pvt = sc;
00139
00140 return 0;
00141 }
00142
00143
00144 static int softmix_bridge_leave(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
00145 {
00146 struct softmix_channel *sc = bridge_channel->bridge_pvt;
00147
00148
00149 ast_mutex_destroy(&sc->lock);
00150
00151
00152 ast_slinfactory_destroy(&sc->factory);
00153
00154
00155 ast_free(sc);
00156
00157 return 0;
00158 }
00159
00160
00161 static enum ast_bridge_write_result softmix_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
00162 {
00163 struct softmix_channel *sc = bridge_channel->bridge_pvt;
00164
00165
00166 if (frame->frametype != AST_FRAME_VOICE) {
00167 return AST_BRIDGE_WRITE_UNSUPPORTED;
00168 }
00169
00170 ast_mutex_lock(&sc->lock);
00171
00172
00173 #ifdef SOFTMIX_16_SUPPORT
00174 if (frame->frametype == AST_FRAME_VOICE && frame->subclass == AST_FORMAT_SLINEAR16) {
00175 #else
00176 if (frame->frametype == AST_FRAME_VOICE && frame->subclass == AST_FORMAT_SLINEAR) {
00177 #endif
00178 ast_slinfactory_feed(&sc->factory, frame);
00179 }
00180
00181
00182 if (sc->have_frame) {
00183 ast_write(bridge_channel->chan, &sc->frame);
00184 sc->have_frame = 0;
00185 }
00186
00187
00188 ast_mutex_unlock(&sc->lock);
00189
00190 return AST_BRIDGE_WRITE_SUCCESS;
00191 }
00192
00193
00194 static int softmix_bridge_poke(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
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 }
00209
00210
00211 static int softmix_bridge_thread(struct ast_bridge *bridge)
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
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
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
00235 for (i = 0, data1 = buf, data2 = sc->our_buf; i < SOFTMIX_DATALEN; i++, data1++, data2++)
00236 ast_slinear_saturated_add(data1, data2);
00237
00238 sc->have_audio = 1;
00239 } else {
00240
00241 sc->have_audio = 0;
00242 }
00243 ast_mutex_unlock(&sc->lock);
00244 }
00245
00246
00247 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
00248 struct softmix_channel *sc = bridge_channel->bridge_pvt;
00249 int i = 0;
00250
00251
00252 memcpy(sc->final_buf, buf, sizeof(sc->final_buf));
00253
00254
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
00262 sc->have_frame = 1;
00263
00264
00265 pthread_kill(bridge_channel->thread, SIGURG);
00266 }
00267
00268 ao2_unlock(bridge);
00269
00270
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 }
00280
00281 static struct ast_bridge_technology softmix_bridge = {
00282 .name = "softmix",
00283 .capabilities = AST_BRIDGE_CAPABILITY_MULTIMIX | AST_BRIDGE_CAPABILITY_THREAD | AST_BRIDGE_CAPABILITY_MULTITHREADED,
00284 .preference = AST_BRIDGE_PREFERENCE_LOW,
00285 #ifdef SOFTMIX_16_SUPPORT
00286 .formats = AST_FORMAT_SLINEAR16,
00287 #else
00288 .formats = AST_FORMAT_SLINEAR,
00289 #endif
00290 .create = softmix_bridge_create,
00291 .destroy = softmix_bridge_destroy,
00292 .join = softmix_bridge_join,
00293 .leave = softmix_bridge_leave,
00294 .write = softmix_bridge_write,
00295 .thread = softmix_bridge_thread,
00296 .poke = softmix_bridge_poke,
00297 };
00298
00299 static int unload_module(void)
00300 {
00301 return ast_bridge_technology_unregister(&softmix_bridge);
00302 }
00303
00304 static int load_module(void)
00305 {
00306 return ast_bridge_technology_register(&softmix_bridge);
00307 }
00308
00309 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Multi-party software based channel mixing");