Add resolution query support for MediaCapabilities

Bug: chromium:505034803
Change-Id: Ic8a61b90a68f29c641e354e8879a53e6e29ec6b6
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/466180
Reviewed-by: Johannes Kron <kron@webrtc.org>
Commit-Queue: Johannes Kron <kron@webrtc.org>
Reviewed-by: Evan Shrubsole <eshr@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#47587}
diff --git a/api/video_codecs/BUILD.gn b/api/video_codecs/BUILD.gn
index 51da74c..07d343d 100644
--- a/api/video_codecs/BUILD.gn
+++ b/api/video_codecs/BUILD.gn
@@ -155,6 +155,7 @@
     "../../media:rtc_simulcast_encoder_adapter",
     "../../rtc_base/system:rtc_export",
     "../environment",
+    "../video:resolution",
   ]
 }
 
@@ -168,6 +169,7 @@
     ":video_codecs_api",
     "../../modules/video_coding/svc:scalability_mode_util",
     "../environment",
+    "../video:resolution",
     "//third_party/abseil-cpp/absl/algorithm:container",
   ]
 }
diff --git a/api/video_codecs/builtin_video_encoder_factory.cc b/api/video_codecs/builtin_video_encoder_factory.cc
index bd4bad6..109444f 100644
--- a/api/video_codecs/builtin_video_encoder_factory.cc
+++ b/api/video_codecs/builtin_video_encoder_factory.cc
@@ -16,6 +16,7 @@
 #include <vector>
 
 #include "api/environment/environment.h"
+#include "api/video/resolution.h"
 #include "api/video_codecs/sdp_video_format.h"
 #include "api/video_codecs/video_encoder.h"
 #include "api/video_codecs/video_encoder_factory.h"
@@ -54,9 +55,10 @@
 
   CodecSupport QueryCodecSupport(
       const SdpVideoFormat& format,
-      std::optional<std::string> scalability_mode) const override {
-    return internal_encoder_factory_->QueryCodecSupport(format,
-                                                        scalability_mode);
+      std::optional<std::string> scalability_mode,
+      std::optional<Resolution> resolution) const override {
+    return internal_encoder_factory_->QueryCodecSupport(
+        format, scalability_mode, resolution);
   }
 
  private:
diff --git a/api/video_codecs/test/video_encoder_factory_template_tests.cc b/api/video_codecs/test/video_encoder_factory_template_tests.cc
index 9860104..733ef30 100644
--- a/api/video_codecs/test/video_encoder_factory_template_tests.cc
+++ b/api/video_codecs/test/video_encoder_factory_template_tests.cc
@@ -90,13 +90,14 @@
 
 TEST(VideoEncoderFactoryTemplate, OneTemplateAdapterCodecSupport) {
   VideoEncoderFactoryTemplate<FooEncoderTemplateAdapter> factory;
-  EXPECT_THAT(factory.QueryCodecSupport(kFooSdp, std::nullopt),
+  EXPECT_THAT(factory.QueryCodecSupport(kFooSdp, std::nullopt, std::nullopt),
               Field(&CodecSupport::is_supported, true));
-  EXPECT_THAT(factory.QueryCodecSupport(kFooSdp, "L1T2"),
+  EXPECT_THAT(factory.QueryCodecSupport(kFooSdp, "L1T2", std::nullopt),
               Field(&CodecSupport::is_supported, true));
-  EXPECT_THAT(factory.QueryCodecSupport(kFooSdp, "S3T3"),
+  EXPECT_THAT(factory.QueryCodecSupport(kFooSdp, "S3T3", std::nullopt),
               Field(&CodecSupport::is_supported, false));
-  EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat("FooX"), std::nullopt),
+  EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat("FooX"), std::nullopt,
+                                        std::nullopt),
               Field(&CodecSupport::is_supported, false));
 }
 
@@ -125,19 +126,20 @@
   VideoEncoderFactoryTemplate<FooEncoderTemplateAdapter,
                               BarEncoderTemplateAdapter>
       factory;
