bridge_softmix.c File Reference

Multi-party software based channel mixing. More...

#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/bridge.h"
#include "asterisk/bridge_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"
#include "asterisk/translate.h"

Include dependency graph for bridge_softmix.c:

Go to the source code of this file.

Data Structures

struct  softmix_bridge_data
struct  softmix_channel
 Structure which contains per-channel mixing information. More...
struct  softmix_mixing_array
struct  softmix_stats
struct  softmix_translate_helper
struct  softmix_translate_helper_entry
struct  video_follow_talker_data

Defines

#define DEFAULT_ENERGY_HISTORY_LEN   150
#define DEFAULT_SOFTMIX_INTERVAL   20
 Interval at which mixing will take place. Valid options are 10, 20, and 40.
#define DEFAULT_SOFTMIX_SILENCE_THRESHOLD   2500
#define DEFAULT_SOFTMIX_TALKING_THRESHOLD   160
#define MAX_DATALEN   8096
#define SOFTMIX_DATALEN(rate, interval)   ((rate/50) * (interval / 10))
 Size of the buffer used for sample manipulation.
#define SOFTMIX_MIN_SAMPLE_RATE   8000
#define SOFTMIX_SAMPLES(rate, interval)   (SOFTMIX_DATALEN(rate, interval) / 2)
 Number of samples we are dealing with.
#define SOFTMIX_STAT_INTERVAL   100
 Number of mixing iterations to perform between gathering statistics.

Functions

static void __reg_module (void)
static void __unreg_module (void)
static unsigned int analyse_softmix_stats (struct softmix_stats *stats, struct softmix_bridge_data *softmix_data)
static void gather_softmix_stats (struct softmix_stats *stats, const struct softmix_bridge_data *softmix_data, struct ast_bridge_channel *bridge_channel)
static int load_module (void)
static void set_softmix_bridge_data (int rate, int interval, struct ast_bridge_channel *bridge_channel, int reset)
static int softmix_bridge_create (struct ast_bridge *bridge)
 Function called when a bridge is created.
