Sat Feb 11 06:34:16 2012

Asterisk developer's documentation


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/bridging.h"
#include "asterisk/bridging_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_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 (void *obj)
static int 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 int softmix_bridge_leave (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 Function called when a channel leaves the bridge.
static int softmix_bridge_poke (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 Function called when the channel's thread is poked.
static int softmix_bridge_thread (struct ast_bridge *bridge)
 Function which acts as the mixing thread.
static enum ast_bridge_write_result softmix_bridge_write (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
 Function called when a channel writes a frame into the bridge.
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 void softmix_pass_dtmf (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
static void softmix_pass_video_all (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame, int echo)
static void softmix_pass_video_top_priority (struct ast_bridge *bridge, struct ast_frame *frame)
static int16_t * softmix_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 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, }
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 77 of file bridge_softmix.c.

Referenced by softmix_bridge_write().

#define DEFAULT_SOFTMIX_INTERVAL   20

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

Definition at line 61 of file bridge_softmix.c.

Referenced by softmix_bridge_create(), and softmix_bridge_join().

#define DEFAULT_SOFTMIX_SILENCE_THRESHOLD   2500

Definition at line 74 of file bridge_softmix.c.

Referenced by softmix_bridge_write().

#define DEFAULT_SOFTMIX_TALKING_THRESHOLD   160

Definition at line 75 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_bridge_thread(), 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 64 of file bridge_softmix.c.

Referenced by set_softmix_bridge_data(), and softmix_bridge_thread().

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

Number of samples we are dealing with.

Definition at line 67 of file bridge_softmix.c.

Referenced by set_softmix_bridge_data(), softmix_bridge_thread(), and softmix_bridge_write().

#define SOFTMIX_STAT_INTERVAL   100

Number of mixing iterations to perform between gathering statistics.

Definition at line 70 of file bridge_softmix.c.

Referenced by softmix_bridge_thread().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 936 of file bridge_softmix.c.

static void __unreg_module ( void   )  [static]

Definition at line 936 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 647 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_bridge_thread().

00648 {
00649    int i;
00650    /* Re-adjust the internal bridge sample rate if
00651     * 1. The bridge's internal sample rate is locked in at a sample
00652     *    rate other than the current sample rate being used.
00653     * 2. two or more channels support a higher sample rate
00654     * 3. no channels support the current sample rate or a higher rate
00655     */
00656    if (stats->locked_rate) {
00657       /* if the rate is locked by the bridge, only update it if it differs
00658        * from the current rate we are using. */
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       /* the highest rate is just used as a starting point */
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          /* best_rate starts out being the first sample rate
00674           * greater than the internal sample rate that 2 or
00675           * more channels support. */
00676          if (stats->num_channels[i] >= 2 && (best_index == -1)) {
00677             best_rate = stats->sample_rates[i];
00678             best_index = i;
00679          /* If it has been detected that multiple rates above
00680           * the internal rate are present, compare those rates
00681           * to each other and pick the highest one two or more
00682           * channels support. */
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          /* It is possible that multiple channels exist with native sample
00689           * rates above the internal sample rate, but none of those channels
00690           * have the same rate in common.  In this case, the lowest sample
00691           * rate among those channels is picked. Over time as additional
00692           * statistic runs are made the internal sample rate number will
00693           * adjust to the most optimal sample rate, but it may take multiple
00694           * iterations. */
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       /* In this case, the highest supported rate is actually lower than the internal rate */
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 }

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

References ARRAY_LEN, ast_format_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, ast_channel::rawreadformat, ast_channel::rawwriteformat, and softmix_stats::sample_rates.

Referenced by softmix_bridge_thread().

00613 {
00614    int channel_native_rate;
00615    int i;
00616    /* Gather stats about channel sample rates. */
00617    channel_native_rate = MAX(ast_format_rate(&bridge_channel->chan->rawwriteformat),
00618       ast_format_rate(&bridge_channel->chan->rawreadformat));
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 }

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

References ast_dsp_free(), ast_dsp_new_with_rate(), ast_dsp_set_threshold(), ast_format_rate(), ast_format_set(), ast_format_slin_by_rate(), AST_FRAME_VOICE, ast_mutex_lock, ast_mutex_unlock, ast_set_read_format(), ast_set_write_format(), ast_slinfactory_destroy(), ast_slinfactory_init_with_format(), ast_bridge_channel::bridge_pvt, 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, softmix_channel::our_buf, ast_frame::ptr, ast_channel::rawreadformat, softmix_channel::read_frame, ast_frame::samples, SOFTMIX_DATALEN, SOFTMIX_SAMPLES, ast_frame::subclass, ast_bridge_tech_optimizations::talking_threshold, ast_bridge_channel::tech_args, and softmix_channel::write_frame.

Referenced by softmix_bridge_join(), and softmix_bridge_thread().

00337 {
00338    struct softmix_channel *sc = bridge_channel->bridge_pvt;
00339    unsigned int channel_read_rate = ast_format_rate(&bridge_channel->chan->rawreadformat);
00340 
00341    ast_mutex_lock(&sc->lock);
00342    if (reset) {
00343       ast_slinfactory_destroy(&sc->factory);
00344       ast_dsp_free(sc->dsp);
00345    }
00346    /* Setup read/write frame parameters */
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    /* Setup smoother */
00360    ast_slinfactory_init_with_format(&sc->factory, &sc->write_frame.subclass.format);
00361 
00362    /* set new read and write formats on channel. */
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    /* set up new DSP.  This is on the read side only right before the read frame enters the smoother.  */
00367    sc->dsp = ast_dsp_new_with_rate(channel_read_rate);
00368    /* we want to aggressively detect silence to avoid feedback */
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 }

static int softmix_bridge_create ( struct ast_bridge bridge  )  [static]

Function called when a bridge is created.

Definition at line 304 of file bridge_softmix.c.

References ao2_alloc, ao2_ref, ast_timer_open(), ast_bridge::bridge_pvt, DEFAULT_SOFTMIX_INTERVAL, softmix_bridge_data::internal_mixing_interval, softmix_bridge_data::internal_rate, softmix_bridge_data_destroy(), and softmix_bridge_data::timer.

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    /* start at 8khz, let it grow from there */
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 }

static void softmix_bridge_data_destroy ( void *  obj  )  [static]

Definition at line 297 of file bridge_softmix.c.

References ast_timer_close(), and softmix_bridge_data::timer.

Referenced by softmix_bridge_create().

00298 {
00299    struct softmix_bridge_data *softmix_data = obj;
00300    ast_timer_close(softmix_data->timer);
00301 }

static int softmix_bridge_destroy ( struct ast_bridge bridge  )  [static]

Function called when a bridge is destroyed.

Definition at line 325 of file bridge_softmix.c.

References ao2_ref, and ast_bridge::bridge_pvt.

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 }

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

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

00380 {
00381    struct softmix_channel *sc = NULL;
00382    struct softmix_bridge_data *softmix_data = bridge->bridge_pvt;
00383 
00384    /* Create a new softmix_channel structure and allocate various things on it */
00385    if (!(sc = ast_calloc(1, sizeof(*sc)))) {
00386       return -1;
00387    }
00388 
00389    /* Can't forget the lock */
00390    ast_mutex_init(&sc->lock);
00391 
00392    /* Can't forget to record our pvt structure within the bridged channel structure */
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 }

static int 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 403 of file bridge_softmix.c.

References ast_dsp_free(), ast_free, ast_mutex_destroy, ast_slinfactory_destroy(), ast_bridge_channel::bridge_pvt, softmix_channel::dsp, softmix_channel::factory, and softmix_channel::lock.

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    /* Drop mutex lock */
00413    ast_mutex_destroy(&sc->lock);
00414 
00415    /* Drop the factory */
00416    ast_slinfactory_destroy(&sc->factory);
00417 
00418    /* Drop the DSP */
00419    ast_dsp_free(sc->dsp);
00420 
00421    /* Eep! drop ourselves */
00422    ast_free(sc);
00423 
00424    return 0;
00425 }

static int softmix_bridge_poke ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel 
) [static]

Function called when the channel's thread is poked.

Definition at line 594 of file bridge_softmix.c.

References ast_mutex_lock, ast_mutex_unlock, ast_write(), ast_bridge_channel::bridge_pvt, ast_bridge_channel::chan, softmix_channel::have_frame, softmix_channel::lock, and softmix_channel::write_frame.

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 }

