1 /* 2 * Copyright (c) 2022 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef API_VIDEO_CODECS_VIDEO_ENCODER_FACTORY_TEMPLATE_H_ 12 #define API_VIDEO_CODECS_VIDEO_ENCODER_FACTORY_TEMPLATE_H_ 13 14 #include <memory> 15 #include <string> 16 #include <vector> 17 18 #include "absl/algorithm/container.h" 19 #include "api/array_view.h" 20 #include "api/video_codecs/video_encoder.h" 21 #include "api/video_codecs/video_encoder_factory.h" 22 #include "modules/video_coding/svc/scalability_mode_util.h" 23 24 namespace webrtc { 25 // The VideoEncoderFactoryTemplate supports encoders implementations given as 26 // template arguments. 27 // 28 // To include an encoder in the factory it requires three static members 29 // functions to be defined: 30 // 31 // // Returns the supported SdpVideoFormats this encoder can produce. 32 // static std::vector<SdpVideoFormat> SupportedFormats(); 33 // 34 // // Creates an encoder instance for the given format. 35 // static std::unique_ptr<VideoEncoder> 36 // CreateEncoder(const SdpVideoFormat& format); 37 // 38 // // Returns true if the encoder supports the given scalability mode. 39 // static bool 40 // IsScalabilityModeSupported(ScalabilityMode scalability_mode); 41 // 42 // Note that the order of the template arguments matter as the factory will 43 // query/return the first encoder implementation supporting the given 44 // SdpVideoFormat. 45 template <typename... Ts> 46 class VideoEncoderFactoryTemplate : public VideoEncoderFactory { 47 public: GetSupportedFormats()48 std::vector<SdpVideoFormat> GetSupportedFormats() const override { 49 return GetSupportedFormatsInternal<Ts...>(); 50 } 51 CreateVideoEncoder(const SdpVideoFormat & format)52 std::unique_ptr<VideoEncoder> CreateVideoEncoder( 53 const SdpVideoFormat& format) override { 54 return CreateVideoEncoderInternal<Ts...>(format); 55 } 56 QueryCodecSupport(const SdpVideoFormat & format,absl::optional<std::string> scalability_mode)57 CodecSupport QueryCodecSupport( 58 const SdpVideoFormat& format, 59 absl::optional<std::string> scalability_mode) const override { 60 return QueryCodecSupportInternal<Ts...>(format, scalability_mode); 61 } 62 63 private: IsFormatInList(const SdpVideoFormat & format,rtc::ArrayView<const SdpVideoFormat> supported_formats)64 bool IsFormatInList( 65 const SdpVideoFormat& format, 66 rtc::ArrayView<const SdpVideoFormat> supported_formats) const { 67 return absl::c_any_of( 68 supported_formats, [&](const SdpVideoFormat& supported_format) { 69 return supported_format.name == format.name && 70 supported_format.parameters == format.parameters; 71 }); 72 } 73 74 template <typename V> IsScalabilityModeSupported(const absl::optional<std::string> & scalability_mode_string)75 bool IsScalabilityModeSupported( 76 const absl::optional<std::string>& scalability_mode_string) const { 77 if (!scalability_mode_string.has_value()) { 78 return true; 79 } 80 absl::optional<ScalabilityMode> scalability_mode = 81 ScalabilityModeFromString(*scalability_mode_string); 82 return scalability_mode.has_value() && 83 V::IsScalabilityModeSupported(*scalability_mode); 84 } 85 86 template <typename V, typename... Vs> GetSupportedFormatsInternal()87 std::vector<SdpVideoFormat> GetSupportedFormatsInternal() const { 88 auto supported_formats = V::SupportedFormats(); 89 90 if constexpr (sizeof...(Vs) > 0) { 91 // Supported formats may overlap between implementations, so duplicates 92 // should be filtered out. 93 for (const auto& other_format : GetSupportedFormatsInternal<Vs...>()) { 94 if (!IsFormatInList(other_format, supported_formats)) { 95 supported_formats.push_back(other_format); 96 } 97 } 98 } 99 100 return supported_formats; 101 } 102 103 template <typename V, typename... Vs> CreateVideoEncoderInternal(const SdpVideoFormat & format)104 std::unique_ptr<VideoEncoder> CreateVideoEncoderInternal( 105 const SdpVideoFormat& format) { 106 if (IsFormatInList(format, V::SupportedFormats())) { 107 return V::CreateEncoder(format); 108 } 109 110 if constexpr (sizeof...(Vs) > 0) { 111 return CreateVideoEncoderInternal<Vs...>(format); 112 } 113 114 return nullptr; 115 } 116 117 template <typename V, typename... Vs> QueryCodecSupportInternal(const SdpVideoFormat & format,const absl::optional<std::string> & scalability_mode)118 CodecSupport QueryCodecSupportInternal( 119 const SdpVideoFormat& format, 120 const absl::optional<std::string>& scalability_mode) const { 121 if (IsFormatInList(format, V::SupportedFormats())) { 122 return {.is_supported = IsScalabilityModeSupported<V>(scalability_mode)}; 123 } 124 125 if constexpr (sizeof...(Vs) > 0) { 126 return QueryCodecSupportInternal<Vs...>(format, scalability_mode); 127 } 128 129 return {.is_supported = false}; 130 } 131 }; 132 133 } // namespace webrtc 134 135 #endif // API_VIDEO_CODECS_VIDEO_ENCODER_FACTORY_TEMPLATE_H_ 136