static void softmix_bridge_data_destroy (struct softmix_bridge_data *softmix_data)
static void 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 void softmix_bridge_leave (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 Function called when a channel leaves the bridge.
static void softmix_bridge_stop (struct ast_bridge *bridge)
static void softmix_bridge_unsuspend (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 Function called when a channel is unsuspended from the bridge.
static int softmix_bridge_write (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
static int softmix_bridge_write_control (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
static void softmix_bridge_write_video (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
static void softmix_bridge_write_voice (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
static void softmix_mixing_array_destroy (struct softmix_mixing_array *mixing_array)
static int softmix_mixing_array_grow (struct softmix_mixing_array *mixing_array, unsigned int num_entries)
static int softmix_mixing_array_init (struct softmix_mixing_array *mixing_array, unsigned int starting_num_entries)
static int softmix_mixing_loop (struct ast_bridge *bridge)
 Mixing loop.
static void * softmix_mixing_thread (void *data)
static void softmix_pass_video_top_priority (struct ast_bridge *bridge, struct ast_frame *frame)
static void softmix_poke_thread (struct softmix_bridge_data *softmix_data)
static int16_tsoftmix_process_read_audio (struct softmix_channel *sc, unsigned int num_samples)
static void softmix_process_write_audio (struct softmix_translate_helper *trans_helper, struct ast_format *raw_write_fmt, struct softmix_channel *sc)
static int softmix_src_change (struct ast_bridge_channel *bridge_channel)
static void softmix_translate_helper_change_rate (struct softmix_translate_helper *trans_helper, unsigned int sample_rate)
static void softmix_translate_helper_cleanup (struct softmix_translate_helper *trans_helper)
static void softmix_translate_helper_destroy (struct softmix_translate_helper *trans_helper)
static struct
softmix_translate_helper_entry
softmix_translate_helper_entry_alloc (struct ast_format *dst)
static void * softmix_translate_helper_free_entry (struct softmix_translate_helper_entry *entry)
static void softmix_translate_helper_init (struct softmix_translate_helper *trans_helper, unsigned int sample_rate)
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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_bridge_technology softmix_bridge


Detailed Description

Multi-party software based channel mixing.

Author:
Joshua Colp <jcolp@digium.com>

David Vossel <dvossel@digium.com>

Definition in file bridge_softmix.c.


Define Documentation

#define DEFAULT_ENERGY_HISTORY_LEN   150

Definition at line 80 of file bridge_softmix.c.

Referenced by softmix_bridge_write_voice().

#define DEFAULT_SOFTMIX_INTERVAL   20

Interval at which mixing will take place. Valid options are 10, 20, and 40.

Definition at line 64 of file bridge_softmix.c.

Referenced by softmix_bridge_create(), and softmix_bridge_join().

#define DEFAULT_SOFTMIX_SILENCE_THRESHOLD   2500

Definition at line 77 of file bridge_softmix.c.

Referenced by softmix_bridge_write_voice().

#define DEFAULT_SOFTMIX_TALKING_THRESHOLD   160

Definition at line 78 of file bridge_softmix.c.

Referenced by set_softmix_bridge_data().

#define MAX_DATALEN   8096

Definition at line 58 of file bridge_softmix.c.

Referenced by softmix_mixing_loop(), and softmix_process_write_audio().

#define SOFTMIX_DATALEN ( rate,
interval   )     ((rate/50) * (interval / 10))

Size of the buffer used for sample manipulation.

Definition at line 67 of file bridge_softmix.c.

Referenced by set_softmix_bridge_data(), and softmix_mixing_loop().

#define SOFTMIX_MIN_SAMPLE_RATE   8000

The minimum sample rate of the bridge.

Definition at line 61 of file bridge_softmix.c.

Referenced by gather_softmix_stats(), and softmix_bridge_create().

#define SOFTMIX_SAMPLES ( rate,
interval   )     (SOFTMIX_DATALEN(rate, interval) / 2)

Number of samples we are dealing with.

Definition at line 70 of file bridge_softmix.c.

Referenced by set_softmix_bridge_data(), softmix_bridge_write_voice(), and softmix_mixing_loop().

#define SOFTMIX_STAT_INTERVAL   100

Number of mixing iterations to perform between gathering statistics.

Definition at line 73 of file bridge_softmix.c.

Referenced by softmix_mixing_loop().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1247 of file bridge_softmix.c.

static void __unreg_module ( void   )  [static]

Definition at line 1247 of file bridge_softmix.c.

static unsigned int analyse_softmix_stats ( struct softmix_stats stats,
struct softmix_bridge_data softmix_data 
) [static]

Definition at line 794 of file bridge_softmix.c.

References ARRAY_LEN, ast_debug, softmix_stats::highest_supported_rate, softmix_bridge_data::internal_rate, softmix_stats::locked_rate, MIN, softmix_stats::num_above_internal_rate, softmix_stats::num_at_internal_rate, softmix_stats::num_channels, and softmix_stats::sample_rates.

Referenced by softmix_mixing_loop().

00795 {
00796    int i;
00797 
00798    /*
00799     * Re-adjust the internal bridge sample rate if
00800     * 1. The bridge's internal sample rate is locked in at a sample
00801     *    rate other than the current sample rate being used.
00802     * 2. two or more channels support a higher sample rate
00803     * 3. no channels support the current sample rate or a higher rate
00804     */
00805    if (stats->locked_rate) {
00806       /* if the rate is locked by the bridge, only update it if it differs
00807        * from the current rate we are using. */
00808       if (softmix_data->internal_rate != stats->locked_rate) {
00809          ast_debug(1, "Locking at new rate.  Bridge changed from %u to %u.\n",
00810             softmix_data->internal_rate, stats->locked_rate);
00811          softmix_data->internal_rate = stats->locked_rate;
00812          return 1;
00813       }
00814    } else if (stats->num_above_internal_rate >= 2) {
00815       /* the highest rate is just used as a starting point */
00816       unsigned int best_rate = stats->highest_supported_rate;
00817       int best_index = -1;
00818 
00819       for (i = 0; i < ARRAY_LEN(stats->num_channels); i++) {
00820          if (stats->num_channels[i]) {
00821             break;
00822          }
00823          if (2 <= stats->num_channels[i]) {
00824             /* Two or more channels support this rate. */
00825             if (best_index == -1
00826                || stats->sample_rates[best_index] < stats->sample_rates[i]) {
00827                /*
00828                 * best_rate starts out being the first sample rate
00829                 * greater than the internal sample rate that two or
00830                 * more channels support.
00831                 *
00832                 * or
00833                 *
00834                 * There are multiple rates above the internal rate
00835                 * and this rate is higher than the previous rate two
00836                 * or more channels support.
00837                 */
00838                best_rate = stats->sample_rates[i];
00839                best_index = i;
00840             }
00841          } else if (best_index == -1) {
00842             /*
00843              * It is possible that multiple channels exist with native sample
00844              * rates above the internal sample rate, but none of those channels
00845              * have the same rate in common.  In this case, the lowest sample
00846              * rate among those channels is picked. Over time as additional
00847              * statistic runs are made the internal sample rate number will
00848              * adjust to the most optimal sample rate, but it may take multiple
00849              * iterations.
00850              */
00851             best_rate = MIN(best_rate, stats->sample_rates[i]);
00852          }
00853       }
00854 
00855       ast_debug(1, "Multiple above internal rate.  Bridge changed from %u to %u.\n",
00856          softmix_data->internal_rate, best_rate);
00857       softmix_data->internal_rate = best_rate;
00858       return 1;
00859    } else if (!stats->num_at_internal_rate && !stats->num_above_internal_rate) {
00860       /* In this case, the highest supported rate is actually lower than the internal rate */
00861       ast_debug(1, "All below internal rate.  Bridge changed from %u to %u.\n",
00862          softmix_data->internal_rate, stats->highest_supported_rate);
00863       softmix_data->internal_rate = stats->highest_supported_rate;
00864       return 1;
00865    }
00866    return 0;
00867 }

static void gather_softmix_stats ( struct softmix_stats stats,
const struct softmix_bridge_data softmix_data,
struct ast_bridge_channel bridge_channel 
) [static]

Definition at line 752 of file bridge_softmix.c.

References ARRAY_LEN, ast_channel_lock, ast_channel_rawreadformat(), ast_channel_unlock, ast_format_get_sample_rate(), ast_bridge_channel::chan, softmix_stats::highest_supported_rate, softmix_bridge_data::internal_rate, MAX, softmix_stats::num_above_internal_rate, softmix_stats::num_at_internal_rate, softmix_stats::num_channels, softmix_stats::sample_rates, and SOFTMIX_MIN_SAMPLE_RATE.

Referenced by softmix_mixing_loop().

00755 {
00756    int channel_native_rate;
00757 
00758    /* Gather stats about channel sample rates. */
00759    ast_channel_lock(bridge_channel->chan);
00760    channel_native_rate = MAX(SOFTMIX_MIN_SAMPLE_RATE,
00761       ast_format_get_sample_rate(ast_channel_rawreadformat(bridge_channel->chan)));
00762    ast_channel_unlock(bridge_channel->chan);
00763 
00764    if (stats->highest_supported_rate < channel_native_rate) {
00765       stats->highest_supported_rate = channel_native_rate;
00766    }
00767    if (softmix_data->internal_rate < channel_native_rate) {
00768       int i;
00769 
00770       for (i = 0; i < ARRAY_LEN(stats->sample_rates); i++) {
00771          if (stats->sample_rates[i] == channel_native_rate) {
00772             stats->num_channels[i]++;
00773             break;
00774          } else if (!stats->sample_rates[i]) {
00775             stats->sample_rates[i] = channel_native_rate;
00776             stats->num_channels[i]++;
00777             break;
00778          }
00779       }
00780       stats->num_above_internal_rate++;
00781    } else if (softmix_data->internal_rate == channel_native_rate) {
00782       stats->num_at_internal_rate++;
00783    }
00784 }

static int load_module ( void   )  [static]

static void set_softmix_bridge_data ( int  rate,
int  interval,
struct ast_bridge_channel bridge_channel,
int  reset 
) [static]

Definition at line 356 of file bridge_softmix.c.

References ao2_replace, ast_channel_lock, ast_channel_rawreadformat(), ast_channel_unlock, ast_dsp_free(), ast_dsp_new_with_rate(), ast_dsp_set_threshold(), ast_format_cache_get_slin_by_rate(), AST_FRAME_VOICE, ast_mutex_lock, ast_mutex_unlock, ast_set_read_format_path(), ast_set_write_format(), ast_slinfactory_destroy(), ast_slinfactory_init_with_format(), ast_bridge_channel::chan, ast_frame::data, ast_frame::datalen, DEFAULT_SOFTMIX_TALKING_THRESHOLD, softmix_channel::dsp, softmix_channel::factory, softmix_channel::final_buf, ast_frame_subclass::format, ast_frame::frametype, softmix_channel::lock, ast_frame::ptr, softmix_channel::read_slin_format, ast_frame::samples, SOFTMIX_DATALEN, SOFTMIX_SAMPLES, ast_frame::subclass, ast_bridge_tech_optimizations::talking_threshold, ast_bridge_channel::tech_args, ast_bridge_channel::tech_pvt, and softmix_channel::write_frame.

Referenced by softmix_bridge_join(), and softmix_mixing_loop().

00357 {
00358    struct softmix_channel *sc = bridge_channel->tech_pvt;
00359    struct ast_format *slin_format;
00360 
00361    slin_format = ast_format_cache_get_slin_by_rate(rate);
00362 
00363    ast_mutex_lock(&sc->lock);
00364    if (reset) {
00365       ast_slinfactory_destroy(&sc->factory);
00366       ast_dsp_free(sc->dsp);
00367    }
00368 
00369    /* Setup write frame parameters */
00370    sc->write_frame.frametype = AST_FRAME_VOICE;
00371    /*
00372     * NOTE: The write_frame format holds a reference because translation
00373     * could be needed and the format changed to the translated format
00374     * for the channel.  The translated format may not be a
00375     * static cached format.
00376     */
00377    ao2_replace(sc->write_frame.subclass.format, slin_format);
00378    sc->write_frame.data.ptr = sc->final_buf;
00379    sc->write_frame.datalen = SOFTMIX_DATALEN(rate, interval);
00380    sc->write_frame.samples = SOFTMIX_SAMPLES(rate, interval);
00381 
00382    /*
00383     * NOTE: The read_slin_format does not hold a reference because it
00384     * will always be a signed linear format.
00385     */
00386    sc->read_slin_format = slin_format;
00387 
00388    /* Setup smoother */
00389    ast_slinfactory_init_with_format(&sc->factory, slin_format);
00390 
00391    /* set new read and write formats on channel. */
00392    ast_channel_lock(bridge_channel->chan);
00393    ast_set_read_format_path(bridge_channel->chan,
00394       ast_channel_rawreadformat(bridge_channel->chan), slin_format);
00395    ast_channel_unlock(bridge_channel->chan);
00396    ast_set_write_format(bridge_channel->chan, slin_format);
00397 
00398    /* set up new DSP.  This is on the read side only right before the read frame enters the smoother.  */
00399    sc->dsp = ast_dsp_new_with_rate(rate);
00400    /* we want to aggressively detect silence to avoid feedback */
00401    if (bridge_channel->tech_args.talking_threshold) {
00402       ast_dsp_set_threshold(sc->dsp, bridge_channel->tech_args.talking_threshold);
00403    } else {
00404       ast_dsp_set_threshold(sc->dsp, DEFAULT_SOFTMIX_TALKING_THRESHOLD);
00405    }
00406 
00407    ast_mutex_unlock(&sc->lock);
00408 }

static int softmix_bridge_create ( struct ast_bridge bridge  )  [static]

Function called when a bridge is created.

Definition at line 1134 of file bridge_softmix.c.

References ast_calloc, ast_cond_init, ast_log, AST_LOG_WARNING, ast_mutex_init, ast_pthread_create, AST_PTHREADT_NULL, ast_timer_open(), softmix_bridge_data::bridge, softmix_bridge_data::cond, DEFAULT_SOFTMIX_INTERVAL, softmix_bridge_data::internal_mixing_interval, softmix_bridge_data::internal_rate, softmix_bridge_data::lock, NULL, softmix_bridge_data_destroy(), SOFTMIX_MIN_SAMPLE_RATE, softmix_mixing_thread(), ast_bridge::tech_pvt, softmix_bridge_data::thread, and softmix_bridge_data::timer.

01135 {
01136    struct softmix_bridge_data *softmix_data;
01137 
01138    softmix_data = ast_calloc(1, sizeof(*softmix_data));
01139    if (!softmix_data) {
01140       return -1;
01141    }
01142    softmix_data->bridge = bridge;
01143    ast_mutex_init(&softmix_data->lock);
01144    ast_cond_init(&softmix_data->cond, NULL);
01145    softmix_data->timer = ast_timer_open();
01146    if (!softmix_data->timer) {
01147       ast_log(AST_LOG_WARNING, "Failed to open timer for softmix bridge\n");
01148       softmix_bridge_data_destroy(softmix_data);
01149       return -1;
01150    }
01151    /* start at minimum rate, let it grow from there */
01152    softmix_data->internal_rate = SOFTMIX_MIN_SAMPLE_RATE;
01153    softmix_data->internal_mixing_interval = DEFAULT_SOFTMIX_INTERVAL;
01154 
01155    bridge->tech_pvt = softmix_data;
01156 
01157    /* Start the mixing thread. */
01158    if (ast_pthread_create(&softmix_data->thread, NULL, softmix_mixing_thread,
01159       softmix_data)) {
01160       softmix_data->thread = AST_PTHREADT_NULL;
01161       softmix_bridge_data_destroy(softmix_data);
01162       bridge->tech_pvt = NULL;
01163       return -1;
01164    }
01165 
01166    return 0;
01167 }

static void softmix_bridge_data_destroy ( struct softmix_bridge_data softmix_data  )  [static]

Definition at line 1122 of file bridge_softmix.c.

References ast_cond_destroy, ast_free, ast_mutex_destroy, ast_timer_close(), softmix_bridge_data::cond, softmix_bridge_data::lock, NULL, and softmix_bridge_data::timer.

Referenced by softmix_bridge_create(), and softmix_bridge_destroy().

01123 {
01124    if (softmix_data->timer) {
01125       ast_timer_close(softmix_data->timer);
01126       softmix_data->timer = NULL;
01127    }
01128    ast_mutex_destroy(&softmix_data->lock);
01129    ast_cond_destroy(&softmix_data->cond);
01130    ast_free(softmix_data);
01131 }

static void softmix_bridge_destroy ( struct ast_bridge bridge  )  [static]

Function called when a bridge is destroyed.

Definition at line 1193 of file bridge_softmix.c.

References ast_cond_signal, ast_debug, ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, softmix_bridge_data::cond, softmix_bridge_data::lock, NULL, softmix_bridge_data_destroy(), softmix_bridge_data::stop, ast_bridge::tech_pvt, softmix_bridge_data::thread, thread, and ast_bridge::uniqueid.

01194 {
01195    struct softmix_bridge_data *softmix_data;
01196    pthread_t thread;
01197 
01198    softmix_data = bridge->tech_pvt;
01199    if (!softmix_data) {
01200       return;
01201    }
01202 
01203    /* Stop the mixing thread. */
01204    ast_mutex_lock(&softmix_data->lock);
01205    softmix_data->stop = 1;
01206    ast_cond_signal(&softmix_data->cond);
01207    thread = softmix_data->thread;
01208    softmix_data->thread = AST_PTHREADT_NULL;
01209    ast_mutex_unlock(&softmix_data->lock);
01210    if (thread != AST_PTHREADT_NULL) {
01211       ast_debug(1, "Bridge %s: Waiting for mixing thread to die.\n", bridge->uniqueid);
01212       pthread_join(thread, NULL);
01213    }
01214 
01215    softmix_bridge_data_destroy(softmix_data);
01216    bridge->tech_pvt = NULL;
01217 }

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 450 of file bridge_softmix.c.

References ast_calloc, ast_mutex_init, DEFAULT_SOFTMIX_INTERVAL, softmix_bridge_data::internal_mixing_interval, softmix_bridge_data::internal_rate, softmix_channel::lock, set_softmix_bridge_data(), softmix_poke_thread(), softmix_src_change(), ast_bridge_channel::tech_pvt, and ast_bridge::tech_pvt.

00451 {
00452    struct softmix_channel *sc;
00453    struct softmix_bridge_data *softmix_data;
00454 
00455    softmix_data = bridge->tech_pvt;
00456    if (!softmix_data) {
00457       return -1;
00458    }
00459 
00460    /* Create a new softmix_channel structure and allocate various things on it */
00461    if (!(sc = ast_calloc(1, sizeof(*sc)))) {
00462       return -1;
00463    }
00464 
00465    softmix_src_change(bridge_channel);
00466 
00467    /* Can't forget the lock */
00468    ast_mutex_init(&sc->lock);
00469 
00470    /* Can't forget to record our pvt structure within the bridged channel structure */
00471    bridge_channel->tech_pvt = sc;
00472 
00473    set_softmix_bridge_data(softmix_data->internal_rate,
00474       softmix_data->internal_mixing_interval
00475          ? softmix_data->internal_mixing_interval
00476          : DEFAULT_SOFTMIX_INTERVAL,
00477       bridge_channel, 0);
00478 
00479    softmix_poke_thread(softmix_data);
00480    return 0;
00481 }

static void 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 484 of file bridge_softmix.c.

References ao2_cleanup, ast_dsp_free(), ast_free, ast_mutex_destroy, ast_slinfactory_destroy(), softmix_channel::dsp, softmix_channel::factory, ast_frame_subclass::format, softmix_channel::lock, NULL, softmix_src_change(), ast_frame::subclass, ast_bridge_channel::tech_pvt, and softmix_channel::write_frame.

00485 {
00486    struct softmix_channel *sc = bridge_channel->tech_pvt;
00487 
00488    if (!sc) {
00489       return;
00490    }
00491    bridge_channel->tech_pvt = NULL;
00492 
00493    softmix_src_change(bridge_channel);
00494 
00495    /* Drop mutex lock */
00496    ast_mutex_destroy(&sc->lock);
00497 
00498    /* Drop the factory */
00499    ast_slinfactory_destroy(&sc->factory);
00500 
00501    /* Drop any formats on the frames */
00502    ao2_cleanup(sc->write_frame.subclass.format);
00503 
00504    /* Drop the DSP */
00505    ast_dsp_free(sc->dsp);
00506 
00507    /* Eep! drop ourselves */
00508    ast_free(sc);
00509 }

static void softmix_bridge_stop ( struct ast_bridge bridge  )  [static]

Definition at line 1178 of file bridge_softmix.c.

References ast_mutex_lock, ast_mutex_unlock, softmix_bridge_data::lock, softmix_bridge_data::stop, and ast_bridge::tech_pvt.

01179 {
01180    struct softmix_bridge_data *softmix_data;
01181 
01182    softmix_data = bridge->tech_pvt;
01183    if (!softmix_data) {
01184       return;
01185    }
01186 
01187    ast_mutex_lock(&softmix_data->lock);
01188    softmix_data->stop = 1;
01189    ast_mutex_unlock(&softmix_data->lock);
01190 }

static void softmix_bridge_unsuspend ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel 
) [static]

Function called when a channel is unsuspended from the bridge.

Definition at line 427 of file bridge_softmix.c.

References softmix_poke_thread(), and ast_bridge::tech_pvt.

00428 {
00429    if (bridge->tech_pvt) {
00430       softmix_poke_thread(bridge->tech_pvt);
00431    }
00432 }

static int softmix_bridge_write ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel,
struct ast_frame frame 
) [static]

Definition at line 702 of file bridge_softmix.c.

References ast_assert, ast_bridge_queue_everyone_else(), ast_debug, AST_FRAME_BRIDGE_ACTION, AST_FRAME_BRIDGE_ACTION_SYNC, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_log, ast_frame::frametype, LOG_ERROR, softmix_bridge_write_control(), softmix_bridge_write_video(), softmix_bridge_write_voice(), ast_bridge_channel::tech_pvt, and ast_bridge::tech_pvt.

00703 {
00704    int res = 0;
00705 
00706    if (!bridge->tech_pvt || (bridge_channel && !bridge_channel->tech_pvt)) {
00707       /* "Accept" the frame and discard it. */
00708       return 0;
00709    }
00710 
00711    /*
00712     * XXX Softmix needs to use channel roles to determine who gets
00713     * what frame.  Possible roles: announcer, recorder, agent,
00714     * supervisor.
00715     */
00716    switch (frame->frametype) {
00717    case AST_FRAME_NULL:
00718       /* "Accept" the frame and discard it. */
00719       break;
00720    case AST_FRAME_DTMF_BEGIN:
00721    case AST_FRAME_DTMF_END:
00722       res = ast_bridge_queue_everyone_else(bridge, bridge_channel, frame);
00723       break;
00724    case AST_FRAME_VOICE:
00725       if (bridge_channel) {
00726          softmix_bridge_write_voice(bridge, bridge_channel, frame);
00727       }
00728       break;
00729    case AST_FRAME_VIDEO:
00730       if (bridge_channel) {
00731          softmix_bridge_write_video(bridge, bridge_channel, frame);
00732       }
00733       break;
00734    case AST_FRAME_CONTROL:
00735       res = softmix_bridge_write_control(bridge, bridge_channel, frame);
00736       break;
00737    case AST_FRAME_BRIDGE_ACTION:
00738       res = ast_bridge_queue_everyone_else(bridge, bridge_channel, frame);
00739       break;
00740    case AST_FRAME_BRIDGE_ACTION_SYNC:
00741       ast_log(LOG_ERROR, "Synchronous bridge action written to a softmix bridge.\n");
00742       ast_assert(0);
00743    default:
00744       ast_debug(3, "Frame type %u unsupported\n", frame->frametype);
00745       /* "Accept" the frame and discard it. */
00746       break;
00747    }
00748 
00749    return res;
00750 }

static int softmix_bridge_write_control ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel,
struct ast_frame frame 
) [static]

Definition at line 679 of file bridge_softmix.c.

Referenced by softmix_bridge_write().

00680 {
00681    /*
00682     * XXX Softmix needs to use channel roles to determine what to
00683     * do with control frames.
00684     */
00685    return 0;
00686 }

static void softmix_bridge_write_video ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel,
struct ast_frame frame 
) [static]