-  EXPECT_THAT(factory.QueryCodecSupport(kFooSdp, std::nullopt),
+  EXPECT_THAT(factory.QueryCodecSupport(kFooSdp, std::nullopt, std::nullopt),
               Field(&CodecSupport::is_supported, true));
-  EXPECT_THAT(factory.QueryCodecSupport(kFooSdp, "L1T2"),
+  EXPECT_THAT(factory.QueryCodecSupport(kFooSdp, "L1T2", std::nullopt),
               Field(&CodecSupport::is_supported, true));
-  EXPECT_THAT(factory.QueryCodecSupport(kFooSdp, "S3T3"),
+  EXPECT_THAT(factory.QueryCodecSupport(kFooSdp, "S3T3", std::nullopt),
               Field(&CodecSupport::is_supported, false));
-  EXPECT_THAT(factory.QueryCodecSupport(kBarLowSdp, std::nullopt),
+  EXPECT_THAT(factory.QueryCodecSupport(kBarLowSdp, std::nullopt, std::nullopt),
               Field(&CodecSupport::is_supported, true));
-  EXPECT_THAT(factory.QueryCodecSupport(kBarHighSdp, std::nullopt),
+  EXPECT_THAT(
+      factory.QueryCodecSupport(kBarHighSdp, std::nullopt, std::nullopt),
+      Field(&CodecSupport::is_supported, true));
+  EXPECT_THAT(factory.QueryCodecSupport(kBarLowSdp, "S2T1", std::nullopt),
               Field(&CodecSupport::is_supported, true));
-  EXPECT_THAT(factory.QueryCodecSupport(kBarLowSdp, "S2T1"),
-              Field(&CodecSupport::is_supported, true));
-  EXPECT_THAT(factory.QueryCodecSupport(kBarHighSdp, "S3T2"),
+  EXPECT_THAT(factory.QueryCodecSupport(kBarHighSdp, "S3T2", std::nullopt),
               Field(&CodecSupport::is_supported, false));
 }
 
diff --git a/api/video_codecs/test/video_encoder_factory_unittest.cc b/api/video_codecs/test/video_encoder_factory_unittest.cc
index 2480b56..94c8f55 100644
--- a/api/video_codecs/test/video_encoder_factory_unittest.cc
+++ b/api/video_codecs/test/video_encoder_factory_unittest.cc
@@ -60,50 +60,57 @@
 
 TEST(VideoEncoderFactoryTest, QueryCodecSupportNoScalabilityMode) {
   TestVideoEncoderFactory factory({SdpVideoFormat("VP8")});
-  EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat("VP8"), std::nullopt),
+  EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat("VP8"), std::nullopt,
+                                        std::nullopt),
               SupportIs(kSupported));
 }
 
 TEST(VideoEncoderFactoryTest, QueryCodecSupportUnsupportedFormat) {
   TestVideoEncoderFactory factory({SdpVideoFormat("VP8")});
-  EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat("H264"), std::nullopt),
+  EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat("H264"), std::nullopt,
+                                        std::nullopt),
               SupportIs(kUnsupported));
 }
 
 TEST(VideoEncoderFactoryTest,
      QueryCodecSupportWithScalabilityModeAndEmptyModeList) {
   TestVideoEncoderFactory factory({SdpVideoFormat("VP8")});
-  EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat("VP8"), "L1T2"),
-              SupportIs(kUnsupported));
+  EXPECT_THAT(
+      factory.QueryCodecSupport(SdpVideoFormat("VP8"), "L1T2", std::nullopt),
+      SupportIs(kUnsupported));
 }
 
 TEST(VideoEncoderFactoryTest, QueryCodecSupportWithMatchingScalabilityMode) {
   SdpVideoFormat format("VP8", {}, {ScalabilityMode::kL1T2});
   TestVideoEncoderFactory factory({format});
-  EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat("VP8"), "L1T2"),
-              SupportIs(kSupported));
+  EXPECT_THAT(
+      factory.QueryCodecSupport(SdpVideoFormat("VP8"), "L1T2", std::nullopt),
+      SupportIs(kSupported));
 }
 
 TEST(VideoEncoderFactoryTest, QueryCodecSupportWithNonMatchingScalabilityMode) {
   SdpVideoFormat format("VP8", {}, {ScalabilityMode::kL1T2});
   TestVideoEncoderFactory factory({format});
-  EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat("VP8"), "L3T3"),
-              SupportIs(kUnsupported));
+  EXPECT_THAT(
+      factory.QueryCodecSupport(SdpVideoFormat("VP8"), "L3T3", std::nullopt),
+      SupportIs(kUnsupported));
 }
 
 TEST(VideoEncoderFactoryTest, QueryCodecSupportWithInvalidScalabilityMode) {
   SdpVideoFormat format("VP8", {}, {ScalabilityMode::kL1T2});
   TestVideoEncoderFactory factory({format});
-  EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat("VP8"), "INVALID"),
-              SupportIs(kUnsupported));
+  EXPECT_THAT(
+      factory.QueryCodecSupport(SdpVideoFormat("VP8"), "INVALID", std::nullopt),
+      SupportIs(kUnsupported));
 }
 
 TEST(VideoEncoderFactoryTest,
      QueryCodecSupportScalabilityModeUnsupportedFormat) {
   SdpVideoFormat format("VP8", {}, {ScalabilityMode::kL1T2});
   TestVideoEncoderFactory factory({format});
-  EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat("H264"), "L1T2"),
-              SupportIs(kUnsupported));
+  EXPECT_THAT(
+      factory.QueryCodecSupport(SdpVideoFormat("H264"), "L1T2", std::nullopt),
+      SupportIs(kUnsupported));
 }
 
 TEST(VideoEncoderFactoryTest,
@@ -115,10 +122,12 @@
   TestVideoEncoderFactory factory({vp9_profile0, vp9_profile2});
 
   EXPECT_THAT(factory.QueryCodecSupport(
-                  SdpVideoFormat("VP9", {{kVP9FmtpProfileId, "0"}}), "L3T3"),
+                  SdpVideoFormat("VP9", {{kVP9FmtpProfileId, "0"}}), "L3T3",
+                  std::nullopt),
               SupportIs(kSupported));
   EXPECT_THAT(factory.QueryCodecSupport(
-                  SdpVideoFormat("VP9", {{kVP9FmtpProfileId, "2"}}), "L3T3"),
+                  SdpVideoFormat("VP9", {{kVP9FmtpProfileId, "2"}}), "L3T3",
+                  std::nullopt),
               SupportIs(kUnsupported));
 }
 
diff --git a/api/video_codecs/video_decoder_factory.cc b/api/video_codecs/video_decoder_factory.cc
index 20e9fff..c0fc1b2 100644
--- a/api/video_codecs/video_decoder_factory.cc
+++ b/api/video_codecs/video_decoder_factory.cc
@@ -10,13 +10,17 @@
 
 #include "api/video_codecs/video_decoder_factory.h"
 
