Asterisk - The Open Source Telephony Project  21.4.1
Data Structures | Macros | Functions | Variables
bridge_softmix.c File Reference

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

#include "asterisk.h"
#include <math.h>
#include "asterisk/stream.h"
#include "asterisk/test.h"
#include "asterisk/vector.h"
#include "asterisk/message.h"
#include "bridge_softmix/include/bridge_softmix_internal.h"

Go to the source code of this file.

Data Structures

struct  softmix_remb_collector
 
struct  softmix_stats
 
struct  softmix_translate_helper
 
struct  softmix_translate_helper_entry
 

Macros

#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
 Default time in ms of silence necessary to declare talking stopped by the bridge. More...
 
#define DEFAULT_SOFTMIX_TALKING_THRESHOLD   160
 
#define SOFTBRIDGE_VIDEO_DEST_LEN   strlen(SOFTBRIDGE_VIDEO_DEST_PREFIX)
 
#define SOFTBRIDGE_VIDEO_DEST_PREFIX   "softbridge_dest"
 
#define SOFTBRIDGE_VIDEO_DEST_SEPARATOR   '_'
 
#define SOFTMIX_DATALEN(rate, interval)   ((rate/50) * (interval / 10))
 Size of the buffer used for sample manipulation.
 
#define SOFTMIX_MIN_SAMPLE_RATE   8000 /* 8 kHz sample rate */
 
#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, int binaural_active)
 
static int append_all_streams (struct ast_stream_topology *dest, const struct ast_stream_topology *source)
 
static int append_source_stream (struct ast_stream_topology *dest, const char *channel_name, const char *sdp_label, struct ast_stream *stream, int index)
 
static int append_source_streams (struct ast_stream_topology *dest, const char *channel_name, const char *sdp_label, const struct ast_stream_topology *source)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static void clear_talking (struct ast_bridge_channel *bridge_channel)
 
static void gather_softmix_stats (struct softmix_stats *stats, const struct softmix_bridge_data *softmix_data, struct ast_bridge_channel *bridge_channel)
 
static int is_video_dest (const struct ast_stream *stream, const char *source_channel_name, int source_channel_stream_position)
 Determine if a stream is a video destination stream. More...
 
static int is_video_source (const struct ast_stream *stream)
 Determine if a stream is a video source stream. More...
 
static int load_module (void)
 
static void map_source_to_destinations (const char *source_channel_name, size_t bridge_stream_position, struct ast_bridge_channels_list *participants, int source_channel_stream_position)
 Map a source stream to all of its destination streams. More...
 
static void remb_collect_report (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct softmix_bridge_data *softmix_data, struct softmix_channel *sc)
 
static void remb_collect_report_all (struct ast_bridge *bridge, struct softmix_bridge_data *softmix_data, float bitrate)
 
static struct softmix_remb_collectorremb_collector_alloc (void)
 Allocate a REMB collector. More...
 
static void remb_enable_collection (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, size_t bridge_stream_position)
 Setup REMB collection for a particular bridge stream and channel. More...
 
static void remb_send_report (struct ast_bridge_channel *bridge_channel, struct softmix_bridge_data *softmix_data, struct softmix_channel *sc)
 
static int remove_all_original_streams (struct ast_stream_topology *dest, const struct ast_stream_topology *source, const struct ast_stream_topology *original)
 
static int remove_destination_streams (struct ast_stream_topology *topology, const char *channel_name)
 
static void set_softmix_bridge_data (int rate, int interval, struct ast_bridge_channel *bridge_channel, int reset, int set_binaural, int binaural_pos_id, int is_announcement)
 
static void sfu_topologies_on_join (struct ast_bridge *bridge, struct ast_bridge_channel *joiner)
 Issue channel stream topology change requests. More...
 
static int sfu_topologies_on_leave (struct ast_bridge_channel *leaver, struct ast_bridge_channels_list *participants)
 
static void sfu_topologies_on_source_change (struct ast_bridge *bridge, struct ast_bridge_channel *source)
 
