diff --git a/media/BUILD.gn b/media/BUILD.gn index acfa09f039..d5aa58ce50 100644 --- a/media/BUILD.gn +++ b/media/BUILD.gn @@ -217,7 +217,10 @@ rtc_library("rtc_internal_video_codecs") { "../rtc_base/system:rtc_export", "../test:fake_video_codecs", ] - absl_deps = [ "//third_party/abseil-cpp/absl/strings" ] + absl_deps = [ + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] sources = [ "engine/fake_video_codec_factory.cc", "engine/fake_video_codec_factory.h", @@ -614,6 +617,7 @@ if (rtc_include_tests) { "../modules/video_coding:webrtc_h264", "../modules/video_coding:webrtc_vp8", "../modules/video_coding/codecs/av1:libaom_av1_decoder", + "../modules/video_coding/codecs/av1:libaom_av1_encoder", "../p2p:p2p_test_utils", "../rtc_base", "../rtc_base:checks", @@ -653,6 +657,7 @@ if (rtc_include_tests) { "base/video_common_unittest.cc", "engine/encoder_simulcast_proxy_unittest.cc", "engine/internal_decoder_factory_unittest.cc", + "engine/internal_encoder_factory_unittest.cc", "engine/multiplex_codec_factory_unittest.cc", "engine/null_webrtc_video_engine_unittest.cc", "engine/payload_type_mapper_unittest.cc", diff --git a/media/engine/internal_decoder_factory.cc b/media/engine/internal_decoder_factory.cc index a8d1f00009..c3093189c2 100644 --- a/media/engine/internal_decoder_factory.cc +++ b/media/engine/internal_decoder_factory.cc @@ -12,6 +12,7 @@ #include "absl/strings/match.h" #include "api/video_codecs/sdp_video_format.h" +#include "api/video_codecs/video_codec.h" #include "media/base/codec.h" #include "media/base/media_constants.h" #include "modules/video_coding/codecs/av1/libaom_av1_decoder.h" @@ -36,6 +37,24 @@ std::vector InternalDecoderFactory::GetSupportedFormats() return formats; } +VideoDecoderFactory::CodecSupport InternalDecoderFactory::QueryCodecSupport( + const SdpVideoFormat& format, + bool reference_scaling) 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. + if (reference_scaling) { + VideoCodecType codec = PayloadStringToCodecType(format.name); + if (codec != kVideoCodecVP9 && codec != kVideoCodecAV1) { + return {/*is_supported=*/false, /*is_power_efficient=*/false}; + } + } + + CodecSupport codec_support; + codec_support.is_supported = format.IsCodecInList(GetSupportedFormats()); + return codec_support; +} + std::unique_ptr InternalDecoderFactory::CreateVideoDecoder( const SdpVideoFormat& format) { if (!format.IsCodecInList(GetSupportedFormats())) { diff --git a/media/engine/internal_decoder_factory.h b/media/engine/internal_decoder_factory.h index 2a580dea0b..0129fb2173 100644 --- a/media/engine/internal_decoder_factory.h +++ b/media/engine/internal_decoder_factory.h @@ -24,6 +24,8 @@ namespace webrtc { class RTC_EXPORT InternalDecoderFactory : public VideoDecoderFactory { public: std::vector GetSupportedFormats() const override; + CodecSupport QueryCodecSupport(const SdpVideoFormat& format, + bool reference_scaling) const override; std::unique_ptr CreateVideoDecoder( const SdpVideoFormat& format) override; }; diff --git a/media/engine/internal_decoder_factory_unittest.cc b/media/engine/internal_decoder_factory_unittest.cc index 9d3acee452..d70390f934 100644 --- a/media/engine/internal_decoder_factory_unittest.cc +++ b/media/engine/internal_decoder_factory_unittest.cc @@ -19,39 +19,64 @@ #include "test/gtest.h" namespace webrtc { - +namespace { using ::testing::Contains; using ::testing::Field; using ::testing::Not; -TEST(InternalDecoderFactory, TestVP8) { +#ifdef RTC_ENABLE_VP9 +constexpr bool kVp9Enabled = true; +#else +constexpr bool kVp9Enabled = false; +#endif +#ifdef WEBRTC_USE_H264 +constexpr bool kH264Enabled = true; +#else +constexpr bool kH264Enabled = false; +#endif +constexpr VideoDecoderFactory::CodecSupport kSupported = { + /*is_supported=*/true, /*is_power_efficient=*/false}; +constexpr VideoDecoderFactory::CodecSupport kUnsupported = { + /*is_supported=*/false, /*is_power_efficient=*/false}; + +MATCHER_P(Support, expected, "") { + return arg.is_supported == expected.is_supported && + arg.is_power_efficient == expected.is_power_efficient; +} + +TEST(InternalDecoderFactoryTest, Vp8) { InternalDecoderFactory factory; std::unique_ptr decoder = factory.CreateVideoDecoder(SdpVideoFormat(cricket::kVp8CodecName)); EXPECT_TRUE(decoder); } -#ifdef RTC_ENABLE_VP9 -TEST(InternalDecoderFactory, TestVP9Profile0) { +TEST(InternalDecoderFactoryTest, Vp9Profile0) { InternalDecoderFactory factory; std::unique_ptr decoder = factory.CreateVideoDecoder(SdpVideoFormat( cricket::kVp9CodecName, {{kVP9FmtpProfileId, VP9ProfileToString(VP9Profile::kProfile0)}})); - EXPECT_TRUE(decoder); + EXPECT_EQ(static_cast(decoder), kVp9Enabled); } -TEST(InternalDecoderFactory, TestVP9Profile1) { +TEST(InternalDecoderFactoryTest, Vp9Profile1) { InternalDecoderFactory factory; std::unique_ptr decoder = factory.CreateVideoDecoder(SdpVideoFormat( cricket::kVp9CodecName, {{kVP9FmtpProfileId, VP9ProfileToString(VP9Profile::kProfile1)}})); - EXPECT_TRUE(decoder); + EXPECT_EQ(static_cast(decoder), kVp9Enabled); } -#endif // RTC_ENABLE_VP9 -TEST(InternalDecoderFactory, Av1) { +TEST(InternalDecoderFactoryTest, H264) { + InternalDecoderFactory factory; + std::unique_ptr decoder = + factory.CreateVideoDecoder(SdpVideoFormat(cricket::kH264CodecName)); + EXPECT_EQ(static_cast(decoder), kH264Enabled); +} + +TEST(InternalDecoderFactoryTest, Av1) { InternalDecoderFactory factory; if (kIsLibaomAv1DecoderSupported) { EXPECT_THAT(factory.GetSupportedFormats(), @@ -65,4 +90,45 @@ TEST(InternalDecoderFactory, Av1) { } } +TEST(InternalDecoderFactoryTest, QueryCodecSupportNoReferenceScaling) { + InternalDecoderFactory factory; + EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat(cricket::kVp8CodecName), + /*reference_scaling=*/false), + Support(kSupported)); + EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat(cricket::kVp9CodecName), + /*reference_scaling=*/false), + Support(kVp9Enabled ? kSupported : kUnsupported)); + EXPECT_THAT(factory.QueryCodecSupport( + SdpVideoFormat(cricket::kVp9CodecName, + {{kVP9FmtpProfileId, + VP9ProfileToString(VP9Profile::kProfile1)}}), + /*reference_scaling=*/false), + Support(kVp9Enabled ? kSupported : kUnsupported)); + EXPECT_THAT( + factory.QueryCodecSupport(SdpVideoFormat(cricket::kAv1CodecName), + /*reference_scaling=*/false), + Support(kIsLibaomAv1DecoderSupported ? kSupported : kUnsupported)); +} + +TEST(InternalDecoderFactoryTest, QueryCodecSupportReferenceScaling) { + InternalDecoderFactory factory; + // VP9 and AV1 support for spatial layers. + EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat(cricket::kVp9CodecName), + /*reference_scaling=*/true), + Support(kVp9Enabled ? kSupported : kUnsupported)); + EXPECT_THAT( + factory.QueryCodecSupport(SdpVideoFormat(cricket::kAv1CodecName), + /*reference_scaling=*/true), + Support(kIsLibaomAv1DecoderSupported ? kSupported : kUnsupported)); + + // Invalid config even though VP8 and H264 are supported. + EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat(cricket::kH264CodecName), + /*reference_scaling=*/true), + Support(kUnsupported)); + EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat(cricket::kVp8CodecName), + /*reference_scaling=*/true), + Support(kUnsupported)); +} + +} // namespace } // namespace webrtc diff --git a/media/engine/internal_encoder_factory.cc b/media/engine/internal_encoder_factory.cc index 738516eafc..bb550662f9 100644 --- a/media/engine/internal_encoder_factory.cc +++ b/media/engine/internal_encoder_factory.cc @@ -57,4 +57,38 @@ std::unique_ptr InternalEncoderFactory::CreateVideoEncoder( return nullptr; } +VideoEncoderFactory::CodecSupport InternalEncoderFactory::QueryCodecSupport( + const SdpVideoFormat& format, + absl::optional scalability_mode) const { + // Query for supported formats and check if the specified format is supported. + // Begin with filtering out unsupported scalability modes. + if (scalability_mode) { + bool scalability_mode_supported = false; + if (absl::EqualsIgnoreCase(format.name, cricket::kVp8CodecName)) { + scalability_mode_supported = + VP8Encoder::SupportsScalabilityMode(*scalability_mode); + } else if (absl::EqualsIgnoreCase(format.name, cricket::kVp9CodecName)) { + scalability_mode_supported = + VP9Encoder::SupportsScalabilityMode(*scalability_mode); + } else if (absl::EqualsIgnoreCase(format.name, cricket::kH264CodecName)) { + scalability_mode_supported = + H264Encoder::SupportsScalabilityMode(*scalability_mode); + } else if (kIsLibaomAv1EncoderSupported && + absl::EqualsIgnoreCase(format.name, cricket::kAv1CodecName)) { + scalability_mode_supported = + LibaomAv1EncoderSupportsScalabilityMode(*scalability_mode); + } + + static constexpr VideoEncoderFactory::CodecSupport kUnsupported = { + /*is_supported=*/false, /*is_power_efficient=*/false}; + if (!scalability_mode_supported) { + return kUnsupported; + } + } + + CodecSupport codec_support; + codec_support.is_supported = format.IsCodecInList(GetSupportedFormats()); + return codec_support; +} + } // namespace webrtc diff --git a/media/engine/internal_encoder_factory.h b/media/engine/internal_encoder_factory.h index 3f43e461a7..e12810cd30 100644 --- a/media/engine/internal_encoder_factory.h +++ b/media/engine/internal_encoder_factory.h @@ -12,8 +12,10 @@ #define MEDIA_ENGINE_INTERNAL_ENCODER_FACTORY_H_ #include +#include #include +#include "absl/types/optional.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,7 +27,9 @@ class RTC_EXPORT InternalEncoderFactory : public VideoEncoderFactory { public: static std::vector SupportedFormats(); std::vector GetSupportedFormats() const override; - + CodecSupport QueryCodecSupport( + const SdpVideoFormat& format, + absl::optional scalability_mode) const override; std::unique_ptr CreateVideoEncoder( const SdpVideoFormat& format) override; }; diff --git a/media/engine/internal_encoder_factory_unittest.cc b/media/engine/internal_encoder_factory_unittest.cc new file mode 100644 index 0000000000..3365e59696 --- /dev/null +++ b/media/engine/internal_encoder_factory_unittest.cc @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "media/engine/internal_encoder_factory.h" + +#include "api/video_codecs/sdp_video_format.h" +#include "api/video_codecs/video_encoder.h" +#include "api/video_codecs/vp9_profile.h" +#include "media/base/media_constants.h" +#include "modules/video_coding/codecs/av1/libaom_av1_encoder.h" +#include "test/gmock.h" +#include "test/gtest.h" + +namespace webrtc { +namespace { +using ::testing::Contains; +using ::testing::Field; +using ::testing::Not; + +#ifdef RTC_ENABLE_VP9 +constexpr bool kVp9Enabled = true; +#else +constexpr bool kVp9Enabled = false; +#endif +#ifdef WEBRTC_USE_H264 +constexpr bool kH264Enabled = true; +#else +constexpr bool kH264Enabled = false; +#endif +constexpr VideoEncoderFactory::CodecSupport kSupported = { + /*is_supported=*/true, /*is_power_efficient=*/false}; +constexpr VideoEncoderFactory::CodecSupport kUnsupported = { + /*is_supported=*/false, /*is_power_efficient=*/false}; + +MATCHER_P(Support, expected, "") { + return arg.is_supported == expected.is_supported && + arg.is_power_efficient == expected.is_power_efficient; +} + +TEST(InternalEncoderFactoryTest, Vp8) { + InternalEncoderFactory factory; + std::unique_ptr encoder = + factory.CreateVideoEncoder(SdpVideoFormat(cricket::kVp8CodecName)); + EXPECT_TRUE(encoder); +} + +TEST(InternalEncoderFactoryTest, Vp9Profile0) { + InternalEncoderFactory factory; + if (kVp9Enabled) { + std::unique_ptr encoder = + factory.CreateVideoEncoder(SdpVideoFormat( + cricket::kVp9CodecName, + {{kVP9FmtpProfileId, VP9ProfileToString(VP9Profile::kProfile0)}})); + EXPECT_TRUE(encoder); + } else { + EXPECT_THAT( + factory.GetSupportedFormats(), + Not(Contains(Field(&SdpVideoFormat::name, cricket::kVp9CodecName)))); + } +} + +TEST(InternalEncoderFactoryTest, H264) { + InternalEncoderFactory factory; + if (kH264Enabled) { + std::unique_ptr encoder = + factory.CreateVideoEncoder(SdpVideoFormat(cricket::kH264CodecName)); + EXPECT_TRUE(encoder); + } else { + EXPECT_THAT( + factory.GetSupportedFormats(), + Not(Contains(Field(&SdpVideoFormat::name, cricket::kH264CodecName)))); + } +} + +TEST(InternalEncoderFactoryTest, Av1) { + InternalEncoderFactory factory; + if (kIsLibaomAv1EncoderSupported) { + EXPECT_THAT(factory.GetSupportedFormats(), + Contains(Field(&SdpVideoFormat::name, cricket::kAv1CodecName))); + EXPECT_TRUE( + factory.CreateVideoEncoder(SdpVideoFormat(cricket::kAv1CodecName))); + } else { + EXPECT_THAT( + factory.GetSupportedFormats(), + Not(Contains(Field(&SdpVideoFormat::name, cricket::kAv1CodecName)))); + } +} + +TEST(InternalEncoderFactoryTest, QueryCodecSupportNoScalabilityMode) { + InternalEncoderFactory factory; + EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat(cricket::kVp8CodecName), + /*scalability_mode=*/absl::nullopt), + Support(kSupported)); + EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat(cricket::kVp9CodecName), + /*scalability_mode=*/absl::nullopt), + Support(kVp9Enabled ? kSupported : kUnsupported)); + EXPECT_THAT( + factory.QueryCodecSupport(SdpVideoFormat(cricket::kAv1CodecName), + /*scalability_mode=*/absl::nullopt), + Support(kIsLibaomAv1EncoderSupported ? kSupported : kUnsupported)); +} + +TEST(InternalEncoderFactoryTest, QueryCodecSupportWithScalabilityMode) { + InternalEncoderFactory factory; + // VP8 and VP9 supported for singles spatial layers. + EXPECT_THAT( + factory.QueryCodecSupport(SdpVideoFormat(cricket::kVp8CodecName), "L1T2"), + Support(kSupported)); + EXPECT_THAT( + factory.QueryCodecSupport(SdpVideoFormat(cricket::kVp9CodecName), "L1T3"), + Support(kVp9Enabled ? kSupported : kUnsupported)); + + // VP9 support for spatial layers. + EXPECT_THAT( + factory.QueryCodecSupport(SdpVideoFormat(cricket::kVp9CodecName), "L3T3"), + Support(kVp9Enabled ? kSupported : kUnsupported)); + + EXPECT_THAT( + factory.QueryCodecSupport(SdpVideoFormat(cricket::kAv1CodecName), "L2T1"), + Support(kIsLibaomAv1EncoderSupported ? kSupported : kUnsupported)); + + // Invalid scalability modes even though VP8 and H264 are supported. + EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat(cricket::kH264CodecName), + "L2T2"), + Support(kUnsupported)); + EXPECT_THAT( + factory.QueryCodecSupport(SdpVideoFormat(cricket::kVp8CodecName), "L3T3"), + Support(kUnsupported)); +} + +} // namespace +} // namespace webrtc diff --git a/modules/video_coding/BUILD.gn b/modules/video_coding/BUILD.gn index 500c87d8ad..129d4eab5c 100644 --- a/modules/video_coding/BUILD.gn +++ b/modules/video_coding/BUILD.gn @@ -568,6 +568,7 @@ rtc_library("webrtc_vp8") { ] absl_deps = [ "//third_party/abseil-cpp/absl/algorithm:container", + "//third_party/abseil-cpp/absl/strings:strings", "//third_party/abseil-cpp/absl/types:optional", ] if (rtc_build_libvpx) { diff --git a/modules/video_coding/codecs/av1/BUILD.gn b/modules/video_coding/codecs/av1/BUILD.gn index e7c901cc9a..8162d359eb 100644 --- a/modules/video_coding/codecs/av1/BUILD.gn +++ b/modules/video_coding/codecs/av1/BUILD.gn @@ -60,6 +60,7 @@ rtc_library("libaom_av1_encoder") { absl_deps = [ "//third_party/abseil-cpp/absl/algorithm:container", "//third_party/abseil-cpp/absl/base:core_headers", + "//third_party/abseil-cpp/absl/strings:strings", "//third_party/abseil-cpp/absl/types:optional", ] diff --git a/modules/video_coding/codecs/av1/libaom_av1_encoder.cc b/modules/video_coding/codecs/av1/libaom_av1_encoder.cc index a814c745c3..9c7cc89afc 100644 --- a/modules/video_coding/codecs/av1/libaom_av1_encoder.cc +++ b/modules/video_coding/codecs/av1/libaom_av1_encoder.cc @@ -806,4 +806,11 @@ std::unique_ptr CreateLibaomAv1Encoder() { return std::make_unique(); } +bool LibaomAv1EncoderSupportsScalabilityMode( + absl::string_view scalability_mode) { + // For AV1, the scalability mode is supported if we can create the scalability + // structure. + return ScalabilityStructureConfig(scalability_mode) != absl::nullopt; +} + } // namespace webrtc diff --git a/modules/video_coding/codecs/av1/libaom_av1_encoder.h b/modules/video_coding/codecs/av1/libaom_av1_encoder.h index 4b0ee28d40..0d81c9c17e 100644 --- a/modules/video_coding/codecs/av1/libaom_av1_encoder.h +++ b/modules/video_coding/codecs/av1/libaom_av1_encoder.h @@ -13,6 +13,7 @@ #include #include "absl/base/attributes.h" +#include "absl/strings/string_view.h" #include "api/video_codecs/video_encoder.h" namespace webrtc { @@ -20,6 +21,8 @@ namespace webrtc { ABSL_CONST_INIT extern const bool kIsLibaomAv1EncoderSupported; std::unique_ptr CreateLibaomAv1Encoder(); +bool LibaomAv1EncoderSupportsScalabilityMode( + absl::string_view scalability_mode); } // namespace webrtc diff --git a/modules/video_coding/codecs/av1/libaom_av1_encoder_absent.cc b/modules/video_coding/codecs/av1/libaom_av1_encoder_absent.cc index f394260865..fff1dd9ed8 100644 --- a/modules/video_coding/codecs/av1/libaom_av1_encoder_absent.cc +++ b/modules/video_coding/codecs/av1/libaom_av1_encoder_absent.cc @@ -21,4 +21,9 @@ std::unique_ptr CreateLibaomAv1Encoder() { return nullptr; } +bool LibaomAv1EncoderSupportsScalabilityMode( + absl::string_view scalability_mode) { + return false; +} + } // namespace webrtc diff --git a/modules/video_coding/codecs/h264/h264.cc b/modules/video_coding/codecs/h264/h264.cc index 14e1691153..275e634409 100644 --- a/modules/video_coding/codecs/h264/h264.cc +++ b/modules/video_coding/codecs/h264/h264.cc @@ -44,6 +44,8 @@ bool IsH264CodecSupported() { #endif } +constexpr absl::string_view kSupportedScalabilityModes[] = {"L1T2", "L1T3"}; + } // namespace SdpVideoFormat CreateH264Format(H264Profile profile, @@ -105,6 +107,15 @@ bool H264Encoder::IsSupported() { return IsH264CodecSupported(); } +bool H264Encoder::SupportsScalabilityMode(absl::string_view scalability_mode) { + for (const auto& entry : kSupportedScalabilityModes) { + if (entry == scalability_mode) { + return true; + } + } + return false; +} + std::unique_ptr H264Decoder::Create() { RTC_DCHECK(H264Decoder::IsSupported()); #if defined(WEBRTC_USE_H264) diff --git a/modules/video_coding/codecs/h264/include/h264.h b/modules/video_coding/codecs/h264/include/h264.h index bffd31cf8d..8d1eebc79b 100644 --- a/modules/video_coding/codecs/h264/include/h264.h +++ b/modules/video_coding/codecs/h264/include/h264.h @@ -16,6 +16,7 @@ #include #include +#include "absl/strings/string_view.h" #include "api/video_codecs/h264_profile_level_id.h" #include "media/base/codec.h" #include "modules/video_coding/include/video_codec_interface.h" @@ -46,6 +47,7 @@ class RTC_EXPORT H264Encoder : public VideoEncoder { static std::unique_ptr Create(const cricket::VideoCodec& codec); // If H.264 is supported (any implementation). static bool IsSupported(); + static bool SupportsScalabilityMode(absl::string_view scalability_mode); ~H264Encoder() override {} }; diff --git a/modules/video_coding/codecs/vp8/include/vp8.h b/modules/video_coding/codecs/vp8/include/vp8.h index d05c3a68d1..22f8de623d 100644 --- a/modules/video_coding/codecs/vp8/include/vp8.h +++ b/modules/video_coding/codecs/vp8/include/vp8.h @@ -15,6 +15,7 @@ #include #include "absl/base/attributes.h" +#include "absl/strings/string_view.h" #include "api/video_codecs/video_encoder.h" #include "api/video_codecs/vp8_frame_buffer_controller.h" #include "modules/video_coding/include/video_codec_interface.h" @@ -39,6 +40,7 @@ class VP8Encoder { static std::unique_ptr Create(); static std::unique_ptr Create(Settings settings); + static bool SupportsScalabilityMode(absl::string_view scalability_mode); ABSL_DEPRECATED("") static std::unique_ptr Create( diff --git a/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc b/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc index 1f70569526..88b840cb43 100644 --- a/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc +++ b/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc @@ -49,6 +49,8 @@ constexpr char kVP8IosMaxNumberOfThreadFieldTrial[] = constexpr char kVP8IosMaxNumberOfThreadFieldTrialParameter[] = "max_thread"; #endif +constexpr absl::string_view kSupportedScalabilityModes[] = {"L1T2", "L1T3"}; + constexpr char kVp8ForcePartitionResilience[] = "WebRTC-VP8-ForcePartitionResilience"; @@ -230,6 +232,15 @@ std::unique_ptr VP8Encoder::Create( std::move(settings)); } +bool VP8Encoder::SupportsScalabilityMode(absl::string_view scalability_mode) { + for (const auto& entry : kSupportedScalabilityModes) { + if (entry == scalability_mode) { + return true; + } + } + return false; +} + vpx_enc_frame_flags_t LibvpxVp8Encoder::EncodeFlags( const Vp8FrameConfig& references) { RTC_DCHECK(!references.drop_frame); diff --git a/modules/video_coding/codecs/vp9/include/vp9.h b/modules/video_coding/codecs/vp9/include/vp9.h index 7294de2f33..829680a806 100644 --- a/modules/video_coding/codecs/vp9/include/vp9.h +++ b/modules/video_coding/codecs/vp9/include/vp9.h @@ -15,6 +15,7 @@ #include #include +#include "absl/strings/string_view.h" #include "api/video_codecs/sdp_video_format.h" #include "media/base/codec.h" #include "modules/video_coding/include/video_codec_interface.h" @@ -36,6 +37,7 @@ class VP9Encoder : public VideoEncoder { static std::unique_ptr Create(); // Parses VP9 Profile from `codec` and returns the appropriate implementation. static std::unique_ptr Create(const cricket::VideoCodec& codec); + static bool SupportsScalabilityMode(absl::string_view scalability_mode); ~VP9Encoder() override {} }; diff --git a/modules/video_coding/codecs/vp9/vp9.cc b/modules/video_coding/codecs/vp9/vp9.cc index d9caf0f039..9570e53f33 100644 --- a/modules/video_coding/codecs/vp9/vp9.cc +++ b/modules/video_coding/codecs/vp9/vp9.cc @@ -23,6 +23,13 @@ #include "vpx/vpx_codec.h" namespace webrtc { +namespace { +constexpr absl::string_view kSupportedScalabilityModes[] = { + "L1T2", "L1T3", "L2T1", "L2T2", "L2T3", "L3T1", + "L3T2", "L3T3", "L1T2h", "L1T3h", "L2T1h", "L2T2h", + "L2T3h", "L3T1h", "L3T2h", "L3T3h", "L2T2_KEY", "L2T3_KEY", + "L3T1_KEY", "L3T2_KEY", "L3T3_KEY"}; +} // namespace std::vector SupportedVP9Codecs() { #ifdef RTC_ENABLE_VP9 @@ -86,6 +93,15 @@ std::unique_ptr VP9Encoder::Create( #endif } +bool VP9Encoder::SupportsScalabilityMode(absl::string_view scalability_mode) { + for (const auto& entry : kSupportedScalabilityModes) { + if (entry == scalability_mode) { + return true; + } + } + return false; +} + std::unique_ptr VP9Decoder::Create() { #ifdef RTC_ENABLE_VP9 return std::make_unique();