+#include <optional>
+
+#include "api/video/resolution.h"
 #include "api/video_codecs/sdp_video_format.h"
 
 namespace webrtc {
 
 VideoDecoderFactory::CodecSupport VideoDecoderFactory::QueryCodecSupport(
     const SdpVideoFormat& format,
-    bool reference_scaling) const {
+    bool reference_scaling,
+    std::optional<Resolution> resolution) const {
   // Default implementation, query for supported formats and check if the
   // specified format is supported. Returns false if `reference_scaling` is
   // true.
diff --git a/api/video_codecs/video_decoder_factory.h b/api/video_codecs/video_decoder_factory.h
index 89433e0..4c9c44d 100644
--- a/api/video_codecs/video_decoder_factory.h
+++ b/api/video_codecs/video_decoder_factory.h
@@ -12,9 +12,11 @@
 #define API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_H_
 
 #include <memory>
+#include <optional>
 #include <vector>
 
 #include "api/environment/environment.h"
+#include "api/video/resolution.h"
 #include "api/video_codecs/sdp_video_format.h"
 #include "api/video_codecs/video_decoder.h"
 #include "rtc_base/system/rtc_export.h"
@@ -36,6 +38,13 @@
   // for signaling etc.
   virtual std::vector<SdpVideoFormat> GetSupportedFormats() const = 0;
 
+  // TODO(crbug.com/505034803): Deprecate once all clients are switched.
+  // [[deprecated("Use the 3-parameter version instead")]]
+  virtual CodecSupport QueryCodecSupport(const SdpVideoFormat& format,
+                                         bool reference_scaling) const {
+    return QueryCodecSupport(format, reference_scaling, std::nullopt);
+  }
+
   // Query whether the specifed format is supported or not and if it will be
   // power efficient, which is currently interpreted as if there is support for
   // hardware acceleration.
@@ -44,10 +53,16 @@
   // needed is if the video stream is produced with a scalability mode that has
   // a dependency between the spatial layers. See
   // https://w3c.github.io/webrtc-svc/#scalabilitymodes* for a specification of
-  // different scalabilty modes. NOTE: QueryCodecSupport is currently an
-  // experimental feature that is subject to change without notice.
-  virtual CodecSupport QueryCodecSupport(const SdpVideoFormat& format,
-                                         bool reference_scaling) const;
+  // different scalabilty modes.
+  // The parameter `resolution` may optionally be provided to require the format
+  // has decoding support up to the provided resolution to mark it as supported.
+  //
+  // NOTE: QueryCodecSupport is currently an experimental feature that is
+  // subject to change without notice.
+  virtual CodecSupport QueryCodecSupport(
+      const SdpVideoFormat& format,
+      bool reference_scaling,
+      std::optional<Resolution> resolution) const;
 
   // Creates a VideoDecoder for the specified `format`.
   virtual std::unique_ptr<VideoDecoder> Create(
diff --git a/api/video_codecs/video_encoder_factory.cc b/api/video_codecs/video_encoder_factory.cc
index bee7ae2..e351323 100644
--- a/api/video_codecs/video_encoder_factory.cc
+++ b/api/video_codecs/video_encoder_factory.cc
@@ -14,6 +14,7 @@
 #include <string>
 
 #include "absl/algorithm/container.h"
+#include "api/video/resolution.h"
 #include "api/video_codecs/scalability_mode.h"
 #include "api/video_codecs/sdp_video_format.h"
 
@@ -21,7 +22,8 @@
 
 VideoEncoderFactory::CodecSupport VideoEncoderFactory::QueryCodecSupport(
     const SdpVideoFormat& format,
-    std::optional<std::string> scalability_mode) const {
+    std::optional<std::string> scalability_mode,
+    std::optional<Resolution> resolution) const {
   // Default implementation, query for supported formats and check if the
   // specified format is supported. If a scalability mode is specified, check
   // that it is present in the matching format's scalability_modes list.
diff --git a/api/video_codecs/video_encoder_factory.h b/api/video_codecs/video_encoder_factory.h
index a5cf3db..a86911c 100644
--- a/api/video_codecs/video_encoder_factory.h
+++ b/api/video_codecs/video_encoder_factory.h
@@ -20,6 +20,7 @@
 #include "api/ref_counted_base.h"
 #include "api/units/data_rate.h"
 #include "api/video/render_resolution.h"
+#include "api/video/resolution.h"
 #include "api/video_codecs/sdp_video_format.h"
 #include "api/video_codecs/video_encoder.h"
 #include "rtc_base/system/rtc_export.h"
@@ -81,16 +82,28 @@
     return GetSupportedFormats();
   }
 
+  // TODO(crbug.com/505034803): Deprecate once all clients are switched.
+  // [[deprecated("Use the 3-parameter version instead")]]
+  virtual CodecSupport QueryCodecSupport(
+      const SdpVideoFormat& format,
+      std::optional<std::string> scalability_mode) const {
+    return QueryCodecSupport(format, scalability_mode, std::nullopt);
+  }
+
   // Query whether the specifed format is supported or not and if it will be
   // power efficient, which is currently interpreted as if there is support for
   // hardware acceleration.
   // See https://w3c.github.io/webrtc-svc/#scalabilitymodes* for a specification
   // of valid values for `scalability_mode`.
+  // The parameter `resolution` may optionally be provided to require the format
+  // has encoding support up to the provided resolution to mark it as supported.
+  //
   // NOTE: QueryCodecSupport is currently an experimental feature that is
   // subject to change without notice.
   virtual CodecSupport QueryCodecSupport(
       const SdpVideoFormat& format,
-      std::optional<std::string> scalability_mode) const;
+      std::optional<std::string> scalability_mode,
+      std::optional<Resolution> resolution) const;
 
   // Creates a VideoEncoder for the specified format.
   virtual std::unique_ptr<VideoEncoder> Create(
diff --git a/api/video_codecs/video_encoder_factory_template.h b/api/video_codecs/video_encoder_factory_template.h
index 938a73b..037cf7e 100644
--- a/api/video_codecs/video_encoder_factory_template.h
+++ b/api/video_codecs/video_encoder_factory_template.h
@@ -19,6 +19,7 @@
 
 #include "absl/algorithm/container.h"
 #include "api/environment/environment.h"
+#include "api/video/resolution.h"
 #include "api/video_codecs/scalability_mode.h"
 #include "api/video_codecs/sdp_video_format.h"
 #include "api/video_codecs/video_encoder.h"
@@ -50,6 +51,7 @@
 template <typename... Ts>
 class VideoEncoderFactoryTemplate : public VideoEncoderFactory {
  public:
+  using VideoEncoderFactory::QueryCodecSupport;
   std::vector<SdpVideoFormat> GetSupportedFormats() const override {
     return GetSupportedFormatsInternal<Ts...>();
   }
@@ -70,8 +72,10 @@
 
   CodecSupport QueryCodecSupport(
       const SdpVideoFormat& format,
-      std::optional<std::string> scalability_mode) const override {
-    return QueryCodecSupportInternal<Ts...>(format, scalability_mode);
+      std::optional<std::string> scalability_mode,
+      std::optional<Resolution> resolution) const override {
+    return QueryCodecSupportInternal<Ts...>(format, scalability_mode,
+                                            resolution);
   }
 
  private:
@@ -130,13 +134,15 @@
   template <typename V, typename... Vs>
   CodecSupport QueryCodecSupportInternal(
       const SdpVideoFormat& format,
-      const std::optional<std::string>& scalability_mode) const {
+      const std::optional<std::string>& scalability_mode,
+      const std::optional<Resolution>& resolution) const {
     if (IsFormatInList(format, V::SupportedFormats())) {
       return {.is_supported = IsScalabilityModeSupported<V>(scalability_mode)};
     }
 
     if constexpr (sizeof...(Vs) > 0) {
-      return QueryCodecSupportInternal<Vs...>(format, scalability_mode);
+      return QueryCodecSupportInternal<Vs...>(format, scalability_mode,
+                                              resolution);
     }
 
     return {.is_supported = false};
diff --git a/media/BUILD.gn b/media/BUILD.gn
index dcdb269..785318b 100644
--- a/media/BUILD.gn
+++ b/media/BUILD.gn
@@ -533,6 +533,7 @@
     ":rtc_simulcast_encoder_adapter",
     "../api/environment",
     "../api/video:encoded_image",
+    "../api/video:resolution",
     "../api/video:video_bitrate_allocation",
     "../api/video:video_frame",
     "../api/video:video_rtp_headers",
@@ -847,6 +848,7 @@
       "../api/units:timestamp",
       "../api/video:encoded_image",
       "../api/video:recordable_encoded_frame",
+      "../api/video:resolution",
       "../api/video:video_bitrate_allocation",
       "../api/video:video_bitrate_allocator_factory",
       "../api/video:video_frame",
diff --git a/media/engine/fake_webrtc_video_engine.cc b/media/engine/fake_webrtc_video_engine.cc
index c240915..2ba4217 100644
--- a/media/engine/fake_webrtc_video_engine.cc
+++ b/media/engine/fake_webrtc_video_engine.cc
@@ -21,6 +21,7 @@
 #include "api/fec_controller_override.h"
 #include "api/units/time_delta.h"
 #include "api/video/encoded_image.h"
+#include "api/video/resolution.h"
 #include "api/video/video_frame.h"
 #include "api/video/video_frame_type.h"
 #include "api/video_codecs/scalability_mode.h"
@@ -239,7 +240,8 @@
 VideoEncoderFactory::CodecSupport
 FakeWebRtcVideoEncoderFactory::QueryCodecSupport(
     const SdpVideoFormat& format,
-    std::optional<std::string> scalability_mode) const {
+    std::optional<std::string> scalability_mode,
+    std::optional<Resolution> resolution) const {
   std::vector<SdpVideoFormat> supported_formats;
   for (const auto& f : formats_) {
     if (format.IsSameCodec(f))
diff --git a/media/engine/fake_webrtc_video_engine.h b/media/engine/fake_webrtc_video_engine.h
index ea5995d..fb344a3 100644
--- a/media/engine/fake_webrtc_video_engine.h
+++ b/media/engine/fake_webrtc_video_engine.h
@@ -22,6 +22,7 @@
 #include "api/environment/environment.h"
 #include "api/fec_controller_override.h"
 #include "api/video/encoded_image.h"
+#include "api/video/resolution.h"
 #include "api/video/video_frame.h"
 #include "api/video/video_frame_type.h"
 #include "api/video_codecs/scalability_mode.h"
@@ -114,10 +115,12 @@
  public:
   FakeWebRtcVideoEncoderFactory();
 
+  using VideoEncoderFactory::QueryCodecSupport;
   std::vector<SdpVideoFormat> GetSupportedFormats() const override;
   VideoEncoderFactory::CodecSupport QueryCodecSupport(
       const SdpVideoFormat& format,
-      std::optional<std::string> scalability_mode) const override;
+      std::optional<std::string> scalability_mode,
+      std::optional<Resolution> resolution) const override;
   std::unique_ptr<VideoEncoder> Create(const Environment& env,
                                        const SdpVideoFormat& format) override;
 
diff --git a/media/engine/internal_decoder_factory.cc b/media/engine/internal_decoder_factory.cc
index ed05e71..111ca43 100644
--- a/media/engine/internal_decoder_factory.cc
+++ b/media/engine/internal_decoder_factory.cc
@@ -11,10 +11,12 @@
 #include "media/engine/internal_decoder_factory.h"
 
 #include <memory>
+#include <optional>
 #include <vector>
 
 #include "absl/strings/match.h"
 #include "api/environment/environment.h"
+#include "api/video/resolution.h"
 #include "api/video/video_codec_type.h"
 #include "api/video_codecs/h264_profile_level_id.h"
 #include "api/video_codecs/sdp_video_format.h"
@@ -65,7 +67,8 @@
 
 VideoDecoderFactory::CodecSupport InternalDecoderFactory::QueryCodecSupport(
     const SdpVideoFormat& format,
-    bool reference_scaling) const {
+    bool reference_scaling,
+    std::optional<Resolution> resolution) const {
   // Query for supported formats and check if the specified format is supported.
   // Return unsupported if an invalid combination of format and
   // reference_scaling is specified.
@@ -98,7 +101,7 @@
 std::unique_ptr<VideoDecoder> InternalDecoderFactory::Create(
     const Environment& env,
     const SdpVideoFormat& format) {
-  if (!QueryCodecSupport(format, false).is_supported) {
+  if (!QueryCodecSupport(format, false, std::nullopt).is_supported) {
     RTC_LOG(LS_WARNING) << "Trying to create decoder for unsupported format. "
                         << format.ToString();
     return nullptr;
diff --git a/media/engine/internal_decoder_factory.h b/media/engine/internal_decoder_factory.h
index a2cd362..ab07c21 100644
--- a/media/engine/internal_decoder_factory.h
+++ b/media/engine/internal_decoder_factory.h
@@ -12,9 +12,11 @@
 #define MEDIA_ENGINE_INTERNAL_DECODER_FACTORY_H_
 
 #include <memory>
+#include <optional>
 #include <vector>
 
 #include "api/environment/environment.h"
+#include "api/video/resolution.h"
 #include "api/video_codecs/sdp_video_format.h"
 #include "api/video_codecs/video_decoder.h"
 #include "api/video_codecs/video_decoder_factory.h"
@@ -24,9 +26,12 @@
 
 class RTC_EXPORT InternalDecoderFactory : public VideoDecoderFactory {
  public:
+  using VideoDecoderFactory::QueryCodecSupport;
   std::vector<SdpVideoFormat> GetSupportedFormats() const override;
-  CodecSupport QueryCodecSupport(const SdpVideoFormat& format,
-                                 bool reference_scaling) const override;
+  CodecSupport QueryCodecSupport(
+      const SdpVideoFormat& format,
+      bool reference_scaling,
+      std::optional<Resolution> resolution) const override;
   std::unique_ptr<VideoDecoder> Create(const Environment& env,
                                        const SdpVideoFormat& format) override;
 };
diff --git a/media/engine/internal_decoder_factory_unittest.cc b/media/engine/internal_decoder_factory_unittest.cc
index b10cc47..6f4a55f 100644
--- a/media/engine/internal_decoder_factory_unittest.cc
+++ b/media/engine/internal_decoder_factory_unittest.cc
@@ -11,6 +11,7 @@
 #include "media/engine/internal_decoder_factory.h"
 
 #include <memory>
+#include <optional>
 
 #include "api/environment/environment.h"
 #include "api/environment/environment_factory.h"
@@ -129,21 +130,26 @@
 TEST(InternalDecoderFactoryTest, QueryCodecSupportNoReferenceScaling) {
   InternalDecoderFactory factory;
   EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat::VP8(),
-                                        /*reference_scaling=*/false),
+                                        /*reference_scaling=*/false,
+                                        /*resolution=*/std::nullopt),
               Support(kSupported));
   EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat::VP9Profile0(),
-                                        /*reference_scaling=*/false),
+                                        /*reference_scaling=*/false,
+                                        /*resolution=*/std::nullopt),
               Support(kVp9Enabled ? kSupported : kUnsupported));
   EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat::VP9Profile1(),
-                                        /*reference_scaling=*/false),
+                                        /*reference_scaling=*/false,
+                                        /*resolution=*/std::nullopt),
               Support(kVp9Enabled ? kSupported : kUnsupported));
 
 #if defined(RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY)
   EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat::AV1Profile0(),
-                                        /*reference_scaling=*/false),
+                                        /*reference_scaling=*/false,
+                                        /*resolution=*/std::nullopt),
               Support(kSupported));
   EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat::AV1Profile1(),
