diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c
index 7fe727e530..0beffe7542 100644
--- a/apps/app_confbridge.c
+++ b/apps/app_confbridge.c
@@ -1706,6 +1706,8 @@ static struct confbridge_conference *join_conference_bridge(const char *conferen
/* Set the internal sample rate on the bridge from the bridge profile */
ast_bridge_set_internal_sample_rate(conference->bridge, conference->b_profile.internal_sample_rate);
+ /* Set the maximum sample rate on the bridge from the bridge profile */
+ ast_bridge_set_maximum_sample_rate(conference->bridge, conference->b_profile.maximum_sample_rate);
/* Set the internal mixing interval on the bridge from the bridge profile */
ast_bridge_set_mixing_interval(conference->bridge, conference->b_profile.mix_interval);
ast_bridge_set_binaural_active(conference->bridge, ast_test_flag(&conference->b_profile, BRIDGE_OPT_BINAURAL_ACTIVE));
diff --git a/apps/confbridge/conf_config_parser.c b/apps/confbridge/conf_config_parser.c
index f732c45402..b0c717ab22 100644
--- a/apps/confbridge/conf_config_parser.c
+++ b/apps/confbridge/conf_config_parser.c
@@ -274,6 +274,15 @@
will be used.
+
+ Set the maximum native sample rate for mixing the conference
+
+ Sets the maximum native sample rate the
+ conference is mixed at. This is set to not have a
+ maximum by default. If a sample rate is specified,
+ though, the native sample rate will never exceed it.
+
+
The language used for announcements to the conference.
@@ -1682,6 +1691,13 @@ static char *handle_cli_confbridge_show_bridge_profile(struct ast_cli_entry *e,
}
ast_cli(a->fd,"Internal Sample Rate: %s\n", tmp);
+ if (b_profile.maximum_sample_rate) {
+ snprintf(tmp, sizeof(tmp), "%u", b_profile.maximum_sample_rate);
+ } else {
+ ast_copy_string(tmp, "none", sizeof(tmp));
+ }
+ ast_cli(a->fd,"Maximum Sample Rate: %s\n", tmp);
+
if (b_profile.mix_interval) {
ast_cli(a->fd,"Mixing Interval: %u\n", b_profile.mix_interval);
} else {
@@ -2376,6 +2392,7 @@ int conf_load_config(void)
/* "auto" will fail to parse as a uint, but we use PARSE_DEFAULT to set the value to 0 in that case, which is the value that auto resolves to */
aco_option_register(&cfg_info, "internal_sample_rate", ACO_EXACT, bridge_types, "0", OPT_UINT_T, PARSE_DEFAULT, FLDSET(struct bridge_profile, internal_sample_rate), 0);
aco_option_register(&cfg_info, "binaural_active", ACO_EXACT, bridge_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct bridge_profile, flags), BRIDGE_OPT_BINAURAL_ACTIVE);
+ aco_option_register(&cfg_info, "maximum_sample_rate", ACO_EXACT, bridge_types, "0", OPT_UINT_T, PARSE_DEFAULT, FLDSET(struct bridge_profile, maximum_sample_rate), 0);
aco_option_register_custom(&cfg_info, "mixing_interval", ACO_EXACT, bridge_types, "20", mix_interval_handler, 0);
aco_option_register(&cfg_info, "record_conference", ACO_EXACT, bridge_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct bridge_profile, flags), BRIDGE_OPT_RECORD_CONFERENCE);
aco_option_register_custom(&cfg_info, "video_mode", ACO_EXACT, bridge_types, NULL, video_mode_handler, 0);
diff --git a/apps/confbridge/include/confbridge.h b/apps/confbridge/include/confbridge.h
index f932da8587..82e709acdf 100644
--- a/apps/confbridge/include/confbridge.h
+++ b/apps/confbridge/include/confbridge.h
@@ -228,6 +228,7 @@ struct bridge_profile {
unsigned int flags;
unsigned int max_members; /*!< The maximum number of participants allowed in the conference */
unsigned int internal_sample_rate; /*!< The internal sample rate of the bridge. 0 when set to auto adjust mode. */
+ unsigned int maximum_sample_rate; /*!< The maximum sample rate of the bridge. 0 when set to no maximum. */
unsigned int mix_interval; /*!< The internal mixing interval used by the bridge. When set to 0 the bridgewill use a default interval. */
struct bridge_profile_sounds *sounds;
char regcontext[AST_MAX_CONTEXT];
diff --git a/bridges/bridge_softmix.c b/bridges/bridge_softmix.c
index d907084cf1..c24fa7a27f 100644
--- a/bridges/bridge_softmix.c
+++ b/bridges/bridge_softmix.c
@@ -88,12 +88,16 @@ struct softmix_stats {
unsigned int num_channels[16];
/*! The number of channels above the internal sample rate */
unsigned int num_above_internal_rate;
+ /*! The number of channels above the maximum sample rate */
+ unsigned int num_above_maximum_rate;
/*! The number of channels at the internal sample rate */
unsigned int num_at_internal_rate;
/*! The absolute highest sample rate preferred by any channel in the bridge */
unsigned int highest_supported_rate;
/*! Is the sample rate locked by the bridge, if so what is that rate.*/
unsigned int locked_rate;
+ /*! The maximum sample rate the bridge may use */
+ unsigned int maximum_rate;
};
struct softmix_translate_helper_entry {
@@ -1541,7 +1545,9 @@ static void gather_softmix_stats(struct softmix_stats *stats,
if (stats->highest_supported_rate < channel_native_rate) {
stats->highest_supported_rate = channel_native_rate;
}
- if (softmix_data->internal_rate < channel_native_rate) {
+ if (stats->maximum_rate && stats->maximum_rate < channel_native_rate) {
+ stats->num_above_maximum_rate++;
+ } else if (softmix_data->internal_rate < channel_native_rate) {
int i;
for (i = 0; i < ARRAY_LEN(stats->sample_rates); i++) {
@@ -1593,6 +1599,15 @@ static unsigned int analyse_softmix_stats(struct softmix_stats *stats,
softmix_data->internal_rate = stats->locked_rate;
return 1;
}
+ } else if (stats->num_above_maximum_rate) {
+ /* if the bridge has a maximum rate set and channels are above it only
+ * update if it differs from the current rate we are using. */
+ if (softmix_data->internal_rate != stats->maximum_rate) {
+ ast_debug(1, "Locking at new maximum rate. Bridge changed from %u to %u.\n",
+ softmix_data->internal_rate, stats->maximum_rate);
+ softmix_data->internal_rate = stats->maximum_rate;
+ return 1;
+ }
} else if (stats->num_above_internal_rate >= 2) {
/* the highest rate is just used as a starting point */
unsigned int best_rate = stats->highest_supported_rate;
@@ -1775,6 +1790,7 @@ static int softmix_mixing_loop(struct ast_bridge *bridge)
if (!stat_iteration_counter) {
memset(&stats, 0, sizeof(stats));
stats.locked_rate = bridge->softmix.internal_sample_rate;
+ stats.maximum_rate = bridge->softmix.maximum_sample_rate;
}
/* If the sample rate has changed, update the translator helper */
diff --git a/configs/samples/confbridge.conf.sample b/configs/samples/confbridge.conf.sample
index e1481818be..520b357f63 100644
--- a/configs/samples/confbridge.conf.sample
+++ b/configs/samples/confbridge.conf.sample
@@ -203,6 +203,10 @@ type=bridge
; closest sample rate Asterisk does support to the one requested
; will be used.
+;maximum_sample_rate=none ; Sets the maximum sample rate the conference
+ ; is mixed at. This is set to no maximum by default.
+ ; Values can be anything from 8000-192000.
+
;mixing_interval=40 ; Sets the internal mixing interval in milliseconds for the bridge. This
; number reflects how tight or loose the mixing will be for the conference.
; In order to improve performance a larger mixing interval such as 40ms may
diff --git a/doc/CHANGES-staging/app_confbridge_maximum_sample_rate.txt b/doc/CHANGES-staging/app_confbridge_maximum_sample_rate.txt
new file mode 100644
index 0000000000..1c584fa8f0
--- /dev/null
+++ b/doc/CHANGES-staging/app_confbridge_maximum_sample_rate.txt
@@ -0,0 +1,5 @@
+Subject: app_confbridge
+
+A new bridge profile option, maximum_sample_rate, has been added which sets
+a maximum sample rate that the bridge will be mixed at. This allows the bridge
+to move below the maximum sample rate as needed but caps it at the maximum.
diff --git a/include/asterisk/bridge.h b/include/asterisk/bridge.h
index 439d42b253..a0aa4c5d76 100644
--- a/include/asterisk/bridge.h
+++ b/include/asterisk/bridge.h
@@ -302,6 +302,12 @@ struct ast_bridge_softmix {
* the channel uniqueid. Used for participant info correlation.
*/
unsigned int send_sdp_label;
+ /*!
+ * \brief The maximum sample rate softmix uses to mix channels.
+ *
+ * \note If this value is 0, there is no maximum sample rate.
+ */
+ unsigned int maximum_sample_rate;
};
AST_LIST_HEAD_NOLOCK(ast_bridge_channels_list, ast_bridge_channel);
@@ -956,6 +962,21 @@ int ast_bridge_queue_everyone_else(struct ast_bridge *bridge, struct ast_bridge_
*/
void ast_bridge_set_internal_sample_rate(struct ast_bridge *bridge, unsigned int sample_rate);
+/*!
+ * \brief Adjust the maximum mixing sample rate of a bridge
+ * used during multimix mode.
+ * \since 13.31.0
+ * \since 16.8.0
+ * \since 17.2.0
+ *
+ * \param bridge Channel to change the sample rate on.
+ * \param sample_rate the maximum sample rate to use. If a
+ * value of 0 is passed here, the bridge will be free to pick
+ * what ever sample rate it chooses.
+ *
+ */
+void ast_bridge_set_maximum_sample_rate(struct ast_bridge *bridge, unsigned int sample_rate);
+
/*!
* \brief Adjust the internal mixing interval of a bridge used
* during multimix mode.
diff --git a/main/bridge.c b/main/bridge.c
index 366d375d89..ab9b1e6aed 100644
--- a/main/bridge.c
+++ b/main/bridge.c
@@ -3770,6 +3770,13 @@ void ast_bridge_set_internal_sample_rate(struct ast_bridge *bridge, unsigned int
ast_bridge_unlock(bridge);
}
+void ast_bridge_set_maximum_sample_rate(struct ast_bridge *bridge, unsigned int sample_rate)
+{
+ ast_bridge_lock(bridge);
+ bridge->softmix.maximum_sample_rate = sample_rate;
+ ast_bridge_unlock(bridge);
+}
+
static void cleanup_video_mode(struct ast_bridge *bridge)
{
switch (bridge->softmix.video_mode.mode) {