Reland "Rename requested_resolution to scale_resolution_down_to."

This is a reland of commit 82617ac51e7825db53451818f4d1ad52b69761fd

The reason for the revert was a downstream use of
`rtc::VideoSinkWants::requested_resolution`, so in this reland we don't
rename this field, it's fine just to rename the one in
RtpEncodingParameters for now.

Original change's description:
> Rename `requested_resolution` to `scale_resolution_down_to`.
>
> This is a pure refactor/rename CL without any changes in behavior.
>
> This field is called scaleResolutionDownTo in the spec and JavaScript.
> Let's make C++ match to avoid confusion.
>
> In order not to break downstream during the transition a variable with
> the old name being a pure reference to the renamed attribute is added.
> This means we have to add custom constructors, but we can change this
> back to "= default" when the transition is completed, which should only
> be a couple of CLs away.
>
> Bug: webrtc:375048799
> Change-Id: If755102ccd79d46020ce5b33acd3dfcc29799e47
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/366560
> Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
> Reviewed-by: Henrik Andreassson <henrika@webrtc.org>
> Commit-Queue: Henrik Boström <hbos@webrtc.org>
> Cr-Commit-Position: refs/heads/main@{#43300}

NOTRY=True

Bug: webrtc:375048799
Change-Id: Ic4ee156c1d50aa36070a8d84059870791dcbbe5e
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/366660
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Henrik Andreassson <henrika@webrtc.org>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#43304}
This commit is contained in:
Henrik Boström 2024-10-25 09:51:44 +02:00 committed by WebRTC LUCI CQ
parent 115aea4774
commit e8c97c0d09
22 changed files with 369 additions and 292 deletions

View File

@ -106,9 +106,27 @@ RtpRtxParameters::RtpRtxParameters(uint32_t ssrc) : ssrc(ssrc) {}
RtpRtxParameters::RtpRtxParameters(const RtpRtxParameters& rhs) = default; RtpRtxParameters::RtpRtxParameters(const RtpRtxParameters& rhs) = default;
RtpRtxParameters::~RtpRtxParameters() = default; RtpRtxParameters::~RtpRtxParameters() = default;
RtpEncodingParameters::RtpEncodingParameters() = default; // TODO(https://crbug.com/webrtc/375048799): Use "= default" when
RtpEncodingParameters::RtpEncodingParameters(const RtpEncodingParameters& rhs) = // `requested_resolution` has been deleted
default; RtpEncodingParameters::RtpEncodingParameters()
: requested_resolution(scale_resolution_down_to) {}
RtpEncodingParameters::RtpEncodingParameters(const RtpEncodingParameters& rhs)
: ssrc(rhs.ssrc),
bitrate_priority(rhs.bitrate_priority),
network_priority(rhs.network_priority),
max_bitrate_bps(rhs.max_bitrate_bps),
min_bitrate_bps(rhs.min_bitrate_bps),
max_framerate(rhs.max_framerate),
num_temporal_layers(rhs.num_temporal_layers),
scale_resolution_down_by(rhs.scale_resolution_down_by),
scalability_mode(rhs.scalability_mode),
scale_resolution_down_to(rhs.scale_resolution_down_to),
requested_resolution(scale_resolution_down_to),
active(rhs.active),
rid(rhs.rid),
request_key_frame(rhs.request_key_frame),
adaptive_ptime(rhs.adaptive_ptime),
codec(rhs.codec) {}
RtpEncodingParameters::~RtpEncodingParameters() = default; RtpEncodingParameters::~RtpEncodingParameters() = default;
RtpCodecParameters::RtpCodecParameters() = default; RtpCodecParameters::RtpCodecParameters() = default;

View File

@ -497,23 +497,22 @@ struct RTC_EXPORT RtpEncodingParameters {
// https://w3c.github.io/webrtc-svc/#rtcrtpencodingparameters // https://w3c.github.io/webrtc-svc/#rtcrtpencodingparameters
std::optional<std::string> scalability_mode; std::optional<std::string> scalability_mode;
// Requested encode resolution. // This is an alternative API to `scale_resolution_down_by` but expressed in
// absolute terms (max width and max height) as opposed to relative terms (a
// scaling factor that is relative to the input frame size).
// //
// This field provides an alternative to `scale_resolution_down_by` // If both `scale_resolution_down_by` and `scale_resolution_down_to` are
// that is not dependent on the video source. // specified, the "scale by" value is ignored.
// //
// When setting requested_resolution it is not necessary to adapt the // See spec:
// video source using OnOutputFormatRequest, since the VideoStreamEncoder // https://w3c.github.io/webrtc-extensions/#dom-rtcrtpencodingparameters-scaleresolutiondownto
// will apply downscaling if necessary. requested_resolution will also be
// propagated to the video source, this allows downscaling earlier in the
// pipeline which can be beneficial if the source is consumed by multiple
// encoders, but is not strictly necessary.
// //
// The `requested_resolution` is subject to resource adaptation. // This was previously known as "requested_resolution" in C++.
// std::optional<Resolution> scale_resolution_down_to;
// It is an error to set both `requested_resolution` and // Alternative name for `scale_resolution_down_to`.
// `scale_resolution_down_by`. // TODO(https://crbug.com/webrtc/375048799): Delete when downstream projects
std::optional<Resolution> requested_resolution; // have migrated from `requested_resolution` to `scale_resolution_down_to`.
std::optional<Resolution>& requested_resolution;
// For an RtpSender, set to true to cause this encoding to be encoded and // For an RtpSender, set to true to cause this encoding to be encoded and
// sent, and false for it not to be encoded and sent. This allows control // sent, and false for it not to be encoded and sent. This allows control
@ -545,11 +544,31 @@ struct RTC_EXPORT RtpEncodingParameters {
scale_resolution_down_by == o.scale_resolution_down_by && scale_resolution_down_by == o.scale_resolution_down_by &&
active == o.active && rid == o.rid && active == o.active && rid == o.rid &&
adaptive_ptime == o.adaptive_ptime && adaptive_ptime == o.adaptive_ptime &&
requested_resolution == o.requested_resolution && codec == o.codec; scale_resolution_down_to == o.scale_resolution_down_to &&
codec == o.codec;
} }
bool operator!=(const RtpEncodingParameters& o) const { bool operator!=(const RtpEncodingParameters& o) const {
return !(*this == o); return !(*this == o);
} }
// TODO(https://crbug.com/webrtc/375048799): Delete this operator overload
// when `requested_resolution` has been deleted in favor of auto generated op.
void operator=(const RtpEncodingParameters& o) {
ssrc = o.ssrc;
bitrate_priority = o.bitrate_priority;
network_priority = o.network_priority;
max_bitrate_bps = o.max_bitrate_bps;
min_bitrate_bps = o.min_bitrate_bps;
max_framerate = o.max_framerate;
num_temporal_layers = o.num_temporal_layers;
scale_resolution_down_by = o.scale_resolution_down_by;
scalability_mode = o.scalability_mode;
scale_resolution_down_to = o.scale_resolution_down_to;
active = o.active;
rid = o.rid;
request_key_frame = o.request_key_frame;
adaptive_ptime = o.adaptive_ptime;
codec = o.codec;
}
}; };
struct RTC_EXPORT RtpCodecParameters : public RtpCodec { struct RTC_EXPORT RtpCodecParameters : public RtpCodec {

View File

@ -82,7 +82,8 @@ struct RTC_EXPORT VideoSinkWants {
// should only be used as a hint when constructing the webrtc::VideoFrame. // should only be used as a hint when constructing the webrtc::VideoFrame.
std::vector<FrameSize> resolutions; std::vector<FrameSize> resolutions;
// This is the resolution requested by the user using RtpEncodingParameters. // This is the resolution requested by the user using RtpEncodingParameters,
// which is the maximum `scale_resolution_down_by` value of any encoding.
std::optional<FrameSize> requested_resolution; std::optional<FrameSize> requested_resolution;
// `is_active` : Is this VideoSinkWants from an encoder that is encoding any // `is_active` : Is this VideoSinkWants from an encoder that is encoding any
@ -96,7 +97,7 @@ struct RTC_EXPORT VideoSinkWants {
// that aggregates several VideoSinkWants (and sends them to // that aggregates several VideoSinkWants (and sends them to
// AdaptedVideoTrackSource). // AdaptedVideoTrackSource).
struct Aggregates { struct Aggregates {
// `active_without_requested_resolution` is set by VideoBroadcaster // `any_active_without_requested_resolution` is set by VideoBroadcaster
// when aggregating sink wants if there exists any sink (encoder) that is // when aggregating sink wants if there exists any sink (encoder) that is
// active but has not set the `requested_resolution`, i.e is relying on // active but has not set the `requested_resolution`, i.e is relying on
// OnOutputFormatRequest to handle encode resolution. // OnOutputFormatRequest to handle encode resolution.

View File

@ -160,7 +160,7 @@ webrtc::RTCError CheckRtpParametersValues(
const webrtc::FieldTrialsView& field_trials) { const webrtc::FieldTrialsView& field_trials) {
using webrtc::RTCErrorType; using webrtc::RTCErrorType;
bool has_requested_resolution = false; bool has_scale_resolution_down_to = false;
for (size_t i = 0; i < rtp_parameters.encodings.size(); ++i) { for (size_t i = 0; i < rtp_parameters.encodings.size(); ++i) {
if (rtp_parameters.encodings[i].bitrate_priority <= 0) { if (rtp_parameters.encodings[i].bitrate_priority <= 0) {
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE, LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
@ -199,10 +199,10 @@ webrtc::RTCError CheckRtpParametersValues(
} }
} }
if (rtp_parameters.encodings[i].requested_resolution.has_value()) { if (rtp_parameters.encodings[i].scale_resolution_down_to.has_value()) {
has_requested_resolution = true; has_scale_resolution_down_to = true;
if (rtp_parameters.encodings[i].requested_resolution->width <= 0 || if (rtp_parameters.encodings[i].scale_resolution_down_to->width <= 0 ||
rtp_parameters.encodings[i].requested_resolution->height <= 0) { rtp_parameters.encodings[i].scale_resolution_down_to->height <= 0) {
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION, LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
"The resolution dimensions must be positive."); "The resolution dimensions must be positive.");
} }
@ -218,11 +218,11 @@ webrtc::RTCError CheckRtpParametersValues(
} }
} }
if (has_requested_resolution && if (has_scale_resolution_down_to &&
absl::c_any_of(rtp_parameters.encodings, absl::c_any_of(rtp_parameters.encodings,
[](const webrtc::RtpEncodingParameters& encoding) { [](const webrtc::RtpEncodingParameters& encoding) {
return encoding.active && return encoding.active &&
!encoding.requested_resolution.has_value(); !encoding.scale_resolution_down_to.has_value();
})) { })) {
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION, LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
"If a resolution is specified on any encoding then " "If a resolution is specified on any encoding then "

View File

@ -244,27 +244,30 @@ bool VideoAdapter::AdaptFrameResolution(int in_width,
RTC_DCHECK_EQ(0, *out_height % resolution_alignment_); RTC_DCHECK_EQ(0, *out_height % resolution_alignment_);
// Lastly, make the output size fit within the resolution restrictions as // Lastly, make the output size fit within the resolution restrictions as
// specified by `requested_resolution_`. This does not modify aspect ratio or // specified by `scale_resolution_down_to_`. This does not modify aspect ratio
// cropping, only `out_width` and `out_height`. // or cropping, only `out_width` and `out_height`.
if (requested_resolution_.has_value()) { if (scale_resolution_down_to_.has_value()) {
// Make frame and requested resolution have matching orientation. // Make frame and "scale to" have matching orientation.
webrtc::Resolution requested_resolution = requested_resolution_.value(); webrtc::Resolution scale_resolution_down_to =
if ((*out_width < *out_height) != scale_resolution_down_to_.value();
(requested_resolution_->width < requested_resolution_->height)) { if ((*out_width < *out_height) != (scale_resolution_down_to_->width <
requested_resolution = {.width = requested_resolution_->height, scale_resolution_down_to_->height)) {
.height = requested_resolution_->width}; scale_resolution_down_to = {.width = scale_resolution_down_to_->height,
.height = scale_resolution_down_to_->width};
} }
// Downscale by smallest scaling factor, if necessary. // Downscale by smallest scaling factor, if necessary.
if (*out_width > 0 && *out_height > 0 && if (*out_width > 0 && *out_height > 0 &&
(requested_resolution.width < *out_width || (scale_resolution_down_to.width < *out_width ||
requested_resolution.height < *out_height)) { scale_resolution_down_to.height < *out_height)) {
double scale_factor = std::min( double scale_factor = std::min(
requested_resolution.width / static_cast<double>(*out_width), scale_resolution_down_to.width / static_cast<double>(*out_width),
requested_resolution.height / static_cast<double>(*out_height)); scale_resolution_down_to.height / static_cast<double>(*out_height));
*out_width = roundUp(std::round(*out_width * scale_factor), *out_width =
resolution_alignment_, requested_resolution.width); roundUp(std::round(*out_width * scale_factor), resolution_alignment_,
*out_height = roundUp(std::round(*out_height * scale_factor), scale_resolution_down_to.width);
resolution_alignment_, requested_resolution.height); *out_height =
roundUp(std::round(*out_height * scale_factor), resolution_alignment_,
scale_resolution_down_to.height);
RTC_DCHECK_EQ(0, *out_width % resolution_alignment_); RTC_DCHECK_EQ(0, *out_width % resolution_alignment_);
RTC_DCHECK_EQ(0, *out_height % resolution_alignment_); RTC_DCHECK_EQ(0, *out_height % resolution_alignment_);
} }
@ -346,7 +349,7 @@ void VideoAdapter::OnOutputFormatRequest(
if (stashed_output_format_request_) { if (stashed_output_format_request_) {
// Save the output format request for later use in case the encoder making // Save the output format request for later use in case the encoder making
// this call would become active, because currently all active encoders use // this call would become active, because currently all active encoders use
// requested_resolution instead. // scale_resolution_down_to instead.
stashed_output_format_request_ = request; stashed_output_format_request_ = request;
RTC_LOG(LS_INFO) << "Stashing OnOutputFormatRequest: " RTC_LOG(LS_INFO) << "Stashing OnOutputFormatRequest: "
<< stashed_output_format_request_->ToString(); << stashed_output_format_request_->ToString();
@ -370,21 +373,22 @@ void VideoAdapter::OnSinkWants(const rtc::VideoSinkWants& sink_wants) {
source_resolution_alignment_, sink_wants.resolution_alignment); source_resolution_alignment_, sink_wants.resolution_alignment);
// Convert from std::optional<rtc::VideoSinkWants::FrameSize> to // Convert from std::optional<rtc::VideoSinkWants::FrameSize> to
// std::optional<webrtc::Resolution>. Both are {int,int}. // std::optional<webrtc::Resolution>. Both are {int,int}.
requested_resolution_ = std::nullopt; scale_resolution_down_to_ = std::nullopt;
if (sink_wants.requested_resolution.has_value()) { if (sink_wants.requested_resolution.has_value()) {
requested_resolution_ = {.width = sink_wants.requested_resolution->width, scale_resolution_down_to_ = {
.width = sink_wants.requested_resolution->width,
.height = sink_wants.requested_resolution->height}; .height = sink_wants.requested_resolution->height};
} }
// If requested_resolution is used, and there are no active encoders // If scale_resolution_down_to is used, and there are no active encoders
// that are NOT using requested_resolution (aka newapi), then override // that are NOT using scale_resolution_down_to (aka newapi), then override
// calls to OnOutputFormatRequest and use values from requested_resolution // calls to OnOutputFormatRequest and use values from scale_resolution_down_to
// instead (combined with qualityscaling based on pixel counts above). // instead (combined with qualityscaling based on pixel counts above).
if (!sink_wants.requested_resolution) { if (!sink_wants.requested_resolution) {
if (stashed_output_format_request_) { if (stashed_output_format_request_) {
// because current active_output_format_request is based on // because current active_output_format_request is based on
// requested_resolution logic, while current encoder(s) doesn't want that, // scale_resolution_down_to logic, while current encoder(s) doesn't want
// we have to restore the stashed request. // that, we have to restore the stashed request.
RTC_LOG(LS_INFO) << "Unstashing OnOutputFormatRequest: " RTC_LOG(LS_INFO) << "Unstashing OnOutputFormatRequest: "
<< stashed_output_format_request_->ToString(); << stashed_output_format_request_->ToString();
output_format_request_ = *stashed_output_format_request_; output_format_request_ = *stashed_output_format_request_;
@ -393,9 +397,10 @@ void VideoAdapter::OnSinkWants(const rtc::VideoSinkWants& sink_wants) {
return; return;
} }
// The code below is only needed when `requested_resolution` is signalled back // The code below is only needed when `scale_resolution_down_to` is signalled
// to the video source which only happens if // back to the video source which only happens if
// `VideoStreamEncoderSettings::use_standard_requested_resolution` is false. // `VideoStreamEncoderSettings::use_standard_scale_resolution_down_to` is
// false.
// TODO(https://crbug.com/webrtc/366284861): Delete the code below as part of // TODO(https://crbug.com/webrtc/366284861): Delete the code below as part of
// deleting this flag and only supporting the standard behavior. // deleting this flag and only supporting the standard behavior.
@ -413,8 +418,8 @@ void VideoAdapter::OnSinkWants(const rtc::VideoSinkWants& sink_wants) {
<< stashed_output_format_request_->ToString(); << stashed_output_format_request_->ToString();
} }
// Clear the output format request. Requested resolution will be applied // Clear the output format request, `scale_resolution_down_to_` will be
// instead which happens inside AdaptFrameResolution(). // applied instead which happens inside AdaptFrameResolution().
output_format_request_ = {}; output_format_request_ = {};
} }

View File

@ -149,14 +149,14 @@ class RTC_EXPORT VideoAdapter {
int resolution_request_target_pixel_count_ RTC_GUARDED_BY(mutex_); int resolution_request_target_pixel_count_ RTC_GUARDED_BY(mutex_);
int resolution_request_max_pixel_count_ RTC_GUARDED_BY(mutex_); int resolution_request_max_pixel_count_ RTC_GUARDED_BY(mutex_);
int max_framerate_request_ RTC_GUARDED_BY(mutex_); int max_framerate_request_ RTC_GUARDED_BY(mutex_);
std::optional<webrtc::Resolution> requested_resolution_ std::optional<webrtc::Resolution> scale_resolution_down_to_
RTC_GUARDED_BY(mutex_); RTC_GUARDED_BY(mutex_);
// Stashed OutputFormatRequest that is used to save value of // Stashed OutputFormatRequest that is used to save value of
// OnOutputFormatRequest in case all active encoders are using // OnOutputFormatRequest in case all active encoders are using
// requested_resolution. I.e when all active encoders are using // scale_resolution_down_to. I.e when all active encoders are using
// requested_resolution, the call to OnOutputFormatRequest is ignored // scale_resolution_down_to, the call to OnOutputFormatRequest is ignored
// and the value from requested_resolution is used instead (to scale/crop // and the value from scale_resolution_down_to is used instead (to scale/crop
// frame). This allows for an application to only use // frame). This allows for an application to only use
// RtpEncodingParameters::request_resolution and get the same behavior as if // RtpEncodingParameters::request_resolution and get the same behavior as if
// it had used VideoAdapter::OnOutputFormatRequest. // it had used VideoAdapter::OnOutputFormatRequest.

View File

@ -52,15 +52,15 @@ rtc::VideoSinkWants BuildSinkWants(std::optional<int> target_pixel_count,
} }
rtc::VideoSinkWants BuildSinkWants( rtc::VideoSinkWants BuildSinkWants(
std::optional<webrtc::Resolution> requested_resolution, std::optional<webrtc::Resolution> scale_resolution_down_to,
bool any_active_without_requested_resolution) { bool any_active_without_requested_resolution) {
rtc::VideoSinkWants wants; rtc::VideoSinkWants wants;
wants.max_framerate_fps = kDefaultFps; wants.max_framerate_fps = kDefaultFps;
wants.resolution_alignment = 1; wants.resolution_alignment = 1;
wants.is_active = true; wants.is_active = true;
if (requested_resolution) { if (scale_resolution_down_to) {
wants.requested_resolution.emplace(rtc::VideoSinkWants::FrameSize( wants.requested_resolution.emplace(rtc::VideoSinkWants::FrameSize(
requested_resolution->width, requested_resolution->height)); scale_resolution_down_to->width, scale_resolution_down_to->height));
} }
wants.aggregates.emplace(rtc::VideoSinkWants::Aggregates()); wants.aggregates.emplace(rtc::VideoSinkWants::Aggregates());
wants.aggregates->any_active_without_requested_resolution = wants.aggregates->any_active_without_requested_resolution =
@ -1202,8 +1202,9 @@ TEST_P(VideoAdapterTest, AdaptResolutionWithSinkAlignment) {
} }
// Verify the cases the OnOutputFormatRequest is ignored and // Verify the cases the OnOutputFormatRequest is ignored and
// requested_resolution is used instead. // scale_resolution_down_to is used instead.
TEST_P(VideoAdapterTest, UseRequestedResolutionInsteadOfOnOutputFormatRequest) { TEST_P(VideoAdapterTest,
UseScaleResolutionDownToInsteadOfOnOutputFormatRequest) {
{ {
// Both new and old API active => Use OnOutputFormatRequest // Both new and old API active => Use OnOutputFormatRequest
OnOutputFormatRequest(640, 360, kDefaultFps); OnOutputFormatRequest(640, 360, kDefaultFps);
@ -1218,7 +1219,7 @@ TEST_P(VideoAdapterTest, UseRequestedResolutionInsteadOfOnOutputFormatRequest) {
} }
{ {
// New API active, old API inactive, ignore OnOutputFormatRequest and use // New API active, old API inactive, ignore OnOutputFormatRequest and use
// requested_resolution. // scale_resolution_down_to.
OnOutputFormatRequest(640, 360, kDefaultFps); OnOutputFormatRequest(640, 360, kDefaultFps);
adapter_.OnSinkWants( adapter_.OnSinkWants(
BuildSinkWants(Resolution{.width = 960, .height = 540}, BuildSinkWants(Resolution{.width = 960, .height = 540},
@ -1256,7 +1257,7 @@ TEST_P(VideoAdapterTest, UseRequestedResolutionInsteadOfOnOutputFormatRequest) {
Eq(Resolution{.width = 960, .height = 540})); Eq(Resolution{.width = 960, .height = 540}));
// This is ignored since there is not any active NOT using // This is ignored since there is not any active NOT using
// requested_resolution. // scale_resolution_down_to.
OnOutputFormatRequest(320, 180, kDefaultFps); OnOutputFormatRequest(320, 180, kDefaultFps);
EXPECT_THAT( EXPECT_THAT(
@ -1276,7 +1277,7 @@ TEST_P(VideoAdapterTest, UseRequestedResolutionInsteadOfOnOutputFormatRequest) {
} }
} }
TEST_P(VideoAdapterTest, RequestedResolutionIsOrientationAgnostic) { TEST_P(VideoAdapterTest, ScaleResolutionDownToIsOrientationAgnostic) {
// Request 1280x720 when frame is 720x1280. // Request 1280x720 when frame is 720x1280.
{ {
adapter_.OnSinkWants( adapter_.OnSinkWants(
@ -1301,7 +1302,7 @@ TEST_P(VideoAdapterTest, RequestedResolutionIsOrientationAgnostic) {
} }
} }
TEST_P(VideoAdapterTest, RequestedResolutionMaintainsAspectRatio) { TEST_P(VideoAdapterTest, ScaleResolutionDownToMaintainsAspectRatio) {
// Request 720x720. // Request 720x720.
adapter_.OnSinkWants( adapter_.OnSinkWants(
BuildSinkWants(Resolution{.width = 720, .height = 720}, BuildSinkWants(Resolution{.width = 720, .height = 720},
@ -1366,7 +1367,7 @@ TEST_P(VideoAdapterWithSourceAlignmentTest, AdaptResolutionWithSinkAlignment) {
} }
TEST_P(VideoAdapterWithSourceAlignmentTest, TEST_P(VideoAdapterWithSourceAlignmentTest,
RequestedResolutionMaintainsAspectRatioWithAlignment) { ScaleResolutionDownToMaintainsAspectRatioWithAlignment) {
// Request 720x720. // Request 720x720.
adapter_.OnSinkWants( adapter_.OnSinkWants(
BuildSinkWants(Resolution{.width = 720, .height = 720}, BuildSinkWants(Resolution{.width = 720, .height = 720},

View File

@ -131,7 +131,7 @@ void VideoBroadcaster::UpdateWants() {
// "ignore" encoders that are not active. But that would // "ignore" encoders that are not active. But that would
// probably require a controlled roll out with a field trials? // probably require a controlled roll out with a field trials?
// To play it safe, only ignore inactive encoders is there is an // To play it safe, only ignore inactive encoders is there is an
// active encoder using the new api (requested_resolution), // active encoder using the new api (scale_resolution_down_to),
// this means that there is only a behavioural change when using new // this means that there is only a behavioural change when using new
// api. // api.
bool ignore_inactive_encoders_old_api = false; bool ignore_inactive_encoders_old_api = false;
@ -171,8 +171,8 @@ void VideoBroadcaster::UpdateWants() {
wants.resolution_alignment = cricket::LeastCommonMultiple( wants.resolution_alignment = cricket::LeastCommonMultiple(
wants.resolution_alignment, sink.wants.resolution_alignment); wants.resolution_alignment, sink.wants.resolution_alignment);
// Pick MAX(requested_resolution) since the actual can be downscaled // Pick MAX(requested_resolution) since the actual can be downscaled in
// in encoder instead. // encoder instead.
if (sink.wants.requested_resolution) { if (sink.wants.requested_resolution) {
if (!wants.requested_resolution) { if (!wants.requested_resolution) {
wants.requested_resolution = sink.wants.requested_resolution; wants.requested_resolution = sink.wants.requested_resolution;

View File

@ -332,7 +332,7 @@ TEST(VideoBroadcasterTest, ForwardsConstraintsToSink) {
broadcaster.ProcessConstraints(webrtc::VideoTrackSourceConstraints{2, 3}); broadcaster.ProcessConstraints(webrtc::VideoTrackSourceConstraints{2, 3});
} }
TEST(VideoBroadcasterTest, AppliesMaxOfSinkWantsRequestedResolution) { TEST(VideoBroadcasterTest, AppliesMaxOfSinkWantsScaleResolutionDownTo) {
VideoBroadcaster broadcaster; VideoBroadcaster broadcaster;
FakeVideoRenderer sink1; FakeVideoRenderer sink1;
@ -374,7 +374,7 @@ TEST(VideoBroadcasterTest, AnyActive) {
EXPECT_EQ(false, broadcaster.wants().is_active); EXPECT_EQ(false, broadcaster.wants().is_active);
} }
TEST(VideoBroadcasterTest, AnyActiveWithoutRequestedResolution) { TEST(VideoBroadcasterTest, AnyActiveWithoutScaleResolutionDownTo) {
VideoBroadcaster broadcaster; VideoBroadcaster broadcaster;
FakeVideoRenderer sink1; FakeVideoRenderer sink1;
@ -402,8 +402,9 @@ TEST(VideoBroadcasterTest, AnyActiveWithoutRequestedResolution) {
} }
// This verifies that the VideoSinkWants from a Sink that is_active = false // This verifies that the VideoSinkWants from a Sink that is_active = false
// is ignored IF there is an active sink using new api (Requested_Resolution). // is ignored IF there is an active sink using requested_resolution (controlled
// The uses resolution_alignment for verification. // via new API scale_resolution_down_to). The uses resolution_alignment for
// verification.
TEST(VideoBroadcasterTest, IgnoreInactiveSinkIfNewApiUsed) { TEST(VideoBroadcasterTest, IgnoreInactiveSinkIfNewApiUsed) {
VideoBroadcaster broadcaster; VideoBroadcaster broadcaster;

View File

@ -2087,8 +2087,8 @@ WebRtcVideoSendChannel::WebRtcVideoSendStream::SetRtpParameters(
rtp_parameters_.encodings[i].scale_resolution_down_by) || rtp_parameters_.encodings[i].scale_resolution_down_by) ||
(new_parameters.encodings[i].num_temporal_layers != (new_parameters.encodings[i].num_temporal_layers !=
rtp_parameters_.encodings[i].num_temporal_layers) || rtp_parameters_.encodings[i].num_temporal_layers) ||
(new_parameters.encodings[i].requested_resolution != (new_parameters.encodings[i].scale_resolution_down_to !=
rtp_parameters_.encodings[i].requested_resolution) || rtp_parameters_.encodings[i].scale_resolution_down_to) ||
(new_parameters.encodings[i].scalability_mode != (new_parameters.encodings[i].scalability_mode !=
rtp_parameters_.encodings[i].scalability_mode) || rtp_parameters_.encodings[i].scalability_mode) ||
(new_parameters.encodings[i].codec != (new_parameters.encodings[i].codec !=
@ -2228,7 +2228,7 @@ WebRtcVideoSendChannel::WebRtcVideoSendStream::CreateVideoEncoderConfig(
rtp_parameters_.encodings) { rtp_parameters_.encodings) {
if (encoding.scalability_mode.has_value() && if (encoding.scalability_mode.has_value() &&
(encoding.scale_resolution_down_by.has_value() || (encoding.scale_resolution_down_by.has_value() ||
encoding.requested_resolution.has_value())) { encoding.scale_resolution_down_to.has_value())) {
legacy_scalability_mode = false; legacy_scalability_mode = false;
break; break;
} }
@ -2309,8 +2309,8 @@ WebRtcVideoSendChannel::WebRtcVideoSendStream::CreateVideoEncoderConfig(
encoder_config.simulcast_layers[i].num_temporal_layers = encoder_config.simulcast_layers[i].num_temporal_layers =
*rtp_parameters_.encodings[i].num_temporal_layers; *rtp_parameters_.encodings[i].num_temporal_layers;
} }
encoder_config.simulcast_layers[i].requested_resolution = encoder_config.simulcast_layers[i].scale_resolution_down_to =
rtp_parameters_.encodings[i].requested_resolution; rtp_parameters_.encodings[i].scale_resolution_down_to;
} }
encoder_config.legacy_conference_mode = parameters_.conference_mode; encoder_config.legacy_conference_mode = parameters_.conference_mode;

View File

@ -9750,7 +9750,7 @@ TEST_F(WebRtcVideoChannelBaseTest, EncoderSelectorSwitchCodec) {
send_channel_->SetEncoderSelector(kSsrc, nullptr); send_channel_->SetEncoderSelector(kSsrc, nullptr);
} }
TEST_F(WebRtcVideoChannelTest, RequestedResolutionSinglecast) { TEST_F(WebRtcVideoChannelTest, ScaleResolutionDownToSinglecast) {
cricket::VideoSenderParameters parameters; cricket::VideoSenderParameters parameters;
parameters.codecs.push_back(GetEngineCodec("VP8")); parameters.codecs.push_back(GetEngineCodec("VP8"));
ASSERT_TRUE(send_channel_->SetSenderParameters(parameters)); ASSERT_TRUE(send_channel_->SetSenderParameters(parameters));
@ -9762,11 +9762,11 @@ TEST_F(WebRtcVideoChannelTest, RequestedResolutionSinglecast) {
EXPECT_TRUE( EXPECT_TRUE(
send_channel_->SetVideoSend(last_ssrc_, nullptr, &frame_forwarder)); send_channel_->SetVideoSend(last_ssrc_, nullptr, &frame_forwarder));
{ // TEST requested_resolution < frame size { // TEST scale_resolution_down_to < frame size
webrtc::RtpParameters rtp_parameters = webrtc::RtpParameters rtp_parameters =
send_channel_->GetRtpSendParameters(last_ssrc_); send_channel_->GetRtpSendParameters(last_ssrc_);
EXPECT_EQ(1UL, rtp_parameters.encodings.size()); EXPECT_EQ(1UL, rtp_parameters.encodings.size());
rtp_parameters.encodings[0].requested_resolution = {.width = 640, rtp_parameters.encodings[0].scale_resolution_down_to = {.width = 640,
.height = 360}; .height = 360};
send_channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters); send_channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters);
@ -9778,10 +9778,10 @@ TEST_F(WebRtcVideoChannelTest, RequestedResolutionSinglecast) {
EXPECT_EQ(rtc::checked_cast<size_t>(360), streams[0].height); EXPECT_EQ(rtc::checked_cast<size_t>(360), streams[0].height);
} }
{ // TEST requested_resolution == frame size { // TEST scale_resolution_down_to == frame size
auto rtp_parameters = send_channel_->GetRtpSendParameters(last_ssrc_); auto rtp_parameters = send_channel_->GetRtpSendParameters(last_ssrc_);
EXPECT_EQ(1UL, rtp_parameters.encodings.size()); EXPECT_EQ(1UL, rtp_parameters.encodings.size());
rtp_parameters.encodings[0].requested_resolution = {.width = 1280, rtp_parameters.encodings[0].scale_resolution_down_to = {.width = 1280,
.height = 720}; .height = 720};
send_channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters); send_channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters);
@ -9792,10 +9792,10 @@ TEST_F(WebRtcVideoChannelTest, RequestedResolutionSinglecast) {
EXPECT_EQ(rtc::checked_cast<size_t>(720), streams[0].height); EXPECT_EQ(rtc::checked_cast<size_t>(720), streams[0].height);
} }
{ // TEST requested_resolution > frame size { // TEST scale_resolution_down_to > frame size
auto rtp_parameters = send_channel_->GetRtpSendParameters(last_ssrc_); auto rtp_parameters = send_channel_->GetRtpSendParameters(last_ssrc_);
EXPECT_EQ(1UL, rtp_parameters.encodings.size()); EXPECT_EQ(1UL, rtp_parameters.encodings.size());
rtp_parameters.encodings[0].requested_resolution = {.width = 2 * 1280, rtp_parameters.encodings[0].scale_resolution_down_to = {.width = 2 * 1280,
.height = 2 * 720}; .height = 2 * 720};
send_channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters); send_channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters);
@ -9809,7 +9809,7 @@ TEST_F(WebRtcVideoChannelTest, RequestedResolutionSinglecast) {
EXPECT_TRUE(send_channel_->SetVideoSend(last_ssrc_, nullptr, nullptr)); EXPECT_TRUE(send_channel_->SetVideoSend(last_ssrc_, nullptr, nullptr));
} }
TEST_F(WebRtcVideoChannelTest, RequestedResolutionSinglecastScaling) { TEST_F(WebRtcVideoChannelTest, ScaleResolutionDownToSinglecastScaling) {
cricket::VideoSenderParameters parameters; cricket::VideoSenderParameters parameters;
parameters.codecs.push_back(GetEngineCodec("VP8")); parameters.codecs.push_back(GetEngineCodec("VP8"));
ASSERT_TRUE(send_channel_->SetSenderParameters(parameters)); ASSERT_TRUE(send_channel_->SetSenderParameters(parameters));
@ -9824,7 +9824,7 @@ TEST_F(WebRtcVideoChannelTest, RequestedResolutionSinglecastScaling) {
{ {
auto rtp_parameters = send_channel_->GetRtpSendParameters(last_ssrc_); auto rtp_parameters = send_channel_->GetRtpSendParameters(last_ssrc_);
EXPECT_EQ(1UL, rtp_parameters.encodings.size()); EXPECT_EQ(1UL, rtp_parameters.encodings.size());
rtp_parameters.encodings[0].requested_resolution = {.width = 720, rtp_parameters.encodings[0].scale_resolution_down_to = {.width = 720,
.height = 720}; .height = 720};
send_channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters); send_channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters);
@ -9841,7 +9841,7 @@ TEST_F(WebRtcVideoChannelTest, RequestedResolutionSinglecastScaling) {
{ {
auto rtp_parameters = send_channel_->GetRtpSendParameters(last_ssrc_); auto rtp_parameters = send_channel_->GetRtpSendParameters(last_ssrc_);
EXPECT_EQ(1UL, rtp_parameters.encodings.size()); EXPECT_EQ(1UL, rtp_parameters.encodings.size());
rtp_parameters.encodings[0].requested_resolution = {.width = 1280, rtp_parameters.encodings[0].scale_resolution_down_to = {.width = 1280,
.height = 1280}; .height = 1280};
send_channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters); send_channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters);
@ -9857,7 +9857,7 @@ TEST_F(WebRtcVideoChannelTest, RequestedResolutionSinglecastScaling) {
{ {
auto rtp_parameters = send_channel_->GetRtpSendParameters(last_ssrc_); auto rtp_parameters = send_channel_->GetRtpSendParameters(last_ssrc_);
EXPECT_EQ(1UL, rtp_parameters.encodings.size()); EXPECT_EQ(1UL, rtp_parameters.encodings.size());
rtp_parameters.encodings[0].requested_resolution = {.width = 650, rtp_parameters.encodings[0].scale_resolution_down_to = {.width = 650,
.height = 650}; .height = 650};
send_channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters); send_channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters);
@ -9872,7 +9872,7 @@ TEST_F(WebRtcVideoChannelTest, RequestedResolutionSinglecastScaling) {
{ {
auto rtp_parameters = send_channel_->GetRtpSendParameters(last_ssrc_); auto rtp_parameters = send_channel_->GetRtpSendParameters(last_ssrc_);
EXPECT_EQ(1UL, rtp_parameters.encodings.size()); EXPECT_EQ(1UL, rtp_parameters.encodings.size());
rtp_parameters.encodings[0].requested_resolution = {.width = 2560, rtp_parameters.encodings[0].scale_resolution_down_to = {.width = 2560,
.height = 1440}; .height = 1440};
send_channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters); send_channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters);
@ -9886,7 +9886,7 @@ TEST_F(WebRtcVideoChannelTest, RequestedResolutionSinglecastScaling) {
EXPECT_TRUE(send_channel_->SetVideoSend(last_ssrc_, nullptr, nullptr)); EXPECT_TRUE(send_channel_->SetVideoSend(last_ssrc_, nullptr, nullptr));
} }
TEST_F(WebRtcVideoChannelTest, RequestedResolutionSimulcast) { TEST_F(WebRtcVideoChannelTest, ScaleResolutionDownToSimulcast) {
cricket::VideoSenderParameters parameters; cricket::VideoSenderParameters parameters;
parameters.codecs.push_back(GetEngineCodec("VP8")); parameters.codecs.push_back(GetEngineCodec("VP8"));
ASSERT_TRUE(send_channel_->SetSenderParameters(parameters)); ASSERT_TRUE(send_channel_->SetSenderParameters(parameters));
@ -9902,11 +9902,11 @@ TEST_F(WebRtcVideoChannelTest, RequestedResolutionSimulcast) {
webrtc::RtpParameters rtp_parameters = webrtc::RtpParameters rtp_parameters =
send_channel_->GetRtpSendParameters(last_ssrc_); send_channel_->GetRtpSendParameters(last_ssrc_);
EXPECT_EQ(3UL, rtp_parameters.encodings.size()); EXPECT_EQ(3UL, rtp_parameters.encodings.size());
rtp_parameters.encodings[0].requested_resolution = {.width = 320, rtp_parameters.encodings[0].scale_resolution_down_to = {.width = 320,
.height = 180}; .height = 180};
rtp_parameters.encodings[1].requested_resolution = {.width = 640, rtp_parameters.encodings[1].scale_resolution_down_to = {.width = 640,
.height = 360}; .height = 360};
rtp_parameters.encodings[2].requested_resolution = {.width = 1280, rtp_parameters.encodings[2].scale_resolution_down_to = {.width = 1280,
.height = 720}; .height = 720};
send_channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters); send_channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters);
@ -9924,11 +9924,11 @@ TEST_F(WebRtcVideoChannelTest, RequestedResolutionSimulcast) {
webrtc::RtpParameters rtp_parameters = webrtc::RtpParameters rtp_parameters =
send_channel_->GetRtpSendParameters(last_ssrc_); send_channel_->GetRtpSendParameters(last_ssrc_);
EXPECT_EQ(3UL, rtp_parameters.encodings.size()); EXPECT_EQ(3UL, rtp_parameters.encodings.size());
rtp_parameters.encodings[0].requested_resolution = {.width = 320, rtp_parameters.encodings[0].scale_resolution_down_to = {.width = 320,
.height = 180}; .height = 180};
rtp_parameters.encodings[1].active = false; rtp_parameters.encodings[1].active = false;
rtp_parameters.encodings[2].requested_resolution = {.width = 1280, rtp_parameters.encodings[2].scale_resolution_down_to = {.width = 1280,
.height = 720}; .height = 720};
send_channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters); send_channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters);
@ -9945,12 +9945,12 @@ TEST_F(WebRtcVideoChannelTest, RequestedResolutionSimulcast) {
webrtc::RtpParameters rtp_parameters = webrtc::RtpParameters rtp_parameters =
send_channel_->GetRtpSendParameters(last_ssrc_); send_channel_->GetRtpSendParameters(last_ssrc_);
EXPECT_EQ(3UL, rtp_parameters.encodings.size()); EXPECT_EQ(3UL, rtp_parameters.encodings.size());
rtp_parameters.encodings[0].requested_resolution = {.width = 320, rtp_parameters.encodings[0].scale_resolution_down_to = {.width = 320,
.height = 180}; .height = 180};
rtp_parameters.encodings[1].active = true; rtp_parameters.encodings[1].active = true;
rtp_parameters.encodings[1].requested_resolution = {.width = 640, rtp_parameters.encodings[1].scale_resolution_down_to = {.width = 640,
.height = 360}; .height = 360};
rtp_parameters.encodings[2].requested_resolution = {.width = 960, rtp_parameters.encodings[2].scale_resolution_down_to = {.width = 960,
.height = 540}; .height = 540};
send_channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters); send_channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters);

View File

@ -2115,17 +2115,16 @@ TEST_F(PeerConnectionEncodingsIntegrationTest,
ASSERT_TRUE(transceiver_or_error.ok()); ASSERT_TRUE(transceiver_or_error.ok());
} }
TEST_F(PeerConnectionEncodingsIntegrationTest, TEST_F(PeerConnectionEncodingsIntegrationTest, ScaleToParameterChecking) {
RequestedResolutionParameterChecking) {
rtc::scoped_refptr<PeerConnectionTestWrapper> pc_wrapper = CreatePc(); rtc::scoped_refptr<PeerConnectionTestWrapper> pc_wrapper = CreatePc();
// AddTransceiver: If `requested_resolution` is specified on any encoding it // AddTransceiver: If `scale_resolution_down_to` is specified on any encoding
// must be specified on all encodings. // it must be specified on all encodings.
RtpTransceiverInit init; RtpTransceiverInit init;
RtpEncodingParameters encoding; RtpEncodingParameters encoding;
encoding.requested_resolution = std::nullopt; encoding.scale_resolution_down_to = std::nullopt;
init.send_encodings.push_back(encoding); init.send_encodings.push_back(encoding);
encoding.requested_resolution = {.width = 1280, .height = 720}; encoding.scale_resolution_down_to = {.width = 1280, .height = 720};
init.send_encodings.push_back(encoding); init.send_encodings.push_back(encoding);
auto transceiver_or_error = auto transceiver_or_error =
pc_wrapper->pc()->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, init); pc_wrapper->pc()->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, init);
@ -2134,64 +2133,74 @@ TEST_F(PeerConnectionEncodingsIntegrationTest,
RTCErrorType::UNSUPPORTED_OPERATION); RTCErrorType::UNSUPPORTED_OPERATION);
// AddTransceiver: Width and height must not be zero. // AddTransceiver: Width and height must not be zero.
init.send_encodings[0].requested_resolution = {.width = 1280, .height = 0}; init.send_encodings[0].scale_resolution_down_to = {.width = 1280,
init.send_encodings[1].requested_resolution = {.width = 0, .height = 720}; .height = 0};
init.send_encodings[1].scale_resolution_down_to = {.width = 0, .height = 720};
transceiver_or_error = transceiver_or_error =
pc_wrapper->pc()->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, init); pc_wrapper->pc()->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, init);
EXPECT_FALSE(transceiver_or_error.ok()); EXPECT_FALSE(transceiver_or_error.ok());
EXPECT_EQ(transceiver_or_error.error().type(), EXPECT_EQ(transceiver_or_error.error().type(),
RTCErrorType::UNSUPPORTED_OPERATION); RTCErrorType::UNSUPPORTED_OPERATION);
// AddTransceiver: Specifying both `requested_resolution` and // AddTransceiver: Specifying both `scale_resolution_down_to` and
// `scale_resolution_down_by` is allowed (the latter is ignored). // `scale_resolution_down_by` is allowed (the latter is ignored).
init.send_encodings[0].requested_resolution = {.width = 640, .height = 480}; init.send_encodings[0].scale_resolution_down_to = {.width = 640,
.height = 480};
init.send_encodings[0].scale_resolution_down_by = 1.0; init.send_encodings[0].scale_resolution_down_by = 1.0;
init.send_encodings[1].requested_resolution = {.width = 1280, .height = 720}; init.send_encodings[1].scale_resolution_down_to = {.width = 1280,
.height = 720};
init.send_encodings[1].scale_resolution_down_by = 2.0; init.send_encodings[1].scale_resolution_down_by = 2.0;
transceiver_or_error = transceiver_or_error =
pc_wrapper->pc()->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, init); pc_wrapper->pc()->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, init);
ASSERT_TRUE(transceiver_or_error.ok()); ASSERT_TRUE(transceiver_or_error.ok());
// SetParameters: If `requested_resolution` is specified on any active // SetParameters: If `scale_resolution_down_to` is specified on any active
// encoding it must be specified on all active encodings. // encoding it must be specified on all active encodings.
auto sender = transceiver_or_error.value()->sender(); auto sender = transceiver_or_error.value()->sender();
auto parameters = sender->GetParameters(); auto parameters = sender->GetParameters();
parameters.encodings[0].requested_resolution = {.width = 640, .height = 480}; parameters.encodings[0].scale_resolution_down_to = {.width = 640,
parameters.encodings[1].requested_resolution = std::nullopt; .height = 480};
parameters.encodings[1].scale_resolution_down_to = std::nullopt;
auto error = sender->SetParameters(parameters); auto error = sender->SetParameters(parameters);
EXPECT_FALSE(error.ok()); EXPECT_FALSE(error.ok());
EXPECT_EQ(error.type(), RTCErrorType::INVALID_MODIFICATION); EXPECT_EQ(error.type(), RTCErrorType::INVALID_MODIFICATION);
// But it's OK not to specify `requested_resolution` on an inactive encoding. // But it's OK not to specify `scale_resolution_down_to` on an inactive
// encoding.
parameters = sender->GetParameters(); parameters = sender->GetParameters();
parameters.encodings[0].requested_resolution = {.width = 640, .height = 480}; parameters.encodings[0].scale_resolution_down_to = {.width = 640,
.height = 480};
parameters.encodings[1].active = false; parameters.encodings[1].active = false;
parameters.encodings[1].requested_resolution = std::nullopt; parameters.encodings[1].scale_resolution_down_to = std::nullopt;
error = sender->SetParameters(parameters); error = sender->SetParameters(parameters);
EXPECT_TRUE(error.ok()); EXPECT_TRUE(error.ok());
// SetParameters: Width and height must not be zero. // SetParameters: Width and height must not be zero.
sender = transceiver_or_error.value()->sender(); sender = transceiver_or_error.value()->sender();
parameters = sender->GetParameters(); parameters = sender->GetParameters();
parameters.encodings[0].requested_resolution = {.width = 1280, .height = 0}; parameters.encodings[0].scale_resolution_down_to = {.width = 1280,
.height = 0};
parameters.encodings[1].active = true; parameters.encodings[1].active = true;
parameters.encodings[1].requested_resolution = {.width = 0, .height = 720}; parameters.encodings[1].scale_resolution_down_to = {.width = 0,
.height = 720};
error = sender->SetParameters(parameters); error = sender->SetParameters(parameters);
EXPECT_FALSE(error.ok()); EXPECT_FALSE(error.ok());
EXPECT_EQ(error.type(), RTCErrorType::INVALID_MODIFICATION); EXPECT_EQ(error.type(), RTCErrorType::INVALID_MODIFICATION);
// SetParameters: Specifying both `requested_resolution` and // SetParameters: Specifying both `scale_resolution_down_to` and
// `scale_resolution_down_by` is allowed (the latter is ignored). // `scale_resolution_down_by` is allowed (the latter is ignored).
parameters = sender->GetParameters(); parameters = sender->GetParameters();
parameters.encodings[0].requested_resolution = {.width = 640, .height = 480}; parameters.encodings[0].scale_resolution_down_to = {.width = 640,
.height = 480};
parameters.encodings[0].scale_resolution_down_by = 2.0; parameters.encodings[0].scale_resolution_down_by = 2.0;
parameters.encodings[1].requested_resolution = {.width = 1280, .height = 720}; parameters.encodings[1].scale_resolution_down_to = {.width = 1280,
.height = 720};
parameters.encodings[1].scale_resolution_down_by = 1.0; parameters.encodings[1].scale_resolution_down_by = 1.0;
error = sender->SetParameters(parameters); error = sender->SetParameters(parameters);
EXPECT_TRUE(error.ok()); EXPECT_TRUE(error.ok());
} }
TEST_F(PeerConnectionEncodingsIntegrationTest, TEST_F(PeerConnectionEncodingsIntegrationTest,
ScaleResolutionDownByIsIgnoredWhenRequestedResolutionIsSpecified) { ScaleResolutionDownByIsIgnoredWhenScaleToIsSpecified) {
rtc::scoped_refptr<PeerConnectionTestWrapper> local_pc_wrapper = CreatePc(); rtc::scoped_refptr<PeerConnectionTestWrapper> local_pc_wrapper = CreatePc();
rtc::scoped_refptr<PeerConnectionTestWrapper> remote_pc_wrapper = CreatePc(); rtc::scoped_refptr<PeerConnectionTestWrapper> remote_pc_wrapper = CreatePc();
@ -2204,7 +2213,7 @@ TEST_F(PeerConnectionEncodingsIntegrationTest,
RtpTransceiverInit init; RtpTransceiverInit init;
RtpEncodingParameters encoding; RtpEncodingParameters encoding;
encoding.scale_resolution_down_by = 2.0; encoding.scale_resolution_down_by = 2.0;
encoding.requested_resolution = {.width = 640, .height = 360}; encoding.scale_resolution_down_to = {.width = 640, .height = 360};
init.send_encodings.push_back(encoding); init.send_encodings.push_back(encoding);
auto transceiver_or_error = auto transceiver_or_error =
local_pc_wrapper->pc()->AddTransceiver(track, init); local_pc_wrapper->pc()->AddTransceiver(track, init);
@ -2222,7 +2231,7 @@ TEST_F(PeerConnectionEncodingsIntegrationTest,
} }
// Tests that use the standard path (specifying both `scalability_mode` and // Tests that use the standard path (specifying both `scalability_mode` and
// `scale_resolution_down_by` or `requested_resolution`) should pass for all // `scale_resolution_down_by` or `scale_resolution_down_to`) should pass for all
// codecs. // codecs.
class PeerConnectionEncodingsIntegrationParameterizedTest class PeerConnectionEncodingsIntegrationParameterizedTest
: public PeerConnectionEncodingsIntegrationTest, : public PeerConnectionEncodingsIntegrationTest,
@ -2358,9 +2367,9 @@ TEST_P(PeerConnectionEncodingsIntegrationParameterizedTest, Simulcast) {
EXPECT_THAT(*outbound_rtps[2]->scalability_mode, StrEq("L1T3")); EXPECT_THAT(*outbound_rtps[2]->scalability_mode, StrEq("L1T3"));
} }
// Configure 4:2:1 using `requested_resolution`. // Configure 4:2:1 using `scale_resolution_down_to`.
TEST_P(PeerConnectionEncodingsIntegrationParameterizedTest, TEST_P(PeerConnectionEncodingsIntegrationParameterizedTest,
SimulcastWithRequestedResolution) { SimulcastWithScaleTo) {
rtc::scoped_refptr<PeerConnectionTestWrapper> local_pc_wrapper = CreatePc(); rtc::scoped_refptr<PeerConnectionTestWrapper> local_pc_wrapper = CreatePc();
if (SkipTestDueToAv1Missing(local_pc_wrapper)) { if (SkipTestDueToAv1Missing(local_pc_wrapper)) {
return; return;
@ -2381,11 +2390,14 @@ TEST_P(PeerConnectionEncodingsIntegrationParameterizedTest,
RtpParameters parameters = sender->GetParameters(); RtpParameters parameters = sender->GetParameters();
ASSERT_THAT(parameters.encodings, SizeIs(3)); ASSERT_THAT(parameters.encodings, SizeIs(3));
parameters.encodings[0].scalability_mode = "L1T3"; parameters.encodings[0].scalability_mode = "L1T3";
parameters.encodings[0].requested_resolution = {.width = 320, .height = 180}; parameters.encodings[0].scale_resolution_down_to = {.width = 320,
.height = 180};
parameters.encodings[1].scalability_mode = "L1T3"; parameters.encodings[1].scalability_mode = "L1T3";
parameters.encodings[1].requested_resolution = {.width = 640, .height = 360}; parameters.encodings[1].scale_resolution_down_to = {.width = 640,
.height = 360};
parameters.encodings[2].scalability_mode = "L1T3"; parameters.encodings[2].scalability_mode = "L1T3";
parameters.encodings[2].requested_resolution = {.width = 1280, .height = 720}; parameters.encodings[2].scale_resolution_down_to = {.width = 1280,
.height = 720};
sender->SetParameters(parameters); sender->SetParameters(parameters);
NegotiateWithSimulcastTweaks(local_pc_wrapper, remote_pc_wrapper); NegotiateWithSimulcastTweaks(local_pc_wrapper, remote_pc_wrapper);
@ -2501,9 +2513,9 @@ TEST_P(PeerConnectionEncodingsIntegrationParameterizedTest,
} }
// Simulcast starting in 720p 4:2:1 then changing to {180p, 360p, 540p} using // Simulcast starting in 720p 4:2:1 then changing to {180p, 360p, 540p} using
// the `requested_resolution` API. // the `scale_resolution_down_to` API.
TEST_P(PeerConnectionEncodingsIntegrationParameterizedTest, TEST_P(PeerConnectionEncodingsIntegrationParameterizedTest,
SimulcastRequestedResolutionNoLongerPowerOfTwo) { SimulcastScaleToNoLongerPowerOfTwo) {
rtc::scoped_refptr<PeerConnectionTestWrapper> local_pc_wrapper = CreatePc(); rtc::scoped_refptr<PeerConnectionTestWrapper> local_pc_wrapper = CreatePc();
if (SkipTestDueToAv1Missing(local_pc_wrapper)) { if (SkipTestDueToAv1Missing(local_pc_wrapper)) {
return; return;
@ -2525,11 +2537,14 @@ TEST_P(PeerConnectionEncodingsIntegrationParameterizedTest,
RtpParameters parameters = sender->GetParameters(); RtpParameters parameters = sender->GetParameters();
ASSERT_THAT(parameters.encodings, SizeIs(3)); ASSERT_THAT(parameters.encodings, SizeIs(3));
parameters.encodings[0].scalability_mode = "L1T1"; parameters.encodings[0].scalability_mode = "L1T1";
parameters.encodings[0].requested_resolution = {.width = 320, .height = 180}; parameters.encodings[0].scale_resolution_down_to = {.width = 320,
.height = 180};
parameters.encodings[1].scalability_mode = "L1T1"; parameters.encodings[1].scalability_mode = "L1T1";
parameters.encodings[1].requested_resolution = {.width = 640, .height = 360}; parameters.encodings[1].scale_resolution_down_to = {.width = 640,
.height = 360};
parameters.encodings[2].scalability_mode = "L1T1"; parameters.encodings[2].scalability_mode = "L1T1";
parameters.encodings[2].requested_resolution = {.width = 1280, .height = 720}; parameters.encodings[2].scale_resolution_down_to = {.width = 1280,
.height = 720};
sender->SetParameters(parameters); sender->SetParameters(parameters);
NegotiateWithSimulcastTweaks(local_pc_wrapper, remote_pc_wrapper); NegotiateWithSimulcastTweaks(local_pc_wrapper, remote_pc_wrapper);
@ -2548,9 +2563,12 @@ TEST_P(PeerConnectionEncodingsIntegrationParameterizedTest,
// Configure {180p, 360p, 540p}. // Configure {180p, 360p, 540p}.
parameters = sender->GetParameters(); parameters = sender->GetParameters();
parameters.encodings[0].requested_resolution = {.width = 320, .height = 180}; parameters.encodings[0].scale_resolution_down_to = {.width = 320,
parameters.encodings[1].requested_resolution = {.width = 640, .height = 360}; .height = 180};
parameters.encodings[2].requested_resolution = {.width = 960, .height = 540}; parameters.encodings[1].scale_resolution_down_to = {.width = 640,
.height = 360};
parameters.encodings[2].scale_resolution_down_to = {.width = 960,
.height = 540};
sender->SetParameters(parameters); sender->SetParameters(parameters);
// Wait for the new resolutions to be produced. // Wait for the new resolutions to be produced.
@ -2577,11 +2595,11 @@ TEST_P(PeerConnectionEncodingsIntegrationParameterizedTest,
} }
// The code path that disables layers based on resolution size should NOT run // The code path that disables layers based on resolution size should NOT run
// when `requested_resolution` is specified. (It shouldn't run in any case but // when `scale_resolution_down_to` is specified. (It shouldn't run in any case
// that is an existing legacy code and non-compliance problem that we don't have // but that is an existing legacy code and non-compliance problem that we don't
// to repeat here.) // have to repeat here.)
TEST_P(PeerConnectionEncodingsIntegrationParameterizedTest, TEST_P(PeerConnectionEncodingsIntegrationParameterizedTest,
LowResolutionSimulcastWithRequestedResolution) { LowResolutionSimulcastWithScaleTo) {
rtc::scoped_refptr<PeerConnectionTestWrapper> local_pc_wrapper = CreatePc(); rtc::scoped_refptr<PeerConnectionTestWrapper> local_pc_wrapper = CreatePc();
if (SkipTestDueToAv1Missing(local_pc_wrapper)) { if (SkipTestDueToAv1Missing(local_pc_wrapper)) {
return; return;
@ -2597,13 +2615,13 @@ TEST_P(PeerConnectionEncodingsIntegrationParameterizedTest,
RtpEncodingParameters encoding; RtpEncodingParameters encoding;
encoding.scalability_mode = "L1T3"; encoding.scalability_mode = "L1T3";
encoding.rid = "q"; encoding.rid = "q";
encoding.requested_resolution = {.width = 40, .height = 20}; encoding.scale_resolution_down_to = {.width = 40, .height = 20};
init.send_encodings.push_back(encoding); init.send_encodings.push_back(encoding);
encoding.rid = "h"; encoding.rid = "h";
encoding.requested_resolution = {.width = 80, .height = 40}; encoding.scale_resolution_down_to = {.width = 80, .height = 40};
init.send_encodings.push_back(encoding); init.send_encodings.push_back(encoding);
encoding.rid = "f"; encoding.rid = "f";
encoding.requested_resolution = {.width = 160, .height = 80}; encoding.scale_resolution_down_to = {.width = 160, .height = 80};
init.send_encodings.push_back(encoding); init.send_encodings.push_back(encoding);
rtc::scoped_refptr<MediaStreamInterface> stream = rtc::scoped_refptr<MediaStreamInterface> stream =
local_pc_wrapper->GetUserMedia( local_pc_wrapper->GetUserMedia(
@ -2698,7 +2716,7 @@ TEST_P(PeerConnectionEncodingsIntegrationParameterizedTest,
} }
TEST_P(PeerConnectionEncodingsIntegrationParameterizedTest, TEST_P(PeerConnectionEncodingsIntegrationParameterizedTest,
RequestedResolutionDownscaleAndThenUpscale) { ScaleToDownscaleAndThenUpscale) {
rtc::scoped_refptr<PeerConnectionTestWrapper> local_pc_wrapper = CreatePc(); rtc::scoped_refptr<PeerConnectionTestWrapper> local_pc_wrapper = CreatePc();
if (SkipTestDueToAv1Missing(local_pc_wrapper)) { if (SkipTestDueToAv1Missing(local_pc_wrapper)) {
return; return;
@ -2726,7 +2744,8 @@ TEST_P(PeerConnectionEncodingsIntegrationParameterizedTest,
RtpParameters parameters = sender->GetParameters(); RtpParameters parameters = sender->GetParameters();
ASSERT_THAT(parameters.encodings, SizeIs(1)); ASSERT_THAT(parameters.encodings, SizeIs(1));
parameters.encodings[0].scalability_mode = "L1T3"; parameters.encodings[0].scalability_mode = "L1T3";
parameters.encodings[0].requested_resolution = {.width = 640, .height = 360}; parameters.encodings[0].scale_resolution_down_to = {.width = 640,
.height = 360};
sender->SetParameters(parameters); sender->SetParameters(parameters);
// Confirm 640x360 is sent. // Confirm 640x360 is sent.
ASSERT_TRUE_WAIT(GetEncodingResolution(local_pc_wrapper) == ASSERT_TRUE_WAIT(GetEncodingResolution(local_pc_wrapper) ==
@ -2744,7 +2763,8 @@ TEST_P(PeerConnectionEncodingsIntegrationParameterizedTest,
// Request the full 1280x720 resolution. // Request the full 1280x720 resolution.
parameters = sender->GetParameters(); parameters = sender->GetParameters();
parameters.encodings[0].requested_resolution = {.width = 1280, .height = 720}; parameters.encodings[0].scale_resolution_down_to = {.width = 1280,
.height = 720};
sender->SetParameters(parameters); sender->SetParameters(parameters);
// Confirm 1280x720 is sent. // Confirm 1280x720 is sent.
ASSERT_TRUE_WAIT(GetEncodingResolution(local_pc_wrapper) == ASSERT_TRUE_WAIT(GetEncodingResolution(local_pc_wrapper) ==
@ -2753,7 +2773,7 @@ TEST_P(PeerConnectionEncodingsIntegrationParameterizedTest,
} }
TEST_P(PeerConnectionEncodingsIntegrationParameterizedTest, TEST_P(PeerConnectionEncodingsIntegrationParameterizedTest,
RequestedResolutionIsOrientationAgnostic) { ScaleToIsOrientationAgnostic) {
rtc::scoped_refptr<PeerConnectionTestWrapper> local_pc_wrapper = CreatePc(); rtc::scoped_refptr<PeerConnectionTestWrapper> local_pc_wrapper = CreatePc();
if (SkipTestDueToAv1Missing(local_pc_wrapper)) { if (SkipTestDueToAv1Missing(local_pc_wrapper)) {
return; return;
@ -2781,7 +2801,8 @@ TEST_P(PeerConnectionEncodingsIntegrationParameterizedTest,
rtc::scoped_refptr<RtpSenderInterface> sender = transceiver->sender(); rtc::scoped_refptr<RtpSenderInterface> sender = transceiver->sender();
RtpParameters parameters = sender->GetParameters(); RtpParameters parameters = sender->GetParameters();
ASSERT_THAT(parameters.encodings, SizeIs(1)); ASSERT_THAT(parameters.encodings, SizeIs(1));
parameters.encodings[0].requested_resolution = {.width = 360, .height = 640}; parameters.encodings[0].scale_resolution_down_to = {.width = 360,
.height = 640};
sender->SetParameters(parameters); sender->SetParameters(parameters);
// Confirm 640x360 is sent. // Confirm 640x360 is sent.
ASSERT_TRUE_WAIT(GetEncodingResolution(local_pc_wrapper) == ASSERT_TRUE_WAIT(GetEncodingResolution(local_pc_wrapper) ==
@ -2790,7 +2811,7 @@ TEST_P(PeerConnectionEncodingsIntegrationParameterizedTest,
} }
TEST_P(PeerConnectionEncodingsIntegrationParameterizedTest, TEST_P(PeerConnectionEncodingsIntegrationParameterizedTest,
RequestedResolutionMaintainsAspectRatio) { ScaleToMaintainsAspectRatio) {
rtc::scoped_refptr<PeerConnectionTestWrapper> local_pc_wrapper = CreatePc(); rtc::scoped_refptr<PeerConnectionTestWrapper> local_pc_wrapper = CreatePc();
if (SkipTestDueToAv1Missing(local_pc_wrapper)) { if (SkipTestDueToAv1Missing(local_pc_wrapper)) {
return; return;
@ -2818,7 +2839,8 @@ TEST_P(PeerConnectionEncodingsIntegrationParameterizedTest,
rtc::scoped_refptr<RtpSenderInterface> sender = transceiver->sender(); rtc::scoped_refptr<RtpSenderInterface> sender = transceiver->sender();
RtpParameters parameters = sender->GetParameters(); RtpParameters parameters = sender->GetParameters();
ASSERT_THAT(parameters.encodings, SizeIs(1)); ASSERT_THAT(parameters.encodings, SizeIs(1));
parameters.encodings[0].requested_resolution = {.width = 1280, .height = 360}; parameters.encodings[0].scale_resolution_down_to = {.width = 1280,
.height = 360};
sender->SetParameters(parameters); sender->SetParameters(parameters);
// Confirm 640x360 is sent. // Confirm 640x360 is sent.
ASSERT_TRUE_WAIT(GetEncodingResolution(local_pc_wrapper) == ASSERT_TRUE_WAIT(GetEncodingResolution(local_pc_wrapper) ==

View File

@ -150,7 +150,7 @@ void OverrideStreamSettings(
webrtc::VideoStream& layer = layers[i]; webrtc::VideoStream& layer = layers[i];
layer.active = overrides.active; layer.active = overrides.active;
layer.scalability_mode = overrides.scalability_mode; layer.scalability_mode = overrides.scalability_mode;
layer.requested_resolution = overrides.requested_resolution; layer.scale_resolution_down_to = overrides.scale_resolution_down_to;
// Update with configured num temporal layers if supported by codec. // Update with configured num temporal layers if supported by codec.
if (overrides.num_temporal_layers > 0 && temporal_layers_supported) { if (overrides.num_temporal_layers > 0 && temporal_layers_supported) {
layer.num_temporal_layers = *overrides.num_temporal_layers; layer.num_temporal_layers = *overrides.num_temporal_layers;
@ -352,18 +352,18 @@ EncoderStreamFactory::CreateDefaultVideoStreams(
layer.width = width; layer.width = width;
layer.height = height; layer.height = height;
layer.max_framerate = max_framerate; layer.max_framerate = max_framerate;
layer.requested_resolution = layer.scale_resolution_down_to =
encoder_config.simulcast_layers[0].requested_resolution; encoder_config.simulcast_layers[0].scale_resolution_down_to;
// Note: VP9 seems to have be sending if any layer is active, // Note: VP9 seems to have be sending if any layer is active,
// (see `UpdateSendState`) and still use parameters only from // (see `UpdateSendState`) and still use parameters only from
// encoder_config.simulcast_layers[0]. // encoder_config.simulcast_layers[0].
layer.active = absl::c_any_of(encoder_config.simulcast_layers, layer.active = absl::c_any_of(encoder_config.simulcast_layers,
[](const auto& layer) { return layer.active; }); [](const auto& layer) { return layer.active; });
if (encoder_config.simulcast_layers[0].requested_resolution) { if (encoder_config.simulcast_layers[0].scale_resolution_down_to) {
auto res = GetLayerResolutionFromRequestedResolution( auto res = GetLayerResolutionFromScaleResolutionDownTo(
width, height, width, height,
*encoder_config.simulcast_layers[0].requested_resolution); *encoder_config.simulcast_layers[0].scale_resolution_down_to);
layer.width = res.width; layer.width = res.width;
layer.height = res.height; layer.height = res.height;
} else if (encoder_config.simulcast_layers[0].scale_resolution_down_by > 1.) { } else if (encoder_config.simulcast_layers[0].scale_resolution_down_by > 1.) {
@ -468,23 +468,23 @@ EncoderStreamFactory::CreateSimulcastOrConferenceModeScreenshareStreams(
} }
webrtc::Resolution webrtc::Resolution
EncoderStreamFactory::GetLayerResolutionFromRequestedResolution( EncoderStreamFactory::GetLayerResolutionFromScaleResolutionDownTo(
int frame_width, int frame_width,
int frame_height, int frame_height,
webrtc::Resolution requested_resolution) const { webrtc::Resolution scale_resolution_down_to) const {
// Make frame and requested resolution have matching orientation. // Make frame and `scale_resolution_down_to` have matching orientation.
if ((frame_width < frame_height) != if ((frame_width < frame_height) !=
(requested_resolution.width < requested_resolution.height)) { (scale_resolution_down_to.width < scale_resolution_down_to.height)) {
requested_resolution = {.width = requested_resolution.height, scale_resolution_down_to = {.width = scale_resolution_down_to.height,
.height = requested_resolution.width}; .height = scale_resolution_down_to.width};
} }
// Downscale by smallest scaling factor, if necessary. // Downscale by smallest scaling factor, if necessary.
if (frame_width > 0 && frame_height > 0 && if (frame_width > 0 && frame_height > 0 &&
(requested_resolution.width < frame_width || (scale_resolution_down_to.width < frame_width ||
requested_resolution.height < frame_height)) { scale_resolution_down_to.height < frame_height)) {
double scale_factor = std::min( double scale_factor = std::min(
requested_resolution.width / static_cast<double>(frame_width), scale_resolution_down_to.width / static_cast<double>(frame_width),
requested_resolution.height / static_cast<double>(frame_height)); scale_resolution_down_to.height / static_cast<double>(frame_height));
frame_width = std::round(frame_width * scale_factor); frame_width = std::round(frame_width * scale_factor);
frame_height = std::round(frame_height * scale_factor); frame_height = std::round(frame_height * scale_factor);
} }
@ -528,33 +528,34 @@ std::vector<webrtc::Resolution> EncoderStreamFactory::GetStreamResolutions(
} else { } else {
size_t min_num_layers = FindRequiredActiveLayers(encoder_config); size_t min_num_layers = FindRequiredActiveLayers(encoder_config);
size_t max_num_layers = size_t max_num_layers =
!encoder_config.HasRequestedResolution() !encoder_config.HasScaleResolutionDownTo()
? LimitSimulcastLayerCount( ? LimitSimulcastLayerCount(
min_num_layers, encoder_config.number_of_streams, width, min_num_layers, encoder_config.number_of_streams, width,
height, trials, encoder_config.codec_type) height, trials, encoder_config.codec_type)
: encoder_config.number_of_streams; : encoder_config.number_of_streams;
RTC_DCHECK_LE(max_num_layers, encoder_config.number_of_streams); RTC_DCHECK_LE(max_num_layers, encoder_config.number_of_streams);
// When the `requested_resolution` API is used, disable upper layers that // When the `scale_resolution_down_to` API is used, disable upper layers
// are bigger than what adaptation restrictions allow. For example if // that are bigger than what adaptation restrictions allow. For example if
// restrictions are 540p, simulcast 180p:360p:720p becomes 180p:360p:- as // restrictions are 540p, simulcast 180p:360p:720p becomes 180p:360p:- as
// opposed to 180p:360p:540p. This makes CPU adaptation consistent with BW // opposed to 180p:360p:540p. This makes CPU adaptation consistent with BW
// adaptation (bitrate allocator disabling layers rather than downscaling) // adaptation (bitrate allocator disabling layers rather than downscaling)
// and means we don't have to break power of two optimization paths (i.e. // and means we don't have to break power of two optimization paths (i.e.
// S-modes based simulcast). Note that the lowest layer is never disabled. // S-modes based simulcast). Note that the lowest layer is never disabled.
if (encoder_config.HasRequestedResolution() && restrictions_.has_value() && if (encoder_config.HasScaleResolutionDownTo() &&
restrictions_.has_value() &&
restrictions_->max_pixels_per_frame().has_value()) { restrictions_->max_pixels_per_frame().has_value()) {
int max_pixels = rtc::dchecked_cast<int>( int max_pixels = rtc::dchecked_cast<int>(
restrictions_->max_pixels_per_frame().value()); restrictions_->max_pixels_per_frame().value());
int prev_pixel_count = int prev_pixel_count =
encoder_config.simulcast_layers[0] encoder_config.simulcast_layers[0]
.requested_resolution.value_or(webrtc::Resolution()) .scale_resolution_down_to.value_or(webrtc::Resolution())
.PixelCount(); .PixelCount();
std::optional<size_t> restricted_num_layers; std::optional<size_t> restricted_num_layers;
for (size_t i = 1; i < max_num_layers; ++i) { for (size_t i = 1; i < max_num_layers; ++i) {
int pixel_count = int pixel_count =
encoder_config.simulcast_layers[i] encoder_config.simulcast_layers[i]
.requested_resolution.value_or(webrtc::Resolution()) .scale_resolution_down_to.value_or(webrtc::Resolution())
.PixelCount(); .PixelCount();
if (!restricted_num_layers.has_value() && max_pixels < pixel_count) { if (!restricted_num_layers.has_value() && max_pixels < pixel_count) {
// Current layer is the highest layer allowed by restrictions. // Current layer is the highest layer allowed by restrictions.
@ -596,10 +597,11 @@ std::vector<webrtc::Resolution> EncoderStreamFactory::GetStreamResolutions(
resolutions.resize(max_num_layers); resolutions.resize(max_num_layers);
for (size_t i = 0; i < max_num_layers; i++) { for (size_t i = 0; i < max_num_layers; i++) {
if (encoder_config.simulcast_layers[i].requested_resolution.has_value()) { if (encoder_config.simulcast_layers[i]
resolutions[i] = GetLayerResolutionFromRequestedResolution( .scale_resolution_down_to.has_value()) {
resolutions[i] = GetLayerResolutionFromScaleResolutionDownTo(
normalized_width, normalized_height, normalized_width, normalized_height,
*encoder_config.simulcast_layers[i].requested_resolution); *encoder_config.simulcast_layers[i].scale_resolution_down_to);
} else if (has_scale_resolution_down_by) { } else 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);

View File

@ -49,10 +49,10 @@ class EncoderStreamFactory
const webrtc::VideoEncoderConfig& encoder_config, const webrtc::VideoEncoderConfig& encoder_config,
const std::optional<webrtc::DataRate>& experimental_min_bitrate) const; const std::optional<webrtc::DataRate>& experimental_min_bitrate) const;
webrtc::Resolution GetLayerResolutionFromRequestedResolution( webrtc::Resolution GetLayerResolutionFromScaleResolutionDownTo(
int in_frame_width, int in_frame_width,
int in_frame_height, int in_frame_height,
webrtc::Resolution requested_resolution) const; webrtc::Resolution scale_resolution_down_to) const;
std::vector<webrtc::Resolution> GetStreamResolutions( std::vector<webrtc::Resolution> GetStreamResolutions(
const webrtc::FieldTrialsView& trials, const webrtc::FieldTrialsView& trials,

View File

@ -79,23 +79,23 @@ std::vector<VideoStream> CreateEncoderStreams(
} // namespace } // namespace
TEST(EncoderStreamFactory, SinglecastRequestedResolution) { TEST(EncoderStreamFactory, SinglecastScaleResolutionDownTo) {
ExplicitKeyValueConfig field_trials(""); ExplicitKeyValueConfig field_trials("");
VideoEncoderConfig encoder_config; VideoEncoderConfig encoder_config;
encoder_config.number_of_streams = 1; encoder_config.number_of_streams = 1;
encoder_config.simulcast_layers.resize(1); encoder_config.simulcast_layers.resize(1);
encoder_config.simulcast_layers[0].requested_resolution = {.width = 640, encoder_config.simulcast_layers[0].scale_resolution_down_to = {.width = 640,
.height = 360}; .height = 360};
auto streams = CreateEncoderStreams( auto streams = CreateEncoderStreams(
field_trials, {.width = 1280, .height = 720}, encoder_config); field_trials, {.width = 1280, .height = 720}, encoder_config);
EXPECT_EQ(streams[0].requested_resolution, EXPECT_EQ(streams[0].scale_resolution_down_to,
(Resolution{.width = 640, .height = 360})); (Resolution{.width = 640, .height = 360}));
EXPECT_EQ(GetStreamResolutions(streams), (std::vector<Resolution>{ EXPECT_EQ(GetStreamResolutions(streams), (std::vector<Resolution>{
{.width = 640, .height = 360}, {.width = 640, .height = 360},
})); }));
} }
TEST(EncoderStreamFactory, SinglecastRequestedResolutionWithAdaptation) { TEST(EncoderStreamFactory, SinglecastScaleResolutionDownToWithAdaptation) {
ExplicitKeyValueConfig field_trials(""); ExplicitKeyValueConfig field_trials("");
VideoSourceRestrictions restrictions( VideoSourceRestrictions restrictions(
/* max_pixels_per_frame= */ (320 * 320), /* max_pixels_per_frame= */ (320 * 320),
@ -104,28 +104,28 @@ TEST(EncoderStreamFactory, SinglecastRequestedResolutionWithAdaptation) {
VideoEncoderConfig encoder_config; VideoEncoderConfig encoder_config;
encoder_config.number_of_streams = 1; encoder_config.number_of_streams = 1;
encoder_config.simulcast_layers.resize(1); encoder_config.simulcast_layers.resize(1);
encoder_config.simulcast_layers[0].requested_resolution = {.width = 640, encoder_config.simulcast_layers[0].scale_resolution_down_to = {.width = 640,
.height = 360}; .height = 360};
auto streams = auto streams =
CreateEncoderStreams(field_trials, {.width = 1280, .height = 720}, CreateEncoderStreams(field_trials, {.width = 1280, .height = 720},
encoder_config, restrictions); encoder_config, restrictions);
EXPECT_EQ(streams[0].requested_resolution, EXPECT_EQ(streams[0].scale_resolution_down_to,
(Resolution{.width = 640, .height = 360})); (Resolution{.width = 640, .height = 360}));
EXPECT_EQ(GetStreamResolutions(streams), (std::vector<Resolution>{ EXPECT_EQ(GetStreamResolutions(streams), (std::vector<Resolution>{
{.width = 320, .height = 180}, {.width = 320, .height = 180},
})); }));
} }
TEST(EncoderStreamFactory, SimulcastRequestedResolutionUnrestricted) { TEST(EncoderStreamFactory, SimulcastScaleResolutionDownToUnrestricted) {
ExplicitKeyValueConfig field_trials(""); ExplicitKeyValueConfig field_trials("");
VideoEncoderConfig encoder_config; VideoEncoderConfig encoder_config;
encoder_config.number_of_streams = 3; encoder_config.number_of_streams = 3;
encoder_config.simulcast_layers.resize(3); encoder_config.simulcast_layers.resize(3);
encoder_config.simulcast_layers[0].requested_resolution = {.width = 320, encoder_config.simulcast_layers[0].scale_resolution_down_to = {.width = 320,
.height = 180}; .height = 180};
encoder_config.simulcast_layers[1].requested_resolution = {.width = 640, encoder_config.simulcast_layers[1].scale_resolution_down_to = {.width = 640,
.height = 360}; .height = 360};
encoder_config.simulcast_layers[2].requested_resolution = {.width = 1280, encoder_config.simulcast_layers[2].scale_resolution_down_to = {.width = 1280,
.height = 720}; .height = 720};
auto streams = CreateEncoderStreams( auto streams = CreateEncoderStreams(
field_trials, {.width = 1280, .height = 720}, encoder_config); field_trials, {.width = 1280, .height = 720}, encoder_config);
@ -136,7 +136,7 @@ TEST(EncoderStreamFactory, SimulcastRequestedResolutionUnrestricted) {
EXPECT_EQ(stream_resolutions[2], (Resolution{.width = 1280, .height = 720})); EXPECT_EQ(stream_resolutions[2], (Resolution{.width = 1280, .height = 720}));
} }
TEST(EncoderStreamFactory, SimulcastRequestedResolutionWith360pRestriction) { TEST(EncoderStreamFactory, SimulcastScaleResolutionDownToWith360pRestriction) {
ExplicitKeyValueConfig field_trials(""); ExplicitKeyValueConfig field_trials("");
VideoSourceRestrictions restrictions( VideoSourceRestrictions restrictions(
/* max_pixels_per_frame= */ (640 * 360), /* max_pixels_per_frame= */ (640 * 360),
@ -145,11 +145,11 @@ TEST(EncoderStreamFactory, SimulcastRequestedResolutionWith360pRestriction) {
VideoEncoderConfig encoder_config; VideoEncoderConfig encoder_config;
encoder_config.number_of_streams = 3; encoder_config.number_of_streams = 3;
encoder_config.simulcast_layers.resize(3); encoder_config.simulcast_layers.resize(3);
encoder_config.simulcast_layers[0].requested_resolution = {.width = 320, encoder_config.simulcast_layers[0].scale_resolution_down_to = {.width = 320,
.height = 180}; .height = 180};
encoder_config.simulcast_layers[1].requested_resolution = {.width = 640, encoder_config.simulcast_layers[1].scale_resolution_down_to = {.width = 640,
.height = 360}; .height = 360};
encoder_config.simulcast_layers[2].requested_resolution = {.width = 1280, encoder_config.simulcast_layers[2].scale_resolution_down_to = {.width = 1280,
.height = 720}; .height = 720};
auto streams = auto streams =
CreateEncoderStreams(field_trials, {.width = 1280, .height = 720}, CreateEncoderStreams(field_trials, {.width = 1280, .height = 720},
@ -161,7 +161,7 @@ TEST(EncoderStreamFactory, SimulcastRequestedResolutionWith360pRestriction) {
EXPECT_EQ(stream_resolutions[1], (Resolution{.width = 640, .height = 360})); EXPECT_EQ(stream_resolutions[1], (Resolution{.width = 640, .height = 360}));
} }
TEST(EncoderStreamFactory, SimulcastRequestedResolutionWith90pRestriction) { TEST(EncoderStreamFactory, SimulcastScaleResolutionDownToWith90pRestriction) {
ExplicitKeyValueConfig field_trials(""); ExplicitKeyValueConfig field_trials("");
VideoSourceRestrictions restrictions( VideoSourceRestrictions restrictions(
/* max_pixels_per_frame= */ (160 * 90), /* max_pixels_per_frame= */ (160 * 90),
@ -170,11 +170,11 @@ TEST(EncoderStreamFactory, SimulcastRequestedResolutionWith90pRestriction) {
VideoEncoderConfig encoder_config; VideoEncoderConfig encoder_config;
encoder_config.number_of_streams = 3; encoder_config.number_of_streams = 3;
encoder_config.simulcast_layers.resize(3); encoder_config.simulcast_layers.resize(3);
encoder_config.simulcast_layers[0].requested_resolution = {.width = 320, encoder_config.simulcast_layers[0].scale_resolution_down_to = {.width = 320,
.height = 180}; .height = 180};
encoder_config.simulcast_layers[1].requested_resolution = {.width = 640, encoder_config.simulcast_layers[1].scale_resolution_down_to = {.width = 640,
.height = 360}; .height = 360};
encoder_config.simulcast_layers[2].requested_resolution = {.width = 1280, encoder_config.simulcast_layers[2].scale_resolution_down_to = {.width = 1280,
.height = 720}; .height = 720};
auto streams = auto streams =
CreateEncoderStreams(field_trials, {.width = 1280, .height = 720}, CreateEncoderStreams(field_trials, {.width = 1280, .height = 720},
@ -186,7 +186,8 @@ TEST(EncoderStreamFactory, SimulcastRequestedResolutionWith90pRestriction) {
EXPECT_EQ(stream_resolutions[0], (Resolution{.width = 160, .height = 90})); EXPECT_EQ(stream_resolutions[0], (Resolution{.width = 160, .height = 90}));
} }
TEST(EncoderStreamFactory, ReverseSimulcastRequestedResolutionWithRestriction) { TEST(EncoderStreamFactory,
ReverseSimulcastScaleResolutionDownToWithRestriction) {
ExplicitKeyValueConfig field_trials(""); ExplicitKeyValueConfig field_trials("");
VideoSourceRestrictions restrictions( VideoSourceRestrictions restrictions(
/* max_pixels_per_frame= */ (640 * 360), /* max_pixels_per_frame= */ (640 * 360),
@ -196,11 +197,11 @@ TEST(EncoderStreamFactory, ReverseSimulcastRequestedResolutionWithRestriction) {
encoder_config.number_of_streams = 3; encoder_config.number_of_streams = 3;
encoder_config.simulcast_layers.resize(3); encoder_config.simulcast_layers.resize(3);
// 720p, 360p, 180p (instead of the usual 180p, 360p, 720p). // 720p, 360p, 180p (instead of the usual 180p, 360p, 720p).
encoder_config.simulcast_layers[0].requested_resolution = {.width = 1280, encoder_config.simulcast_layers[0].scale_resolution_down_to = {.width = 1280,
.height = 720}; .height = 720};
encoder_config.simulcast_layers[1].requested_resolution = {.width = 640, encoder_config.simulcast_layers[1].scale_resolution_down_to = {.width = 640,
.height = 360}; .height = 360};
encoder_config.simulcast_layers[2].requested_resolution = {.width = 320, encoder_config.simulcast_layers[2].scale_resolution_down_to = {.width = 320,
.height = 180}; .height = 180};
auto streams = auto streams =
CreateEncoderStreams(field_trials, {.width = 1280, .height = 720}, CreateEncoderStreams(field_trials, {.width = 1280, .height = 720},

View File

@ -88,9 +88,9 @@ std::string VideoEncoderConfig::ToString() const {
return ss.str(); return ss.str();
} }
bool VideoEncoderConfig::HasRequestedResolution() const { bool VideoEncoderConfig::HasScaleResolutionDownTo() const {
for (const VideoStream& simulcast_layer : simulcast_layers) { for (const VideoStream& simulcast_layer : simulcast_layers) {
if (simulcast_layer.requested_resolution.has_value()) { if (simulcast_layer.scale_resolution_down_to.has_value()) {
return true; return true;
} }
} }

View File

@ -36,7 +36,7 @@ struct VideoStream {
// Width/Height in pixels. // Width/Height in pixels.
// This is the actual width and height used to configure encoder, // This is the actual width and height used to configure encoder,
// which might be less than `requested_resolution` due to adaptation // which might be less than `scale_resolution_down_to` due to adaptation
// or due to the source providing smaller frames than requested. // or due to the source providing smaller frames than requested.
size_t width; size_t width;
size_t height; size_t height;
@ -75,14 +75,14 @@ struct VideoStream {
// An optional user supplied max_frame_resolution // An optional user supplied max_frame_resolution
// than can be set independently of (adapted) VideoSource. // than can be set independently of (adapted) VideoSource.
// This value is set from RtpEncodingParameters::requested_resolution // This value is set from RtpEncodingParameters::scale_resolution_down_to
// (i.e. used for signaling app-level settings). // (i.e. used for signaling app-level settings).
// //
// The actual encode resolution is in `width` and `height`, // The actual encode resolution is in `width` and `height`,
// which can be lower than requested_resolution, // which can be lower than scale_resolution_down_to,
// e.g. if source only provides lower resolution or // e.g. if source only provides lower resolution or
// if resource adaptation is active. // if resource adaptation is active.
std::optional<Resolution> requested_resolution; std::optional<Resolution> scale_resolution_down_to;
}; };
class VideoEncoderConfig { class VideoEncoderConfig {
@ -166,7 +166,7 @@ class VideoEncoderConfig {
~VideoEncoderConfig(); ~VideoEncoderConfig();
std::string ToString() const; std::string ToString() const;
bool HasRequestedResolution() const; bool HasScaleResolutionDownTo() const;
// TODO(bugs.webrtc.org/6883): Consolidate on one of these. // TODO(bugs.webrtc.org/6883): Consolidate on one of these.
VideoCodecType codec_type; VideoCodecType codec_type;

View File

@ -105,9 +105,9 @@ bool VideoSourceSinkController::active() const {
} }
std::optional<rtc::VideoSinkWants::FrameSize> std::optional<rtc::VideoSinkWants::FrameSize>
VideoSourceSinkController::requested_resolution() const { VideoSourceSinkController::scale_resolution_down_to() const {
RTC_DCHECK_RUN_ON(&sequence_checker_); RTC_DCHECK_RUN_ON(&sequence_checker_);
return requested_resolution_; return scale_resolution_down_to_;
} }
void VideoSourceSinkController::SetRestrictions( void VideoSourceSinkController::SetRestrictions(
@ -150,10 +150,10 @@ void VideoSourceSinkController::SetActive(bool active) {
active_ = active; active_ = active;
} }
void VideoSourceSinkController::SetRequestedResolution( void VideoSourceSinkController::SetScaleResolutionDownTo(
std::optional<rtc::VideoSinkWants::FrameSize> requested_resolution) { std::optional<rtc::VideoSinkWants::FrameSize> scale_resolution_down_to) {
RTC_DCHECK_RUN_ON(&sequence_checker_); RTC_DCHECK_RUN_ON(&sequence_checker_);
requested_resolution_ = std::move(requested_resolution); scale_resolution_down_to_ = std::move(scale_resolution_down_to);
} }
// RTC_EXCLUSIVE_LOCKS_REQUIRED(sequence_checker_) // RTC_EXCLUSIVE_LOCKS_REQUIRED(sequence_checker_)
@ -186,7 +186,7 @@ rtc::VideoSinkWants VideoSourceSinkController::CurrentSettingsToSinkWants()
: std::numeric_limits<int>::max()); : std::numeric_limits<int>::max());
wants.resolutions = resolutions_; wants.resolutions = resolutions_;
wants.is_active = active_; wants.is_active = active_;
wants.requested_resolution = requested_resolution_; wants.requested_resolution = scale_resolution_down_to_;
return wants; return wants;
} }

View File

@ -52,7 +52,8 @@ class VideoSourceSinkController {
int resolution_alignment() const; int resolution_alignment() const;
const std::vector<rtc::VideoSinkWants::FrameSize>& resolutions() const; const std::vector<rtc::VideoSinkWants::FrameSize>& resolutions() const;
bool active() const; bool active() const;
std::optional<rtc::VideoSinkWants::FrameSize> requested_resolution() const; std::optional<rtc::VideoSinkWants::FrameSize> scale_resolution_down_to()
const;
// Updates the settings stored internally. In order for these settings to be // Updates the settings stored internally. In order for these settings to be
// applied to the sink, PushSourceSinkSettings() must subsequently be called. // applied to the sink, PushSourceSinkSettings() must subsequently be called.
@ -64,8 +65,8 @@ class VideoSourceSinkController {
void SetResolutionAlignment(int resolution_alignment); void SetResolutionAlignment(int resolution_alignment);
void SetResolutions(std::vector<rtc::VideoSinkWants::FrameSize> resolutions); void SetResolutions(std::vector<rtc::VideoSinkWants::FrameSize> resolutions);
void SetActive(bool active); void SetActive(bool active);
void SetRequestedResolution( void SetScaleResolutionDownTo(
std::optional<rtc::VideoSinkWants::FrameSize> requested_resolution); std::optional<rtc::VideoSinkWants::FrameSize> scale_resolution_down_to);
private: private:
rtc::VideoSinkWants CurrentSettingsToSinkWants() const rtc::VideoSinkWants CurrentSettingsToSinkWants() const
@ -93,7 +94,7 @@ class VideoSourceSinkController {
std::vector<rtc::VideoSinkWants::FrameSize> resolutions_ std::vector<rtc::VideoSinkWants::FrameSize> resolutions_
RTC_GUARDED_BY(&sequence_checker_); RTC_GUARDED_BY(&sequence_checker_);
bool active_ RTC_GUARDED_BY(&sequence_checker_) = true; bool active_ RTC_GUARDED_BY(&sequence_checker_) = true;
std::optional<rtc::VideoSinkWants::FrameSize> requested_resolution_ std::optional<rtc::VideoSinkWants::FrameSize> scale_resolution_down_to_
RTC_GUARDED_BY(&sequence_checker_); RTC_GUARDED_BY(&sequence_checker_);
}; };

View File

@ -62,7 +62,7 @@ TEST(VideoSourceSinkControllerTest, UnconstrainedByDefault) {
EXPECT_FALSE(controller.pixels_per_frame_upper_limit().has_value()); EXPECT_FALSE(controller.pixels_per_frame_upper_limit().has_value());
EXPECT_FALSE(controller.frame_rate_upper_limit().has_value()); EXPECT_FALSE(controller.frame_rate_upper_limit().has_value());
EXPECT_FALSE(controller.rotation_applied()); EXPECT_FALSE(controller.rotation_applied());
EXPECT_FALSE(controller.requested_resolution().has_value()); EXPECT_FALSE(controller.scale_resolution_down_to().has_value());
EXPECT_EQ(controller.resolution_alignment(), 1); EXPECT_EQ(controller.resolution_alignment(), 1);
EXPECT_CALL(source, AddOrUpdateSink(_, _)) EXPECT_CALL(source, AddOrUpdateSink(_, _))
@ -166,12 +166,12 @@ TEST(VideoSourceSinkControllerTest,
controller.RequestRefreshFrame(); controller.RequestRefreshFrame();
} }
TEST(VideoSourceSinkControllerTest, RequestedResolutionPropagatesToWants) { TEST(VideoSourceSinkControllerTest, ScaleResolutionDownToPropagatesToWants) {
MockVideoSinkWithVideoFrame sink; MockVideoSinkWithVideoFrame sink;
MockVideoSourceWithVideoFrame source; MockVideoSourceWithVideoFrame source;
VideoSourceSinkController controller(&sink, &source); VideoSourceSinkController controller(&sink, &source);
controller.SetRequestedResolution(FrameSize(640, 360)); controller.SetScaleResolutionDownTo(FrameSize(640, 360));
EXPECT_TRUE(controller.requested_resolution().has_value()); EXPECT_TRUE(controller.scale_resolution_down_to().has_value());
EXPECT_CALL(source, AddOrUpdateSink(_, _)) EXPECT_CALL(source, AddOrUpdateSink(_, _))
.WillOnce([](rtc::VideoSinkInterface<VideoFrame>* sink, .WillOnce([](rtc::VideoSinkInterface<VideoFrame>* sink,

View File

@ -872,38 +872,40 @@ void VideoStreamEncoder::ConfigureEncoder(VideoEncoderConfig config,
RTC_DCHECK_RUN_ON(worker_queue_); RTC_DCHECK_RUN_ON(worker_queue_);
// Inform source about max configured framerate, // Inform source about max configured framerate,
// requested_resolution and which layers are active. // scale_resolution_down_to and which layers are active.
int max_framerate = -1; int max_framerate = -1;
// Is any layer active. // Is any layer active.
bool active = false; bool active = false;
// The max requested_resolution. // The max scale_resolution_down_to.
std::optional<rtc::VideoSinkWants::FrameSize> requested_resolution; std::optional<rtc::VideoSinkWants::FrameSize> scale_resolution_down_to;
for (const auto& stream : config.simulcast_layers) { for (const auto& stream : config.simulcast_layers) {
active |= stream.active; active |= stream.active;
if (stream.active) { if (stream.active) {
max_framerate = std::max(stream.max_framerate, max_framerate); max_framerate = std::max(stream.max_framerate, max_framerate);
} }
// Note: we propagate the highest requested_resolution regardless // Note: we propagate the highest scale_resolution_down_to regardless
// if layer is active or not. // if layer is active or not.
if (stream.requested_resolution) { if (stream.scale_resolution_down_to) {
if (!requested_resolution) { if (!scale_resolution_down_to) {
requested_resolution.emplace(stream.requested_resolution->width, scale_resolution_down_to.emplace(
stream.requested_resolution->height); stream.scale_resolution_down_to->width,
stream.scale_resolution_down_to->height);
} else { } else {
requested_resolution.emplace( scale_resolution_down_to.emplace(
std::max(stream.requested_resolution->width, std::max(stream.scale_resolution_down_to->width,
requested_resolution->width), scale_resolution_down_to->width),
std::max(stream.requested_resolution->height, std::max(stream.scale_resolution_down_to->height,
requested_resolution->height)); scale_resolution_down_to->height));
} }
} }
} }
if (requested_resolution != if (scale_resolution_down_to !=
video_source_sink_controller_.requested_resolution() || video_source_sink_controller_.scale_resolution_down_to() ||
active != video_source_sink_controller_.active() || active != video_source_sink_controller_.active() ||
max_framerate != max_framerate !=
video_source_sink_controller_.frame_rate_upper_limit().value_or(-1)) { video_source_sink_controller_.frame_rate_upper_limit().value_or(-1)) {
video_source_sink_controller_.SetRequestedResolution(requested_resolution); video_source_sink_controller_.SetScaleResolutionDownTo(
scale_resolution_down_to);
if (max_framerate >= 0) { if (max_framerate >= 0) {
video_source_sink_controller_.SetFrameRateUpperLimit(max_framerate); video_source_sink_controller_.SetFrameRateUpperLimit(max_framerate);
} else { } else {
@ -2412,12 +2414,12 @@ void VideoStreamEncoder::OnVideoSourceRestrictionsUpdated(
// so that ownership on restrictions/wants is kept on &encoder_queue_ // so that ownership on restrictions/wants is kept on &encoder_queue_
latest_restrictions_ = restrictions; latest_restrictions_ = restrictions;
// When the `requested_resolution` API is used, we need to reconfigure any // When the `scale_resolution_down_to` API is used, we need to reconfigure any
// time the restricted resolution is updated. When that API isn't used, the // time the restricted resolution is updated. When that API isn't used, the
// encoder settings are relative to the frame size and reconfiguration happens // encoder settings are relative to the frame size and reconfiguration happens
// automatically on new frame size and we don't need to reconfigure here. // automatically on new frame size and we don't need to reconfigure here.
if (encoder_ && max_pixels_updated && if (encoder_ && max_pixels_updated &&
encoder_config_.HasRequestedResolution()) { encoder_config_.HasScaleResolutionDownTo()) {
// The encoder will be reconfigured on the next frame. // The encoder will be reconfigured on the next frame.
pending_encoder_reconfiguration_ = true; pending_encoder_reconfiguration_ = true;
} }

View File

@ -2588,7 +2588,7 @@ TEST_F(VideoStreamEncoderTest, FrameRateLimitCanBeReset) {
} }
TEST_F(VideoStreamEncoderTest, RequestInSinkWantsBeforeFirstFrame) { TEST_F(VideoStreamEncoderTest, RequestInSinkWantsBeforeFirstFrame) {
// Use a real video stream factory or else `requested_resolution` is not // Use a real video stream factory or else `scale_resolution_down_to` is not
// applied correctly. // applied correctly.
video_encoder_config_.video_stream_factory = nullptr; video_encoder_config_.video_stream_factory = nullptr;
ConfigureEncoder(video_encoder_config_.Copy()); ConfigureEncoder(video_encoder_config_.Copy());
@ -2596,7 +2596,7 @@ TEST_F(VideoStreamEncoderTest, RequestInSinkWantsBeforeFirstFrame) {
kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0); kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
ASSERT_THAT(video_encoder_config_.simulcast_layers, SizeIs(1)); ASSERT_THAT(video_encoder_config_.simulcast_layers, SizeIs(1));
video_encoder_config_.simulcast_layers[0].requested_resolution.emplace( video_encoder_config_.simulcast_layers[0].scale_resolution_down_to.emplace(
Resolution({.width = 320, .height = 160})); Resolution({.width = 320, .height = 160}));
video_stream_encoder_->ConfigureEncoder(video_encoder_config_.Copy(), video_stream_encoder_->ConfigureEncoder(video_encoder_config_.Copy(),
@ -2605,8 +2605,10 @@ TEST_F(VideoStreamEncoderTest, RequestInSinkWantsBeforeFirstFrame) {
EXPECT_EQ(video_source_.sink_wants().requested_resolution, EXPECT_EQ(video_source_.sink_wants().requested_resolution,
rtc::VideoSinkWants::FrameSize(320, 160)); rtc::VideoSinkWants::FrameSize(320, 160));
video_encoder_config_.simulcast_layers[0].requested_resolution->height = 320; video_encoder_config_.simulcast_layers[0].scale_resolution_down_to->height =
video_encoder_config_.simulcast_layers[0].requested_resolution->width = 640; 320;
video_encoder_config_.simulcast_layers[0].scale_resolution_down_to->width =
640;
video_stream_encoder_->ConfigureEncoder(video_encoder_config_.Copy(), video_stream_encoder_->ConfigureEncoder(video_encoder_config_.Copy(),
kMaxPayloadLength); kMaxPayloadLength);
@ -2617,7 +2619,7 @@ TEST_F(VideoStreamEncoderTest, RequestInSinkWantsBeforeFirstFrame) {
} }
TEST_F(VideoStreamEncoderTest, RequestInWrongAspectRatioWithAdapter) { TEST_F(VideoStreamEncoderTest, RequestInWrongAspectRatioWithAdapter) {
// Use a real video stream factory or else `requested_resolution` is not // Use a real video stream factory or else `scale_resolution_down_to` is not
// applied correctly. // applied correctly.
video_encoder_config_.video_stream_factory = nullptr; video_encoder_config_.video_stream_factory = nullptr;
ConfigureEncoder(video_encoder_config_.Copy()); ConfigureEncoder(video_encoder_config_.Copy());
@ -2631,7 +2633,7 @@ TEST_F(VideoStreamEncoderTest, RequestInWrongAspectRatioWithAdapter) {
&source, webrtc::DegradationPreference::MAINTAIN_FRAMERATE); &source, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
ASSERT_THAT(video_encoder_config_.simulcast_layers, SizeIs(1)); ASSERT_THAT(video_encoder_config_.simulcast_layers, SizeIs(1));
video_encoder_config_.simulcast_layers[0].requested_resolution = { video_encoder_config_.simulcast_layers[0].scale_resolution_down_to = {
.width = 30, .height = 30}; .width = 30, .height = 30};
video_stream_encoder_->ConfigureEncoder(video_encoder_config_.Copy(), video_stream_encoder_->ConfigureEncoder(video_encoder_config_.Copy(),
kMaxPayloadLength); kMaxPayloadLength);
@ -6314,8 +6316,8 @@ TEST_F(VideoStreamEncoderTest,
enum class FrameResolutionChangeMethod { enum class FrameResolutionChangeMethod {
MODIFY_SOURCE, MODIFY_SOURCE,
MODIFY_REQUESTED_RESOLUTION, MODIFY_SCALE_RESOLUTION_DOWN_TO,
MODIFY_SCALE_RESOLUTION_BY, MODIFY_SCALE_RESOLUTION_DOWN_BY,
}; };
class VideoStreamEncoderInitialFrameDropperTest class VideoStreamEncoderInitialFrameDropperTest
: public VideoStreamEncoderTest, : public VideoStreamEncoderTest,
@ -6329,12 +6331,12 @@ class VideoStreamEncoderInitialFrameDropperTest
switch (frame_resolution_change_method_) { switch (frame_resolution_change_method_) {
case FrameResolutionChangeMethod::MODIFY_SOURCE: case FrameResolutionChangeMethod::MODIFY_SOURCE:
break; break;
case FrameResolutionChangeMethod::MODIFY_REQUESTED_RESOLUTION: case FrameResolutionChangeMethod::MODIFY_SCALE_RESOLUTION_DOWN_TO:
video_encoder_config_.video_stream_factory = nullptr; video_encoder_config_.video_stream_factory = nullptr;
captureWidth = kWidth; captureWidth = kWidth;
captureHeight = kHeight; captureHeight = kHeight;
break; break;
case FrameResolutionChangeMethod::MODIFY_SCALE_RESOLUTION_BY: case FrameResolutionChangeMethod::MODIFY_SCALE_RESOLUTION_DOWN_BY:
captureWidth = kWidth; captureWidth = kWidth;
captureHeight = kHeight; captureHeight = kHeight;
break; break;
@ -6347,14 +6349,15 @@ class VideoStreamEncoderInitialFrameDropperTest
captureWidth = width; captureWidth = width;
captureHeight = height; captureHeight = height;
break; break;
case FrameResolutionChangeMethod::MODIFY_REQUESTED_RESOLUTION: case FrameResolutionChangeMethod::MODIFY_SCALE_RESOLUTION_DOWN_TO:
ASSERT_THAT(video_encoder_config_.simulcast_layers, SizeIs(1)); ASSERT_THAT(video_encoder_config_.simulcast_layers, SizeIs(1));
video_encoder_config_.simulcast_layers[0].requested_resolution.emplace( video_encoder_config_.simulcast_layers[0]
.scale_resolution_down_to.emplace(
Resolution({.width = width, .height = height})); Resolution({.width = width, .height = height}));
video_stream_encoder_->ConfigureEncoder(video_encoder_config_.Copy(), video_stream_encoder_->ConfigureEncoder(video_encoder_config_.Copy(),
kMaxPayloadLength); kMaxPayloadLength);
break; break;
case FrameResolutionChangeMethod::MODIFY_SCALE_RESOLUTION_BY: case FrameResolutionChangeMethod::MODIFY_SCALE_RESOLUTION_DOWN_BY:
ASSERT_THAT(video_encoder_config_.simulcast_layers, SizeIs(1)); ASSERT_THAT(video_encoder_config_.simulcast_layers, SizeIs(1));
double scale_height = double scale_height =
static_cast<double>(kHeight) / static_cast<double>(height); static_cast<double>(kHeight) / static_cast<double>(height);
@ -6381,9 +6384,10 @@ class VideoStreamEncoderInitialFrameDropperTest
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
VideoStreamEncoderInitialFrameDropperTest, VideoStreamEncoderInitialFrameDropperTest,
VideoStreamEncoderInitialFrameDropperTest, VideoStreamEncoderInitialFrameDropperTest,
::testing::Values(FrameResolutionChangeMethod::MODIFY_SOURCE, ::testing::Values(
FrameResolutionChangeMethod::MODIFY_REQUESTED_RESOLUTION, FrameResolutionChangeMethod::MODIFY_SOURCE,
FrameResolutionChangeMethod::MODIFY_SCALE_RESOLUTION_BY)); FrameResolutionChangeMethod::MODIFY_SCALE_RESOLUTION_DOWN_TO,
FrameResolutionChangeMethod::MODIFY_SCALE_RESOLUTION_DOWN_BY));
TEST_P(VideoStreamEncoderInitialFrameDropperTest, TEST_P(VideoStreamEncoderInitialFrameDropperTest,
InitialFrameDropActivatesWhenResolutionIncreases) { InitialFrameDropActivatesWhenResolutionIncreases) {
@ -6431,7 +6435,7 @@ TEST_P(VideoStreamEncoderInitialFrameDropperTest,
int timestamp = 1; int timestamp = 1;
// By using the `requested_resolution` API, ReconfigureEncoder() gets // By using the `scale_resolution_down_to` API, ReconfigureEncoder() gets
// triggered from VideoStreamEncoder::OnVideoSourceRestrictionsUpdated(). // triggered from VideoStreamEncoder::OnVideoSourceRestrictionsUpdated().
SetEncoderFrameSize(kWidth, kHeight); SetEncoderFrameSize(kWidth, kHeight);