-                                        /*reference_scaling=*/false),
+                                        /*reference_scaling=*/false,
+                                        /*resolution=*/std::nullopt),
               Support(kSupported));
 
 #endif
@@ -159,34 +165,40 @@
   // subsets of High Predictive 4:4:4.
   EXPECT_THAT(
       factory.QueryCodecSupport(
-          SdpVideoFormat("H264", {{"profile-level-id", "42e01f"}}), false),
+          SdpVideoFormat("H264", {{"profile-level-id", "42e01f"}}), false,
+          /*resolution=*/std::nullopt),
       Support(h264_support));
   EXPECT_THAT(
       factory.QueryCodecSupport(
-          SdpVideoFormat("H264", {{"profile-level-id", "42001f"}}), false),
+          SdpVideoFormat("H264", {{"profile-level-id", "42001f"}}), false,
+          /*resolution=*/std::nullopt),
       Support(h264_support));
   EXPECT_THAT(
       factory.QueryCodecSupport(
-          SdpVideoFormat("H264", {{"profile-level-id", "4d001f"}}), false),
+          SdpVideoFormat("H264", {{"profile-level-id", "4d001f"}}), false,
+          /*resolution=*/std::nullopt),
       Support(h264_support));
   EXPECT_THAT(
       factory.QueryCodecSupport(
-          SdpVideoFormat("H264", {{"profile-level-id", "640c1f"}}), false),
+          SdpVideoFormat("H264", {{"profile-level-id", "640c1f"}}), false,
+          /*resolution=*/std::nullopt),
       Support(h264_support));
   EXPECT_THAT(
       factory.QueryCodecSupport(
-          SdpVideoFormat("H264", {{"profile-level-id", "64001f"}}), false),
+          SdpVideoFormat("H264", {{"profile-level-id", "64001f"}}), false,
+          /*resolution=*/std::nullopt),
       Support(h264_support));
 
   EXPECT_THAT(
       factory.QueryCodecSupport(
-          SdpVideoFormat("H264", {{"profile-level-id", "ff0000"}}), false),
+          SdpVideoFormat("H264", {{"profile-level-id", "ff0000"}}), false,
+          /*resolution=*/std::nullopt),
       Support(kUnsupported));
 
   EXPECT_THAT(factory.QueryCodecSupport(
                   SdpVideoFormat("H264", {{"profile-level-id", "42e01f"},
                                           {"packetization-mode", "2"}}),
-                  false),
+                  false, /*resolution=*/std::nullopt),
               Support(kUnsupported));
 }
 