static int softmix_bridge_thread ( struct ast_bridge bridge  )  [static]

Function which acts as the mixing thread.

Definition at line 742 of file bridge_softmix.c.

References analyse_softmix_stats(), ao2_lock, ao2_ref, ao2_unlock, ast_bridge::array_num, ast_format_set(), ast_format_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(), ast_bridge_channel::bridge_pvt, ast_bridge::bridge_pvt, softmix_mixing_array::buffers, ast_bridge_channel::chan, ast_frame::datalen, softmix_channel::final_buf, ast_frame_subclass::format, gather_softmix_stats(), softmix_channel::have_frame, ast_format::id, ast_bridge::internal_mixing_interval, softmix_bridge_data::internal_mixing_interval, softmix_bridge_data::internal_rate, ast_bridge::internal_sample_rate, softmix_channel::lock, softmix_stats::locked_rate, LOG_NOTICE, LOG_WARNING, MAX_DATALEN, softmix_mixing_array::max_num_entries, ast_bridge::num, ast_channel::rawwriteformat, ast_bridge::refresh, ast_frame::samples, set_softmix_bridge_data(), 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(), ast_bridge::stop, ast_frame::subclass, ast_bridge_channel::suspended, ast_bridge_channel::thread, softmix_bridge_data::timer, timer, softmix_mixing_array::used_entries, and softmix_channel::write_frame.

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; /* counts down, gather stats at zero and reset. */
00751    int timingfd;
00752    int update_all_rates = 0; /* set this when the internal sample rate has changed */
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    /* Give the mixing array room to grow, memory is cheap but allocations are expensive. */
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          /* This should NEVER happen, but if it does we need to know about it. Almost
00781           * all the memcpys used during this process depend on this assumption.  Rather
00782           * than checking this over and over again through out the code, this single
00783           * verification is done on each iteration. */
00784          ast_log(LOG_WARNING, "Conference mixing error, requested mixing length greater than mixing buffer.\n");
00785          goto softmix_cleanup;
00786       }
00787 
00788       /* Grow the mixing array buffer as participants are added. */
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       /* init the number of buffers stored in the mixing array to 0.
00794        * As buffers are added for mixing, this number is incremented. */
00795       mixing_array.used_entries = 0;
00796 
00797       /* These variables help determine if a rate change is required */
00798       if (!stat_iteration_counter) {
00799          memset(&stats, 0, sizeof(stats));
00800          stats.locked_rate = bridge->internal_sample_rate;
00801       }
00802 
00803       /* If the sample rate has changed, update the translator helper */
00804       if (update_all_rates) {
00805          softmix_translate_helper_change_rate(&trans_helper, softmix_data->internal_rate);
00806       }
00807 
00808       /* Go through pulling audio from each factory that has it available */
00809       AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
00810          struct softmix_channel *sc = bridge_channel->bridge_pvt;
00811 
00812          /* Update the sample rate to match the bridge's native sample rate if necessary. */
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          /* If stat_iteration_counter is 0, then collect statistics during this mixing interation */
00818          if (!stat_iteration_counter) {
00819             gather_softmix_stats(&stats, softmix_data, bridge_channel);
00820          }
00821 
00822          /* if the channel is suspended, don't check for audio, but still gather stats */
00823          if (bridge_channel->suspended) {
00824             continue;
00825          }
00826 
00827          /* Try to get audio from the factory if available */
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       /* mix it like crazy */
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       /* Next step go through removing the channel's own audio and creating a good frame... */
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          /* Make SLINEAR write frame from local buffer */
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          /* process the softmix channel's new write audio */
00862          softmix_process_write_audio(&trans_helper, &bridge_channel->chan->rawwriteformat, sc);
00863 
00864          /* The frame is now ready for use... */
00865          sc->have_frame = 1;
00866 
00867          ast_mutex_unlock(&sc->lock);
00868 
00869          /* Poke bridged channel thread just in case */
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       /* cleanup any translation frame data from the previous mixing iteration. */
00882       softmix_translate_helper_cleanup(&trans_helper);
00883       /* Wait for the timing source to tell us to wake up and get things done */
00884       ast_waitfor_n_fd(&timingfd, 1, &timeout, NULL);
00885       ast_timer_ack(timer, 1);
00886       ao2_lock(bridge);
00887 
00888       /* make sure to detect mixing interval changes if they occur. */
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; /* if the interval changes, the rates must be adjusted as well just to be notified new interval.*/
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 }

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

