Override stream settings in a separate function
Bug: webrtc:351644568, b/352504711 Change-Id: I706d5a85b83603613693f63c5d3faa9946e90afc No-Try: True Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/357440 Commit-Queue: Sergey Silkin <ssilkin@webrtc.org> Reviewed-by: Danil Chapovalov <danilchap@webrtc.org> Cr-Commit-Position: refs/heads/main@{#42655}
This commit is contained in:
parent
5fe85d23a2
commit
1a33aa4a8e
@ -127,6 +127,123 @@ int NormalizeSimulcastSize(const FieldTrialsView& field_trials,
|
||||
return ((size >> base2_exponent) << base2_exponent);
|
||||
}
|
||||
|
||||
// Override bitrate limits and other stream settings with values from
|
||||
// `encoder_config.simulcast_layers` which come from `RtpEncodingParameters`.
|
||||
void OverrideStreamSettings(
|
||||
const webrtc::VideoEncoderConfig& encoder_config,
|
||||
const absl::optional<webrtc::DataRate>& experimental_min_bitrate,
|
||||
std::vector<webrtc::VideoStream>& layers) {
|
||||
RTC_DCHECK_LE(layers.size(), encoder_config.simulcast_layers.size());
|
||||
|
||||
// Allow an experiment to override the minimum bitrate for the lowest
|
||||
// spatial layer. The experiment's configuration has the lowest priority.
|
||||
layers[0].min_bitrate_bps = experimental_min_bitrate
|
||||
.value_or(webrtc::DataRate::BitsPerSec(
|
||||
webrtc::kDefaultMinVideoBitrateBps))
|
||||
.bps<int>();
|
||||
|
||||
const bool temporal_layers_supported =
|
||||
IsTemporalLayersSupported(encoder_config.codec_type);
|
||||
|
||||
for (size_t i = 0; i < layers.size(); ++i) {
|
||||
const webrtc::VideoStream& overrides = encoder_config.simulcast_layers[i];
|
||||
webrtc::VideoStream& layer = layers[i];
|
||||
layer.active = overrides.active;
|
||||
layer.scalability_mode = overrides.scalability_mode;
|
||||
layer.requested_resolution = overrides.requested_resolution;
|
||||
// Update with configured num temporal layers if supported by codec.
|
||||
if (overrides.num_temporal_layers > 0 && temporal_layers_supported) {
|
||||
layer.num_temporal_layers = *overrides.num_temporal_layers;
|
||||
}
|
||||
if (overrides.max_framerate > 0) {
|
||||
layer.max_framerate = overrides.max_framerate;
|
||||
}
|
||||
// Update simulcast bitrates with configured min and max bitrate.
|
||||
if (overrides.min_bitrate_bps > 0) {
|
||||
layer.min_bitrate_bps = overrides.min_bitrate_bps;
|
||||
}
|
||||
if (overrides.max_bitrate_bps > 0) {
|
||||
layer.max_bitrate_bps = overrides.max_bitrate_bps;
|
||||
}
|
||||
if (overrides.target_bitrate_bps > 0) {
|
||||
layer.target_bitrate_bps = overrides.target_bitrate_bps;
|
||||
}
|
||||
if (overrides.min_bitrate_bps > 0 && overrides.max_bitrate_bps > 0) {
|
||||
// Min and max bitrate are configured.
|
||||
// Set target to 3/4 of the max bitrate (or to max if below min).
|
||||
if (overrides.target_bitrate_bps <= 0)
|
||||
layer.target_bitrate_bps = layer.max_bitrate_bps * 3 / 4;
|
||||
if (layer.target_bitrate_bps < layer.min_bitrate_bps)
|
||||
layer.target_bitrate_bps = layer.max_bitrate_bps;
|
||||
} else if (overrides.min_bitrate_bps > 0) {
|
||||
// Only min bitrate is configured, make sure target/max are above min.
|
||||
layer.target_bitrate_bps =
|
||||
std::max(layer.target_bitrate_bps, layer.min_bitrate_bps);
|
||||
layer.max_bitrate_bps =
|
||||
std::max(layer.max_bitrate_bps, layer.min_bitrate_bps);
|
||||
} else if (overrides.max_bitrate_bps > 0) {
|
||||
// Only max bitrate is configured, make sure min/target are below max.
|
||||
// Keep target bitrate if it is set explicitly in encoding config.
|
||||
// Otherwise set target bitrate to 3/4 of the max bitrate
|
||||
// or the one calculated from GetSimulcastConfig() which is larger.
|
||||
layer.min_bitrate_bps =
|
||||
std::min(layer.min_bitrate_bps, layer.max_bitrate_bps);
|
||||
if (overrides.target_bitrate_bps <= 0) {
|
||||
layer.target_bitrate_bps =
|
||||
std::max(layer.target_bitrate_bps, layer.max_bitrate_bps * 3 / 4);
|
||||
}
|
||||
layer.target_bitrate_bps =
|
||||
std::clamp(layer.target_bitrate_bps, layer.min_bitrate_bps,
|
||||
layer.max_bitrate_bps);
|
||||
}
|
||||
|
||||
if (overrides.max_qp > 0) {
|
||||
layer.max_qp = overrides.max_qp;
|
||||
} else if (encoder_config.max_qp > 0) {
|
||||
layer.max_qp = encoder_config.max_qp;
|
||||
} else {
|
||||
layer.max_qp = GetDefaultMaxQp(encoder_config.codec_type);
|
||||
}
|
||||
}
|
||||
|
||||
bool is_highest_layer_max_bitrate_configured =
|
||||
encoder_config.simulcast_layers[layers.size() - 1].max_bitrate_bps > 0;
|
||||
bool is_screencast = encoder_config.content_type ==
|
||||
webrtc::VideoEncoderConfig::ContentType::kScreen;
|
||||
if (!is_screencast && !is_highest_layer_max_bitrate_configured &&
|
||||
encoder_config.max_bitrate_bps > 0) {
|
||||
// No application-configured maximum for the largest layer.
|
||||
// If there is bitrate leftover, give it to the largest layer.
|
||||
BoostMaxSimulcastLayer(
|
||||
webrtc::DataRate::BitsPerSec(encoder_config.max_bitrate_bps), &layers);
|
||||
}
|
||||
|
||||
// Sort the layers by max_bitrate_bps, they might not always be from
|
||||
// smallest to biggest
|
||||
std::vector<size_t> index(layers.size());
|
||||
std::iota(index.begin(), index.end(), 0);
|
||||
absl::c_stable_sort(index, [&layers](size_t a, size_t b) {
|
||||
return layers[a].max_bitrate_bps < layers[b].max_bitrate_bps;
|
||||
});
|
||||
|
||||
if (!layers[index[0]].active) {
|
||||
// Adjust min bitrate of the first active layer to allow it to go as low as
|
||||
// the lowest (now inactive) layer could.
|
||||
// Otherwise, if e.g. a single HD stream is active, it would have 600kbps
|
||||
// min bitrate, which would always be allocated to the stream.
|
||||
// This would lead to congested network, dropped frames and overall bad
|
||||
// experience.
|
||||
|
||||
const int min_configured_bitrate = layers[index[0]].min_bitrate_bps;
|
||||
for (size_t i = 0; i < layers.size(); ++i) {
|
||||
if (layers[index[i]].active) {
|
||||
layers[index[i]].min_bitrate_bps = min_configured_bitrate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
EncoderStreamFactory::EncoderStreamFactory(
|
||||
@ -334,132 +451,18 @@ EncoderStreamFactory::CreateSimulcastOrConferenceModeScreenshareStreams(
|
||||
int height,
|
||||
const webrtc::VideoEncoderConfig& encoder_config,
|
||||
const absl::optional<webrtc::DataRate>& experimental_min_bitrate) const {
|
||||
bool is_screencast = encoder_config.content_type ==
|
||||
webrtc::VideoEncoderConfig::ContentType::kScreen;
|
||||
const bool is_legacy_screencast =
|
||||
webrtc::SimulcastUtility::IsConferenceModeScreenshare(encoder_config);
|
||||
|
||||
std::vector<webrtc::Resolution> resolutions =
|
||||
GetStreamResolutions(trials, width, height, encoder_config);
|
||||
|
||||
const bool temporal_layers_supported =
|
||||
IsTemporalLayersSupported(encoder_config.codec_type);
|
||||
// Use legacy simulcast screenshare if conference mode is explicitly enabled
|
||||
// or use the regular simulcast configuration path which is generic.
|
||||
std::vector<webrtc::VideoStream> layers = GetSimulcastConfig(
|
||||
resolutions, is_legacy_screencast, temporal_layers_supported, trials,
|
||||
resolutions,
|
||||
webrtc::SimulcastUtility::IsConferenceModeScreenshare(encoder_config),
|
||||
IsTemporalLayersSupported(encoder_config.codec_type), trials,
|
||||
encoder_config.codec_type);
|
||||
// Allow an experiment to override the minimum bitrate for the lowest
|
||||
// spatial layer. The experiment's configuration has the lowest priority.
|
||||
layers[0].min_bitrate_bps = experimental_min_bitrate
|
||||
.value_or(webrtc::DataRate::BitsPerSec(
|
||||
webrtc::kDefaultMinVideoBitrateBps))
|
||||
.bps<int>();
|
||||
|
||||
// Update the active simulcast layers and configured bitrates.
|
||||
for (size_t i = 0; i < layers.size(); ++i) {
|
||||
layers[i].active = encoder_config.simulcast_layers[i].active;
|
||||
layers[i].scalability_mode =
|
||||
encoder_config.simulcast_layers[i].scalability_mode;
|
||||
layers[i].requested_resolution =
|
||||
encoder_config.simulcast_layers[i].requested_resolution;
|
||||
// Update with configured num temporal layers if supported by codec.
|
||||
if (encoder_config.simulcast_layers[i].num_temporal_layers &&
|
||||
temporal_layers_supported) {
|
||||
layers[i].num_temporal_layers =
|
||||
*encoder_config.simulcast_layers[i].num_temporal_layers;
|
||||
}
|
||||
if (encoder_config.simulcast_layers[i].max_framerate > 0) {
|
||||
layers[i].max_framerate =
|
||||
encoder_config.simulcast_layers[i].max_framerate;
|
||||
}
|
||||
// Update simulcast bitrates with configured min and max bitrate.
|
||||
if (encoder_config.simulcast_layers[i].min_bitrate_bps > 0) {
|
||||
layers[i].min_bitrate_bps =
|
||||
encoder_config.simulcast_layers[i].min_bitrate_bps;
|
||||
}
|
||||
if (encoder_config.simulcast_layers[i].max_bitrate_bps > 0) {
|
||||
layers[i].max_bitrate_bps =
|
||||
encoder_config.simulcast_layers[i].max_bitrate_bps;
|
||||
}
|
||||
if (encoder_config.simulcast_layers[i].target_bitrate_bps > 0) {
|
||||
layers[i].target_bitrate_bps =
|
||||
encoder_config.simulcast_layers[i].target_bitrate_bps;
|
||||
}
|
||||
if (encoder_config.simulcast_layers[i].min_bitrate_bps > 0 &&
|
||||
encoder_config.simulcast_layers[i].max_bitrate_bps > 0) {
|
||||
// Min and max bitrate are configured.
|
||||
// Set target to 3/4 of the max bitrate (or to max if below min).
|
||||
if (encoder_config.simulcast_layers[i].target_bitrate_bps <= 0)
|
||||
layers[i].target_bitrate_bps = layers[i].max_bitrate_bps * 3 / 4;
|
||||
if (layers[i].target_bitrate_bps < layers[i].min_bitrate_bps)
|
||||
layers[i].target_bitrate_bps = layers[i].max_bitrate_bps;
|
||||
} else if (encoder_config.simulcast_layers[i].min_bitrate_bps > 0) {
|
||||
// Only min bitrate is configured, make sure target/max are above min.
|
||||
layers[i].target_bitrate_bps =
|
||||
std::max(layers[i].target_bitrate_bps, layers[i].min_bitrate_bps);
|
||||
layers[i].max_bitrate_bps =
|
||||
std::max(layers[i].max_bitrate_bps, layers[i].min_bitrate_bps);
|
||||
} else if (encoder_config.simulcast_layers[i].max_bitrate_bps > 0) {
|
||||
// Only max bitrate is configured, make sure min/target are below max.
|
||||
// Keep target bitrate if it is set explicitly in encoding config.
|
||||
// Otherwise set target bitrate to 3/4 of the max bitrate
|
||||
// or the one calculated from GetSimulcastConfig() which is larger.
|
||||
layers[i].min_bitrate_bps =
|
||||
std::min(layers[i].min_bitrate_bps, layers[i].max_bitrate_bps);
|
||||
if (encoder_config.simulcast_layers[i].target_bitrate_bps <= 0) {
|
||||
layers[i].target_bitrate_bps = std::max(
|
||||
layers[i].target_bitrate_bps, layers[i].max_bitrate_bps * 3 / 4);
|
||||
}
|
||||
layers[i].target_bitrate_bps = std::max(
|
||||
std::min(layers[i].target_bitrate_bps, layers[i].max_bitrate_bps),
|
||||
layers[i].min_bitrate_bps);
|
||||
}
|
||||
|
||||
if (encoder_config.simulcast_layers[i].max_qp > 0) {
|
||||
layers[i].max_qp = encoder_config.simulcast_layers[i].max_qp;
|
||||
} else if (encoder_config.max_qp > 0) {
|
||||
layers[i].max_qp = encoder_config.max_qp;
|
||||
} else {
|
||||
layers[i].max_qp = GetDefaultMaxQp(encoder_config.codec_type);
|
||||
}
|
||||
}
|
||||
|
||||
bool is_highest_layer_max_bitrate_configured =
|
||||
encoder_config.simulcast_layers[layers.size() - 1].max_bitrate_bps > 0;
|
||||
|
||||
if (!is_screencast && !is_highest_layer_max_bitrate_configured &&
|
||||
encoder_config.max_bitrate_bps > 0) {
|
||||
// No application-configured maximum for the largest layer.
|
||||
// If there is bitrate leftover, give it to the largest layer.
|
||||
BoostMaxSimulcastLayer(
|
||||
webrtc::DataRate::BitsPerSec(encoder_config.max_bitrate_bps), &layers);
|
||||
}
|
||||
|
||||
// Sort the layers by max_bitrate_bps, they might not always be from
|
||||
// smallest to biggest
|
||||
std::vector<size_t> index(layers.size());
|
||||
std::iota(index.begin(), index.end(), 0);
|
||||
std::stable_sort(index.begin(), index.end(), [&layers](size_t a, size_t b) {
|
||||
return layers[a].max_bitrate_bps < layers[b].max_bitrate_bps;
|
||||
});
|
||||
|
||||
if (!layers[index[0]].active) {
|
||||
// Adjust min bitrate of the first active layer to allow it to go as low as
|
||||
// the lowest (now inactive) layer could.
|
||||
// Otherwise, if e.g. a single HD stream is active, it would have 600kbps
|
||||
// min bitrate, which would always be allocated to the stream.
|
||||
// This would lead to congested network, dropped frames and overall bad
|
||||
// experience.
|
||||
|
||||
const int min_configured_bitrate = layers[index[0]].min_bitrate_bps;
|
||||
for (size_t i = 0; i < layers.size(); ++i) {
|
||||
if (layers[index[i]].active) {
|
||||
layers[index[i]].min_bitrate_bps = min_configured_bitrate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
OverrideStreamSettings(encoder_config, experimental_min_bitrate, layers);
|
||||
|
||||
return layers;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user