@@ -194,20 +206,24 @@
   InternalDecoderFactory factory;
   // VP9 and AV1 support for spatial layers.
   EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat::VP9Profile0(),
-                                        /*reference_scaling=*/true),
+                                        /*reference_scaling=*/true,
+                                        /*resolution=*/std::nullopt),
               Support(kVp9Enabled ? kSupported : kUnsupported));
 #if defined(RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY)
   EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat::AV1Profile0(),
-                                        /*reference_scaling=*/true),
+                                        /*reference_scaling=*/true,
+                                        /*resolution=*/std::nullopt),
               Support(kSupported));
 #endif
 
   // Invalid config even though VP8 and H264 are supported.
   EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat::H264(),
-                                        /*reference_scaling=*/true),
+                                        /*reference_scaling=*/true,
+                                        /*resolution=*/std::nullopt),
               Support(kUnsupported));
   EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat::VP8(),
-                                        /*reference_scaling=*/true),
+                                        /*reference_scaling=*/true,
+                                        /*resolution=*/std::nullopt),
               Support(kUnsupported));
 }
 
diff --git a/media/engine/internal_encoder_factory.cc b/media/engine/internal_encoder_factory.cc
index 43992b3..acf38e7 100644
--- a/media/engine/internal_encoder_factory.cc
+++ b/media/engine/internal_encoder_factory.cc
@@ -16,6 +16,7 @@
 #include <vector>
 
 #include "api/environment/environment.h"