Function called when a channel writes a frame into the bridge.

Definition at line 471 of file bridge_softmix.c.

References ast_bridge_is_video_src(), ast_bridge_notify_talking(), ast_bridge_number_video_src(), 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_BRIDGE_WRITE_SUCCESS, AST_BRIDGE_WRITE_UNSUPPORTED, ast_dsp_silence_with_energy(), ast_format_get_video_mark(), ast_format_is_slinear(), AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_mutex_lock, ast_mutex_unlock, ast_slinfactory_available(), ast_slinfactory_feed(), ast_slinfactory_flush(), ast_write(), ast_bridge::bridge_pvt, ast_bridge_channel::bridge_pvt, ast_bridge_channel::chan, ast_frame::datalen, 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, ast_frame::frametype, softmix_channel::have_frame, softmix_bridge_data::internal_mixing_interval, softmix_bridge_data::internal_rate, softmix_channel::lock, ast_bridge_video_mode::mode, ast_bridge_tech_optimizations::silence_threshold, softmix_pass_dtmf(), softmix_pass_video_all(), softmix_pass_video_top_priority(), SOFTMIX_SAMPLES, ast_frame::subclass, softmix_channel::talking, ast_bridge_channel::tech_args, ast_bridge::video_mode, softmix_channel::video_talker, and softmix_channel::write_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;  /* if this is set to 0 or 1, tell the bridge that the channel has started or stopped talking. */
00481    int res = AST_BRIDGE_WRITE_SUCCESS;
00482 
00483    /* Only accept audio frames, all others are unsupported */
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    /* Determine if this video frame should be distributed or not */
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    /* If we made it here, we are going to write the frame into the conference */
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; /* wrap around */
00535       }
00536    }
00537 
00538    if (totalsilence < silence_threshold) {
00539       if (!sc->talking) {
00540          update_talking = 1;
00541       }
00542       sc->talking = 1; /* tell the write process we have audio to be mixed out */
00543    } else {
00544       if (sc->talking) {
00545          update_talking = 0;
00546       }
00547       sc->talking = 0;
00548    }
00549 
00550    /* Before adding audio in, make sure we haven't fallen behind. If audio has fallen
00551     * behind 4 times the amount of samples mixed on every iteration of the mixer, Re-sync
00552     * the audio by flushing the buffer before adding new audio in. */
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    /* If a frame was provided add it to the smoother, unless drop silence is enabled and this frame
00558     * is not determined to be talking. */
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    /* If a frame is ready to be written out, do so */
00565    if (sc->have_frame) {
00566       ast_write(bridge_channel->chan, &sc->write_frame);
00567       sc->have_frame = 0;
00568    }
00569 
00570    /* Alllll done */
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    /* Even though the frame is not being written into the conference because it is not audio,
00581     * we should use this opportunity to check to see if a frame is ready to be written out from
00582     * the conference to the channel. */
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 }