Definition at line 537 of file bridge_softmix.c.

References ast_bridge_is_video_src(), ast_bridge_number_video_src(), ast_bridge_queue_everyone_else(), ast_bridge_update_talker_src_video_mode(), AST_BRIDGE_VIDEO_MODE_NONE, AST_BRIDGE_VIDEO_MODE_SINGLE_SRC, AST_BRIDGE_VIDEO_MODE_TALKER_SRC, ast_mutex_lock, ast_mutex_unlock, ast_bridge_channel::chan, video_follow_talker_data::energy_average, ast_frame_subclass::frame_ending, softmix_channel::lock, ast_bridge_video_mode::mode, NULL, ast_bridge::softmix, softmix_pass_video_top_priority(), ast_frame::subclass, ast_bridge_channel::tech_pvt, ast_bridge_softmix::video_mode, and softmix_channel::video_talker.

Referenced by softmix_bridge_write().

00538 {
00539    struct softmix_channel *sc;
00540    int video_src_priority;
00541 
00542    /* Determine if the video frame should be distributed or not */
00543    switch (bridge->softmix.video_mode.mode) {
00544    case AST_BRIDGE_VIDEO_MODE_NONE:
00545       break;
00546    case AST_BRIDGE_VIDEO_MODE_SINGLE_SRC:
00547       video_src_priority = ast_bridge_is_video_src(bridge, bridge_channel->chan);
00548       if (video_src_priority == 1) {
00549          /* Pass to me and everyone else. */
00550          ast_bridge_queue_everyone_else(bridge, NULL, frame);
00551       }
00552       break;
00553    case AST_BRIDGE_VIDEO_MODE_TALKER_SRC:
00554       sc = bridge_channel->tech_pvt;
00555       ast_mutex_lock(&sc->lock);
00556       ast_bridge_update_talker_src_video_mode(bridge, bridge_channel->chan,
00557          sc->video_talker.energy_average,
00558          frame->subclass.frame_ending);
00559       ast_mutex_unlock(&sc->lock);
00560       video_src_priority = ast_bridge_is_video_src(bridge, bridge_channel->chan);
00561       if (video_src_priority == 1) {
00562          int num_src = ast_bridge_number_video_src(bridge);
00563          int echo = num_src > 1 ? 0 : 1;
00564 
00565          ast_bridge_queue_everyone_else(bridge, echo ? NULL : bridge_channel, frame);
00566       } else if (video_src_priority == 2) {
00567          softmix_pass_video_top_priority(bridge, frame);
00568       }
00569       break;
00570    }
00571 }