+#include "api/video/resolution.h"
 #include "api/video_codecs/sdp_video_format.h"
 #include "api/video_codecs/video_encoder.h"
 #include "api/video_codecs/video_encoder_factory.h"
@@ -57,11 +58,13 @@
 
 VideoEncoderFactory::CodecSupport InternalEncoderFactory::QueryCodecSupport(
     const SdpVideoFormat& format,
-    std::optional<std::string> scalability_mode) const {
+    std::optional<std::string> scalability_mode,
+    std::optional<Resolution> resolution) const {
   auto original_format =
       FuzzyMatchSdpVideoFormat(Factory().GetSupportedFormats(), format);
   return original_format
-             ? Factory().QueryCodecSupport(*original_format, scalability_mode)
+             ? Factory().QueryCodecSupport(*original_format, scalability_mode,
+                                           resolution)
              : VideoEncoderFactory::CodecSupport{.is_supported = false};
 }
 
diff --git a/media/engine/internal_encoder_factory.h b/media/engine/internal_encoder_factory.h
index 01c5ef7..dfe69cc 100644
--- a/media/engine/internal_encoder_factory.h
+++ b/media/engine/internal_encoder_factory.h
@@ -17,6 +17,7 @@
 #include <vector>
 
 #include "api/environment/environment.h"
+#include "api/video/resolution.h"
 #include "api/video_codecs/sdp_video_format.h"
 #include "api/video_codecs/video_encoder.h"
 #include "api/video_codecs/video_encoder_factory.h"
@@ -25,10 +26,12 @@
 namespace webrtc {
 class RTC_EXPORT InternalEncoderFactory : public VideoEncoderFactory {
  public:
+  using VideoEncoderFactory::QueryCodecSupport;
   std::vector<SdpVideoFormat> GetSupportedFormats() const override;
   CodecSupport QueryCodecSupport(
       const SdpVideoFormat& format,
-      std::optional<std::string> scalability_mode) const override;
+      std::optional<std::string> scalability_mode,
+      std::optional<Resolution> resolution) const override;
   std::unique_ptr<VideoEncoder> Create(const Environment& env,
                                        const SdpVideoFormat& format) override;
 };
diff --git a/media/engine/internal_encoder_factory_unittest.cc b/media/engine/internal_encoder_factory_unittest.cc
index e70419a..dbe8a49 100644
--- a/media/engine/internal_encoder_factory_unittest.cc
+++ b/media/engine/internal_encoder_factory_unittest.cc
@@ -95,20 +95,25 @@
 TEST(InternalEncoderFactoryTest, QueryCodecSupportWithScalabilityMode) {
   InternalEncoderFactory factory;
   // VP8 and VP9 supported for singles spatial layers.
-  EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat::VP8(), "L1T2"),
-              Support(kSupported));
-  EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat::VP9Profile0(), "L1T3"),
+  EXPECT_THAT(
+      factory.QueryCodecSupport(SdpVideoFormat::VP8(), "L1T2", std::nullopt),
+      Support(kSupported));
+  EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat::VP9Profile0(), "L1T3",
+                                        std::nullopt),
               Support(kVp9Enabled ? kSupported : kUnsupported));
 
   // VP9 support for spatial layers.
-  EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat::VP9Profile0(), "L3T3"),
+  EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat::VP9Profile0(), "L3T3",
+                                        std::nullopt),
               Support(kVp9Enabled ? kSupported : kUnsupported));
 
   // Invalid scalability modes even though VP8 and H264 are supported.
-  EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat::H264(), "L2T2"),
-              Support(kUnsupported));
-  EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat::VP8(), "L3T3"),
-              Support(kUnsupported));
+  EXPECT_THAT(
+      factory.QueryCodecSupport(SdpVideoFormat::H264(), "L2T2", std::nullopt),
+      Support(kUnsupported));
+  EXPECT_THAT(
+      factory.QueryCodecSupport(SdpVideoFormat::VP8(), "L3T3", std::nullopt),
+      Support(kUnsupported));
 }
 
 #if defined(RTC_USE_LIBAOM_AV1_ENCODER)
