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