xref: /aosp_15_r20/external/webrtc/api/video_codecs/video_encoder_factory_template.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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