@@ -123,23 +128,27 @@
 TEST(InternalEncoderFactoryTest, QueryCodecSupportNoScalabilityModeAv1) {
   InternalEncoderFactory factory;
   EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat::AV1Profile0(),
-                                        /*scalability_mode=*/std::nullopt),
+                                        /*scalability_mode=*/std::nullopt,
+                                        std::nullopt),
               Support(kSupported));
 }
 
 TEST(InternalEncoderFactoryTest, QueryCodecSupportNoScalabilityMode) {
   InternalEncoderFactory factory;
   EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat::VP8(),
-                                        /*scalability_mode=*/std::nullopt),
+                                        /*scalability_mode=*/std::nullopt,
+                                        std::nullopt),
               Support(kSupported));
   EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat::VP9Profile0(),
-                                        /*scalability_mode=*/std::nullopt),
+                                        /*scalability_mode=*/std::nullopt,
+                                        std::nullopt),
               Support(kVp9Enabled ? kSupported : kUnsupported));
 }
 
 TEST(InternalEncoderFactoryTest, QueryCodecSupportWithScalabilityModeAv1) {
   InternalEncoderFactory factory;
-  EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat::AV1Profile0(), "L2T1"),
+  EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat::AV1Profile0(), "L2T1",
+                                        std::nullopt),
               Support(kSupported));
 }
 #endif  // defined(RTC_USE_LIBAOM_AV1_ENCODER)
diff --git a/media/engine/webrtc_video_engine.cc b/media/engine/webrtc_video_engine.cc
index 1b81101..9ae3524 100644
--- a/media/engine/webrtc_video_engine.cc
+++ b/media/engine/webrtc_video_engine.cc
@@ -495,7 +495,7 @@
                                        const VideoSendStream::Config& config) {
   return config.encoder_settings.encoder_factory
       ->QueryCodecSupport(SdpVideoFormat(codec.name, codec.params),
-                          scalability_mode)
+                          scalability_mode, std::nullopt)
       .is_supported;
 }
 
diff --git a/modules/video_coding/codecs/test/video_codec_test.cc b/modules/video_coding/codecs/test/video_codec_test.cc
index 9cbfd71..e020caf 100644
--- a/modules/video_coding/codecs/test/video_codec_test.cc
+++ b/modules/video_coding/codecs/test/video_codec_test.cc
@@ -204,7 +204,8 @@
       CreateEncoderFactory(encoder_impl);
   if (!encoder_factory
            ->QueryCodecSupport(sdp_video_format,
-                               /*scalability_mode=*/std::nullopt)
+                               /*scalability_mode=*/std::nullopt,
+                               /*resolution=*/std::nullopt)
            .is_supported) {
     RTC_LOG(LS_WARNING) << "No " << encoder_impl << " encoder for video format "
                         << sdp_video_format.ToString();
@@ -215,7 +216,8 @@
       CreateDecoderFactory(decoder_impl);
   if (!decoder_factory
            ->QueryCodecSupport(sdp_video_format,
-                               /*reference_scaling=*/false)
+                               /*reference_scaling=*/false,
+                               /*resolution=*/std::nullopt)
            .is_supported) {
     RTC_LOG(LS_WARNING) << "No " << decoder_impl << " decoder for video format "
                         << sdp_video_format.ToString()
@@ -225,7 +227,8 @@
     decoder_factory = CreateDecoderFactory("builtin");
     if (!decoder_factory
              ->QueryCodecSupport(sdp_video_format,
-                                 /*reference_scaling=*/false)
+                                 /*reference_scaling=*/false,
+                                 /*resolution=*/std::nullopt)
              .is_supported) {
       RTC_LOG(LS_WARNING) << "No " << decoder_impl
                           << " decoder for video format "
@@ -275,7 +278,8 @@
       CreateEncoderFactory(encoder_impl);
   if (!encoder_factory
            ->QueryCodecSupport(sdp_video_format,
-                               /*scalability_mode=*/std::nullopt)
+                               /*scalability_mode=*/std::nullopt,
+                               /*resolution=*/std::nullopt)
            .is_supported) {
     RTC_LOG(LS_WARNING) << "No encoder for video format "
                         << sdp_video_format.ToString();
diff --git a/pc/test/peer_connection_test_wrapper.cc b/pc/test/peer_connection_test_wrapper.cc
index 0b9a404..0360f4a 100644
--- a/pc/test/peer_connection_test_wrapper.cc
+++ b/pc/test/peer_connection_test_wrapper.cc
@@ -97,10 +97,12 @@
     return nullptr;
   }
 
+  using VideoEncoderFactory::QueryCodecSupport;
   CodecSupport QueryCodecSupport(
       const SdpVideoFormat& format,
-      std::optional<std::string> scalability_mode) const override {
-    return factory_.QueryCodecSupport(format, scalability_mode);
+      std::optional<std::string> scalability_mode,
+      std::optional<Resolution> resolution) const override {
+    return factory_.QueryCodecSupport(format, scalability_mode, resolution);
   }
 
  private:
diff --git a/rtc_tools/video_encoder/video_encoder.cc b/rtc_tools/video_encoder/video_encoder.cc
index fbcb84f..91cb8bd 100644
--- a/rtc_tools/video_encoder/video_encoder.cc
+++ b/rtc_tools/video_encoder/video_encoder.cc
@@ -392,7 +392,8 @@
     // VP9 profile2 is not implemented at this moment.
     VideoEncoderFactory::CodecSupport support =
         builtin_video_encoder_factory_->QueryCodecSupport(
-            SdpVideoFormat(video_codec_string), scalability_mode_string);
+            SdpVideoFormat(video_codec_string), scalability_mode_string,
+            /*resolution=*/std::nullopt);
     return support.is_supported;
   }
 