static void softmix_bridge_write_voice ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel,
struct ast_frame frame 
) [static]

Definition at line 584 of file bridge_softmix.c.

References ast_bridge_channel_notify_talking(), AST_BRIDGE_VIDEO_MODE_TALKER_SRC, ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_debug, ast_dsp_silence_with_energy(), ast_format_cmp(), AST_FORMAT_CMP_EQUAL, ast_format_get_name(), ast_mutex_lock, ast_mutex_unlock, ast_set_read_format_path(), ast_slinfactory_available(), ast_slinfactory_feed(), ast_slinfactory_flush(), ast_bridge_channel::chan, DEFAULT_ENERGY_HISTORY_LEN, DEFAULT_SOFTMIX_SILENCE_THRESHOLD, ast_bridge_tech_optimizations::drop_silence, softmix_channel::dsp, video_follow_talker_data::energy_accum, video_follow_talker_data::energy_average, video_follow_talker_data::energy_history, video_follow_talker_data::energy_history_cur_slot, softmix_channel::factory, ast_frame_subclass::format, softmix_bridge_data::internal_mixing_interval, softmix_bridge_data::internal_rate, softmix_channel::lock, ast_bridge_video_mode::mode, softmix_channel::read_slin_format, ast_bridge_tech_optimizations::silence_threshold, ast_bridge::softmix, SOFTMIX_SAMPLES, ast_frame::subclass, softmix_channel::talking, ast_bridge_channel::tech_args, ast_bridge::tech_pvt, ast_bridge_channel::tech_pvt, ast_bridge_softmix::video_mode, and softmix_channel::video_talker.

