Wed Jan 8 2020 09:49:58

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"

Go to the source code of this file.

Data Structures

struct  softmix_channel
 Define used to turn on 16 kHz audio support. More...
 

Macros

#define SOFTMIX_DATALEN   (160 * (SOFTMIX_INTERVAL / 10))
 Size of the buffer used for sample manipulation. More...
 
#define SOFTMIX_INTERVAL   20
 Interval at which mixing will take place. Valid options are 10, 20, and 40. More...
 
#define SOFTMIX_SAMPLES   (SOFTMIX_DATALEN / 2)
 Number of samples we are dealing with. More...
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static int load_module (void)
 
static int softmix_bridge_create (struct ast_bridge *bridge)
 Function called when a bridge is created. More...
 
static int softmix_bridge_destroy (struct ast_bridge *bridge)
 Function called when a bridge is destroyed. More...
 
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. More...
 
static int softmix_bridge_leave (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 Function called when a channel leaves the bridge. More...
 
static int softmix_bridge_poke (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 Function called when the channel's thread is poked. More...
 
static int softmix_bridge_thread (struct ast_bridge *bridge)
 Function which acts as the mixing thread. More...
 
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. More...
 
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 = "ac1f6a56484a8820659555499174e588" , .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.nosp@m.@dig.nosp@m.ium.c.nosp@m.om
Todo:
This bridge operates in 8 kHz mode unless a define is uncommented. This needs to be improved so the bridge moves between the dominant codec as needed depending on channels present in the bridge and transcoding capabilities.

Definition in file bridge_softmix.c.

Macro Definition Documentation

#define SOFTMIX_DATALEN   (160 * (SOFTMIX_INTERVAL / 10))

Size of the buffer used for sample manipulation.

Definition at line 63 of file bridge_softmix.c.

Referenced by softmix_bridge_join(), and softmix_bridge_thread().

#define SOFTMIX_INTERVAL   20

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

Definition at line 60 of file bridge_softmix.c.

Referenced by softmix_bridge_thread().

#define SOFTMIX_SAMPLES   (SOFTMIX_DATALEN / 2)

Number of samples we are dealing with.

Definition at line 66 of file bridge_softmix.c.

Referenced by softmix_bridge_join(), and softmix_bridge_thread().

Function Documentation

static void __reg_module ( void  )
static

Definition at line 322 of file bridge_softmix.c.

static void __unreg_module ( void  )
static

Definition at line 322 of file bridge_softmix.c.

static int load_module ( void  )
static

Definition at line 317 of file bridge_softmix.c.

References ast_bridge_technology_register.

318 {
320 }
#define ast_bridge_technology_register(technology)
See __ast_bridge_technology_register()
static struct ast_bridge_technology softmix_bridge
static int softmix_bridge_create ( struct ast_bridge bridge)
static

Function called when a bridge is created.

Definition at line 90 of file bridge_softmix.c.

References ast_timer_open(), ast_bridge::bridge_pvt, and timer.

91 {
92  struct ast_timer *timer;
93 
94  if (!(timer = ast_timer_open())) {
95  return -1;
96  }
97 
98  bridge->bridge_pvt = timer;
99 
100  return 0;
101 }
struct ast_timer * ast_timer_open(void)
Open a timer.
Definition: timing.c:123
static struct ast_timer * timer
Definition: chan_iax2.c:313
void * bridge_pvt
Definition: bridging.h:163
static int softmix_bridge_destroy ( struct ast_bridge bridge)
static

Function called when a bridge is destroyed.

Definition at line 104 of file bridge_softmix.c.

References ast_timer_close(), and ast_bridge::bridge_pvt.

105 {
106  if (!bridge->bridge_pvt) {
107  return -1;
108  }
109  ast_timer_close((struct ast_timer *) bridge->bridge_pvt);
110  bridge->bridge_pvt = NULL;
111  return 0;
112 }
void ast_timer_close(struct ast_timer *handle)
Close an opened timing handle.
Definition: timing.c:150
void * bridge_pvt
Definition: bridging.h:163
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 115 of file bridge_softmix.c.

References ast_calloc, AST_FORMAT_SLINEAR, AST_FORMAT_SLINEAR16, AST_FRAME_VOICE, ast_mutex_init, ast_slinfactory_init(), ast_bridge_channel::bridge_pvt, ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, softmix_channel::factory, softmix_channel::final_buf, softmix_channel::frame, ast_frame::frametype, softmix_channel::lock, ast_frame::ptr, ast_frame::samples, SOFTMIX_DATALEN, SOFTMIX_SAMPLES, and ast_frame::subclass.

116 {
117  struct softmix_channel *sc = NULL;
118 
119  /* Create a new softmix_channel structure and allocate various things on it */
120  if (!(sc = ast_calloc(1, sizeof(*sc)))) {
121  return -1;
122  }
123 
124  /* Can't forget the lock */
125  ast_mutex_init(&sc->lock);
126 
127  /* Setup smoother */
129 
130  /* Setup frame parameters */
132 #ifdef SOFTMIX_16_SUPPORT
134 #else
136 #endif
137  sc->frame.data.ptr = sc->final_buf;
140 
141  /* Can't forget to record our pvt structure within the bridged channel structure */
142  bridge_channel->bridge_pvt = sc;
143 
144  return 0;
145 }
union ast_frame_subclass subclass
Definition: frame.h:146
void * ptr
Definition: frame.h:160
#define SOFTMIX_DATALEN
Size of the buffer used for sample manipulation.
format_t codec
Definition: frame.h:137
int datalen
Definition: frame.h:148
#define AST_FORMAT_SLINEAR16
Definition: frame.h:272
#define SOFTMIX_SAMPLES
Number of samples we are dealing with.
Define used to turn on 16 kHz audio support.
struct ast_frame frame
struct ast_slinfactory factory
void ast_slinfactory_init(struct ast_slinfactory *sf)
Initialize a slinfactory.
Definition: slinfactory.c:39
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
#define ast_calloc(a, b)
Definition: astmm.h:82
short final_buf[SOFTMIX_DATALEN]
enum ast_frame_type frametype
Definition: frame.h:144
#define ast_mutex_init(pmutex)
Definition: lock.h:152
union ast_frame::@172 data
ast_mutex_t lock
int samples
Definition: frame.h:150
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 148 of file bridge_softmix.c.

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

149 {
150  struct softmix_channel *sc = bridge_channel->bridge_pvt;
151 
152  if (!(bridge_channel->bridge_pvt)) {
153  return 0;
154  }
155  bridge_channel->bridge_pvt = NULL;
156 
157  /* Drop mutex lock */
158  ast_mutex_destroy(&sc->lock);
159 
160  /* Drop the factory */
162 
163  /* Eep! drop ourselves */
164  ast_free(sc);
165 
166  return 0;
167 }
void ast_slinfactory_destroy(struct ast_slinfactory *sf)
Destroy the contents of a slinfactory.
Definition: slinfactory.c:64
Define used to turn on 16 kHz audio support.
struct ast_slinfactory factory
#define ast_free(a)
Definition: astmm.h:97
#define ast_mutex_destroy(a)
Definition: lock.h:154
ast_mutex_t lock
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 203 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::frame, softmix_channel::have_frame, and softmix_channel::lock.

204 {
205  struct softmix_channel *sc = bridge_channel->bridge_pvt;
206 
207  ast_mutex_lock(&sc->lock);
208 
209  if (sc->have_frame) {
210  ast_write(bridge_channel->chan, &sc->frame);
211  sc->have_frame = 0;
212  }
213 
214  ast_mutex_unlock(&sc->lock);
215 
216  return 0;
217 }
#define ast_mutex_lock(a)
Definition: lock.h:155
Define used to turn on 16 kHz audio support.
struct ast_frame frame
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
Definition: channel.c:4916
struct ast_channel * chan
Definition: bridging.h:125
ast_mutex_t lock
#define ast_mutex_unlock(a)
Definition: lock.h:156
static int softmix_bridge_thread ( struct ast_bridge bridge)
static

Function which acts as the mixing thread.

Definition at line 220 of file bridge_softmix.c.

References ao2_lock, ao2_unlock, ast_bridge::array_num, AST_LIST_TRAVERSE, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_slinear_saturated_add(), ast_slinear_saturated_subtract(), ast_slinfactory_available(), ast_slinfactory_read(), ast_timer_ack(), ast_timer_fd(), ast_timer_set_rate(), ast_waitfor_n_fd(), ast_bridge_channel::bridge_pvt, ast_bridge::bridge_pvt, softmix_channel::factory, softmix_channel::final_buf, softmix_channel::have_audio, softmix_channel::have_frame, softmix_channel::lock, LOG_ERROR, softmix_channel::our_buf, ast_bridge::refresh, SOFTMIX_DATALEN, SOFTMIX_INTERVAL, SOFTMIX_SAMPLES, ast_bridge::stop, ast_bridge_channel::thread, and timer.

221 {
222  struct ast_timer *timer = (struct ast_timer *) bridge->bridge_pvt;
223  int timingfd = ast_timer_fd(timer);
224 
225  ast_timer_set_rate(timer, (1000 / SOFTMIX_INTERVAL));
226 
227  while (!bridge->stop && !bridge->refresh && bridge->array_num) {
228  struct ast_bridge_channel *bridge_channel = NULL;
229  short buf[SOFTMIX_DATALEN] = {0, };
230  int timeout = -1;
231 
232  /* Go through pulling audio from each factory that has it available */
233  AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
234  struct softmix_channel *sc = bridge_channel->bridge_pvt;
235 
236  ast_mutex_lock(&sc->lock);
237 
238  /* Try to get audio from the factory if available */
240  short *data1, *data2;
241  int i;
242 
243  /* Put into the local final buffer */
244  for (i = 0, data1 = buf, data2 = sc->our_buf; i < SOFTMIX_DATALEN; i++, data1++, data2++)
245  ast_slinear_saturated_add(data1, data2);
246  /* Yay we have our own audio */
247  sc->have_audio = 1;
248  } else {
249  /* Awww we don't have audio ;( */
250  sc->have_audio = 0;
251  }
252  ast_mutex_unlock(&sc->lock);
253  }
254 
255  /* Next step go through removing the channel's own audio and creating a good frame... */
256  AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
257  struct softmix_channel *sc = bridge_channel->bridge_pvt;
258  int i = 0;
259 
260  /* Copy from local final buffer to our final buffer */
261  memcpy(sc->final_buf, buf, sizeof(sc->final_buf));
262 
263  /* If we provided audio then take it out */
264  if (sc->have_audio) {
265  for (i = 0; i < SOFTMIX_DATALEN; i++) {
267  }
268  }
269 
270  /* The frame is now ready for use... */
271  sc->have_frame = 1;
272 
273  /* Poke bridged channel thread just in case */
274  pthread_kill(bridge_channel->thread, SIGURG);
275  }
276 
277  ao2_unlock(bridge);
278 
279  /* Wait for the timing source to tell us to wake up and get things done */
280  ast_waitfor_n_fd(&timingfd, 1, &timeout, NULL);
281 
282  if (ast_timer_ack(timer, 1) < 0) {
283  ast_log(LOG_ERROR, "Failed to acknowledge timer in softmix bridge\n");
284  ao2_lock(bridge);
285  break;
286  }
287 
288  ao2_lock(bridge);
289  }
290 
291  return 0;
292 }
pthread_t thread
Definition: bridging.h:133
#define SOFTMIX_DATALEN
Size of the buffer used for sample manipulation.
#define ast_mutex_lock(a)
Definition: lock.h:155
#define ao2_unlock(a)
Definition: astobj2.h:497
unsigned int ast_slinfactory_available(const struct ast_slinfactory *sf)
Retrieve number of samples currently in a slinfactory.
Definition: slinfactory.c:196
size_t array_num
Definition: bridging.h:171
int ast_waitfor_n_fd(int *fds, int n, int *ms, int *exception)
Waits for input on an fd.
Definition: channel.c:3176
unsigned int refresh
Definition: bridging.h:157
#define ao2_lock(a)
Definition: astobj2.h:488
static force_inline void ast_slinear_saturated_add(short *input, short *value)
Definition: utils.h:312
unsigned int stop
Definition: bridging.h:155
#define SOFTMIX_SAMPLES
Number of samples we are dealing with.
int ast_timer_ack(const struct ast_timer *handle, unsigned int quantity)
Acknowledge a timer event.
Definition: timing.c:172
#define LOG_ERROR
Definition: logger.h:155
Define used to turn on 16 kHz audio support.
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct ast_slinfactory factory
int ast_timer_fd(const struct ast_timer *handle)
Get a poll()-able file descriptor for a timer.
Definition: timing.c:158
int ast_timer_set_rate(const struct ast_timer *handle, unsigned int rate)
Set the timing tick rate.
Definition: timing.c:163
short our_buf[SOFTMIX_DATALEN]
Structure that contains information regarding a channel in a bridge.
Definition: bridging.h:117
#define SOFTMIX_INTERVAL
Interval at which mixing will take place. Valid options are 10, 20, and 40.
int ast_slinfactory_read(struct ast_slinfactory *sf, short *buf, size_t samples)
Read samples from a slinfactory.
Definition: slinfactory.c:142
static force_inline void ast_slinear_saturated_subtract(short *input, short *value)
Definition: utils.h:325
short final_buf[SOFTMIX_DATALEN]
static struct ast_timer * timer
Definition: chan_iax2.c:313
ast_mutex_t lock
void * bridge_pvt
Definition: bridging.h:163
#define ast_mutex_unlock(a)
Definition: lock.h:156
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 170 of file bridge_softmix.c.