static void softmix_mixing_array_destroy ( struct softmix_mixing_array mixing_array  )  [static]

Definition at line 723 of file bridge_softmix.c.

References ast_free, and softmix_mixing_array::buffers.

Referenced by softmix_bridge_thread().

00724 {
00725    ast_free(mixing_array->buffers);
00726 }

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

Definition at line 728 of file bridge_softmix.c.

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

Referenced by softmix_bridge_thread().

00729 {
00730    int16_t **tmp;
00731    /* give it some room to grow since memory is cheap but allocations can be expensive */
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 }

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

Definition at line 712 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_bridge_thread().

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 }

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

Definition at line 431 of file bridge_softmix.c.

References AST_LIST_TRAVERSE, ast_write(), and ast_bridge_channel::chan.

Referenced by softmix_bridge_write().

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 }

static void softmix_pass_video_all ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel,
struct ast_frame frame,
int  echo 
) [static]

Definition at line 456 of file bridge_softmix.c.

References AST_LIST_TRAVERSE, ast_write(), ast_bridge_channel::chan, and ast_bridge_channel::suspended.

Referenced by softmix_bridge_write().

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 }

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

Definition at line 442 of file bridge_softmix.c.

References ast_bridge_is_video_src(), AST_LIST_TRAVERSE, ast_write(), ast_bridge_channel::chan, and ast_bridge_channel::suspended.

