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 #include "asterisk.h"
00035
00036 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 356573 $")
00037
00038 #include <stdio.h>
00039 #include <stdlib.h>
00040 #include <string.h>
00041 #include <sys/time.h>
00042 #include <signal.h>
00043 #include <errno.h>
00044 #include <unistd.h>
00045
00046 #include "asterisk/module.h"
00047 #include "asterisk/channel.h"
00048 #include "asterisk/bridging.h"
00049 #include "asterisk/bridging_technology.h"
00050 #include "asterisk/frame.h"
00051 #include "asterisk/options.h"
00052 #include "asterisk/logger.h"
00053 #include "asterisk/slinfactory.h"
00054 #include "asterisk/astobj2.h"
00055 #include "asterisk/timing.h"
00056 #include "asterisk/translate.h"
00057
00058 #define MAX_DATALEN 8096
00059
00060
00061 #define DEFAULT_SOFTMIX_INTERVAL 20
00062
00063
00064 #define SOFTMIX_DATALEN(rate, interval) ((rate/50) * (interval / 10))
00065
00066
00067 #define SOFTMIX_SAMPLES(rate, interval) (SOFTMIX_DATALEN(rate, interval) / 2)
00068
00069
00070 #define SOFTMIX_STAT_INTERVAL 100
00071
00072
00073
00074 #define DEFAULT_SOFTMIX_SILENCE_THRESHOLD 2500
00075 #define DEFAULT_SOFTMIX_TALKING_THRESHOLD 160
00076
00077 #define DEFAULT_ENERGY_HISTORY_LEN 150
00078
00079 struct video_follow_talker_data {
00080
00081 int energy_history[DEFAULT_ENERGY_HISTORY_LEN];
00082
00083
00084 int energy_history_cur_slot;
00085
00086 int energy_accum;
00087
00088 int energy_average;
00089 };
00090
00091
00092 struct softmix_channel {
00093
00094 ast_mutex_t lock;
00095
00096 struct ast_slinfactory factory;
00097
00098 struct ast_frame write_frame;
00099
00100 struct ast_frame read_frame;
00101
00102 struct ast_dsp *dsp;
00103
00104
00105 int talking:1;
00106
00107 int have_audio:1;
00108
00109 int have_frame:1;
00110
00111 short final_buf[MAX_DATALEN];
00112
00113 short our_buf[MAX_DATALEN];
00114
00115 struct video_follow_talker_data video_talker;
00116 };
00117
00118 struct softmix_bridge_data {
00119 struct ast_timer *timer;
00120 unsigned int internal_rate;
00121 unsigned int internal_mixing_interval;
00122 };
00123
00124 struct softmix_stats {
00125
00126 unsigned int sample_rates[16];
00127
00128 unsigned int num_channels[16];
00129
00130 unsigned int num_above_internal_rate;
00131
00132 unsigned int num_at_internal_rate;
00133
00134 unsigned int highest_supported_rate;
00135
00136 unsigned int locked_rate;
00137 };
00138
00139 struct softmix_mixing_array {
00140 int max_num_entries;
00141 int used_entries;
00142 int16_t **buffers;
00143 };
00144
00145 struct softmix_translate_helper_entry {
00146 int num_times_requested;
00147
00148 struct ast_format dst_format;
00149 struct ast_trans_pvt *trans_pvt;
00150 struct ast_frame *out_frame;
00151 AST_LIST_ENTRY(softmix_translate_helper_entry) entry;
00152 };
00153
00154 struct softmix_translate_helper {
00155 struct ast_format slin_src;
00156 AST_LIST_HEAD_NOLOCK(, softmix_translate_helper_entry) entries;
00157 };
00158
00159 static struct softmix_translate_helper_entry *softmix_translate_helper_entry_alloc(struct ast_format *dst)
00160 {
00161 struct softmix_translate_helper_entry *entry;
00162 if (!(entry = ast_calloc(1, sizeof(*entry)))) {
00163 return NULL;
00164 }
00165 ast_format_copy(&entry->dst_format, dst);
00166 return entry;
00167 }
00168
00169 static void *softmix_translate_helper_free_entry(struct softmix_translate_helper_entry *entry)
00170 {
00171 if (entry->trans_pvt) {
00172 ast_translator_free_path(entry->trans_pvt);
00173 }
00174 if (entry->out_frame) {
00175 ast_frfree(entry->out_frame);
00176 }
00177 ast_free(entry);
00178 return NULL;
00179 }
00180
00181 static void softmix_translate_helper_init(struct softmix_translate_helper *trans_helper, unsigned int sample_rate)
00182 {
00183 memset(trans_helper, 0, sizeof(*trans_helper));
00184 ast_format_set(&trans_helper->slin_src, ast_format_slin_by_rate(sample_rate), 0);
00185 }
00186
00187 static void softmix_translate_helper_destroy(struct softmix_translate_helper *trans_helper)
00188 {
00189 struct softmix_translate_helper_entry *entry;
00190
00191 while ((entry = AST_LIST_REMOVE_HEAD(&trans_helper->entries, entry))) {
00192 softmix_translate_helper_free_entry(entry);
00193 }
00194 }
00195
00196 static void softmix_translate_helper_change_rate(struct softmix_translate_helper *trans_helper, unsigned int sample_rate)
00197 {
00198 struct softmix_translate_helper_entry *entry;
00199
00200 ast_format_set(&trans_helper->slin_src, ast_format_slin_by_rate(sample_rate), 0);
00201 AST_LIST_TRAVERSE_SAFE_BEGIN(&trans_helper->entries, entry, entry) {
00202 if (entry->trans_pvt) {
00203 ast_translator_free_path(entry->trans_pvt);
00204 if (!(entry->trans_pvt = ast_translator_build_path(&entry->dst_format, &trans_helper->slin_src))) {
00205 AST_LIST_REMOVE_CURRENT(entry);
00206 entry = softmix_translate_helper_free_entry(entry);
00207 }
00208 }
00209 }
00210 AST_LIST_TRAVERSE_SAFE_END;
00211 }
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221 static int16_t *softmix_process_read_audio(struct softmix_channel *sc, unsigned int num_samples)
00222 {
00223 if ((ast_slinfactory_available(&sc->factory) >= num_samples) &&
00224 ast_slinfactory_read(&sc->factory, sc->our_buf, num_samples)) {
00225 sc->have_audio = 1;
00226 return sc->our_buf;
00227 }
00228 sc->have_audio = 0;
00229 return NULL;
00230 }
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 static void softmix_process_write_audio(struct softmix_translate_helper *trans_helper,
00241 struct ast_format *raw_write_fmt,
00242 struct softmix_channel *sc)
00243 {
00244 struct softmix_translate_helper_entry *entry = NULL;
00245 int i;
00246
00247
00248
00249 if (sc->have_audio && sc->talking) {
00250 for (i = 0; i < sc->write_frame.samples; i++) {
00251 ast_slinear_saturated_subtract(&sc->final_buf[i], &sc->our_buf[i]);
00252 }
00253
00254
00255 return;
00256 }
00257
00258 AST_LIST_TRAVERSE(&trans_helper->entries, entry, entry) {
00259 if (ast_format_cmp(&entry->dst_format, raw_write_fmt) == AST_FORMAT_CMP_EQUAL) {
00260 entry->num_times_requested++;
00261 } else {
00262 continue;
00263 }
00264 if (!entry->trans_pvt && (entry->num_times_requested > 1)) {
00265 entry->trans_pvt = ast_translator_build_path(&entry->dst_format, &trans_helper->slin_src);
00266 }
00267 if (entry->trans_pvt && !entry->out_frame) {
00268 entry->out_frame = ast_translate(entry->trans_pvt, &sc->write_frame, 0);
00269 }
00270 if (entry->out_frame && (entry->out_frame->datalen < MAX_DATALEN)) {
00271 ast_format_copy(&sc->write_frame.subclass.format, &entry->out_frame->subclass.format);
00272 memcpy(sc->final_buf, entry->out_frame->data.ptr, entry->out_frame->datalen);
00273 sc->write_frame.datalen = entry->out_frame->datalen;
00274 sc->write_frame.samples = entry->out_frame->samples;
00275 }
00276 break;
00277 }
00278
00279
00280 if (!entry && (entry = softmix_translate_helper_entry_alloc(raw_write_fmt))) {
00281 AST_LIST_INSERT_HEAD(&trans_helper->entries, entry, entry);
00282 }
00283 }
00284
00285 static void softmix_translate_helper_cleanup(struct softmix_translate_helper *trans_helper)
00286 {
00287 struct softmix_translate_helper_entry *entry = NULL;
00288 AST_LIST_TRAVERSE(&trans_helper->entries, entry, entry) {
00289 if (entry->out_frame) {
00290 ast_frfree(entry->out_frame);
00291 entry->out_frame = NULL;
00292 }
00293 entry->num_times_requested = 0;
00294 }
00295 }
00296
00297 static void softmix_bridge_data_destroy(void *obj)
00298 {
00299 struct softmix_bridge_data *softmix_data = obj;
00300 ast_timer_close(softmix_data->timer);
00301 }
00302
00303
00304 static int softmix_bridge_create(struct ast_bridge *bridge)
00305 {
00306 struct softmix_bridge_data *softmix_data;
00307
00308 if (!(softmix_data = ao2_alloc(sizeof(*softmix_data), softmix_bridge_data_destroy))) {
00309 return -1;
00310 }
00311 if (!(softmix_data->timer = ast_timer_open())) {
00312 ao2_ref(softmix_data, -1);
00313 return -1;
00314 }
00315
00316
00317 softmix_data->internal_rate = 8000;
00318 softmix_data->internal_mixing_interval = DEFAULT_SOFTMIX_INTERVAL;
00319
00320 bridge->bridge_pvt = softmix_data;
00321 return 0;
00322 }
00323
00324
00325 static int softmix_bridge_destroy(struct ast_bridge *bridge)
00326 {
00327 struct softmix_bridge_data *softmix_data = bridge->bridge_pvt;
00328 if (!bridge->bridge_pvt) {
00329 return -1;
00330 }
00331 ao2_ref(softmix_data, -1);
00332 bridge->bridge_pvt = NULL;
00333 return 0;
00334 }
00335
00336 static void set_softmix_bridge_data(int rate, int interval, struct ast_bridge_channel *bridge_channel, int reset)
00337 {
00338 struct softmix_channel *sc = bridge_channel->bridge_pvt;
00339 unsigned int channel_read_rate = ast_format_rate(ast_channel_rawreadformat(bridge_channel->chan));
00340
00341 ast_mutex_lock(&sc->lock);
00342 if (reset) {
00343 ast_slinfactory_destroy(&sc->factory);
00344 ast_dsp_free(sc->dsp);
00345 }
00346
00347 sc->write_frame.frametype = AST_FRAME_VOICE;
00348 ast_format_set(&sc->write_frame.subclass.format, ast_format_slin_by_rate(rate), 0);
00349 sc->write_frame.data.ptr = sc->final_buf;
00350 sc->write_frame.datalen = SOFTMIX_DATALEN(rate, interval);
00351 sc->write_frame.samples = SOFTMIX_SAMPLES(rate, interval);
00352
00353 sc->read_frame.frametype = AST_FRAME_VOICE;
00354 ast_format_set(&sc->read_frame.subclass.format, ast_format_slin_by_rate(channel_read_rate), 0);
00355 sc->read_frame.data.ptr = sc->our_buf;
00356 sc->read_frame.datalen = SOFTMIX_DATALEN(channel_read_rate, interval);
00357 sc->read_frame.samples = SOFTMIX_SAMPLES(channel_read_rate, interval);
00358
00359
00360 ast_slinfactory_init_with_format(&sc->factory, &sc->write_frame.subclass.format);
00361
00362
00363 ast_set_read_format(bridge_channel->chan, &sc->read_frame.subclass.format);
00364 ast_set_write_format(bridge_channel->chan, &sc->write_frame.subclass.format);
00365
00366
00367 sc->dsp = ast_dsp_new_with_rate(channel_read_rate);
00368
00369 if (bridge_channel->tech_args.talking_threshold) {
00370 ast_dsp_set_threshold(sc->dsp, bridge_channel->tech_args.talking_threshold);
00371 } else {
00372 ast_dsp_set_threshold(sc->dsp, DEFAULT_SOFTMIX_TALKING_THRESHOLD);
00373 }
00374
00375 ast_mutex_unlock(&sc->lock);
00376 }
00377
00378
00379 static int softmix_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
00380 {
00381 struct softmix_channel *sc = NULL;
00382 struct softmix_bridge_data *softmix_data = bridge->bridge_pvt;
00383
00384
00385 if (!(sc = ast_calloc(1, sizeof(*sc)))) {
00386 return -1;
00387 }
00388
00389
00390 ast_mutex_init(&sc->lock);
00391
00392
00393 bridge_channel->bridge_pvt = sc;
00394
00395 set_softmix_bridge_data(softmix_data->internal_rate,
00396 softmix_data->internal_mixing_interval ? softmix_data->internal_mixing_interval : DEFAULT_SOFTMIX_INTERVAL,
00397 bridge_channel, 0);
00398
00399 return 0;
00400 }
00401
00402
00403 static int softmix_bridge_leave(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
00404 {
00405 struct softmix_channel *sc = bridge_channel->bridge_pvt;
00406
00407 if (!(bridge_channel->bridge_pvt)) {
00408 return 0;
00409 }
00410 bridge_channel->bridge_pvt = NULL;
00411
00412
00413 ast_mutex_destroy(&sc->lock);
00414
00415
00416 ast_slinfactory_destroy(&sc->factory);
00417
00418
00419 ast_dsp_free(sc->dsp);
00420
00421
00422 ast_free(sc);
00423
00424 return 0;
00425 }
00426
00427
00428
00429
00430
00431 static void softmix_pass_dtmf(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
00432 {
00433 struct ast_bridge_channel *tmp;
00434 AST_LIST_TRAVERSE(&bridge->channels, tmp, entry) {
00435 if (tmp == bridge_channel) {
00436 continue;
00437 }
00438 ast_write(tmp->chan, frame);
00439 }
00440 }
00441
00442 static void softmix_pass_video_top_priority(struct ast_bridge *bridge, struct ast_frame *frame)
00443 {
00444 struct ast_bridge_channel *tmp;
00445 AST_LIST_TRAVERSE(&bridge->channels, tmp, entry) {
00446 if (tmp->suspended) {
00447 continue;
00448 }
00449 if (ast_bridge_is_video_src(bridge, tmp->chan) == 1) {
00450 ast_write(tmp->chan, frame);
00451 break;
00452 }
00453 }
00454 }
00455
00456 static void softmix_pass_video_all(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame, int echo)
00457 {
00458 struct ast_bridge_channel *tmp;
00459 AST_LIST_TRAVERSE(&bridge->channels, tmp, entry) {
00460 if (tmp->suspended) {
00461 continue;
00462 }
00463 if ((tmp->chan == bridge_channel->chan) && !echo) {
00464 continue;
00465 }
00466 ast_write(tmp->chan, frame);
00467 }
00468 }
00469
00470
00471 static enum ast_bridge_write_result softmix_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
00472 {
00473 struct softmix_channel *sc = bridge_channel->bridge_pvt;
00474 struct softmix_bridge_data *softmix_data = bridge->bridge_pvt;
00475 int totalsilence = 0;
00476 int cur_energy = 0;
00477 int silence_threshold = bridge_channel->tech_args.silence_threshold ?
00478 bridge_channel->tech_args.silence_threshold :
00479 DEFAULT_SOFTMIX_SILENCE_THRESHOLD;
00480 char update_talking = -1;
00481 int res = AST_BRIDGE_WRITE_SUCCESS;
00482
00483
00484 if (frame->frametype == AST_FRAME_DTMF_END || frame->frametype == AST_FRAME_DTMF_BEGIN) {
00485 softmix_pass_dtmf(bridge, bridge_channel, frame);
00486 goto bridge_write_cleanup;
00487 } else if (frame->frametype != AST_FRAME_VOICE && frame->frametype != AST_FRAME_VIDEO) {
00488 res = AST_BRIDGE_WRITE_UNSUPPORTED;
00489 goto bridge_write_cleanup;
00490 } else if (frame->datalen == 0) {
00491 goto bridge_write_cleanup;
00492 }
00493
00494
00495 if (frame->frametype == AST_FRAME_VIDEO) {
00496 int num_src = ast_bridge_number_video_src(bridge);
00497 int video_src_priority = ast_bridge_is_video_src(bridge, bridge_channel->chan);
00498
00499 switch (bridge->video_mode.mode) {
00500 case AST_BRIDGE_VIDEO_MODE_NONE:
00501 break;
00502 case AST_BRIDGE_VIDEO_MODE_SINGLE_SRC:
00503 if (video_src_priority == 1) {
00504 softmix_pass_video_all(bridge, bridge_channel, frame, 1);
00505 }
00506 break;
00507 case AST_BRIDGE_VIDEO_MODE_TALKER_SRC:
00508 ast_mutex_lock(&sc->lock);
00509 ast_bridge_update_talker_src_video_mode(bridge, bridge_channel->chan, sc->video_talker.energy_average, ast_format_get_video_mark(&frame->subclass.format));
00510 ast_mutex_unlock(&sc->lock);
00511 if (video_src_priority == 1) {
00512 int echo = num_src > 1 ? 0 : 1;
00513 softmix_pass_video_all(bridge, bridge_channel, frame, echo);
00514 } else if (video_src_priority == 2) {
00515 softmix_pass_video_top_priority(bridge, frame);
00516 }
00517 break;
00518 }
00519 goto bridge_write_cleanup;
00520 }
00521
00522
00523 ast_mutex_lock(&sc->lock);
00524 ast_dsp_silence_with_energy(sc->dsp, frame, &totalsilence, &cur_energy);
00525
00526 if (bridge->video_mode.mode == AST_BRIDGE_VIDEO_MODE_TALKER_SRC) {
00527 int cur_slot = sc->video_talker.energy_history_cur_slot;
00528 sc->video_talker.energy_accum -= sc->video_talker.energy_history[cur_slot];
00529 sc->video_talker.energy_accum += cur_energy;
00530 sc->video_talker.energy_history[cur_slot] = cur_energy;
00531 sc->video_talker.energy_average = sc->video_talker.energy_accum / DEFAULT_ENERGY_HISTORY_LEN;
00532 sc->video_talker.energy_history_cur_slot++;
00533 if (sc->video_talker.energy_history_cur_slot == DEFAULT_ENERGY_HISTORY_LEN) {
00534 sc->video_talker.energy_history_cur_slot = 0;
00535 }
00536 }
00537
00538 if (totalsilence < silence_threshold) {
00539 if (!sc->talking) {
00540 update_talking = 1;
00541 }
00542 sc->talking = 1;
00543 } else {
00544 if (sc->talking) {
00545 update_talking = 0;
00546 }
00547 sc->talking = 0;
00548 }
00549
00550
00551
00552
00553 if (ast_slinfactory_available(&sc->factory) > (4 * SOFTMIX_SAMPLES(softmix_data->internal_rate, softmix_data->internal_mixing_interval))) {
00554 ast_slinfactory_flush(&sc->factory);
00555 }
00556
00557
00558
00559 if (!(bridge_channel->tech_args.drop_silence && !sc->talking) &&
00560 (frame->frametype == AST_FRAME_VOICE && ast_format_is_slinear(&frame->subclass.format))) {
00561 ast_slinfactory_feed(&sc->factory, frame);
00562 }
00563
00564
00565 if (sc->have_frame) {
00566 ast_write(bridge_channel->chan, &sc->write_frame);
00567 sc->have_frame = 0;
00568 }
00569
00570
00571 ast_mutex_unlock(&sc->lock);
00572
00573 if (update_talking != -1) {
00574 ast_bridge_notify_talking(bridge, bridge_channel, update_talking);
00575 }
00576
00577 return res;
00578
00579 bridge_write_cleanup:
00580
00581
00582
00583 ast_mutex_lock(&sc->lock);
00584 if (sc->have_frame) {
00585 ast_write(bridge_channel->chan, &sc->write_frame);
00586 sc->have_frame = 0;
00587 }
00588 ast_mutex_unlock(&sc->lock);
00589
00590 return res;
00591 }
00592
00593
00594 static int softmix_bridge_poke(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
00595 {
00596 struct softmix_channel *sc = bridge_channel->bridge_pvt;
00597
00598 ast_mutex_lock(&sc->lock);
00599
00600 if (sc->have_frame) {
00601 ast_write(bridge_channel->chan, &sc->write_frame);
00602 sc->have_frame = 0;
00603 }
00604
00605 ast_mutex_unlock(&sc->lock);
00606
00607 return 0;
00608 }
00609
00610 static void gather_softmix_stats(struct softmix_stats *stats,
00611 const struct softmix_bridge_data *softmix_data,
00612 struct ast_bridge_channel *bridge_channel)
00613 {
00614 int channel_native_rate;
00615 int i;
00616
00617 channel_native_rate = MAX(ast_format_rate(ast_channel_rawwriteformat(bridge_channel->chan)),
00618 ast_format_rate(ast_channel_rawreadformat(bridge_channel->chan)));
00619
00620 if (channel_native_rate > stats->highest_supported_rate) {
00621 stats->highest_supported_rate = channel_native_rate;
00622 }
00623 if (channel_native_rate > softmix_data->internal_rate) {
00624 for (i = 0; i < ARRAY_LEN(stats->sample_rates); i++) {
00625 if (stats->sample_rates[i] == channel_native_rate) {
00626 stats->num_channels[i]++;
00627 break;
00628 } else if (!stats->sample_rates[i]) {
00629 stats->sample_rates[i] = channel_native_rate;
00630 stats->num_channels[i]++;
00631 break;
00632 }
00633 }
00634 stats->num_above_internal_rate++;
00635 } else if (channel_native_rate == softmix_data->internal_rate) {
00636 stats->num_at_internal_rate++;
00637 }
00638 }
00639
00640
00641
00642
00643
00644
00645
00646
00647 static unsigned int analyse_softmix_stats(struct softmix_stats *stats, struct softmix_bridge_data *softmix_data)
00648 {
00649 int i;
00650
00651
00652
00653
00654
00655
00656 if (stats->locked_rate) {
00657
00658
00659 if (softmix_data->internal_rate != stats->locked_rate) {
00660 softmix_data->internal_rate = stats->locked_rate;
00661 ast_debug(1, " Bridge is locked in at sample rate %d\n", softmix_data->internal_rate);
00662 return 1;
00663 }
00664 } else if (stats->num_above_internal_rate >= 2) {
00665
00666 unsigned int best_rate = stats->highest_supported_rate;
00667 int best_index = -1;
00668
00669 for (i = 0; i < ARRAY_LEN(stats->num_channels); i++) {
00670 if (stats->num_channels[i]) {
00671 break;
00672 }
00673
00674
00675
00676 if (stats->num_channels[i] >= 2 && (best_index == -1)) {
00677 best_rate = stats->sample_rates[i];
00678 best_index = i;
00679
00680
00681
00682
00683 } else if (((best_index != -1) &&
00684 (stats->num_channels[i] >= 2) &&
00685 (stats->sample_rates[best_index] < stats->sample_rates[i]))) {
00686 best_rate = stats->sample_rates[i];
00687 best_index = i;
00688
00689
00690
00691
00692
00693
00694
00695 } else if (best_index == -1) {
00696 best_rate = MIN(best_rate, stats->sample_rates[i]);
00697 }
00698 }
00699
00700 ast_debug(1, " Bridge changed from %d To %d\n", softmix_data->internal_rate, best_rate);
00701 softmix_data->internal_rate = best_rate;
00702 return 1;
00703 } else if (!stats->num_at_internal_rate && !stats->num_above_internal_rate) {
00704
00705 softmix_data->internal_rate = stats->highest_supported_rate;
00706 ast_debug(1, " Bridge changed from %d to %d\n", softmix_data->internal_rate, stats->highest_supported_rate);
00707 return 1;
00708 }
00709 return 0;
00710 }
00711
00712 static int softmix_mixing_array_init(struct softmix_mixing_array *mixing_array, unsigned int starting_num_entries)
00713 {
00714 memset(mixing_array, 0, sizeof(*mixing_array));
00715 mixing_array->max_num_entries = starting_num_entries;
00716 if (!(mixing_array->buffers = ast_calloc(mixing_array->max_num_entries, sizeof(int16_t *)))) {
00717 ast_log(LOG_NOTICE, "Failed to allocate softmix mixing structure. \n");
00718 return -1;
00719 }
00720 return 0;
00721 }
00722
00723 static void softmix_mixing_array_destroy(struct softmix_mixing_array *mixing_array)
00724 {
00725 ast_free(mixing_array->buffers);
00726 }
00727
00728 static int softmix_mixing_array_grow(struct softmix_mixing_array *mixing_array, unsigned int num_entries)
00729 {
00730 int16_t **tmp;
00731
00732 mixing_array->max_num_entries = num_entries;
00733 if (!(tmp = ast_realloc(mixing_array->buffers, (mixing_array->max_num_entries * sizeof(int16_t *))))) {
00734 ast_log(LOG_NOTICE, "Failed to re-allocate softmix mixing structure. \n");
00735 return -1;
00736 }
00737 mixing_array->buffers = tmp;
00738 return 0;
00739 }
00740
00741
00742 static int softmix_bridge_thread(struct ast_bridge *bridge)
00743 {
00744 struct softmix_stats stats = { { 0 }, };
00745 struct softmix_mixing_array mixing_array;
00746 struct softmix_bridge_data *softmix_data = bridge->bridge_pvt;
00747 struct ast_timer *timer;
00748 struct softmix_translate_helper trans_helper;
00749 int16_t buf[MAX_DATALEN] = { 0, };
00750 unsigned int stat_iteration_counter = 0;
00751 int timingfd;
00752 int update_all_rates = 0;
00753 int i, x;
00754 int res = -1;
00755
00756 if (!(softmix_data = bridge->bridge_pvt)) {
00757 goto softmix_cleanup;
00758 }
00759
00760 ao2_ref(softmix_data, 1);
00761 timer = softmix_data->timer;
00762 timingfd = ast_timer_fd(timer);
00763 softmix_translate_helper_init(&trans_helper, softmix_data->internal_rate);
00764 ast_timer_set_rate(timer, (1000 / softmix_data->internal_mixing_interval));
00765
00766
00767 if (softmix_mixing_array_init(&mixing_array, bridge->num + 10)) {
00768 ast_log(LOG_NOTICE, "Failed to allocate softmix mixing structure. \n");
00769 goto softmix_cleanup;
00770 }
00771
00772 while (!bridge->stop && !bridge->refresh && bridge->array_num) {
00773 struct ast_bridge_channel *bridge_channel = NULL;
00774 int timeout = -1;
00775 enum ast_format_id cur_slin_id = ast_format_slin_by_rate(softmix_data->internal_rate);
00776 unsigned int softmix_samples = SOFTMIX_SAMPLES(softmix_data->internal_rate, softmix_data->internal_mixing_interval);
00777 unsigned int softmix_datalen = SOFTMIX_DATALEN(softmix_data->internal_rate, softmix_data->internal_mixing_interval);
00778
00779 if (softmix_datalen > MAX_DATALEN) {
00780
00781
00782
00783
00784 ast_log(LOG_WARNING, "Conference mixing error, requested mixing length greater than mixing buffer.\n");
00785 goto softmix_cleanup;
00786 }
00787
00788
00789 if (mixing_array.max_num_entries < bridge->num && softmix_mixing_array_grow(&mixing_array, bridge->num + 5)) {
00790 goto softmix_cleanup;
00791 }
00792
00793
00794
00795 mixing_array.used_entries = 0;
00796
00797
00798 if (!stat_iteration_counter) {
00799 memset(&stats, 0, sizeof(stats));
00800 stats.locked_rate = bridge->internal_sample_rate;
00801 }
00802
00803
00804 if (update_all_rates) {
00805 softmix_translate_helper_change_rate(&trans_helper, softmix_data->internal_rate);
00806 }
00807
00808
00809 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
00810 struct softmix_channel *sc = bridge_channel->bridge_pvt;
00811
00812
00813 if (update_all_rates) {
00814 set_softmix_bridge_data(softmix_data->internal_rate, softmix_data->internal_mixing_interval, bridge_channel, 1);
00815 }
00816
00817
00818 if (!stat_iteration_counter) {
00819 gather_softmix_stats(&stats, softmix_data, bridge_channel);
00820 }
00821
00822
00823 if (bridge_channel->suspended) {
00824 continue;
00825 }
00826
00827
00828 ast_mutex_lock(&sc->lock);
00829 if ((mixing_array.buffers[mixing_array.used_entries] = softmix_process_read_audio(sc, softmix_samples))) {
00830 mixing_array.used_entries++;
00831 }
00832 ast_mutex_unlock(&sc->lock);
00833 }
00834
00835
00836 memset(buf, 0, softmix_datalen);
00837 for (i = 0; i < mixing_array.used_entries; i++) {
00838 for (x = 0; x < softmix_samples; x++) {
00839 ast_slinear_saturated_add(buf + x, mixing_array.buffers[i] + x);
00840 }
00841 }
00842
00843
00844 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
00845 struct softmix_channel *sc = bridge_channel->bridge_pvt;
00846
00847 if (bridge_channel->suspended) {
00848 continue;
00849 }
00850
00851 ast_mutex_lock(&sc->lock);
00852
00853
00854 if (sc->write_frame.subclass.format.id != cur_slin_id) {
00855 ast_format_set(&sc->write_frame.subclass.format, cur_slin_id, 0);
00856 }
00857 sc->write_frame.datalen = softmix_datalen;
00858 sc->write_frame.samples = softmix_samples;
00859 memcpy(sc->final_buf, buf, softmix_datalen);
00860
00861
00862 softmix_process_write_audio(&trans_helper, ast_channel_rawwriteformat(bridge_channel->chan), sc);
00863
00864
00865 sc->have_frame = 1;
00866
00867 ast_mutex_unlock(&sc->lock);
00868
00869
00870 pthread_kill(bridge_channel->thread, SIGURG);
00871 }
00872
00873 update_all_rates = 0;
00874 if (!stat_iteration_counter) {
00875 update_all_rates = analyse_softmix_stats(&stats, softmix_data);
00876 stat_iteration_counter = SOFTMIX_STAT_INTERVAL;
00877 }
00878 stat_iteration_counter--;
00879
00880 ao2_unlock(bridge);
00881
00882 softmix_translate_helper_cleanup(&trans_helper);
00883
00884 ast_waitfor_n_fd(&timingfd, 1, &timeout, NULL);
00885 ast_timer_ack(timer, 1);
00886 ao2_lock(bridge);
00887
00888
00889 if (bridge->internal_mixing_interval && (bridge->internal_mixing_interval != softmix_data->internal_mixing_interval)) {
00890 softmix_data->internal_mixing_interval = bridge->internal_mixing_interval;
00891 ast_timer_set_rate(timer, (1000 / softmix_data->internal_mixing_interval));
00892 update_all_rates = 1;
00893 }
00894 }
00895
00896 res = 0;
00897
00898 softmix_cleanup:
00899 softmix_translate_helper_destroy(&trans_helper);
00900 softmix_mixing_array_destroy(&mixing_array);
00901 if (softmix_data) {
00902 ao2_ref(softmix_data, -1);
00903 }
00904 return res;
00905 }
00906
00907 static struct ast_bridge_technology softmix_bridge = {
00908 .name = "softmix",
00909 .capabilities = AST_BRIDGE_CAPABILITY_MULTIMIX | AST_BRIDGE_CAPABILITY_THREAD | AST_BRIDGE_CAPABILITY_MULTITHREADED | AST_BRIDGE_CAPABILITY_OPTIMIZE | AST_BRIDGE_CAPABILITY_VIDEO,
00910 .preference = AST_BRIDGE_PREFERENCE_LOW,
00911 .create = softmix_bridge_create,
00912 .destroy = softmix_bridge_destroy,
00913 .join = softmix_bridge_join,
00914 .leave = softmix_bridge_leave,
00915 .write = softmix_bridge_write,
00916 .thread = softmix_bridge_thread,
00917 .poke = softmix_bridge_poke,
00918 };
00919
00920 static int unload_module(void)
00921 {
00922 ast_format_cap_destroy(softmix_bridge.format_capabilities);
00923 return ast_bridge_technology_unregister(&softmix_bridge);
00924 }
00925
00926 static int load_module(void)
00927 {
00928 struct ast_format tmp;
00929 if (!(softmix_bridge.format_capabilities = ast_format_cap_alloc())) {
00930 return AST_MODULE_LOAD_DECLINE;
00931 }
00932 ast_format_cap_add(softmix_bridge.format_capabilities, ast_format_set(&tmp, AST_FORMAT_SLINEAR, 0));
00933 return ast_bridge_technology_register(&softmix_bridge);
00934 }
00935
00936 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Multi-party software based channel mixing");