mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-02 19:16:15 +00:00
app_confbridge: Add "all" variants of REMB behavior.
When producing a combined REMB value the normal behavior is to have a REMB value which is unique for each sender based on all of their receivers. This can result in one sender having low bitrate while all the rest are high. This change adds "all" variants which produces a bridge level REMB value instead. All REMB reports are combined together into a single REMB value that is the same for each sender. ASTERISK-28401 Change-Id: I883e6cc26003b497c8180b346111c79a131ba88c
This commit is contained in:
@@ -1332,6 +1332,36 @@ static int softmix_bridge_write(struct ast_bridge *bridge, struct ast_bridge_cha
|
||||
return res;
|
||||
}
|
||||
|
||||
static void remb_collect_report_all(struct ast_bridge *bridge, struct softmix_bridge_data *softmix_data,
|
||||
float bitrate)
|
||||
{
|
||||
if (!softmix_data->bitrate) {
|
||||
softmix_data->bitrate = bitrate;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (bridge->softmix.video_mode.mode_data.sfu_data.remb_behavior) {
|
||||
case AST_BRIDGE_VIDEO_SFU_REMB_AVERAGE_ALL:
|
||||
softmix_data->bitrate = (softmix_data->bitrate + bitrate) / 2;
|
||||
break;
|
||||
case AST_BRIDGE_VIDEO_SFU_REMB_LOWEST_ALL:
|
||||
if (bitrate < softmix_data->bitrate) {
|
||||
softmix_data->bitrate = bitrate;
|
||||
}
|
||||
break;
|
||||
case AST_BRIDGE_VIDEO_SFU_REMB_HIGHEST_ALL:
|
||||
if (bitrate > softmix_data->bitrate) {
|
||||
softmix_data->bitrate = bitrate;
|
||||
}
|
||||
break;
|
||||
case AST_BRIDGE_VIDEO_SFU_REMB_AVERAGE:
|
||||
case AST_BRIDGE_VIDEO_SFU_REMB_LOWEST:
|
||||
case AST_BRIDGE_VIDEO_SFU_REMB_HIGHEST:
|
||||
/* These will never actually get hit due to being handled by remb_collect_report below */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -1355,6 +1385,14 @@ static void remb_collect_report(struct ast_bridge *bridge, struct ast_bridge_cha
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we are using the "all" variants then we should use the bridge bitrate to store information */
|
||||
if (bridge->softmix.video_mode.mode_data.sfu_data.remb_behavior == AST_BRIDGE_VIDEO_SFU_REMB_AVERAGE_ALL ||
|
||||
bridge->softmix.video_mode.mode_data.sfu_data.remb_behavior == AST_BRIDGE_VIDEO_SFU_REMB_LOWEST_ALL ||
|
||||
bridge->softmix.video_mode.mode_data.sfu_data.remb_behavior == AST_BRIDGE_VIDEO_SFU_REMB_HIGHEST_ALL) {
|
||||
remb_collect_report_all(bridge, softmix_data, bitrate);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < AST_VECTOR_SIZE(&sc->video_sources); ++i) {
|
||||
struct softmix_remb_collector *collector;
|
||||
|
||||
@@ -1380,6 +1418,11 @@ static void remb_collect_report(struct ast_bridge *bridge, struct ast_bridge_cha
|
||||
collector->bitrate = bitrate;
|
||||
}
|
||||
break;
|
||||
case AST_BRIDGE_VIDEO_SFU_REMB_AVERAGE_ALL:
|
||||
case AST_BRIDGE_VIDEO_SFU_REMB_LOWEST_ALL:
|
||||
case AST_BRIDGE_VIDEO_SFU_REMB_HIGHEST_ALL:
|
||||
/* These will never actually get hit due to being handled by remb_collect_report_all above */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1390,8 +1433,10 @@ static void remb_collect_report(struct ast_bridge *bridge, struct ast_bridge_cha
|
||||
sc->remb.br_exp = 0;
|
||||
}
|
||||
|
||||
static void remb_send_report(struct ast_bridge_channel *bridge_channel, struct softmix_channel *sc)
|
||||
static void remb_send_report(struct ast_bridge_channel *bridge_channel, struct softmix_bridge_data *softmix_data,
|
||||
struct softmix_channel *sc)
|
||||
{
|
||||
float bitrate = softmix_data->bitrate;
|
||||
int i;
|
||||
int exp;
|
||||
|
||||
@@ -1399,6 +1444,12 @@ static void remb_send_report(struct ast_bridge_channel *bridge_channel, struct s
|
||||
return;
|
||||
}
|
||||
|
||||
/* If there is no bridge level bitrate fall back to collector level */
|
||||
if (!bitrate) {
|
||||
bitrate = sc->remb_collector->bitrate;
|
||||
sc->remb_collector->bitrate = 0;
|
||||
}
|
||||
|
||||
/* We always do this calculation as even when the bitrate is zero the browser
|
||||
* still prefers it to be accurate instead of lying.
|
||||
*
|
||||
@@ -1442,10 +1493,10 @@ static void remb_send_report(struct ast_bridge_channel *bridge_channel, struct s
|
||||
* Precision on the "lower" end is lost due to zeros being shifted in. This loss is
|
||||
* both expected and acceptable.
|
||||
*/
|
||||
frexp(sc->remb_collector->bitrate, &exp);
|
||||
frexp(bitrate, &exp);
|
||||
exp = exp > 18 ? exp - 18 : 0;
|
||||
|
||||
sc->remb_collector->feedback.remb.br_mantissa = sc->remb_collector->bitrate / (1 << exp);
|
||||
sc->remb_collector->feedback.remb.br_mantissa = bitrate / (1 << exp);
|
||||
sc->remb_collector->feedback.remb.br_exp = exp;
|
||||
|
||||
for (i = 0; i < AST_VECTOR_SIZE(&bridge_channel->stream_map.to_bridge); ++i) {
|
||||
@@ -1466,8 +1517,6 @@ static void remb_send_report(struct ast_bridge_channel *bridge_channel, struct s
|
||||
sc->remb_collector->frame.stream_num = bridge_num;
|
||||
ast_bridge_channel_queue_frame(bridge_channel, &sc->remb_collector->frame);
|
||||
}
|
||||
|
||||
sc->remb_collector->bitrate = 0;
|
||||
}
|
||||
|
||||
static void gather_softmix_stats(struct softmix_stats *stats,
|
||||
@@ -1827,10 +1876,15 @@ static int softmix_mixing_loop(struct ast_bridge *bridge)
|
||||
ast_bridge_channel_queue_frame(bridge_channel, &sc->write_frame);
|
||||
|
||||
if (remb_update) {
|
||||
remb_send_report(bridge_channel, sc);
|
||||
remb_send_report(bridge_channel, softmix_data, sc);
|
||||
}
|
||||
}
|
||||
|
||||
if (remb_update) {
|
||||
/* In case we are doing bridge level REMB reset the bitrate so we start fresh */
|
||||
softmix_data->bitrate = 0;
|
||||
}
|
||||
|
||||
update_all_rates = 0;
|
||||
if (!stat_iteration_counter) {
|
||||
update_all_rates = analyse_softmix_stats(&stats, softmix_data,
|
||||
|
@@ -216,6 +216,8 @@ struct softmix_bridge_data {
|
||||
struct timeval last_remb_update;
|
||||
/*! Per-bridge stream REMB collectors, which flow back to video source */
|
||||
AST_VECTOR(, struct softmix_remb_collector *) remb_collectors;
|
||||
/*! Per-bridge REMB bitrate */
|
||||
float bitrate;
|
||||
};
|
||||
|
||||
struct softmix_mixing_array {
|
||||
|
Reference in New Issue
Block a user