diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c index 7fe727e53034ac0dcd616865140872af690a878b..0beffe7542b345387573863ba5d1b7260a2bbc4e 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 f732c45402085756c3e964c69d1872815773ed3e..b0c717ab22a2d46eab182ef18af6f19faf0585e0 100644 --- a/apps/confbridge/conf_config_parser.c +++ b/apps/confbridge/conf_config_parser.c @@ -274,6 +274,15 @@ will be used. </para></description> </configOption> + <configOption name="maximum_sample_rate"> + <synopsis>Set the maximum native sample rate for mixing the conference</synopsis> + <description><para> + 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. + </para></description> + </configOption> <configOption name="language" default="en"> <synopsis>The language used for announcements to the conference.</synopsis> <description><para> @@ -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 f932da8587a951e5fad1ad8948ee89819616ed3d..82e709acdfc2bcdf506fef85d4d39b2bd7ade4a3 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 d907084cf1c9bc3925830410bf8cad7eacf7a558..c24fa7a27fc8007694b6931ba2ceee12726715a2 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 e1481818be0480028459c953d5b4fdd403dd0417..520b357f633827f4286a83f284cfb3dcfa1a6377 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 0000000000000000000000000000000000000000..1c584fa8f03b68c0508285620501d31c7fcf8115 --- /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 439d42b253c7b331270c85e251233320d007490d..a0aa4c5d7689697909588de1f49d38726feb22da 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 366d375d8929aa98d3bd19a5763d41c9b1e49d5d..ab9b1e6aedc8e22912fde25c2baa163da451fc3b 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) {