References AST_BRIDGE_WRITE_SUCCESS, AST_BRIDGE_WRITE_UNSUPPORTED, AST_FORMAT_SLINEAR, AST_FORMAT_SLINEAR16, AST_FRAME_VOICE, ast_mutex_lock, ast_mutex_unlock, ast_slinfactory_feed(), ast_write(), ast_bridge_channel::bridge_pvt, ast_bridge_channel::chan, ast_frame_subclass::codec, softmix_channel::factory, softmix_channel::frame, ast_frame::frametype, softmix_channel::have_frame, softmix_channel::lock, and ast_frame::subclass.

171 {
172  struct softmix_channel *sc = bridge_channel->bridge_pvt;
173 
174  /* Only accept audio frames, all others are unsupported */
175  if (frame->frametype != AST_FRAME_VOICE) {
177  }
178 
179  ast_mutex_lock(&sc->lock);
180 
181  /* If a frame was provided add it to the smoother */
182 #ifdef SOFTMIX_16_SUPPORT
183  if (frame->frametype == AST_FRAME_VOICE && frame->subclass.codec == AST_FORMAT_SLINEAR16) {
184 #else
185  if (frame->frametype == AST_FRAME_VOICE && frame->subclass.codec == AST_FORMAT_SLINEAR) {
186 #endif
187  ast_slinfactory_feed(&sc->factory, frame);
188  }
189 
190  /* If a frame is ready to be written out, do so */
191  if (sc->have_frame) {
192  ast_write(bridge_channel->chan, &sc->frame);
193  sc->have_frame = 0;
194  }
195 
196  /* Alllll done */
197  ast_mutex_unlock(&sc->lock);
198 
200 }
union ast_frame_subclass subclass
Definition: frame.h:146
int ast_slinfactory_feed(struct ast_slinfactory *sf, struct ast_frame *f)
Feed audio into a slinfactory.
Definition: slinfactory.c:77
#define ast_mutex_lock(a)
Definition: lock.h:155
format_t codec
Definition: frame.h:137
#define AST_FORMAT_SLINEAR16
Definition: frame.h:272
Define used to turn on 16 kHz audio support.
struct ast_frame frame
struct ast_slinfactory factory
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
Definition: channel.c:4916
struct ast_channel * chan
Definition: bridging.h:125
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
enum ast_frame_type frametype
Definition: frame.h:144
ast_mutex_t lock
#define ast_mutex_unlock(a)
Definition: lock.h:156
static int unload_module ( void  )
static

Definition at line 312 of file bridge_softmix.c.

References ast_bridge_technology_unregister().

313 {
315 }
int ast_bridge_technology_unregister(struct ast_bridge_technology *technology)
Unregister a bridge technology from use.
Definition: bridging.c:99
static struct ast_bridge_technology softmix_bridge

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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
static

Definition at line 322 of file bridge_softmix.c.

Definition at line 322 of file bridge_softmix.c.

struct ast_bridge_technology softmix_bridge
static

Definition at line 294 of file bridge_softmix.c.