Referenced by softmix_bridge_write().

00585 {
00586    struct softmix_channel *sc = bridge_channel->tech_pvt;
00587    struct softmix_bridge_data *softmix_data = bridge->tech_pvt;
00588    int totalsilence = 0;
00589    int cur_energy = 0;
00590    int silence_threshold = bridge_channel->tech_args.silence_threshold ?
00591       bridge_channel->tech_args.silence_threshold :
00592       DEFAULT_SOFTMIX_SILENCE_THRESHOLD;
00593    char update_talking = -1;  /* if this is set to 0 or 1, tell the bridge that the channel has started or stopped talking. */
00594 
00595    /* Write the frame into the conference */
00596    ast_mutex_lock(&sc->lock);
00597 
00598    if (ast_format_cmp(frame->subclass.format, sc->read_slin_format) != AST_FORMAT_CMP_EQUAL) {
00599       /*
00600        * The incoming frame is not the expected format.  Update
00601        * the channel's translation path to get us slinear from
00602        * the new format for the next frame.
00603        *
00604        * There is the possibility that this frame is an old slinear
00605        * rate frame that was in flight when the softmix bridge
00606        * changed rates.  If so it will self correct on subsequent
00607        * frames.
00608        */
00609       ast_channel_lock(bridge_channel->chan);
00610       ast_debug(1, "Channel %s wrote unexpected format into bridge.  Got %s, expected %s.\n",
00611          ast_channel_name(bridge_channel->chan),
00612          ast_format_get_name(frame->subclass.format),
00613          ast_format_get_name(sc->read_slin_format));
00614       ast_set_read_format_path(bridge_channel->chan, frame->subclass.format,
00615          sc->read_slin_format);
00616       ast_channel_unlock(bridge_channel->chan);
00617    }
00618 
00619    ast_dsp_silence_with_energy(sc->dsp, frame, &totalsilence, &cur_energy);
00620 
00621    if (bridge->softmix.video_mode.mode == AST_BRIDGE_VIDEO_MODE_TALKER_SRC) {
00622       int cur_slot = sc->video_talker.energy_history_cur_slot;
00623 
00624       sc->video_talker.energy_accum -= sc->video_talker.energy_history[cur_slot];
00625       sc->video_talker.energy_accum += cur_energy;
00626       sc->video_talker.energy_history[cur_slot] = cur_energy;
00627       sc->video_talker.energy_average = sc->video_talker.energy_accum / DEFAULT_ENERGY_HISTORY_LEN;
00628       sc->video_talker.energy_history_cur_slot++;
00629       if (sc->video_talker.energy_history_cur_slot == DEFAULT_ENERGY_HISTORY_LEN) {
00630          sc->video_talker.energy_history_cur_slot = 0; /* wrap around */
00631       }
00632    }
00633 
00634    if (totalsilence < silence_threshold) {
00635       if (!sc->talking) {
00636          update_talking = 1;
00637       }
00638       sc->talking = 1; /* tell the write process we have audio to be mixed out */
00639    } else {
00640       if (sc->talking) {
00641          update_talking = 0;
00642       }
00643       sc->talking = 0;
00644    }
00645 
00646    /* Before adding audio in, make sure we haven't fallen behind. If audio has fallen
00647     * behind 4 times the amount of samples mixed on every iteration of the mixer, Re-sync
00648     * the audio by flushing the buffer before adding new audio in. */
00649    if (ast_slinfactory_available(&sc->factory) > (4 * SOFTMIX_SAMPLES(softmix_data->internal_rate, softmix_data->internal_mixing_interval))) {
00650       ast_slinfactory_flush(&sc->factory);
00651    }
00652 
00653    /* If a frame was provided add it to the smoother, unless drop silence is enabled and this frame
00654     * is not determined to be talking. */
00655    if (!(bridge_channel->tech_args.drop_silence && !sc->talking)) {
00656       ast_slinfactory_feed(&sc->factory, frame);
00657    }
00658 
00659    /* Alllll done */
00660    ast_mutex_unlock(&sc->lock);
00661 
00662    if (update_talking != -1) {
00663       ast_bridge_channel_notify_talking(bridge_channel, update_talking);
00664    }
00665 }

static void softmix_mixing_array_destroy ( struct softmix_mixing_array mixing_array  )  [static]

Definition at line 880 of file bridge_softmix.c.

References ast_free, and softmix_mixing_array::buffers.

Referenced by softmix_mixing_loop().

00881 {
00882    ast_free(mixing_array->buffers);
00883 }

static int softmix_mixing_array_grow ( struct softmix_mixing_array mixing_array,
unsigned int  num_entries 
) [static]

Definition at line 885 of file bridge_softmix.c.

References ast_log, ast_realloc, softmix_mixing_array::buffers, LOG_NOTICE, softmix_mixing_array::max_num_entries, and tmp().

Referenced by softmix_mixing_loop().

00886 {
00887    int16_t **tmp;
00888    /* give it some room to grow since memory is cheap but allocations can be expensive */
00889    mixing_array->max_num_entries = num_entries;
00890    if (!(tmp = ast_realloc(mixing_array->buffers, (mixing_array->max_num_entries * sizeof(int16_t *))))) {
00891       ast_log(LOG_NOTICE, "Failed to re-allocate softmix mixing structure.\n");
00892       return -1;
00893    }
00894    mixing_array->buffers = tmp;
00895    return 0;
00896 }

static int softmix_mixing_array_init ( struct softmix_mixing_array mixing_array,
unsigned int  starting_num_entries 
) [static]

Definition at line 869 of file bridge_softmix.c.

References ast_calloc, ast_log, softmix_mixing_array::buffers, LOG_NOTICE, and softmix_mixing_array::max_num_entries.

Referenced by softmix_mixing_loop().

00870 {
00871    memset(mixing_array, 0, sizeof(*mixing_array));
00872    mixing_array->max_num_entries = starting_num_entries;
00873    if (!(mixing_array->buffers = ast_calloc(mixing_array->max_num_entries, sizeof(int16_t *)))) {
00874       ast_log(LOG_NOTICE, "Failed to allocate softmix mixing structure.\n");
00875       return -1;
00876    }
00877    return 0;
00878 }

static int softmix_mixing_loop ( struct ast_bridge bridge  )  [static]

Mixing loop.

Return values:
0 on success
-1 on failure

Definition at line 904 of file bridge_softmix.c.