static void softmix_bridge_check_voice (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 
static int softmix_bridge_create (struct ast_bridge *bridge)
 Function called when a bridge is created.
 
static void softmix_bridge_data_destroy (struct softmix_bridge_data *softmix_data)
 
static void softmix_bridge_destroy (struct ast_bridge *bridge)
 Function called when a bridge is destroyed.
 
static int softmix_bridge_join (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 Function called when a channel is joined into the bridge.
 
static void softmix_bridge_leave (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 Function called when a channel leaves the bridge.
 
static void softmix_bridge_stop (struct ast_bridge *bridge)
 
static void softmix_bridge_stream_sources_update (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct softmix_channel *sc)
 
static void softmix_bridge_stream_topology_changed (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 stream_topology_changed callback More...
 
static void softmix_bridge_unsuspend (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 Function called when a channel is unsuspended from the bridge.
 
static int softmix_bridge_write (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
 
static int softmix_bridge_write_control (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
 
static void softmix_bridge_write_rtcp (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
 
static void softmix_bridge_write_text (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
 
static void softmix_bridge_write_video (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
 
static void softmix_bridge_write_voice (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
 
static void softmix_mixing_array_destroy (struct softmix_mixing_array *mixing_array, unsigned int binaural_active)
 
static int softmix_mixing_array_grow (struct softmix_mixing_array *mixing_array, unsigned int num_entries, unsigned int binaural_active)
 
static int softmix_mixing_array_init (struct softmix_mixing_array *mixing_array, unsigned int starting_num_entries, unsigned int binaural_active)
 
static int softmix_mixing_loop (struct ast_bridge *bridge)
 Mixing loop. More...
 
static void * softmix_mixing_thread (void *data)
 
static void softmix_pass_video_top_priority (struct ast_bridge *bridge, struct ast_frame *frame)
 
static void softmix_poke_thread (struct softmix_bridge_data *softmix_data)
 
static int16_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, unsigned int default_sample_size)
 
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_entrysoftmix_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 = "da6642af068ee5e6490c5b1d2cc1d238" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
 
static const 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
David Vossel dvoss.nosp@m.el@d.nosp@m.igium.nosp@m..com

Definition in file bridge_softmix.c.

Macro Definition Documentation

#define DEFAULT_SOFTMIX_SILENCE_THRESHOLD   2500

Default time in ms of silence necessary to declare talking stopped by the bridge.

This is the time at which a channel's own audio will stop getting mixed out of its own write audio stream because it is no longer talking.

Definition at line 66 of file bridge_softmix.c.

#define DEFAULT_SOFTMIX_TALKING_THRESHOLD   160

Default minimum average magnitude threshold to determine talking by the DSP.

Definition at line 69 of file bridge_softmix.c.

#define SOFTMIX_MIN_SAMPLE_RATE   8000 /* 8 kHz sample rate */

The minimum sample rate of the bridge.

Definition at line 45 of file bridge_softmix.c.

Referenced by softmix_bridge_create().

Function Documentation

static int is_video_dest ( const struct ast_stream stream,
const char *  source_channel_name,
int  source_channel_stream_position 
)
static

Determine if a stream is a video destination stream.

A source channel name can be provided to narrow this to a destination stream for a particular source channel. Further, a source stream name can be provided to narrow this to a particular source stream's destination. However, empty strings can be provided to match any destination video stream, regardless of source channel or source stream.

Parameters
streamThe stream to test
source_channel_nameThe name of a source video channel to match
source_channel_stream_positionThe position of the video on the source channel
Return values
1The stream is a video destination stream
0The stream is not a video destination stream

Definition at line 466 of file bridge_softmix.c.

References ast_alloca, ast_stream_get_name(), ast_stream_get_state(), ast_stream_get_type(), and AST_STREAM_STATE_REMOVED.

Referenced by map_source_to_destinations().

468 {
469  char *dest_video_name;
470  size_t dest_video_name_len;
471 
473  || ast_stream_get_type(stream) != AST_MEDIA_TYPE_VIDEO) {
474  return 0;
475  }
476 
477  dest_video_name_len = SOFTBRIDGE_VIDEO_DEST_LEN + 1;
478  if (!ast_strlen_zero(source_channel_name)) {
479  dest_video_name_len += strlen(source_channel_name) + 1;
480  if (source_channel_stream_position != -1) {
481  dest_video_name_len += 11;
482  }
483 
484  dest_video_name = ast_alloca(dest_video_name_len);
485  if (source_channel_stream_position != -1) {
486  /* We are looking for an exact stream position */
487  snprintf(dest_video_name, dest_video_name_len, "%s%c%s%c%d",
488  SOFTBRIDGE_VIDEO_DEST_PREFIX, SOFTBRIDGE_VIDEO_DEST_SEPARATOR,
489  source_channel_name, SOFTBRIDGE_VIDEO_DEST_SEPARATOR,
490  source_channel_stream_position);
491  return !strcmp(ast_stream_get_name(stream), dest_video_name);
492  }
493  snprintf(dest_video_name, dest_video_name_len, "%s%c%s",
494  SOFTBRIDGE_VIDEO_DEST_PREFIX, SOFTBRIDGE_VIDEO_DEST_SEPARATOR,
495  source_channel_name);
496  } else {
497  dest_video_name = SOFTBRIDGE_VIDEO_DEST_PREFIX;
498  }
499 
500  return !strncmp(ast_stream_get_name(stream), dest_video_name, dest_video_name_len - 1);
501 }
enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
Get the media type of a stream.
Definition: stream.c:316
Set when the stream has been removed/declined.
Definition: stream.h:78
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
const char * ast_stream_get_name(const struct ast_stream *stream)
Get the name of a stream.
Definition: stream.c:309
enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
Get the current state of a stream.
Definition: stream.c:373
static int is_video_source ( const struct ast_stream stream)
static

Determine if a stream is a video source stream.

Parameters
streamThe stream to test
Return values
1The stream is a video source
0The stream is not a video source

Definition at line 439 of file bridge_softmix.c.

References ast_stream_get_name(), ast_stream_get_state(), ast_stream_get_type(), and AST_STREAM_STATE_REMOVED.

Referenced by softmix_bridge_stream_topology_changed().

440 {
442  && ast_stream_get_type(stream) == AST_MEDIA_TYPE_VIDEO
443  && strncmp(ast_stream_get_name(stream), SOFTBRIDGE_VIDEO_DEST_PREFIX,
444  SOFTBRIDGE_VIDEO_DEST_LEN)) {
445  return 1;
446  }
447 
448  return 0;
449 }
enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
Get the media type of a stream.
Definition: stream.c:316
Set when the stream has been removed/declined.
Definition: stream.h:78
const char * ast_stream_get_name(const struct ast_stream *stream)
Get the name of a stream.
Definition: stream.c:309
enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
Get the current state of a stream.
Definition: stream.c:373
static void map_source_to_destinations ( const char *  source_channel_name,
size_t  bridge_stream_position,
struct ast_bridge_channels_list participants,
int  source_channel_stream_position 
)
static

Map a source stream to all of its destination streams.

Parameters
source_channel_nameName of channel where the source stream originates
bridge_stream_positionThe slot in the bridge where source video will come from
participantsThe bridge_channels in the bridge
source_channel_stream_positionThe position of the stream on the source channel

Definition at line 2168 of file bridge_softmix.c.

References ast_bridge_channel_lock, ast_bridge_channel_unlock, ast_channel_get_stream_topology(), AST_LIST_TRAVERSE, ast_stream_topology_get_count(), ast_stream_topology_get_stream(), AST_VECTOR_APPEND, AST_VECTOR_REPLACE, ast_bridge_channel::chan, is_video_dest(), ast_bridge_channel::tech_pvt, ast_bridge_channel::to_channel, and softmix_channel::video_sources.

Referenced by softmix_bridge_stream_topology_changed().

2170 {
2171  struct ast_bridge_channel *participant;
2172 
2173  AST_LIST_TRAVERSE(participants, participant, entry) {
2174  int i;
2175  struct ast_stream_topology *topology;
2176 
2177  if (!strcmp(source_channel_name, ast_channel_name(participant->chan))) {
2178  continue;
2179  }
2180 
2181  ast_bridge_channel_lock(participant);
2182  ast_channel_lock(participant->chan);
2183  topology = ast_channel_get_stream_topology(participant->chan);
2184 
2185  for (i = 0; i < ast_stream_topology_get_count(topology); ++i) {
2186  struct ast_stream *stream;
2187 
2188  stream = ast_stream_topology_get_stream(topology, i);
2189  if (is_video_dest(stream, source_channel_name, source_channel_stream_position)) {
2190  struct softmix_channel *sc = participant->tech_pvt;
2191 
2192  AST_VECTOR_REPLACE(&participant->stream_map.to_channel, bridge_stream_position, i);
2193  AST_VECTOR_APPEND(&sc->video_sources, bridge_stream_position);
2194  break;
2195  }
2196  }
2197  ast_channel_unlock(participant->chan);
2198  ast_bridge_channel_unlock(participant);
2199  }
2200 }
struct ast_stream_topology * ast_channel_get_stream_topology(const struct ast_channel *chan)
Retrieve the topology of streams on a channel.
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
struct ast_stream * ast_stream_topology_get_stream(const struct ast_stream_topology *topology, unsigned int position)
Get a specific stream from the topology.
Definition: stream.c:788
struct softmix_channel::@95 video_sources
#define ast_bridge_channel_lock(bridge_channel)
Lock the bridge_channel.
static int is_video_dest(const struct ast_stream *stream, const char *source_channel_name, int source_channel_stream_position)
Determine if a stream is a video destination stream.
#define ast_bridge_channel_unlock(bridge_channel)
Unlock the bridge_channel.
struct ast_vector_int to_channel
Structure which contains per-channel mixing information.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
void * tech_pvt
Private information unique to the bridge technology.
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition: stream.c:765
struct ast_channel * chan
Structure that contains information regarding a channel in a bridge.
#define AST_VECTOR_REPLACE(vec, idx, elem)
Replace an element at a specific position in a vector, growing the vector if needed.
Definition: vector.h:284
Definition: search.h:40
static struct softmix_remb_collector* remb_collector_alloc ( void  )
static

Allocate a REMB collector.

Return values
non-NULLsuccess
NULLfailure

Definition at line 2208 of file bridge_softmix.c.

References AO2_ALLOC_OPT_LOCK_NOLOCK, AST_FRAME_RTCP, AST_RTP_RTCP_FMT_REMB, AST_RTP_RTCP_PSFB, ast_frame::data, ast_frame::datalen, softmix_remb_collector::feedback, ast_rtp_rtcp_feedback::fmt, softmix_remb_collector::frame, ast_frame::frametype, ast_frame_subclass::integer, and ast_frame::subclass.

Referenced by remb_enable_collection().

2209 {
2210  struct softmix_remb_collector *collector;
2211 
2212  collector = ao2_alloc_options(sizeof(*collector), NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
2213  if (!collector) {
2214  return NULL;
2215  }
2216 
2217  collector->frame.frametype = AST_FRAME_RTCP;
2218  collector->frame.subclass.integer = AST_RTP_RTCP_PSFB;
2219  collector->feedback.fmt = AST_RTP_RTCP_FMT_REMB;
2220  collector->frame.data.ptr = &collector->feedback;
2221  collector->frame.datalen = sizeof(collector->feedback);
2222 
2223  return collector;
2224 }
unsigned int fmt
Definition: rtp_engine.h:389
struct ast_frame_subclass subclass
struct ast_frame frame
union ast_frame::@224 data
struct ast_rtp_rtcp_feedback feedback
#define AST_RTP_RTCP_PSFB
Definition: rtp_engine.h:329
enum ast_frame_type frametype
#define AST_RTP_RTCP_FMT_REMB
Definition: rtp_engine.h:339
static void remb_enable_collection ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel,
size_t  bridge_stream_position 
)
static

Setup REMB collection for a particular bridge stream and channel.

Parameters
bridgeThe bridge
bridge_channelChannel that is collecting REMB information
bridge_stream_positionThe slot in the bridge where source video comes from

Definition at line 2233 of file bridge_softmix.c.

References ao2_ref, AST_VECTOR_REPLACE, softmix_channel::remb_collector, remb_collector_alloc(), softmix_bridge_data::remb_collectors, ast_bridge_channel::tech_pvt, and ast_bridge::tech_pvt.

Referenced by softmix_bridge_stream_topology_changed().

2235 {
2236  struct softmix_channel *sc = bridge_channel->tech_pvt;
2237  struct softmix_bridge_data *softmix_data = bridge->tech_pvt;
2238 
2239  if (!sc->remb_collector) {
2241  if (!sc->remb_collector) {
2242  /* This is not fatal. Things will still continue to work but we won't
2243  * produce a REMB report to the sender.
2244  */
2245  return;
2246  }
2247  }
2248 
2249  ao2_ref(sc->remb_collector, +1);
2250  if (AST_VECTOR_REPLACE(&softmix_data->remb_collectors, bridge_stream_position,
2251  sc->remb_collector)) {
2252  ao2_ref(sc->remb_collector, -1);
2253  }
2254 }
static struct softmix_remb_collector * remb_collector_alloc(void)
Allocate a REMB collector.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
Structure which contains per-channel mixing information.
struct softmix_bridge_data::@96 remb_collectors
void * tech_pvt
Private information unique to the bridge technology.
#define AST_VECTOR_REPLACE(vec, idx, elem)
Replace an element at a specific position in a vector, growing the vector if needed.
Definition: vector.h:284
void * tech_pvt
Definition: bridge.h:357
struct softmix_remb_collector * remb_collector
static void sfu_topologies_on_join ( struct ast_bridge bridge,
struct ast_bridge_channel joiner 
)
static

Issue channel stream topology change requests.

When in SFU mode, each participant needs to be able to send video directly to other participants in the bridge. This means that all participants need to have their topologies updated. The joiner needs to have destination streams for all current participants, and the current participants need to have destinations streams added for the joiner's sources.

Parameters
bridge
joinerThe channel that is joining the softmix bridge

Definition at line 619 of file bridge_softmix.c.

References ast_channel_get_stream_topology(), ast_channel_request_stream_topology_change(), AST_LIST_TRAVERSE, ast_stream_topology_alloc(), ast_stream_topology_clone(), ast_stream_topology_free(), ast_bridge_channel::chan, ast_bridge::channels, RAII_VAR, ast_bridge_softmix::send_sdp_label, ast_bridge::softmix, ast_bridge_channel::tech_pvt, and softmix_channel::topology.

Referenced by softmix_bridge_join().

621 {
622  RAII_VAR(struct ast_stream_topology *, joiner_video, NULL, ast_stream_topology_free);
623  struct ast_bridge_channels_list *participants = &bridge->channels;
624  struct ast_bridge_channel *participant;
625  int res;
626  struct softmix_channel *sc;
627  SCOPE_ENTER(3, "%s: \n", ast_channel_name(joiner->chan));
628 
629  joiner_video = ast_stream_topology_alloc();
630  if (!joiner_video) {
631  SCOPE_EXIT_LOG_RTN(LOG_ERROR, "%s: Couldn't alloc topology\n", ast_channel_name(joiner->chan));
632  }
633 
634  sc = joiner->tech_pvt;
635 
636  ast_channel_lock(joiner->chan);
637  res = append_source_streams(joiner_video, ast_channel_name(joiner->chan),
638  bridge->softmix.send_sdp_label ? ast_channel_uniqueid(joiner->chan) : NULL,
641  ast_channel_unlock(joiner->chan);
642 
643  if (res || !sc->topology) {
644  SCOPE_EXIT_LOG_RTN(LOG_ERROR, "%s: Couldn't append source streams\n", ast_channel_name(joiner->chan));
645  }
646 
647  AST_LIST_TRAVERSE(participants, participant, entry) {
648  if (participant == joiner) {
649  continue;
650  }
651  ast_trace(-1, "%s: Appending existing participant %s\n", ast_channel_name(joiner->chan),
652  ast_channel_name(participant->chan));
653  ast_channel_lock(participant->chan);
654  res = append_source_streams(sc->topology, ast_channel_name(participant->chan),
655  bridge->softmix.send_sdp_label ? ast_channel_uniqueid(participant->chan) : NULL,
656  ast_channel_get_stream_topology(participant->chan));
657  ast_channel_unlock(participant->chan);
658  if (res) {
659  SCOPE_EXIT_LOG_RTN(LOG_ERROR, "%s/%s: Couldn't append source streams\n",
660  ast_channel_name(participant->chan), ast_channel_name(joiner->chan));
661  }
662  }
663 
664  ast_trace(-1, "%s: Requesting topology change.\n", ast_channel_name(joiner->chan));
665  res = ast_channel_request_stream_topology_change(joiner->chan, sc->topology, NULL);
666  if (res) {
667  /* There are conditions under which this is expected so no need to log an ERROR. */
668  SCOPE_EXIT_RTN("%s: Couldn't request topology change\n", ast_channel_name(joiner->chan));
669  }
670 
671  AST_LIST_TRAVERSE(participants, participant, entry) {
672  if (participant == joiner) {
673  continue;
674  }
675 
676  sc = participant->tech_pvt;
677  ast_trace(-1, "%s: Appending joiner %s\n", ast_channel_name(participant->chan),
678  ast_channel_name(joiner->chan));
679 
680  if (append_all_streams(sc->topology, joiner_video)) {
681  SCOPE_EXIT_LOG_RTN(LOG_ERROR, "%s/%s: Couldn't append streams\n",
682  ast_channel_name(participant->chan), ast_channel_name(joiner->chan));
683  }
684  ast_trace(-1, "%s: Requesting topology change\n", ast_channel_name(participant->chan));
685  res = ast_channel_request_stream_topology_change(participant->chan, sc->topology, NULL);
686  if (res) {
687  ast_trace(-1, "%s/%s: Couldn't request topology change\n",
688  ast_channel_name(participant->chan), ast_channel_name(joiner->chan));
689  }
690  }
691 
692  SCOPE_EXIT();
693 }
struct ast_stream_topology * ast_channel_get_stream_topology(const struct ast_channel *chan)
Retrieve the topology of streams on a channel.
struct ast_stream_topology * topology
int ast_channel_request_stream_topology_change(struct ast_channel *chan, struct ast_stream_topology *topology, void *change_source)
Request that the stream topology of a channel change.
Definition: channel.c:10966
struct ast_bridge_softmix softmix
Definition: bridge.h:367
struct ast_stream_topology * ast_stream_topology_alloc(void)
Create a stream topology.
Definition: stream.c:650
Structure which contains per-channel mixing information.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
void * tech_pvt
Private information unique to the bridge technology.
unsigned int send_sdp_label
Definition: bridge.h:300
struct ast_stream_topology * ast_stream_topology_clone(const struct ast_stream_topology *topology)
Create a deep clone of an existing stream topology.
Definition: stream.c:667
struct ast_bridge_channels_list channels
Definition: bridge.h:363
struct ast_channel * chan
Structure that contains information regarding a channel in a bridge.
Definition: search.h:40
void ast_stream_topology_free(struct ast_stream_topology *topology)
Unreference and destroy a stream topology.
Definition: stream.c:743
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
static void softmix_bridge_stream_topology_changed ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel 
)
static

stream_topology_changed callback

For most video modes, nothing beyond the ordinary is required. For the SFU case, though, we need to completely remap the streams in order to ensure video gets directed where it is expected to go.

Parameters
bridgeThe bridge
bridge_channelChannel whose topology has changed

Definition at line 2450 of file bridge_softmix.c.

References ao2_bump, ast_bridge_channel_lock, ast_bridge_channel_stream_map(), ast_bridge_channel_unlock, AST_BRIDGE_VIDEO_MODE_NONE, AST_BRIDGE_VIDEO_MODE_SFU, AST_BRIDGE_VIDEO_MODE_SINGLE_SRC, AST_BRIDGE_VIDEO_MODE_TALKER_SRC, ast_channel_get_stream_topology(), AST_LIST_TRAVERSE, ast_stream_get_state(), ast_stream_get_type(), AST_STREAM_STATE_REMOVED, ast_stream_topology_free(), ast_stream_topology_get_count(), ast_stream_topology_get_stream(), AST_VECTOR_APPEND, AST_VECTOR_ELEM_CLEANUP_NOOP, AST_VECTOR_ELEM_DEFAULT_CMP, AST_VECTOR_FREE, AST_VECTOR_GET, AST_VECTOR_GET_INDEX_NTH, AST_VECTOR_INIT, AST_VECTOR_REPLACE, AST_VECTOR_RESET, AST_VECTOR_SIZE, ast_bridge_channel::chan, ast_bridge::channels, is_video_source(), map_source_to_destinations(), softmix_bridge_data::remb_collectors, remb_enable_collection(), ast_bridge::softmix, ast_bridge_channel::tech_pvt, ast_bridge::tech_pvt, ast_bridge_channel::to_bridge, ast_bridge_channel::to_channel, ast_stream::type, ast_bridge_softmix::video_mode, and softmix_channel::video_sources.

2451 {
2452  struct softmix_bridge_data *softmix_data = bridge->tech_pvt;
2453  struct softmix_channel *sc = bridge_channel->tech_pvt;
2454  struct ast_bridge_channel *participant;
2455  struct ast_vector_int media_types;
2456  int nths[AST_MEDIA_TYPE_END] = {0};
2457  int idx;
2458  SCOPE_ENTER(3, "%s: \n", ast_channel_name(bridge_channel->chan));
2459 
2460  switch (bridge->softmix.video_mode.mode) {
2464  default:
2465  ast_bridge_channel_stream_map(bridge_channel);
2466  SCOPE_EXIT_RTN("%s: Not in SFU mode\n", ast_channel_name(bridge_channel->chan));
2468  break;
2469  }
2470 
2471  ast_channel_lock(bridge_channel->chan);
2472  softmix_bridge_stream_sources_update(bridge, bridge_channel, sc);
2473  ast_channel_unlock(bridge_channel->chan);
2474 
2475  AST_VECTOR_INIT(&media_types, AST_MEDIA_TYPE_END);
2476 
2477  /* The bridge stream identifiers may change, so reset the mapping for them.
2478  * When channels end up getting added back in they'll reuse their existing
2479  * collector and won't need to allocate a new one (unless they were just added).
2480  */
2481  for (idx = 0; idx < AST_VECTOR_SIZE(&softmix_data->remb_collectors); ++idx) {
2482  ao2_cleanup(AST_VECTOR_GET(&softmix_data->remb_collectors, idx));
2483  AST_VECTOR_REPLACE(&softmix_data->remb_collectors, idx, NULL);
2484  }
2485 
2486  /* First traversal: re-initialize all of the participants' stream maps */
2487  AST_LIST_TRAVERSE(&bridge->channels, participant, entry) {
2488  ast_bridge_channel_lock(participant);
2489 
2490  AST_VECTOR_RESET(&participant->stream_map.to_channel, AST_VECTOR_ELEM_CLEANUP_NOOP);
2491  AST_VECTOR_RESET(&participant->stream_map.to_bridge, AST_VECTOR_ELEM_CLEANUP_NOOP);
2492 
2493  sc = participant->tech_pvt;
2495 
2496  ast_bridge_channel_unlock(participant);
2497  }
2498 
2499  /* Second traversal: Map specific video channels from their source to their destinations.
2500  *
2501  * This is similar to what is done in ast_stream_topology_map(),
2502  * except that video channels are handled differently. Each video
2503  * source has it's own unique index on the bridge. This way, a
2504  * particular channel's source video can be distributed to the
2505  * appropriate destination streams on the other channels.
2506  */
2507  AST_LIST_TRAVERSE(&bridge->channels, participant, entry) {
2508  int i;
2509  struct ast_stream_topology *topology;
2510 
2511  ast_bridge_channel_lock(participant);
2512  ast_channel_lock(participant->chan);
2513 
2514  topology = ao2_bump(ast_channel_get_stream_topology(participant->chan));
2515  if (!topology) {
2516  /* Oh, my, we are in trouble. */
2517  ast_channel_unlock(participant->chan);
2518  ast_bridge_channel_unlock(participant);
2519  continue;
2520  }
2521 
2522  for (i = 0; i < ast_stream_topology_get_count(topology); ++i) {
2523  struct ast_stream *stream = ast_stream_topology_get_stream(topology, i);
2524 
2525  if (is_video_source(stream)) {
2526  AST_VECTOR_APPEND(&media_types, AST_MEDIA_TYPE_VIDEO);
2527  AST_VECTOR_REPLACE(&participant->stream_map.to_bridge, i, AST_VECTOR_SIZE(&media_types) - 1);
2528  /*
2529  * There are cases where we need to bidirectionally send frames, such as for REMB reports
2530  * so we also map back to the channel.
2531  */
2532  AST_VECTOR_REPLACE(&participant->stream_map.to_channel, AST_VECTOR_SIZE(&media_types) - 1, i);
2533  remb_enable_collection(bridge, participant, AST_VECTOR_SIZE(&media_types) - 1);
2534  /*
2535  * Unlock the channel and participant to prevent
2536  * potential deadlock in map_source_to_destinations().
2537  */
2538  ast_channel_unlock(participant->chan);
2539  ast_bridge_channel_unlock(participant);
2540 
2541  map_source_to_destinations(ast_channel_name(participant->chan),
2542  AST_VECTOR_SIZE(&media_types) - 1, &bridge->channels, i);
2543  ast_bridge_channel_lock(participant);
2544  ast_channel_lock(participant->chan);
2545  } else if (ast_stream_get_type(stream) == AST_MEDIA_TYPE_VIDEO) {
2546  /* Video stream mapping occurs directly when a video source stream
2547  * is found on a channel. Video streams should otherwise remain
2548  * unmapped.
2549  */
2550  AST_VECTOR_REPLACE(&participant->stream_map.to_bridge, i, -1);
2551  } else if (ast_stream_get_state(stream) != AST_STREAM_STATE_REMOVED) {
2552  /* XXX This is copied from ast_stream_topology_map(). This likely could
2553  * be factored out in some way
2554  */
2555  enum ast_media_type type = ast_stream_get_type(stream);
2556  int index = AST_VECTOR_GET_INDEX_NTH(&media_types, ++nths[type],
2558 
2559  if (index == -1) {
2560  AST_VECTOR_APPEND(&media_types, type);
2561  index = AST_VECTOR_SIZE(&media_types) - 1;
2562  }
2563 
2564  AST_VECTOR_REPLACE(&participant->stream_map.to_bridge, i, index);
2565  AST_VECTOR_REPLACE(&participant->stream_map.to_channel, index, i);
2566  }
2567  }
2568 
2569  ast_stream_topology_free(topology);
2570 
2571  ast_channel_unlock(participant->chan);
2572  ast_bridge_channel_unlock(participant);
2573  }
2574 
2575  AST_VECTOR_FREE(&media_types);
2576  SCOPE_EXIT_RTN("%s\n", ast_channel_name(bridge_channel->chan));
2577 }
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
#define AST_VECTOR_GET_INDEX_NTH(vec, nth, value, cmp)
Get the nth index from a vector that matches the given comparison.
Definition: vector.h:696
struct ast_stream_topology * ast_channel_get_stream_topology(const struct ast_channel *chan)
Retrieve the topology of streams on a channel.
#define AST_VECTOR_ELEM_DEFAULT_CMP(elem, value)
Default comparator for AST_VECTOR_REMOVE_ELEM_UNORDERED()
Definition: vector.h:564
enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
Get the media type of a stream.
Definition: stream.c:316
struct ast_bridge_video_mode video_mode
Definition: bridge.h:279
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
Set when the stream has been removed/declined.
Definition: stream.h:78
struct ast_stream * ast_stream_topology_get_stream(const struct ast_stream_topology *topology, unsigned int position)
Get a specific stream from the topology.
Definition: stream.c:788
static void map_source_to_destinations(const char *source_channel_name, size_t bridge_stream_position, struct ast_bridge_channels_list *participants, int source_channel_stream_position)
Map a source stream to all of its destination streams.
struct ast_bridge_softmix softmix
Definition: bridge.h:367
struct ast_vector_int to_bridge
struct softmix_channel::@95 video_sources
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
#define ast_bridge_channel_lock(bridge_channel)
Lock the bridge_channel.
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
enum ast_media_type type
The type of media the stream is handling.
Definition: stream.c:85
#define AST_VECTOR_ELEM_CLEANUP_NOOP(elem)
Vector element cleanup that does nothing.
Definition: vector.h:571
#define ast_bridge_channel_unlock(bridge_channel)
Unlock the bridge_channel.
struct ast_vector_int to_channel
Structure which contains per-channel mixing information.
struct softmix_bridge_data::@96 remb_collectors
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
Definition: vector.h:625
static int is_video_source(const struct ast_stream *stream)
Determine if a stream is a video source stream.
void * tech_pvt
Private information unique to the bridge technology.
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition: stream.c:765
static void remb_enable_collection(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, size_t bridge_stream_position)
Setup REMB collection for a particular bridge stream and channel.
struct ast_bridge_channels_list channels
Definition: bridge.h:363
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:680
struct ast_channel * chan
Structure that contains information regarding a channel in a bridge.
#define AST_VECTOR_REPLACE(vec, idx, elem)
Replace an element at a specific position in a vector, growing the vector if needed.
Definition: vector.h:284
void ast_bridge_channel_stream_map(struct ast_bridge_channel *bridge_channel)
Maps a channel's stream topology to and from the bridge.
void * tech_pvt
Definition: bridge.h:357
Definition: search.h:40
ast_media_type
Types of media.
Definition: codec.h:30
void ast_stream_topology_free(struct ast_stream_topology *topology)
Unreference and destroy a stream topology.
Definition: stream.c:743
Integer vector definition.
Definition: vector.h:52
enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
Get the current state of a stream.
Definition: stream.c:373
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609
static int softmix_mixing_loop ( struct ast_bridge bridge)
static

Mixing loop.

Return values
0on success
-1on failure

Definition at line 1752 of file bridge_softmix.c.

References add_binaural_mixing(), ast_bridge_channel_queue_frame(), ast_bridge_lock, ast_bridge_unlock, AST_BRIDGE_VIDEO_MODE_SFU, ast_format_cache_get_slin_by_rate(), AST_LIST_TRAVERSE, ast_timer_ack(), ast_timer_fd(), ast_timer_set_rate(), ast_tvdiff_ms(), ast_tvnow(), ast_waitfor_n_fd(), softmix_channel::binaural, convolve_data::binaural_active, ast_bridge_softmix::binaural_active, binaural_mixing(), softmix_bridge_data::bitrate, ast_bridge_channel::chan, ast_bridge::channels, check_binaural_position_change(), softmix_bridge_data::convolve, create_binaural_frame(), ast_frame::datalen, softmix_bridge_data::default_sample_size, softmix_channel::final_buf, ast_frame_subclass::format, ast_bridge_softmix::internal_mixing_interval, ast_bridge_softmix::internal_sample_rate, softmix_bridge_data::last_remb_update, softmix_channel::lock, softmix_stats::locked_rate, softmix_stats::maximum_rate, ast_bridge_softmix::maximum_sample_rate, ast_bridge::num_active, ast_bridge::num_channels, ast_bridge_video_sfu_data::remb_send_interval, ast_frame::samples, ast_bridge::softmix, SOFTMIX_DATALEN, SOFTMIX_SAMPLES, SOFTMIX_STAT_INTERVAL, softmix_bridge_data::stop, ast_frame::subclass, ast_bridge_channel::suspended, ast_bridge_channel::tech_pvt, ast_bridge::tech_pvt, ast_bridge::uniqueid, ast_bridge_softmix::video_mode, and softmix_channel::write_frame.

1753 {
1754  struct softmix_stats stats = { { 0 }, };
1755  struct softmix_mixing_array mixing_array;
1756  struct softmix_bridge_data *softmix_data = bridge->tech_pvt;
1757  struct ast_timer *timer;
1758  struct softmix_translate_helper trans_helper;
1759  int16_t buf[MAX_DATALEN];
1760 #ifdef BINAURAL_RENDERING
1761  int16_t bin_buf[MAX_DATALEN];
1762  int16_t ann_buf[MAX_DATALEN];
1763 #endif
1764  unsigned int stat_iteration_counter = 0; /* counts down, gather stats at zero and reset. */
1765  int timingfd;
1766  int update_all_rates = 0; /* set this when the internal sample rate has changed */
1767  unsigned int idx;
1768  unsigned int x;
1769  int res = -1;
1770 
1771  timer = softmix_data->timer;
1772  timingfd = ast_timer_fd(timer);
1773  softmix_translate_helper_init(&trans_helper, softmix_data->internal_rate);
1774  ast_timer_set_rate(timer, (1000 / softmix_data->internal_mixing_interval));
1775 
1776  /* Give the mixing array room to grow, memory is cheap but allocations are expensive. */
1777  if (softmix_mixing_array_init(&mixing_array, bridge->num_channels + 10,
1778  bridge->softmix.binaural_active)) {
1779  goto softmix_cleanup;
1780  }
1781 
1782  /*
1783  * XXX Softmix needs to use channel roles to determine who gets
1784  * what audio mixed.
1785  */
1786  while (!softmix_data->stop && bridge->num_active) {
1787  struct ast_bridge_channel *bridge_channel;
1788  int timeout = -1;
1789  struct ast_format *cur_slin = ast_format_cache_get_slin_by_rate(softmix_data->internal_rate);
1790  unsigned int softmix_samples = SOFTMIX_SAMPLES(softmix_data->internal_rate, softmix_data->internal_mixing_interval);
1791  unsigned int softmix_datalen = SOFTMIX_DATALEN(softmix_data->internal_rate, softmix_data->internal_mixing_interval);
1792  int remb_update = 0;
1793 
1794  if (softmix_datalen > MAX_DATALEN) {
1795  /* This should NEVER happen, but if it does we need to know about it. Almost
1796  * all the memcpys used during this process depend on this assumption. Rather
1797  * than checking this over and over again through out the code, this single
1798  * verification is done on each iteration. */
1799  ast_log(LOG_WARNING,
1800  "Bridge %s: Conference mixing error, requested mixing length greater than mixing buffer.\n",
1801  bridge->uniqueid);
1802  goto softmix_cleanup;
1803  }
1804 
1805  /* Grow the mixing array buffer as participants are added. */
1806  if (mixing_array.max_num_entries < bridge->num_channels
1807  && softmix_mixing_array_grow(&mixing_array, bridge->num_channels + 5,
1808  bridge->softmix.binaural_active)) {
1809  goto softmix_cleanup;
1810  }
1811 
1812  /* init the number of buffers stored in the mixing array to 0.
1813  * As buffers are added for mixing, this number is incremented. */
1814  mixing_array.used_entries = 0;
1815 
1816  /* These variables help determine if a rate change is required */
1817  if (!stat_iteration_counter) {
1818  memset(&stats, 0, sizeof(stats));
1819  stats.locked_rate = bridge->softmix.internal_sample_rate;
1820  stats.maximum_rate = bridge->softmix.maximum_sample_rate;
1821  }
1822 
1823  /* If the sample rate has changed, update the translator helper */
1824  if (update_all_rates) {
1825  softmix_translate_helper_change_rate(&trans_helper, softmix_data->internal_rate);
1826  }
1827 
1828 #ifdef BINAURAL_RENDERING
1829  check_binaural_position_change(bridge, softmix_data);
1830 #endif
1831 
1832  /* If we need to do a REMB update to all video sources then do so */
1833  if (bridge->softmix.video_mode.mode == AST_BRIDGE_VIDEO_MODE_SFU &&
1834  bridge->softmix.video_mode.mode_data.sfu_data.remb_send_interval &&
1835  ast_tvdiff_ms(ast_tvnow(), softmix_data->last_remb_update) > bridge->softmix.video_mode.mode_data.sfu_data.remb_send_interval) {
1836  remb_update = 1;
1837  softmix_data->last_remb_update = ast_tvnow();
1838  }
1839 
1840  /* Go through pulling audio from each factory that has it available */
1841  AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
1842  struct softmix_channel *sc = bridge_channel->tech_pvt;
1843 
1844  if (!sc) {
1845  /* This channel failed to join successfully. */
1846  continue;
1847  }
1848 
1849  /* Update the sample rate to match the bridge's native sample rate if necessary. */
1850  if (update_all_rates) {
1851  set_softmix_bridge_data(softmix_data->internal_rate,
1852  softmix_data->internal_mixing_interval, bridge_channel, 1, -1, -1, -1);
1853  }
1854 
1855  /* If stat_iteration_counter is 0, then collect statistics during this mixing interaction */
1856  if (!stat_iteration_counter) {
1857  gather_softmix_stats(&stats, softmix_data, bridge_channel);
1858  }
1859 
1860  /* if the channel is suspended, don't check for audio, but still gather stats */
1861  if (bridge_channel->suspended) {
1862  continue;
1863  }
1864 
1865  /* Try to get audio from the factory if available */
1866  ast_mutex_lock(&sc->lock);
1867  if ((mixing_array.buffers[mixing_array.used_entries] = softmix_process_read_audio(sc, softmix_samples))) {
1868 #ifdef BINAURAL_RENDERING
1869  add_binaural_mixing(bridge, softmix_data, softmix_samples, &mixing_array, sc,
1870  ast_channel_name(bridge_channel->chan));
1871 #endif
1872  mixing_array.used_entries++;
1873  }
1874  if (remb_update) {
1875  remb_collect_report(bridge, bridge_channel, softmix_data, sc);
1876  }
1877  ast_mutex_unlock(&sc->lock);
1878  }
1879 
1880  /* mix it like crazy (non binaural channels)*/
1881  memset(buf, 0, softmix_datalen);
1882  for (idx = 0; idx < mixing_array.used_entries; ++idx) {
1883  for (x = 0; x < softmix_samples; ++x) {
1884  ast_slinear_saturated_add(buf + x, mixing_array.buffers[idx] + x);
1885  }
1886  }
1887 
1888 #ifdef BINAURAL_RENDERING
1889  binaural_mixing(bridge, softmix_data, &mixing_array, bin_buf, ann_buf);
1890 #endif
1891 
1892  /* Next step go through removing the channel's own audio and creating a good frame... */
1893  AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
1894  struct softmix_channel *sc = bridge_channel->tech_pvt;
1895 
1896  if (!sc || bridge_channel->suspended) {
1897  /* This channel failed to join successfully or is suspended. */
1898  continue;
1899  }
1900 
1901  ast_mutex_lock(&sc->lock);
1902 
1903  /* Make SLINEAR write frame from local buffer */
1904  ao2_t_replace(sc->write_frame.subclass.format, cur_slin,
1905  "Replace softmix channel slin format");
1906 #ifdef BINAURAL_RENDERING
1907  if (bridge->softmix.binaural_active && softmix_data->convolve.binaural_active
1908  && sc->binaural) {
1909  create_binaural_frame(bridge_channel, sc, bin_buf, ann_buf, softmix_datalen,
1910  softmix_samples, buf);
1911  } else
1912 #endif
1913  {
1914  sc->write_frame.datalen = softmix_datalen;
1915  sc->write_frame.samples = softmix_samples;
1916  memcpy(sc->final_buf, buf, softmix_datalen);
1917  }
1918  /* process the softmix channel's new write audio */
1919  softmix_process_write_audio(&trans_helper,
1920  ast_channel_rawwriteformat(bridge_channel->chan), sc,
1921  softmix_data->default_sample_size);
1922 
1923  ast_mutex_unlock(&sc->lock);
1924 
1925  /* A frame is now ready for the channel. */
1926  ast_bridge_channel_queue_frame(bridge_channel, &sc->write_frame);
1927 
1928  if (remb_update) {
1929  remb_send_report(bridge_channel, softmix_data, sc);
1930  }
1931  }
1932 
1933  if (remb_update) {
1934  /* In case we are doing bridge level REMB reset the bitrate so we start fresh */
1935  softmix_data->bitrate = 0;
1936  }
1937 
1938  update_all_rates = 0;
1939  if (!stat_iteration_counter) {
1940  update_all_rates = analyse_softmix_stats(&stats, softmix_data,
1941  bridge->softmix.binaural_active);
1942  stat_iteration_counter = SOFTMIX_STAT_INTERVAL;
1943  }
1944  stat_iteration_counter--;
1945 
1946  ast_bridge_unlock(bridge);
1947  /* cleanup any translation frame data from the previous mixing iteration. */
1948  softmix_translate_helper_cleanup(&trans_helper);
1949  /* Wait for the timing source to tell us to wake up and get things done */
1950  ast_waitfor_n_fd(&timingfd, 1, &timeout, NULL);
1951  if (ast_timer_ack(timer, 1) < 0) {
1952  ast_log(LOG_ERROR, "Bridge %s: Failed to acknowledge timer in softmix.\n",
1953  bridge->uniqueid);
1954  ast_bridge_lock(bridge);
1955  goto softmix_cleanup;
1956  }
1957  ast_bridge_lock(bridge);
1958 
1959  /* make sure to detect mixing interval changes if they occur. */
1960  if (bridge->softmix.internal_mixing_interval
1961  && (bridge->softmix.internal_mixing_interval != softmix_data->internal_mixing_interval)) {
1962  softmix_data->internal_mixing_interval = bridge->softmix.internal_mixing_interval;
1963  ast_timer_set_rate(timer, (1000 / softmix_data->internal_mixing_interval));
1964  update_all_rates = 1; /* if the interval changes, the rates must be adjusted as well just to be notified new interval.*/
1965  }
1966  }
1967 
1968  res = 0;
1969 
1970 softmix_cleanup:
1971  softmix_translate_helper_destroy(&trans_helper);
1972  softmix_mixing_array_destroy(&mixing_array, bridge->softmix.binaural_active);
1973  return res;
1974 }
void check_binaural_position_change(struct ast_bridge *bridge, struct softmix_bridge_data *softmix_data)
Checks if a position change in the virtual enviroment is requested by one of the participants.
const ast_string_field uniqueid
Definition: bridge.h:401
unsigned int num_active
Definition: bridge.h:375
unsigned int remb_send_interval
Definition: bridge.h:151
unsigned int internal_mixing_interval
The mixing interval indicates how quickly softmix mixing should occur to mix audio.
Definition: bridge.h:293
unsigned int locked_rate
struct ast_bridge_video_mode video_mode
Definition: bridge.h:279
unsigned int suspended
Definition of a media format.
Definition: format.c:43
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107
short final_buf[MAX_DATALEN]
struct ast_bridge_softmix softmix
Definition: bridge.h:367
struct ast_frame_subclass subclass
#define SOFTMIX_SAMPLES(rate, interval)
Number of samples we are dealing with.
int ast_waitfor_n_fd(int *fds, int n, int *ms, int *exception)
Waits for input on an fd.
Definition: channel.c:2980
unsigned int maximum_rate
int ast_timer_ack(const struct ast_timer *handle, unsigned int quantity)
Acknowledge a timer event.
Definition: timing.c:171
struct ast_frame write_frame
Structure which contains per-channel mixing information.
void create_binaural_frame(struct ast_bridge_channel *bridge_channel, struct softmix_channel *sc, int16_t *bin_buf, int16_t *ann_buf, unsigned int softmix_datalen, unsigned int softmix_samples, int16_t *buf)
Creates a frame out of binaural audio data.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define ast_bridge_unlock(bridge)
Unlock the bridge.
Definition: bridge.h:481
void * tech_pvt
Private information unique to the bridge technology.
int ast_timer_fd(const struct ast_timer *handle)
Get a poll()-able file descriptor for a timer.
Definition: timing.c:161
int ast_timer_set_rate(const struct ast_timer *handle, unsigned int rate)
Set the timing tick rate.
Definition: timing.c:166
#define ast_bridge_lock(bridge)
Lock the bridge.
Definition: bridge.h:470
int ast_bridge_channel_queue_frame(struct ast_bridge_channel *bridge_channel, struct ast_frame *fr)
Write a frame to the specified bridge_channel.
struct ast_bridge_channels_list channels
Definition: bridge.h:363
struct ast_channel * chan
Structure that contains information regarding a channel in a bridge.
void add_binaural_mixing(struct ast_bridge *bridge, struct softmix_bridge_data *softmix_data, unsigned int softmix_samples, struct softmix_mixing_array *mixing_array, struct softmix_channel *sc, const char *channel_name)
Processes audio data with the binaural synthesis and adds the result to the mixing array...
struct convolve_data convolve
void * tech_pvt
Definition: bridge.h:357
Definition: search.h:40
struct ast_format * format
unsigned int internal_sample_rate
The internal sample rate softmix uses to mix channels.
Definition: bridge.h:285
unsigned int maximum_sample_rate
The maximum sample rate softmix uses to mix channels.
Definition: bridge.h:306
unsigned int num_channels
Definition: bridge.h:373
struct ast_format * ast_format_cache_get_slin_by_rate(unsigned int rate)
Retrieve the best signed linear format given a sample rate.
Definition: format_cache.c:512
void binaural_mixing(struct ast_bridge *bridge, struct softmix_bridge_data *softmix_data, struct softmix_mixing_array *mixing_array, int16_t *bin_buf, int16_t *ann_buf)
Mixes all binaural audio data contained in the mixing array.
#define SOFTMIX_DATALEN(rate, interval)
Size of the buffer used for sample manipulation.
unsigned int binaural_active
Definition: bridge.h:295
#define SOFTMIX_STAT_INTERVAL
Number of mixing iterations to perform between gathering statistics.