Referenced by softmix_bridge_write().

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 }

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

Definition at line 221 of file bridge_softmix.c.

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

Referenced by softmix_bridge_thread().

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 }

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

References ast_format_cmp(), AST_FORMAT_CMP_EQUAL, ast_format_copy(), 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, 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_bridge_thread().

00243 {
00244    struct softmix_translate_helper_entry *entry = NULL;
00245    int i;
00246 
00247    /* If we provided audio that was not determined to be silence,
00248     * then take it out while in slinear format. */
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       /* do not do any special write translate optimization if we had to make
00254        * a special mix for them to remove their own audio. */
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    /* add new entry into list if this format destination was not matched. */
00280    if (!entry && (entry = softmix_translate_helper_entry_alloc(raw_write_fmt))) {
00281       AST_LIST_INSERT_HEAD(&trans_helper->entries, entry, entry);
00282    }
00283 }

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

References ast_frfree, AST_LIST_TRAVERSE, softmix_translate_helper::entries, softmix_translate_helper_entry::num_times_requested, and softmix_translate_helper_entry::out_frame.

Referenced by softmix_bridge_thread().

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 }

static void softmix_translate_helper_destroy ( struct softmix_translate_helper trans_helper  )  [static]

Definition at line 187 of file bridge_softmix.c.

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

Referenced by softmix_bridge_thread().

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 }

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

Definition at line 159 of file bridge_softmix.c.

References ast_calloc, ast_format_copy(), and softmix_translate_helper_entry::dst_format.

Referenced by softmix_process_write_audio().

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 }

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

Definition at line 169 of file bridge_softmix.c.

References ast_free, ast_frfree, ast_translator_free_path(), softmix_translate_helper_entry::out_frame, and softmix_translate_helper_entry::trans_pvt.

Referenced by softmix_translate_helper_change_rate(), and softmix_translate_helper_destroy().

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 }

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

Definition at line 181 of file bridge_softmix.c.

References ast_format_set(), ast_format_slin_by_rate(), and softmix_translate_helper::slin_src.

Referenced by softmix_bridge_thread().

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 }

static int unload_module ( void   )  [static]


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, } [static]

Definition at line 936 of file bridge_softmix.c.

Definition at line 936 of file bridge_softmix.c.

Definition at line 907 of file bridge_softmix.c.


Generated on Sat Feb 11 06:34:17 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6