References analyse_softmix_stats(), ao2_t_replace, ast_bridge_channel_queue_frame(), ast_bridge_lock, ast_bridge_unlock, ast_channel_rawwriteformat(), ast_format_cache_get_slin_by_rate(), AST_LIST_TRAVERSE, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_slinear_saturated_add(), ast_timer_ack(), ast_timer_fd(), ast_timer_set_rate(), ast_waitfor_n_fd(), buf, softmix_mixing_array::buffers, ast_bridge_channel::chan, ast_bridge::channels, ast_frame::datalen, softmix_channel::final_buf, ast_frame_subclass::format, gather_softmix_stats(), ast_bridge_softmix::internal_mixing_interval, softmix_bridge_data::internal_mixing_interval, softmix_bridge_data::internal_rate, ast_bridge_softmix::internal_sample_rate, softmix_channel::lock, softmix_stats::locked_rate, LOG_ERROR, LOG_WARNING, MAX_DATALEN, softmix_mixing_array::max_num_entries, NULL, ast_bridge::num_active, ast_bridge::num_channels, ast_frame::samples, set_softmix_bridge_data(), ast_bridge::softmix, SOFTMIX_DATALEN, softmix_mixing_array_destroy(), softmix_mixing_array_grow(), softmix_mixing_array_init(), softmix_process_read_audio(), softmix_process_write_audio(), SOFTMIX_SAMPLES, SOFTMIX_STAT_INTERVAL, softmix_translate_helper_change_rate(), softmix_translate_helper_cleanup(), softmix_translate_helper_destroy(), softmix_translate_helper_init(), softmix_bridge_data::stop, ast_frame::subclass, ast_bridge_channel::suspended, ast_bridge_channel::tech_pvt, ast_bridge::tech_pvt, timeout, softmix_bridge_data::timer, timer, ast_bridge::uniqueid, softmix_mixing_array::used_entries, and softmix_channel::write_frame.

Referenced by softmix_mixing_thread().

00905 {
00906    struct softmix_stats stats = { { 0 }, };
00907    struct softmix_mixing_array mixing_array;
00908    struct softmix_bridge_data *softmix_data = bridge->tech_pvt;
00909    struct ast_timer *timer;
00910    struct softmix_translate_helper trans_helper;
00911    int16_t buf[MAX_DATALEN];
00912    unsigned int stat_iteration_counter = 0; /* counts down, gather stats at zero and reset. */
00913    int timingfd;
00914    int update_all_rates = 0; /* set this when the internal sample rate has changed */
00915    unsigned int idx;
00916    unsigned int x;
00917    int res = -1;
00918 
00919    timer = softmix_data->timer;
00920    timingfd = ast_timer_fd(timer);
00921    softmix_translate_helper_init(&trans_helper, softmix_data->internal_rate);
00922    ast_timer_set_rate(timer, (1000 / softmix_data->internal_mixing_interval));
00923 
00924    /* Give the mixing array room to grow, memory is cheap but allocations are expensive. */
00925    if (softmix_mixing_array_init(&mixing_array, bridge->num_channels + 10)) {
00926       goto softmix_cleanup;
00927    }
00928 
00929    /*
00930     * XXX Softmix needs to use channel roles to determine who gets
00931     * what audio mixed.
00932     */
00933    while (!softmix_data->stop && bridge->num_active) {
00934       struct ast_bridge_channel *bridge_channel;
00935       int timeout = -1;
00936       struct ast_format *cur_slin = ast_format_cache_get_slin_by_rate(softmix_data->internal_rate);
00937       unsigned int softmix_samples = SOFTMIX_SAMPLES(softmix_data->internal_rate, softmix_data->internal_mixing_interval);
00938       unsigned int softmix_datalen = SOFTMIX_DATALEN(softmix_data->internal_rate, softmix_data->internal_mixing_interval);
00939 
00940       if (softmix_datalen > MAX_DATALEN) {
00941          /* This should NEVER happen, but if it does we need to know about it. Almost
00942           * all the memcpys used during this process depend on this assumption.  Rather
00943           * than checking this over and over again through out the code, this single
00944           * verification is done on each iteration. */
00945          ast_log(LOG_WARNING,
00946             "Bridge %s: Conference mixing error, requested mixing length greater than mixing buffer.\n",
00947             bridge->uniqueid);
00948          goto softmix_cleanup;
00949       }
00950 
00951       /* Grow the mixing array buffer as participants are added. */
00952       if (mixing_array.max_num_entries < bridge->num_channels
00953          && softmix_mixing_array_grow(&mixing_array, bridge->num_channels + 5)) {
00954          goto softmix_cleanup;
00955       }
00956 
00957       /* init the number of buffers stored in the mixing array to 0.
00958        * As buffers are added for mixing, this number is incremented. */
00959       mixing_array.used_entries = 0;
00960 
00961       /* These variables help determine if a rate change is required */
00962       if (!stat_iteration_counter) {
00963          memset(&stats, 0, sizeof(stats));
00964          stats.locked_rate = bridge->softmix.internal_sample_rate;
00965       }
00966 
00967       /* If the sample rate has changed, update the translator helper */
00968       if (update_all_rates) {
00969          softmix_translate_helper_change_rate(&trans_helper, softmix_data->internal_rate);
00970       }
00971 
00972       /* Go through pulling audio from each factory that has it available */
00973       AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
00974          struct softmix_channel *sc = bridge_channel->tech_pvt;
00975 
00976          /* Update the sample rate to match the bridge's native sample rate if necessary. */
00977          if (update_all_rates) {
00978             set_softmix_bridge_data(softmix_data->internal_rate, softmix_data->internal_mixing_interval, bridge_channel, 1);
00979          }
00980 
00981          /* If stat_iteration_counter is 0, then collect statistics during this mixing interation */
00982          if (!stat_iteration_counter) {
00983             gather_softmix_stats(&stats, softmix_data, bridge_channel);
00984          }
00985 
00986          /* if the channel is suspended, don't check for audio, but still gather stats */
00987          if (bridge_channel->suspended) {
00988             continue;
00989          }
00990 
00991          /* Try to get audio from the factory if available */
00992          ast_mutex_lock(&sc->lock);
00993          if ((mixing_array.buffers[mixing_array.used_entries] = softmix_process_read_audio(sc, softmix_samples))) {
00994             mixing_array.used_entries++;
00995          }
00996          ast_mutex_unlock(&sc->lock);
00997       }
00998 
00999       /* mix it like crazy */
01000       memset(buf, 0, softmix_datalen);
01001       for (idx = 0; idx < mixing_array.used_entries; ++idx) {
01002          for (x = 0; x < softmix_samples; ++x) {
01003             ast_slinear_saturated_add(buf + x, mixing_array.buffers[idx] + x);
01004          }
01005       }
01006 
01007       /* Next step go through removing the channel's own audio and creating a good frame... */
01008       AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
01009          struct softmix_channel *sc = bridge_channel->tech_pvt;
01010 
01011          if (bridge_channel->suspended) {
01012             continue;
01013          }
01014 
01015          ast_mutex_lock(&sc->lock);
01016 
01017          /* Make SLINEAR write frame from local buffer */
01018          ao2_t_replace(sc->write_frame.subclass.format, cur_slin,
01019             "Replace softmix channel slin format");
01020          sc->write_frame.datalen = softmix_datalen;
01021          sc->write_frame.samples = softmix_samples;
01022          memcpy(sc->final_buf, buf, softmix_datalen);
01023 
01024          /* process the softmix channel's new write audio */
01025          softmix_process_write_audio(&trans_helper, ast_channel_rawwriteformat(bridge_channel->chan), sc);
01026 
01027          ast_mutex_unlock(&sc->lock);
01028 
01029          /* A frame is now ready for the channel. */
01030          ast_bridge_channel_queue_frame(bridge_channel, &sc->write_frame);
01031       }
01032 
01033       update_all_rates = 0;
01034       if (!stat_iteration_counter) {
01035          update_all_rates = analyse_softmix_stats(&stats, softmix_data);
01036          stat_iteration_counter = SOFTMIX_STAT_INTERVAL;
01037       }
01038       stat_iteration_counter--;
01039 
01040       ast_bridge_unlock(bridge);
01041       /* cleanup any translation frame data from the previous mixing iteration. */
01042       softmix_translate_helper_cleanup(&trans_helper);
01043       /* Wait for the timing source to tell us to wake up and get things done */
01044       ast_waitfor_n_fd(&timingfd, 1, &timeout, NULL);
01045       if (ast_timer_ack(timer, 1) < 0) {
01046          ast_log(LOG_ERROR, "Bridge %s: Failed to acknowledge timer in softmix.\n",
01047             bridge->uniqueid);
01048          ast_bridge_lock(bridge);
01049          goto softmix_cleanup;
01050       }
01051       ast_bridge_lock(bridge);
01052 
01053       /* make sure to detect mixing interval changes if they occur. */
01054       if (bridge->softmix.internal_mixing_interval
01055          && (bridge->softmix.internal_mixing_interval != softmix_data->internal_mixing_interval)) {
01056          softmix_data->internal_mixing_interval = bridge->softmix.internal_mixing_interval;
01057          ast_timer_set_rate(timer, (1000 / softmix_data->internal_mixing_interval));
01058          update_all_rates = 1; /* if the interval changes, the rates must be adjusted as well just to be notified new interval.*/
01059       }
01060    }
01061 
01062    res = 0;
01063 
01064 softmix_cleanup:
01065    softmix_translate_helper_destroy(&trans_helper);
01066    softmix_mixing_array_destroy(&mixing_array);
01067    return res;
01068 }