diff --git a/sdk/objc/native/src/objc_video_encoder_factory.h b/sdk/objc/native/src/objc_video_encoder_factory.h
index a42f758..39c7571 100644
--- a/sdk/objc/native/src/objc_video_encoder_factory.h
+++ b/sdk/objc/native/src/objc_video_encoder_factory.h
@@ -33,11 +33,13 @@
 
   id<RTC_OBJC_TYPE(RTCVideoEncoderFactory)> wrapped_encoder_factory() const;
 
+  using VideoEncoderFactory::QueryCodecSupport;
   std::vector<SdpVideoFormat> GetSupportedFormats() const override;
   std::vector<SdpVideoFormat> GetImplementations() const override;
   CodecSupport QueryCodecSupport(
       const SdpVideoFormat& format,
-      std::optional<std::string> scalability_mode) const override;
+      std::optional<std::string> scalability_mode,
+      std::optional<Resolution> resolution) const override;
   std::unique_ptr<VideoEncoder> Create(const Environment& env,
                                        const SdpVideoFormat& format) override;
   std::unique_ptr<EncoderSelectorInterface> GetEncoderSelector() const override;
diff --git a/sdk/objc/native/src/objc_video_encoder_factory.mm b/sdk/objc/native/src/objc_video_encoder_factory.mm
index a8ba2db..ba2c5b0 100644
--- a/sdk/objc/native/src/objc_video_encoder_factory.mm
+++ b/sdk/objc/native/src/objc_video_encoder_factory.mm
@@ -212,7 +212,8 @@
 
 VideoEncoderFactory::CodecSupport ObjCVideoEncoderFactory::QueryCodecSupport(
     const SdpVideoFormat &format,
-    std::optional<std::string> scalability_mode) const {
+    std::optional<std::string> scalability_mode,
+    std::optional<Resolution> resolution) const {
   if ([encoder_factory_ respondsToSelector:@selector(queryCodecSupport:
                                                        scalabilityMode:)]) {
     RTC_OBJC_TYPE(RTCVideoCodecInfo) *info = [[RTC_OBJC_TYPE(RTCVideoCodecInfo)
@@ -229,7 +230,8 @@
   }
 
   // Use default implementation.
-  return VideoEncoderFactory::QueryCodecSupport(format, scalability_mode);
+  return VideoEncoderFactory::QueryCodecSupport(
+      format, scalability_mode, resolution);
 }
 
 std::unique_ptr<VideoEncoder> ObjCVideoEncoderFactory::Create(
diff --git a/test/pc/e2e/analyzer/video/BUILD.gn b/test/pc/e2e/analyzer/video/BUILD.gn
index c830de2..96b5faf 100644
--- a/test/pc/e2e/analyzer/video/BUILD.gn
+++ b/test/pc/e2e/analyzer/video/BUILD.gn
@@ -161,6 +161,7 @@
     "../../../../../api/environment",
     "../../../../../api/test/pclf:media_configuration",
     "../../../../../api/video:encoded_image",
+    "../../../../../api/video:resolution",
     "../../../../../api/video:video_bitrate_allocation",
     "../../../../../api/video:video_codec_constants",
     "../../../../../api/video:video_frame",
diff --git a/test/pc/e2e/analyzer/video/quality_analyzing_video_encoder.cc b/test/pc/e2e/analyzer/video/quality_analyzing_video_encoder.cc
index 4b82660..9c26b0b 100644
--- a/test/pc/e2e/analyzer/video/quality_analyzing_video_encoder.cc
+++ b/test/pc/e2e/analyzer/video/quality_analyzing_video_encoder.cc
@@ -26,6 +26,7 @@
 #include "api/fec_controller_override.h"
 #include "api/test/video_quality_analyzer_interface.h"
 #include "api/video/encoded_image.h"
+#include "api/video/resolution.h"
 #include "api/video/video_bitrate_allocation.h"
 #include "api/video/video_codec_constants.h"
 #include "api/video/video_codec_type.h"
@@ -422,8 +423,9 @@
 VideoEncoderFactory::CodecSupport
 QualityAnalyzingVideoEncoderFactory::QueryCodecSupport(
     const SdpVideoFormat& format,
-    std::optional<std::string> scalability_mode) const {
-  return delegate_->QueryCodecSupport(format, scalability_mode);
+    std::optional<std::string> scalability_mode,
+    std::optional<Resolution> resolution) const {
+  return delegate_->QueryCodecSupport(format, scalability_mode, resolution);
 }
 
 std::unique_ptr<VideoEncoder> QualityAnalyzingVideoEncoderFactory::Create(
diff --git a/test/pc/e2e/analyzer/video/quality_analyzing_video_encoder.h b/test/pc/e2e/analyzer/video/quality_analyzing_video_encoder.h
index 0094d22..e797b6a 100644
--- a/test/pc/e2e/analyzer/video/quality_analyzing_video_encoder.h
+++ b/test/pc/e2e/analyzer/video/quality_analyzing_video_encoder.h
@@ -26,6 +26,7 @@
 #include "api/test/pclf/media_configuration.h"
 #include "api/test/video_quality_analyzer_interface.h"
 #include "api/video/encoded_image.h"
+#include "api/video/resolution.h"
 #include "api/video/video_bitrate_allocation.h"
 #include "api/video/video_frame.h"
 #include "api/video/video_frame_type.h"
@@ -184,10 +185,12 @@
   ~QualityAnalyzingVideoEncoderFactory() override;
 
   // Methods of VideoEncoderFactory interface.
+  using VideoEncoderFactory::QueryCodecSupport;
   std::vector<SdpVideoFormat> GetSupportedFormats() const override;
   VideoEncoderFactory::CodecSupport QueryCodecSupport(
       const SdpVideoFormat& format,
-      std::optional<std::string> scalability_mode) const override;
+      std::optional<std::string> scalability_mode,
+      std::optional<Resolution> resolution) const override;
   std::unique_ptr<VideoEncoder> Create(const Environment& env,
                                        const SdpVideoFormat& format) override;