bridge_softmix.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 2011, Digium, Inc.
00005  *
00006  * Joshua Colp <jcolp@digium.com>
00007  * David Vossel <dvossel@digium.com>
00008  *
00009  * See http://www.asterisk.org for more information about
00010  * the Asterisk project. Please do not directly contact
00011  * any of the maintainers of this project for assistance;
00012  * the project provides a web site, mailing lists and IRC
00013  * channels for your use.
00014  *
00015  * This program is free software, distributed under the terms of
00016  * the GNU General Public License Version 2. See the LICENSE file
00017  * at the top of the source tree.
00018  */
00019 
00020 /*! \file
00021  *
00022  * \brief Multi-party software based channel mixing
00023  *
00024  * \author Joshua Colp <jcolp@digium.com>
00025  * \author David Vossel <dvossel@digium.com>
00026  *
00027  * \ingroup bridges
00028  */
00029 
00030 /*** MODULEINFO
00031    <support_level>core</support_level>
00032  ***/
00033 
00034 #include "asterisk.h"
00035 
00036 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 434672 $")
00037 
00038 #include <stdio.h>
00039 #include <stdlib.h>
00040 #include <string.h>
00041 #include <sys/time.h>
00042 #include <signal.h>
00043 #include <errno.h>
00044 #include <unistd.h>
00045 
00046 #include "asterisk/module.h"
00047 #include "asterisk/channel.h"
00048 #include "asterisk/bridge.h"
00049 #include "asterisk/bridge_technology.h"
00050 #include "asterisk/frame.h"
00051 #include "asterisk/options.h"
00052 #include "asterisk/logger.h"
00053 #include "asterisk/slinfactory.h"
00054 #include "asterisk/astobj2.h"
00055 #include "asterisk/timing.h"
00056 #include "asterisk/translate.h"
00057 
00058 #define MAX_DATALEN 8096
00059 
00060 /*! The minimum sample rate of the bridge. */
00061 #define SOFTMIX_MIN_SAMPLE_RATE 8000   /* 8 kHz sample rate */
00062 
00063 /*! \brief Interval at which mixing will take place. Valid options are 10, 20, and 40. */
00064 #define DEFAULT_SOFTMIX_INTERVAL 20
00065 
00066 /*! \brief Size of the buffer used for sample manipulation */
00067 #define SOFTMIX_DATALEN(rate, interval) ((rate/50) * (interval / 10))
00068 
00069 /*! \brief Number of samples we are dealing with */
00070 #define SOFTMIX_SAMPLES(rate, interval) (SOFTMIX_DATALEN(rate, interval) / 2)
00071 
00072 /*! \brief Number of mixing iterations to perform between gathering statistics. */
00073 #define SOFTMIX_STAT_INTERVAL 100
00074 
00075 /* This is the threshold in ms at which a channel's own audio will stop getting
00076  * mixed out its own write audio stream because it is not talking. */
00077 #define DEFAULT_SOFTMIX_SILENCE_THRESHOLD 2500
00078 #define DEFAULT_SOFTMIX_TALKING_THRESHOLD 160
00079 
00080 #define DEFAULT_ENERGY_HISTORY_LEN 150
00081 
00082 struct video_follow_talker_data {
00083    /*! audio energy history */
00084    int energy_history[DEFAULT_ENERGY_HISTORY_LEN];
00085    /*! The current slot being used in the history buffer, this
00086     *  increments and wraps around */
00087    int energy_history_cur_slot;
00088    /*! The current energy sum used for averages. */
00089    int energy_accum;
00090    /*! The current energy average */
00091    int energy_average;
00092 };
00093 
00094 /*! \brief Structure which contains per-channel mixing information */
00095 struct softmix_channel {
00096    /*! Lock to protect this structure */
00097    ast_mutex_t lock;
00098    /*! Factory which contains audio read in from the channel */
00099    struct ast_slinfactory factory;
00100    /*! Frame that contains mixed audio to be written out to the channel */
00101    struct ast_frame write_frame;
00102    /*! Current expected read slinear format. */
00103    struct ast_format *read_slin_format;
00104    /*! DSP for detecting silence */
00105    struct ast_dsp *dsp;
00106    /*!
00107     * \brief TRUE if a channel is talking.
00108     *
00109     * \note This affects how the channel's audio is mixed back to
00110     * it.
00111     */
00112    unsigned int talking:1;
00113    /*! TRUE if the channel provided audio for this mixing interval */
00114    unsigned int have_audio:1;
00115    /*! Buffer containing final mixed audio from all sources */
00116    short final_buf[MAX_DATALEN];
00117    /*! Buffer containing only the audio from the channel */
00118    short our_buf[MAX_DATALEN];
00119    /*! Data pertaining to talker mode for video conferencing */
00120    struct video_follow_talker_data video_talker;
00121 };
00122 
00123 struct softmix_bridge_data {
00124    struct ast_timer *timer;
00125    /*!
00126     * \brief Bridge pointer passed to the softmix mixing thread.
00127     *
00128     * \note Does not need a reference because the bridge will
00129     * always exist while the mixing thread exists even if the
00130     * bridge is no longer actively using the softmix technology.
00131     */
00132    struct ast_bridge *bridge;
00133    /*! Lock for signaling the mixing thread. */
00134    ast_mutex_t lock;
00135    /*! Condition, used if we need to wake up the mixing thread. */
00136    ast_cond_t cond;
00137    /*! Thread handling the mixing */
00138    pthread_t thread;
00139    unsigned int internal_rate;
00140    unsigned int internal_mixing_interval;
00141    /*! TRUE if the mixing thread should stop */
00142    unsigned int stop:1;
00143 };
00144 
00145 struct softmix_stats {
00146    /*! Each index represents a sample rate used above the internal rate. */
00147    unsigned int sample_rates[16];
00148    /*! Each index represents the number of channels using the same index in the sample_rates array.  */
00149    unsigned int num_channels[16];
00150    /*! The number of channels above the internal sample rate */
00151    unsigned int num_above_internal_rate;
00152    /*! The number of channels at the internal sample rate */
00153    unsigned int num_at_internal_rate;
00154    /*! The absolute highest sample rate preferred by any channel in the bridge */
00155    unsigned int highest_supported_rate;
00156    /*! Is the sample rate locked by the bridge, if so what is that rate.*/
00157    unsigned int locked_rate;
00158 };
00159 
00160 struct softmix_mixing_array {
00161    unsigned int max_num_entries;
00162    unsigned int used_entries;
00163    int16_t **buffers;
00164 };
00165 
00166 struct softmix_translate_helper_entry {
00167    int num_times_requested; /*!< Once this entry is no longer requested, free the trans_pvt
00168                                  and re-init if it was usable. */
00169    struct ast_format *dst_format; /*!< The destination format for this helper */
00170    struct ast_trans_pvt *trans_pvt; /*!< the translator for this slot. */
00171    struct ast_frame *out_frame; /*!< The output frame from the last translation */
00172    AST_LIST_ENTRY(softmix_translate_helper_entry) entry;
00173 };
00174 
00175 struct softmix_translate_helper {
00176    struct ast_format *slin_src; /*!< the source format expected for all the translators */
00177    AST_LIST_HEAD_NOLOCK(, softmix_translate_helper_entry) entries;
00178 };
00179 
00180 static struct softmix_translate_helper_entry *softmix_translate_helper_entry_alloc(struct ast_format *dst)
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 }
00192 
00193 static void *softmix_translate_helper_free_entry(struct softmix_translate_helper_entry *entry)
00194 {
00195    ao2_cleanup(entry->dst_format);
00196 
00197    if (entry->trans_pvt) {
00198       ast_translator_free_path(entry->trans_pvt);
00199    }
00200    if (entry->out_frame) {
00201       ast_frfree(entry->out_frame);
00202    }
00203    ast_free(entry);
00204    return NULL;
00205 }
00206 
00207 static void softmix_translate_helper_init(struct softmix_translate_helper *trans_helper, unsigned int sample_rate)
00208 {
00209    memset(trans_helper, 0, sizeof(*trans_helper));
00210    trans_helper->slin_src = ast_format_cache_get_slin_by_rate(sample_rate);
00211 }
00212 
00213 static void softmix_translate_helper_destroy(struct softmix_translate_helper *trans_helper)
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 }
00221 
00222 static void softmix_translate_helper_change_rate(struct softmix_translate_helper *trans_helper, unsigned int sample_rate)
00223 {
00224    struct softmix_translate_helper_entry *entry;
00225 
00226    trans_helper->slin_src = ast_format_cache_get_slin_by_rate(sample_rate);
00227    AST_LIST_TRAVERSE_SAFE_BEGIN(&trans_helper->entries, entry, entry) {
00228       if (entry->trans_pvt) {
00229          ast_translator_free_path(entry->trans_pvt);
00230          if (!(entry->trans_pvt = ast_translator_build_path(entry->dst_format, trans_helper->slin_src))) {
00231             AST_LIST_REMOVE_CURRENT(entry);
00232             entry = softmix_translate_helper_free_entry(entry);
00233          }
00234       }
00235    }
00236    AST_LIST_TRAVERSE_SAFE_END;
00237 }
00238 
00239 /*!
00240  * \internal
00241  * \brief Get the next available audio on the softmix channel's read stream
00242  * and determine if it should be mixed out or not on the write stream.
00243  *
00244  * \retval pointer to buffer containing the exact number of samples requested on success.
00245  * \retval NULL if no samples are present
00246  */
00247 static int16_t *softmix_process_read_audio(struct softmix_channel *sc, unsigned int num_samples)
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 }
00257 
00258 /*!
00259  * \internal
00260  * \brief Process a softmix channel's write audio
00261  *
00262  * \details This function will remove the channel's talking from its own audio if present and
00263  * possibly even do the channel's write translation for it depending on how many other
00264  * channels use the same write format.
00265  */
00266 static void softmix_process_write_audio(struct softmix_translate_helper *trans_helper,
00267    struct ast_format *raw_write_fmt,
00268    struct softmix_channel *sc)
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 }
00323 
00324 static void softmix_translate_helper_cleanup(struct softmix_translate_helper *trans_helper)
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 }
00355 
00356 static void set_softmix_bridge_data(int rate, int interval, struct ast_bridge_channel *bridge_channel, int reset)
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 }
00409 
00410 /*!
00411  * \internal
00412  * \brief Poke the mixing thread in case it is waiting for an active channel.
00413  * \since 12.0.0
00414  *
00415  * \param softmix_data Bridge mixing data.
00416  *
00417  * \return Nothing
00418  */
00419 static void softmix_poke_thread(struct softmix_bridge_data *softmix_data)
00420 {
00421    ast_mutex_lock(&softmix_data->lock);
00422    ast_cond_signal(&softmix_data->cond);
00423    ast_mutex_unlock(&softmix_data->lock);
00424 }
00425 
00426 /*! \brief Function called when a channel is unsuspended from the bridge */
00427 static void softmix_bridge_unsuspend(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
00428 {
00429    if (bridge->tech_pvt) {
00430       softmix_poke_thread(bridge->tech_pvt);
00431    }
00432 }
00433 
00434 /*!
00435  * \internal
00436  * \brief Indicate a source change to the channel.
00437  * \since 12.0.0
00438  *
00439  * \param bridge_channel Which channel source is changing.
00440  *
00441  * \retval 0 on success.
00442  * \retval -1 on error.
00443  */
00444 static int softmix_src_change(struct ast_bridge_channel *bridge_channel)
00445 {
00446    return ast_bridge_channel_queue_control_data(bridge_channel, AST_CONTROL_SRCCHANGE, NULL, 0);
00447 }
00448 
00449 /*! \brief Function called when a channel is joined into the bridge */
00450 static int softmix_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
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 }
00482 
00483 /*! \brief Function called when a channel leaves the bridge */
00484 static void softmix_bridge_leave(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
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 }
00510 
00511 static void softmix_pass_video_top_priority(struct ast_bridge *bridge, struct ast_frame *frame)
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 }
00525 
00526 /*!
00527  * \internal
00528  * \brief Determine what to do with a video frame.
00529  * \since 12.0.0
00530  *
00531  * \param bridge Which bridge is getting the frame
00532  * \param bridge_channel Which channel is writing the frame.
00533  * \param frame What is being written.
00534  *
00535  * \return Nothing
00536  */
00537 static void softmix_bridge_write_video(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
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 }
00572 
00573 /*!
00574  * \internal
00575  * \brief Determine what to do with a voice frame.
00576  * \since 12.0.0
00577  *
00578  * \param bridge Which bridge is getting the frame
00579  * \param bridge_channel Which channel is writing the frame.
00580  * \param frame What is being written.
00581  *
00582  * \return Nothing
00583  */
00584 static void softmix_bridge_write_voice(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
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 }
00666 
00667 /*!
00668  * \internal
00669  * \brief Determine what to do with a control frame.
00670  * \since 12.0.0
00671  *
00672  * \param bridge Which bridge is getting the frame
00673  * \param bridge_channel Which channel is writing the frame.
00674  * \param frame What is being written.
00675  *
00676  * \retval 0 Frame accepted into the bridge.
00677  * \retval -1 Frame needs to be deferred.
00678  */
00679 static int softmix_bridge_write_control(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
00680 {
00681    /*
00682     * XXX Softmix needs to use channel roles to determine what to
00683     * do with control frames.
00684     */
00685    return 0;
00686 }
00687 
00688 /*!
00689  * \internal
00690  * \brief Determine what to do with a frame written into the bridge.
00691  * \since 12.0.0
00692  *
00693  * \param bridge Which bridge is getting the frame
00694  * \param bridge_channel Which channel is writing the frame.
00695  * \param frame What is being written.
00696  *
00697  * \retval 0 Frame accepted into the bridge.
00698  * \retval -1 Frame needs to be deferred.
00699  *
00700  * \note On entry, bridge is already locked.
00701  */
00702 static int softmix_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
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 }
00751 
00752 static void gather_softmix_stats(struct softmix_stats *stats,
00753    const struct softmix_bridge_data *softmix_data,
00754    struct ast_bridge_channel *bridge_channel)
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 }
00785 
00786 /*!
00787  * \internal
00788  * \brief Analyse mixing statistics and change bridges internal rate
00789  * if necessary.
00790  *
00791  * \retval 0, no changes to internal rate
00792  * \retval 1, internal rate was changed, update all the channels on the next mixing iteration.
00793  */
00794 static unsigned int analyse_softmix_stats(struct softmix_stats *stats, struct softmix_bridge_data *softmix_data)
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 }
00868 
00869 static int softmix_mixing_array_init(struct softmix_mixing_array *mixing_array, unsigned int starting_num_entries)
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 }
00879 
00880 static void softmix_mixing_array_destroy(struct softmix_mixing_array *mixing_array)
00881 {
00882    ast_free(mixing_array->buffers);
00883 }
00884 
00885 static int softmix_mixing_array_grow(struct softmix_mixing_array *mixing_array, unsigned int num_entries)
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 }
00897 
00898 /*!
00899  * \brief Mixing loop.
00900  *
00901  * \retval 0 on success
00902  * \retval -1 on failure
00903  */
00904 static int softmix_mixing_loop(struct ast_bridge *bridge)
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 }
01069 
01070 /*!
01071  * \internal
01072  * \brief Mixing thread.
01073  * \since 12.0.0
01074  *
01075  * \note The thread does not have its own reference to the
01076  * bridge.  The lifetime of the thread is tied to the lifetime
01077  * of the mixing technology association with the bridge.
01078  */
01079 static void *softmix_mixing_thread(void *data)
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 }
01121 
01122 static void softmix_bridge_data_destroy(struct softmix_bridge_data *softmix_data)
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 }
01132 
01133 /*! \brief Function called when a bridge is created */
01134 static int softmix_bridge_create(struct ast_bridge *bridge)
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 }
01168 
01169 /*!
01170  * \internal
01171  * \brief Request the softmix mixing thread stop.
01172  * \since 12.0.0
01173  *
01174  * \param bridge Which bridge is being stopped.
01175  *
01176  * \return Nothing
01177  */
01178 static void softmix_bridge_stop(struct ast_bridge *bridge)
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 }
01191 
01192 /*! \brief Function called when a bridge is destroyed */
01193 static void softmix_bridge_destroy(struct ast_bridge *bridge)
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 }
01218 
01219 static struct ast_bridge_technology softmix_bridge = {
01220    .name = "softmix",
01221    .capabilities = AST_BRIDGE_CAPABILITY_MULTIMIX,
01222    .preference = AST_BRIDGE_PREFERENCE_BASE_MULTIMIX,
01223    .create = softmix_bridge_create,
01224    .stop = softmix_bridge_stop,
01225    .destroy = softmix_bridge_destroy,
01226    .join = softmix_bridge_join,
01227    .leave = softmix_bridge_leave,
01228    .unsuspend = softmix_bridge_unsuspend,
01229    .write = softmix_bridge_write,
01230 };
01231 
01232 static int unload_module(void)
01233 {
01234    ast_bridge_technology_unregister(&softmix_bridge);
01235    return 0;
01236 }
01237 
01238 static int load_module(void)
01239 {
01240    if (ast_bridge_technology_register(&softmix_bridge)) {
01241       unload_module();
01242       return AST_MODULE_LOAD_DECLINE;
01243    }
01244    return AST_MODULE_LOAD_SUCCESS;
01245 }
01246 
01247 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Multi-party software based channel mixing");

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