static void* softmix_mixing_thread ( void *  data  )  [static]

Definition at line 1079 of file bridge_softmix.c.

References ast_bridge_lock, ast_bridge_unlock, ast_callid_threadassoc_add(), ast_cond_wait, ast_debug, ast_mutex_lock, ast_mutex_unlock, softmix_bridge_data::bridge, ast_bridge::callid, softmix_bridge_data::cond, softmix_bridge_data::lock, NULL, ast_bridge::num_active, softmix_mixing_loop(), softmix_bridge_data::stop, and ast_bridge::uniqueid.

Referenced by softmix_bridge_create().

01080 {
01081    struct softmix_bridge_data *softmix_data = data;
01082    struct ast_bridge *bridge = softmix_data->bridge;
01083 
01084    ast_bridge_lock(bridge);
01085    if (bridge->callid) {
01086       ast_callid_threadassoc_add(bridge->callid);
01087    }
01088 
01089    ast_debug(1, "Bridge %s: starting mixing thread\n", bridge->uniqueid);
01090 
01091    while (!softmix_data->stop) {
01092       if (!bridge->num_active) {
01093          /* Wait for something to happen to the bridge. */
01094          ast_bridge_unlock(bridge);
01095          ast_mutex_lock(&softmix_data->lock);
01096          if (!softmix_data->stop) {
01097             ast_cond_wait(&softmix_data->cond, &softmix_data->lock);
01098          }
01099          ast_mutex_unlock(&softmix_data->lock);
01100          ast_bridge_lock(bridge);
01101          continue;
01102       }
01103 
01104       if (softmix_mixing_loop(bridge)) {
01105          /*
01106           * A mixing error occurred.  Sleep and try again later so we
01107           * won't flood the logs.
01108           */
01109          ast_bridge_unlock(bridge);
01110          sleep(1);
01111          ast_bridge_lock(bridge);
01112       }
01113    }
01114 
01115    ast_bridge_unlock(bridge);
01116 
01117    ast_debug(1, "Bridge %s: stopping mixing thread\n", bridge->uniqueid);
01118 
01119    return NULL;
01120 }

static void softmix_pass_video_top_priority ( struct ast_bridge bridge,
struct ast_frame frame 
) [static]

Definition at line 511 of file bridge_softmix.c.

References ast_bridge_channel_queue_frame(), ast_bridge_is_video_src(), AST_LIST_TRAVERSE, ast_bridge_channel::chan, ast_bridge::channels, and ast_bridge_channel::suspended.

Referenced by softmix_bridge_write_video().

00512 {
00513    struct ast_bridge_channel *cur;
00514 
00515    AST_LIST_TRAVERSE(&bridge->channels, cur, entry) {
00516       if (cur->suspended) {
00517          continue;
00518       }
00519       if (ast_bridge_is_video_src(bridge, cur->chan) == 1) {
00520          ast_bridge_channel_queue_frame(cur, frame);
00521          break;
00522       }
00523    }
00524 }

static void softmix_poke_thread ( struct softmix_bridge_data softmix_data  )  [static]

Definition at line 419 of file bridge_softmix.c.

References ast_cond_signal, ast_mutex_lock, ast_mutex_unlock, softmix_bridge_data::cond, and softmix_bridge_data::lock.

Referenced by softmix_bridge_join(), and softmix_bridge_unsuspend().

00420 {
00421    ast_mutex_lock(&softmix_data->lock);
00422    ast_cond_signal(&softmix_data->cond);
00423    ast_mutex_unlock(&softmix_data->lock);
00424 }

static int16_t* softmix_process_read_audio ( struct softmix_channel sc,
unsigned int  num_samples 
) [static]

Definition at line 247 of file bridge_softmix.c.

References ast_slinfactory_available(), ast_slinfactory_read(), softmix_channel::factory, softmix_channel::have_audio, NULL, and softmix_channel::our_buf.

Referenced by softmix_mixing_loop().

00248 {
00249    if ((ast_slinfactory_available(&sc->factory) >= num_samples) &&
00250       ast_slinfactory_read(&sc->factory, sc->our_buf, num_samples)) {
00251       sc->have_audio = 1;
00252       return sc->our_buf;
00253    }
00254    sc->have_audio = 0;
00255    return NULL;
00256 }

static void softmix_process_write_audio ( struct softmix_translate_helper trans_helper,
struct ast_format raw_write_fmt,
struct softmix_channel sc 
) [static]

Definition at line 266 of file bridge_softmix.c.

References ao2_replace, ast_format_cmp(), AST_FORMAT_CMP_EQUAL, AST_LIST_INSERT_HEAD, AST_LIST_TRAVERSE, ast_slinear_saturated_subtract(), ast_translate(), ast_translator_build_path(), ast_frame::data, ast_frame::datalen, softmix_translate_helper_entry::dst_format, softmix_translate_helper::entries, softmix_channel::final_buf, ast_frame_subclass::format, softmix_channel::have_audio, MAX_DATALEN, NULL, softmix_translate_helper_entry::num_times_requested, softmix_channel::our_buf, softmix_translate_helper_entry::out_frame, ast_frame::ptr, ast_frame::samples, softmix_translate_helper::slin_src, softmix_translate_helper_entry_alloc(), ast_frame::subclass, softmix_channel::talking, softmix_translate_helper_entry::trans_pvt, and softmix_channel::write_frame.

Referenced by softmix_mixing_loop().

