xref: /aosp_15_r20/external/webrtc/api/video_codecs/video_decoder_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_DECODER_FACTORY_TEMPLATE_H_
12 #define API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_TEMPLATE_H_
13 
14 #include <memory>
15 #include <vector>
16 
17 #include "absl/algorithm/container.h"
18 #include "api/array_view.h"
19 #include "api/video_codecs/video_decoder.h"
20 #include "api/video_codecs/video_decoder_factory.h"
21 
22 namespace webrtc {
23 // The VideoDecoderFactoryTemplate supports decoder implementations given as
24 // template arguments.
25 //
26 // To include a decoder in the factory it requires two static members
27 // functions to be defined:
28 //
29 //   // Returns the supported SdpVideoFormats this decoder can decode.
30 //   static std::vector<SdpVideoFormat> SupportedFormats();
31 //
32 //   // Creates a decoder instance for the given format.
33 //   static std::unique_ptr<VideoDecoder>
34 //       CreateDecoder(const SdpVideoFormat& format);
35 //
36 // Note that the order of the template arguments matter as the factory will
37 // return the first decoder implementation supporting the given SdpVideoFormat.
38 template <typename... Ts>
39 class VideoDecoderFactoryTemplate : public VideoDecoderFactory {
40  public:
GetSupportedFormats()41   std::vector<SdpVideoFormat> GetSupportedFormats() const override {
42     return GetSupportedFormatsInternal<Ts...>();
43   }
44 
CreateVideoDecoder(const SdpVideoFormat & format)45   std::unique_ptr<VideoDecoder> CreateVideoDecoder(
46       const SdpVideoFormat& format) override {
47     return CreateVideoDecoderInternal<Ts...>(format);
48   }
49 
50  private:
IsFormatInList(const SdpVideoFormat & format,rtc::ArrayView<const SdpVideoFormat> supported_formats)51   bool IsFormatInList(
52       const SdpVideoFormat& format,
53       rtc::ArrayView<const SdpVideoFormat> supported_formats) const {
54     return absl::c_any_of(
55         supported_formats, [&](const SdpVideoFormat& supported_format) {
56           return supported_format.name == format.name &&
57                  supported_format.parameters == format.parameters;
58         });
59   }
60 
61   template <typename V, typename... Vs>
GetSupportedFormatsInternal()62   std::vector<SdpVideoFormat> GetSupportedFormatsInternal() const {
63     auto supported_formats = V::SupportedFormats();
64 
65     if constexpr (sizeof...(Vs) > 0) {
66       // Supported formats may overlap between implementations, so duplicates
67       // should be filtered out.
68       for (const auto& other_format : GetSupportedFormatsInternal<Vs...>()) {
69         if (!IsFormatInList(other_format, supported_formats)) {
70           supported_formats.push_back(other_format);
71         }
72       }
73     }
74 
75     return supported_formats;
76   }
77 
78   template <typename V, typename... Vs>
CreateVideoDecoderInternal(const SdpVideoFormat & format)79   std::unique_ptr<VideoDecoder> CreateVideoDecoderInternal(
80       const SdpVideoFormat& format) {
81     if (IsFormatInList(format, V::SupportedFormats())) {
82       return V::CreateDecoder(format);
83     }
84 
85     if constexpr (sizeof...(Vs) > 0) {
86       return CreateVideoDecoderInternal<Vs...>(format);
87     }
88 
89     return nullptr;
90   }
91 };
92 
93 }  // namespace webrtc
94 
95 #endif  // API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_TEMPLATE_H_
96