<p>Friendly Automation <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/11322">View Change</a></p><div style="white-space:pre-wrap">Approvals:
Kevin Harwell: Looks good to me, but someone else must approve
George Joseph: Looks good to me, approved
Friendly Automation: Approved for Submit
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">app_confbridge: Add "all" variants of REMB behavior.<br><br>When producing a combined REMB value the normal behavior<br>is to have a REMB value which is unique for each sender<br>based on all of their receivers. This can result in one<br>sender having low bitrate while all the rest are high.<br><br>This change adds "all" variants which produces a bridge<br>level REMB value instead. All REMB reports are combined<br>together into a single REMB value that is the same for<br>each sender.<br><br>ASTERISK-28401<br><br>Change-Id: I883e6cc26003b497c8180b346111c79a131ba88c<br>---<br>M apps/app_confbridge.c<br>M apps/confbridge/conf_config_parser.c<br>M apps/confbridge/include/confbridge.h<br>M bridges/bridge_softmix.c<br>M bridges/bridge_softmix/include/bridge_softmix_internal.h<br>M configs/samples/confbridge.conf.sample<br>A doc/CHANGES-staging/app_confbridge_remb_behavior_all.txt<br>M include/asterisk/bridge.h<br>8 files changed, 122 insertions(+), 9 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c</span><br><span>index 33cfbb3..6d141bd 100644</span><br><span>--- a/apps/app_confbridge.c</span><br><span>+++ b/apps/app_confbridge.c</span><br><span>@@ -1565,6 +1565,12 @@</span><br><span> ast_brige_set_remb_behavior(conference->bridge, AST_BRIDGE_VIDEO_SFU_REMB_LOWEST);</span><br><span> } else if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_REMB_BEHAVIOR_HIGHEST)) {</span><br><span> ast_brige_set_remb_behavior(conference->bridge, AST_BRIDGE_VIDEO_SFU_REMB_HIGHEST);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_REMB_BEHAVIOR_AVERAGE_ALL)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_brige_set_remb_behavior(conference->bridge, AST_BRIDGE_VIDEO_SFU_REMB_AVERAGE_ALL);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_REMB_BEHAVIOR_LOWEST_ALL)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_brige_set_remb_behavior(conference->bridge, AST_BRIDGE_VIDEO_SFU_REMB_LOWEST_ALL);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_REMB_BEHAVIOR_HIGHEST_ALL)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_brige_set_remb_behavior(conference->bridge, AST_BRIDGE_VIDEO_SFU_REMB_HIGHEST_ALL);</span><br><span> }</span><br><span> }</span><br><span> </span><br><span>diff --git a/apps/confbridge/conf_config_parser.c b/apps/confbridge/conf_config_parser.c</span><br><span>index 53061ba..f732c45 100644</span><br><span>--- a/apps/confbridge/conf_config_parser.c</span><br><span>+++ b/apps/confbridge/conf_config_parser.c</span><br><span>@@ -505,6 +505,18 @@</span><br><span> <enum name="highest"></span><br><span> <para>The highest estimated maximum bitrate is forwarded to the sender.</para></span><br><span> </enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="average_all"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>The average of all estimated maximum bitrates is taken from all</span><br><span style="color: hsl(120, 100%, 40%);">+ receivers in the bridge and a single value is sent to each sender.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ </enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="lowest_all"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>The lowest estimated maximum bitrate of all receivers in the bridge</span><br><span style="color: hsl(120, 100%, 40%);">+ is taken and sent to each sender.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ </enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="highest_all"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>The highest estimated maximum bitrate of all receivers in the bridge</span><br><span style="color: hsl(120, 100%, 40%);">+ is taken and sent to each sender.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ </enum></span><br><span> </enumlist></span><br><span> </description></span><br><span> </configOption></span><br><span>@@ -1737,7 +1749,8 @@</span><br><span> </span><br><span> switch (b_profile.flags</span><br><span> & (BRIDGE_OPT_REMB_BEHAVIOR_AVERAGE | BRIDGE_OPT_REMB_BEHAVIOR_LOWEST</span><br><span style="color: hsl(0, 100%, 40%);">- | BRIDGE_OPT_REMB_BEHAVIOR_HIGHEST)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ | BRIDGE_OPT_REMB_BEHAVIOR_HIGHEST | BRIDGE_OPT_REMB_BEHAVIOR_AVERAGE_ALL</span><br><span style="color: hsl(120, 100%, 40%);">+ | BRIDGE_OPT_REMB_BEHAVIOR_LOWEST_ALL | BRIDGE_OPT_REMB_BEHAVIOR_LOWEST_ALL)) {</span><br><span> case BRIDGE_OPT_REMB_BEHAVIOR_AVERAGE:</span><br><span> ast_cli(a->fd, "REMB Behavior: average\n");</span><br><span> break;</span><br><span>@@ -1747,6 +1760,15 @@</span><br><span> case BRIDGE_OPT_REMB_BEHAVIOR_HIGHEST:</span><br><span> ast_cli(a->fd, "REMB Behavior: highest\n");</span><br><span> break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case BRIDGE_OPT_REMB_BEHAVIOR_AVERAGE_ALL:</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli(a->fd, "REMB Behavior: average_all\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case BRIDGE_OPT_REMB_BEHAVIOR_LOWEST_ALL:</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli(a->fd, "REMB Behavior: lowest_all\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case BRIDGE_OPT_REMB_BEHAVIOR_HIGHEST_ALL:</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli(a->fd, "REMB Behavior: highest_all\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span> default:</span><br><span> ast_assert(0);</span><br><span> break;</span><br><span>@@ -2108,7 +2130,10 @@</span><br><span> </span><br><span> ast_clear_flag(b_profile, BRIDGE_OPT_REMB_BEHAVIOR_AVERAGE |</span><br><span> BRIDGE_OPT_REMB_BEHAVIOR_LOWEST |</span><br><span style="color: hsl(0, 100%, 40%);">- BRIDGE_OPT_REMB_BEHAVIOR_HIGHEST);</span><br><span style="color: hsl(120, 100%, 40%);">+ BRIDGE_OPT_REMB_BEHAVIOR_HIGHEST |</span><br><span style="color: hsl(120, 100%, 40%);">+ BRIDGE_OPT_REMB_BEHAVIOR_AVERAGE_ALL |</span><br><span style="color: hsl(120, 100%, 40%);">+ BRIDGE_OPT_REMB_BEHAVIOR_LOWEST_ALL |</span><br><span style="color: hsl(120, 100%, 40%);">+ BRIDGE_OPT_REMB_BEHAVIOR_HIGHEST_ALL);</span><br><span> </span><br><span> if (!strcasecmp(var->value, "average")) {</span><br><span> ast_set_flag(b_profile, BRIDGE_OPT_REMB_BEHAVIOR_AVERAGE);</span><br><span>@@ -2116,6 +2141,12 @@</span><br><span> ast_set_flag(b_profile, BRIDGE_OPT_REMB_BEHAVIOR_LOWEST);</span><br><span> } else if (!strcasecmp(var->value, "highest")) {</span><br><span> ast_set_flag(b_profile, BRIDGE_OPT_REMB_BEHAVIOR_HIGHEST);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (!strcasecmp(var->value, "average_all")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_set_flag(b_profile, BRIDGE_OPT_REMB_BEHAVIOR_AVERAGE_ALL);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (!strcasecmp(var->value, "lowest_all")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_set_flag(b_profile, BRIDGE_OPT_REMB_BEHAVIOR_LOWEST_ALL);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (!strcasecmp(var->value, "highest_all")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_set_flag(b_profile, BRIDGE_OPT_REMB_BEHAVIOR_HIGHEST_ALL);</span><br><span> } else {</span><br><span> return -1;</span><br><span> }</span><br><span>diff --git a/apps/confbridge/include/confbridge.h b/apps/confbridge/include/confbridge.h</span><br><span>index 4b8249f..237431e 100644</span><br><span>--- a/apps/confbridge/include/confbridge.h</span><br><span>+++ b/apps/confbridge/include/confbridge.h</span><br><span>@@ -82,6 +82,9 @@</span><br><span> BRIDGE_OPT_REMB_BEHAVIOR_LOWEST = (1 << 9), /*!< The lowest estimated maximum bitrate is sent to the sender */</span><br><span> BRIDGE_OPT_REMB_BEHAVIOR_HIGHEST = (1 << 10), /*!< The highest estimated maximum bitrate is sent to the sender */</span><br><span> BRIDGE_OPT_ENABLE_EVENTS = (1 << 11), /*!< Enable sending events to participants */</span><br><span style="color: hsl(120, 100%, 40%);">+ BRIDGE_OPT_REMB_BEHAVIOR_AVERAGE_ALL = (1 << 12), /*!< The average of all REMB reports in the entire bridge is sent to each sender */</span><br><span style="color: hsl(120, 100%, 40%);">+ BRIDGE_OPT_REMB_BEHAVIOR_LOWEST_ALL = (1 << 13), /*!< The lowest estimated maximum bitrate from all receivers is sent to each sender */</span><br><span style="color: hsl(120, 100%, 40%);">+ BRIDGE_OPT_REMB_BEHAVIOR_HIGHEST_ALL = (1 << 14), /*!< The highest estimated maximum bitrate from all receivers is sent to each sender */</span><br><span> };</span><br><span> </span><br><span> enum conf_menu_action_id {</span><br><span>diff --git a/bridges/bridge_softmix.c b/bridges/bridge_softmix.c</span><br><span>index f9f8520..a90c716 100644</span><br><span>--- a/bridges/bridge_softmix.c</span><br><span>+++ b/bridges/bridge_softmix.c</span><br><span>@@ -1332,6 +1332,36 @@</span><br><span> return res;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static void remb_collect_report_all(struct ast_bridge *bridge, struct softmix_bridge_data *softmix_data,</span><br><span style="color: hsl(120, 100%, 40%);">+ float bitrate)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!softmix_data->bitrate) {</span><br><span style="color: hsl(120, 100%, 40%);">+ softmix_data->bitrate = bitrate;</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (bridge->softmix.video_mode.mode_data.sfu_data.remb_behavior) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case AST_BRIDGE_VIDEO_SFU_REMB_AVERAGE_ALL:</span><br><span style="color: hsl(120, 100%, 40%);">+ softmix_data->bitrate = (softmix_data->bitrate + bitrate) / 2;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case AST_BRIDGE_VIDEO_SFU_REMB_LOWEST_ALL:</span><br><span style="color: hsl(120, 100%, 40%);">+ if (bitrate < softmix_data->bitrate) {</span><br><span style="color: hsl(120, 100%, 40%);">+ softmix_data->bitrate = bitrate;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case AST_BRIDGE_VIDEO_SFU_REMB_HIGHEST_ALL:</span><br><span style="color: hsl(120, 100%, 40%);">+ if (bitrate > softmix_data->bitrate) {</span><br><span style="color: hsl(120, 100%, 40%);">+ softmix_data->bitrate = bitrate;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case AST_BRIDGE_VIDEO_SFU_REMB_AVERAGE:</span><br><span style="color: hsl(120, 100%, 40%);">+ case AST_BRIDGE_VIDEO_SFU_REMB_LOWEST:</span><br><span style="color: hsl(120, 100%, 40%);">+ case AST_BRIDGE_VIDEO_SFU_REMB_HIGHEST:</span><br><span style="color: hsl(120, 100%, 40%);">+ /* These will never actually get hit due to being handled by remb_collect_report below */</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static void remb_collect_report(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel,</span><br><span> struct softmix_bridge_data *softmix_data, struct softmix_channel *sc)</span><br><span> {</span><br><span>@@ -1355,6 +1385,14 @@</span><br><span> return;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* If we are using the "all" variants then we should use the bridge bitrate to store information */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (bridge->softmix.video_mode.mode_data.sfu_data.remb_behavior == AST_BRIDGE_VIDEO_SFU_REMB_AVERAGE_ALL ||</span><br><span style="color: hsl(120, 100%, 40%);">+ bridge->softmix.video_mode.mode_data.sfu_data.remb_behavior == AST_BRIDGE_VIDEO_SFU_REMB_LOWEST_ALL ||</span><br><span style="color: hsl(120, 100%, 40%);">+ bridge->softmix.video_mode.mode_data.sfu_data.remb_behavior == AST_BRIDGE_VIDEO_SFU_REMB_HIGHEST_ALL) {</span><br><span style="color: hsl(120, 100%, 40%);">+ remb_collect_report_all(bridge, softmix_data, bitrate);</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> for (i = 0; i < AST_VECTOR_SIZE(&sc->video_sources); ++i) {</span><br><span> struct softmix_remb_collector *collector;</span><br><span> </span><br><span>@@ -1380,6 +1418,11 @@</span><br><span> collector->bitrate = bitrate;</span><br><span> }</span><br><span> break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case AST_BRIDGE_VIDEO_SFU_REMB_AVERAGE_ALL:</span><br><span style="color: hsl(120, 100%, 40%);">+ case AST_BRIDGE_VIDEO_SFU_REMB_LOWEST_ALL:</span><br><span style="color: hsl(120, 100%, 40%);">+ case AST_BRIDGE_VIDEO_SFU_REMB_HIGHEST_ALL:</span><br><span style="color: hsl(120, 100%, 40%);">+ /* These will never actually get hit due to being handled by remb_collect_report_all above */</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span> }</span><br><span> }</span><br><span> </span><br><span>@@ -1390,8 +1433,10 @@</span><br><span> sc->remb.br_exp = 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void remb_send_report(struct ast_bridge_channel *bridge_channel, struct softmix_channel *sc)</span><br><span style="color: hsl(120, 100%, 40%);">+static void remb_send_report(struct ast_bridge_channel *bridge_channel, struct softmix_bridge_data *softmix_data,</span><br><span style="color: hsl(120, 100%, 40%);">+ struct softmix_channel *sc)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+ float bitrate = softmix_data->bitrate;</span><br><span> int i;</span><br><span> int exp;</span><br><span> </span><br><span>@@ -1399,6 +1444,12 @@</span><br><span> return;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* If there is no bridge level bitrate fall back to collector level */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!bitrate) {</span><br><span style="color: hsl(120, 100%, 40%);">+ bitrate = sc->remb_collector->bitrate;</span><br><span style="color: hsl(120, 100%, 40%);">+ sc->remb_collector->bitrate = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* We always do this calculation as even when the bitrate is zero the browser</span><br><span> * still prefers it to be accurate instead of lying.</span><br><span> *</span><br><span>@@ -1442,10 +1493,10 @@</span><br><span> * Precision on the "lower" end is lost due to zeros being shifted in. This loss is</span><br><span> * both expected and acceptable.</span><br><span> */</span><br><span style="color: hsl(0, 100%, 40%);">- frexp(sc->remb_collector->bitrate, &exp);</span><br><span style="color: hsl(120, 100%, 40%);">+ frexp(bitrate, &exp);</span><br><span> exp = exp > 18 ? exp - 18 : 0;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- sc->remb_collector->feedback.remb.br_mantissa = sc->remb_collector->bitrate / (1 << exp);</span><br><span style="color: hsl(120, 100%, 40%);">+ sc->remb_collector->feedback.remb.br_mantissa = bitrate / (1 << exp);</span><br><span> sc->remb_collector->feedback.remb.br_exp = exp;</span><br><span> </span><br><span> for (i = 0; i < AST_VECTOR_SIZE(&bridge_channel->stream_map.to_bridge); ++i) {</span><br><span>@@ -1466,8 +1517,6 @@</span><br><span> sc->remb_collector->frame.stream_num = bridge_num;</span><br><span> ast_bridge_channel_queue_frame(bridge_channel, &sc->remb_collector->frame);</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- sc->remb_collector->bitrate = 0;</span><br><span> }</span><br><span> </span><br><span> static void gather_softmix_stats(struct softmix_stats *stats,</span><br><span>@@ -1827,10 +1876,15 @@</span><br><span> ast_bridge_channel_queue_frame(bridge_channel, &sc->write_frame);</span><br><span> </span><br><span> if (remb_update) {</span><br><span style="color: hsl(0, 100%, 40%);">- remb_send_report(bridge_channel, sc);</span><br><span style="color: hsl(120, 100%, 40%);">+ remb_send_report(bridge_channel, softmix_data, sc);</span><br><span> }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ if (remb_update) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* In case we are doing bridge level REMB reset the bitrate so we start fresh */</span><br><span style="color: hsl(120, 100%, 40%);">+ softmix_data->bitrate = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> update_all_rates = 0;</span><br><span> if (!stat_iteration_counter) {</span><br><span> update_all_rates = analyse_softmix_stats(&stats, softmix_data,</span><br><span>diff --git a/bridges/bridge_softmix/include/bridge_softmix_internal.h b/bridges/bridge_softmix/include/bridge_softmix_internal.h</span><br><span>index 15856b3..ca70c3c 100644</span><br><span>--- a/bridges/bridge_softmix/include/bridge_softmix_internal.h</span><br><span>+++ b/bridges/bridge_softmix/include/bridge_softmix_internal.h</span><br><span>@@ -216,6 +216,8 @@</span><br><span> struct timeval last_remb_update;</span><br><span> /*! Per-bridge stream REMB collectors, which flow back to video source */</span><br><span> AST_VECTOR(, struct softmix_remb_collector *) remb_collectors;</span><br><span style="color: hsl(120, 100%, 40%);">+ /*! Per-bridge REMB bitrate */</span><br><span style="color: hsl(120, 100%, 40%);">+ float bitrate;</span><br><span> };</span><br><span> </span><br><span> struct softmix_mixing_array {</span><br><span>diff --git a/configs/samples/confbridge.conf.sample b/configs/samples/confbridge.conf.sample</span><br><span>index a214f34..e148181 100644</span><br><span>--- a/configs/samples/confbridge.conf.sample</span><br><span>+++ b/configs/samples/confbridge.conf.sample</span><br><span>@@ -254,7 +254,11 @@</span><br><span> ;remb_behavior=average ; How the combined REMB report for an SFU video bridge is constructed. If set to "average" then</span><br><span> ; the estimated maximum bitrate of each receiver is used to construct an average bitrate. If</span><br><span> ; set to "lowest" the lowest maximum bitrate is forwarded to the sender. If set to "highest"</span><br><span style="color: hsl(0, 100%, 40%);">- ; the highest maximum bitrate is forwarded to the sender. This defaults to "average".</span><br><span style="color: hsl(120, 100%, 40%);">+ ; the highest maximum bitrate is forwarded to the sender. If set to "average_all" a single average</span><br><span style="color: hsl(120, 100%, 40%);">+ ; is generated from every receiver and the same value is sent to every sender. If set to</span><br><span style="color: hsl(120, 100%, 40%);">+ ; "lowest_all" the lowest maximum bitrate of all receivers is sent to every sender. If set to</span><br><span style="color: hsl(120, 100%, 40%);">+ ; "highest_all" the highest maximum bitrate of all receivers is sent to every sender. This</span><br><span style="color: hsl(120, 100%, 40%);">+ ; defaults to "average".</span><br><span> </span><br><span> ;enable_events=no ; If enabled, recipients who joined the bridge via a channel driver</span><br><span> ; that supports Enhanced Messaging (currently only chan_pjsip) will</span><br><span>diff --git a/doc/CHANGES-staging/app_confbridge_remb_behavior_all.txt b/doc/CHANGES-staging/app_confbridge_remb_behavior_all.txt</span><br><span>new file mode 100644</span><br><span>index 0000000..6110a6f</span><br><span>--- /dev/null</span><br><span>+++ b/doc/CHANGES-staging/app_confbridge_remb_behavior_all.txt</span><br><span>@@ -0,0 +1,7 @@</span><br><span style="color: hsl(120, 100%, 40%);">+Subject: ConfBridge</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Add "average_all", "highest_all", and "lowest_all" values for</span><br><span style="color: hsl(120, 100%, 40%);">+the remb_behavior option. These values operate on a bridge</span><br><span style="color: hsl(120, 100%, 40%);">+level instead of a per-source level. This means that a single</span><br><span style="color: hsl(120, 100%, 40%);">+REMB value is calculated and sent to every sender, instead of</span><br><span style="color: hsl(120, 100%, 40%);">+a REMB value that is unique for the specific sender..</span><br><span>diff --git a/include/asterisk/bridge.h b/include/asterisk/bridge.h</span><br><span>index 621ed0d..9be38a8 100644</span><br><span>--- a/include/asterisk/bridge.h</span><br><span>+++ b/include/asterisk/bridge.h</span><br><span>@@ -135,6 +135,12 @@</span><br><span> AST_BRIDGE_VIDEO_SFU_REMB_LOWEST,</span><br><span> /*! The highest reported bitrate is forwarded to the sender */</span><br><span> AST_BRIDGE_VIDEO_SFU_REMB_HIGHEST,</span><br><span style="color: hsl(120, 100%, 40%);">+ /*! The average of all reports WITHIN the bridge is sent to each sender */</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_BRIDGE_VIDEO_SFU_REMB_AVERAGE_ALL,</span><br><span style="color: hsl(120, 100%, 40%);">+ /*! The lowest reported bitrate from all channels in the bridge is forwarded to each sender */</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_BRIDGE_VIDEO_SFU_REMB_LOWEST_ALL,</span><br><span style="color: hsl(120, 100%, 40%);">+ /*! The highest reported bitrate from all channels in the bridge is forwarded to each sender */</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_BRIDGE_VIDEO_SFU_REMB_HIGHEST_ALL,</span><br><span> };</span><br><span> </span><br><span> /*! \brief This is used for selective forwarding unit configuration */</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/11322">change 11322</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/c/asterisk/+/11322"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I883e6cc26003b497c8180b346111c79a131ba88c </div>
<div style="display:none"> Gerrit-Change-Number: 11322 </div>
<div style="display:none"> Gerrit-PatchSet: 3 </div>
<div style="display:none"> Gerrit-Owner: Joshua Colp <jcolp@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Benjamin Keith Ford <bford@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Kevin Harwell <kharwell@digium.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>