00269 {
00270    struct softmix_translate_helper_entry *entry = NULL;
00271    int i;
00272 
00273    /* If we provided audio that was not determined to be silence,
00274     * then take it out while in slinear format. */
00275    if (sc->have_audio && sc->talking) {
00276       for (i = 0; i < sc->write_frame.samples; i++) {
00277          ast_slinear_saturated_subtract(&sc->final_buf[i], &sc->our_buf[i]);
00278       }
00279       /* check to see if any entries exist for the format. if not we'll want
00280          to remove it during cleanup */
00281       AST_LIST_TRAVERSE(&trans_helper->entries, entry, entry) {
00282          if (ast_format_cmp(entry->dst_format, raw_write_fmt) == AST_FORMAT_CMP_EQUAL) {
00283             ++entry->num_times_requested;
00284             break;
00285          }
00286       }
00287       /* do not do any special write translate optimization if we had to make
00288        * a special mix for them to remove their own audio. */
00289       return;
00290    }
00291 
00292    /* Attempt to optimize channels using the same translation path/codec. Build a list of entries
00293       of translation paths and track the number of references for each type. Each one of the same
00294       type should be able to use the same out_frame. Since the optimization is only necessary for
00295       multiple channels (>=2) using the same codec make sure resources are allocated only when
00296       needed and released when not (see also softmix_translate_helper_cleanup */
00297    AST_LIST_TRAVERSE(&trans_helper->entries, entry, entry) {
00298       if (ast_format_cmp(entry->dst_format, raw_write_fmt) == AST_FORMAT_CMP_EQUAL) {
00299          entry->num_times_requested++;
00300       } else {
00301          continue;
00302       }
00303       if (!entry->trans_pvt && (entry->num_times_requested > 1)) {
00304          entry->trans_pvt = ast_translator_build_path(entry->dst_format, trans_helper->slin_src);
00305       }
00306       if (entry->trans_pvt && !entry->out_frame) {
00307          entry->out_frame = ast_translate(entry->trans_pvt, &sc->write_frame, 0);
00308       }
00309       if (entry->out_frame && (entry->out_frame->datalen < MAX_DATALEN)) {
00310          ao2_replace(sc->write_frame.subclass.format, entry->out_frame->subclass.format);
00311          memcpy(sc->final_buf, entry->out_frame->data.ptr, entry->out_frame->datalen);
00312          sc->write_frame.datalen = entry->out_frame->datalen;
00313          sc->write_frame.samples = entry->out_frame->samples;
00314       }
00315       break;
00316    }
00317 
00318    /* add new entry into list if this format destination was not matched. */
00319    if (!entry && (entry = softmix_translate_helper_entry_alloc(raw_write_fmt))) {
00320       AST_LIST_INSERT_HEAD(&trans_helper->entries, entry, entry);
00321    }
00322 }

static int softmix_src_change ( struct ast_bridge_channel bridge_channel  )  [static]

Definition at line 444 of file bridge_softmix.c.

References ast_bridge_channel_queue_control_data(), AST_CONTROL_SRCCHANGE, and NULL.

Referenced by softmix_bridge_join(), and softmix_bridge_leave().

00445 {
00446    return ast_bridge_channel_queue_control_data(bridge_channel, AST_CONTROL_SRCCHANGE, NULL, 0);
00447 }

static void softmix_translate_helper_change_rate ( struct softmix_translate_helper trans_helper,
unsigned int  sample_rate 
) [static]

static void softmix_translate_helper_cleanup ( struct softmix_translate_helper trans_helper  )  [static]

Definition at line 324 of file bridge_softmix.c.

References ast_frfree, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_translator_free_path(), softmix_translate_helper::entries, NULL, softmix_translate_helper_entry::num_times_requested, softmix_translate_helper_entry::out_frame, softmix_translate_helper_free_entry(), and softmix_translate_helper_entry::trans_pvt.

Referenced by softmix_mixing_loop().

00325 {
00326    struct softmix_translate_helper_entry *entry;
00327 
00328    AST_LIST_TRAVERSE_SAFE_BEGIN(&trans_helper->entries, entry, entry) {
00329       /* if it hasn't been requested then remove it */
00330       if (!entry->num_times_requested) {
00331          AST_LIST_REMOVE_CURRENT(entry);
00332          softmix_translate_helper_free_entry(entry);
00333          continue;
00334       }
00335 
00336       if (entry->out_frame) {
00337          ast_frfree(entry->out_frame);
00338          entry->out_frame = NULL;
00339       }
00340 
00341       /* nothing is optimized for a single path reference, so there is
00342          no reason to continue to hold onto the codec */
00343       if (entry->num_times_requested == 1 && entry->trans_pvt) {
00344          ast_translator_free_path(entry->trans_pvt);
00345          entry->trans_pvt = NULL;
00346       }
00347 
00348       /* for each iteration (a mixing run) in the bridge softmix thread the number
00349          of references to a given entry is recalculated, so reset the number of
00350          times requested */
00351       entry->num_times_requested = 0;
00352    }
00353    AST_LIST_TRAVERSE_SAFE_END;
00354 }

static void softmix_translate_helper_destroy ( struct softmix_translate_helper trans_helper  )  [static]

Definition at line 213 of file bridge_softmix.c.

References AST_LIST_REMOVE_HEAD, softmix_translate_helper::entries, and softmix_translate_helper_free_entry().

Referenced by softmix_mixing_loop().

00214 {
00215    struct softmix_translate_helper_entry *entry;
00216 
00217    while ((entry = AST_LIST_REMOVE_HEAD(&trans_helper->entries, entry))) {
00218       softmix_translate_helper_free_entry(entry);
00219    }
00220 }

static struct softmix_translate_helper_entry* softmix_translate_helper_entry_alloc ( struct ast_format dst  )  [static, read]

Definition at line 180 of file bridge_softmix.c.

References ao2_bump, ast_calloc, softmix_translate_helper_entry::dst_format, NULL, and softmix_translate_helper_entry::num_times_requested.

Referenced by softmix_process_write_audio().

00181 {
00182    struct softmix_translate_helper_entry *entry;
00183    if (!(entry = ast_calloc(1, sizeof(*entry)))) {
00184       return NULL;
00185    }
00186    entry->dst_format = ao2_bump(dst);
00187    /* initialize this to one so that the first time through the cleanup code after
00188       allocation it won't be removed from the entry list */
00189    entry->num_times_requested = 1;
00190    return entry;
00191 }

static void* softmix_translate_helper_free_entry ( struct softmix_translate_helper_entry entry  )  [static]

static void softmix_translate_helper_init ( struct softmix_translate_helper trans_helper,
unsigned int  sample_rate 
) [static]

Definition at line 207 of file bridge_softmix.c.

References ast_format_cache_get_slin_by_rate(), and softmix_translate_helper::slin_src.

Referenced by softmix_mixing_loop().

00208 {
00209    memset(trans_helper, 0, sizeof(*trans_helper));
00210    trans_helper->slin_src = ast_format_cache_get_slin_by_rate(sample_rate);
00211 }

static int unload_module ( void   )  [static]

Definition at line 1232 of file bridge_softmix.c.

References ast_bridge_technology_unregister().

01233 {
01234    ast_bridge_technology_unregister(&softmix_bridge);
01235    return 0;
01236 }


Variable Documentation

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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, } [static]

Definition at line 1247 of file bridge_softmix.c.

Definition at line 1247 of file bridge_softmix.c.

Definition at line 1219 of file bridge_softmix.c.


Generated on Thu Apr 16 06:29:14 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6