Allow extremely low resolution for simulcast path
Some screen capturers may occasionally send an extremely small frame, e.g. 2x2. If a scale_resolution_down_by is specified, WebrtcVideoEngine would enforce configured resolution to be at least 16x16, which would then break VideoStreamEncoder and cause a crash. This changes disables scaling and alignment for extremely low resolutions. Bug: chromium:1265303, webrtc:13371 Change-Id: Icdb736043e1fdf91fdde5a8e4b3c6a89f6b90577 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/236850 Reviewed-by: Niels Moller <nisse@webrtc.org> Commit-Queue: Ilya Nikolaevskiy <ilnik@webrtc.org> Cr-Commit-Position: refs/heads/main@{#35420}
This commit is contained in:

committed by
WebRTC LUCI CQ

parent
e1bbef1e6b
commit
a40e6de242
@ -57,6 +57,18 @@ constexpr int64_t kUnsignaledSsrcCooldownMs = rtc::kNumMillisecsPerSec / 2;
|
|||||||
// needed.
|
// needed.
|
||||||
constexpr char kAv1xCodecName[] = "AV1X";
|
constexpr char kAv1xCodecName[] = "AV1X";
|
||||||
|
|
||||||
|
int ScaleDownResolution(int resolution,
|
||||||
|
double scale_down_by,
|
||||||
|
int min_resolution) {
|
||||||
|
// Resolution is never scalied down to smaller than min_resolution.
|
||||||
|
// If the input resolution is already smaller than min_resolution,
|
||||||
|
// no scaling should be done at all.
|
||||||
|
if (resolution <= min_resolution)
|
||||||
|
return resolution;
|
||||||
|
return std::max(static_cast<int>(resolution / scale_down_by + 0.5),
|
||||||
|
min_resolution);
|
||||||
|
}
|
||||||
|
|
||||||
const char* StreamTypeToString(
|
const char* StreamTypeToString(
|
||||||
webrtc::VideoSendStream::StreamStats::StreamType type) {
|
webrtc::VideoSendStream::StreamStats::StreamType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -3584,13 +3596,13 @@ EncoderStreamFactory::CreateDefaultVideoStreams(
|
|||||||
layer.max_framerate = max_framerate;
|
layer.max_framerate = max_framerate;
|
||||||
|
|
||||||
if (encoder_config.simulcast_layers[0].scale_resolution_down_by > 1.) {
|
if (encoder_config.simulcast_layers[0].scale_resolution_down_by > 1.) {
|
||||||
layer.width = std::max<size_t>(
|
layer.width = ScaleDownResolution(
|
||||||
layer.width /
|
layer.width,
|
||||||
encoder_config.simulcast_layers[0].scale_resolution_down_by,
|
encoder_config.simulcast_layers[0].scale_resolution_down_by,
|
||||||
kMinLayerSize);
|
kMinLayerSize);
|
||||||
layer.height = std::max<size_t>(
|
layer.height = ScaleDownResolution(
|
||||||
layer.height /
|
layer.height,
|
||||||
encoder_config.simulcast_layers[0].scale_resolution_down_by,
|
encoder_config.simulcast_layers[0].scale_resolution_down_by,
|
||||||
kMinLayerSize);
|
kMinLayerSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3666,14 +3678,15 @@ EncoderStreamFactory::CreateSimulcastOrConferenceModeScreenshareStreams(
|
|||||||
const bool norm_size_configured =
|
const bool norm_size_configured =
|
||||||
webrtc::NormalizeSimulcastSizeExperiment::GetBase2Exponent().has_value();
|
webrtc::NormalizeSimulcastSizeExperiment::GetBase2Exponent().has_value();
|
||||||
const int normalized_width =
|
const int normalized_width =
|
||||||
(default_scale_factors_used || norm_size_configured)
|
(default_scale_factors_used || norm_size_configured) &&
|
||||||
|
(width >= kMinLayerSize)
|
||||||
? NormalizeSimulcastSize(width, encoder_config.number_of_streams)
|
? NormalizeSimulcastSize(width, encoder_config.number_of_streams)
|
||||||
: width;
|
: width;
|
||||||
const int normalized_height =
|
const int normalized_height =
|
||||||
(default_scale_factors_used || norm_size_configured)
|
(default_scale_factors_used || norm_size_configured) &&
|
||||||
|
(height >= kMinLayerSize)
|
||||||
? NormalizeSimulcastSize(height, encoder_config.number_of_streams)
|
? NormalizeSimulcastSize(height, encoder_config.number_of_streams)
|
||||||
: height;
|
: height;
|
||||||
|
|
||||||
for (size_t i = 0; i < layers.size(); ++i) {
|
for (size_t i = 0; i < layers.size(); ++i) {
|
||||||
layers[i].active = encoder_config.simulcast_layers[i].active;
|
layers[i].active = encoder_config.simulcast_layers[i].active;
|
||||||
layers[i].scalability_mode =
|
layers[i].scalability_mode =
|
||||||
@ -3691,12 +3704,10 @@ EncoderStreamFactory::CreateSimulcastOrConferenceModeScreenshareStreams(
|
|||||||
if (has_scale_resolution_down_by) {
|
if (has_scale_resolution_down_by) {
|
||||||
const double scale_resolution_down_by = std::max(
|
const double scale_resolution_down_by = std::max(
|
||||||
encoder_config.simulcast_layers[i].scale_resolution_down_by, 1.0);
|
encoder_config.simulcast_layers[i].scale_resolution_down_by, 1.0);
|
||||||
layers[i].width = std::max(
|
layers[i].width = ScaleDownResolution(
|
||||||
static_cast<int>(normalized_width / scale_resolution_down_by),
|
normalized_width, scale_resolution_down_by, kMinLayerSize);
|
||||||
kMinLayerSize);
|
layers[i].height = ScaleDownResolution(
|
||||||
layers[i].height = std::max(
|
normalized_height, scale_resolution_down_by, kMinLayerSize);
|
||||||
static_cast<int>(normalized_height / scale_resolution_down_by),
|
|
||||||
kMinLayerSize);
|
|
||||||
}
|
}
|
||||||
// Update simulcast bitrates with configured min and max bitrate.
|
// Update simulcast bitrates with configured min and max bitrate.
|
||||||
if (encoder_config.simulcast_layers[i].min_bitrate_bps > 0) {
|
if (encoder_config.simulcast_layers[i].min_bitrate_bps > 0) {
|
||||||
|
Reference in New Issue
Block a user