xref: /aosp_15_r20/external/webrtc/api/audio_codecs/audio_decoder_factory_template.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2017 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_AUDIO_CODECS_AUDIO_DECODER_FACTORY_TEMPLATE_H_
12 #define API_AUDIO_CODECS_AUDIO_DECODER_FACTORY_TEMPLATE_H_
13 
14 #include <memory>
15 #include <vector>
16 
17 #include "api/audio_codecs/audio_decoder_factory.h"
18 #include "api/field_trials_view.h"
19 #include "api/make_ref_counted.h"
20 #include "api/scoped_refptr.h"
21 
22 namespace webrtc {
23 
24 namespace audio_decoder_factory_template_impl {
25 
26 template <typename... Ts>
27 struct Helper;
28 
29 // Base case: 0 template parameters.
30 template <>
31 struct Helper<> {
32   static void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs) {}
33   static bool IsSupportedDecoder(const SdpAudioFormat& format) { return false; }
34   static std::unique_ptr<AudioDecoder> MakeAudioDecoder(
35       const SdpAudioFormat& format,
36       absl::optional<AudioCodecPairId> codec_pair_id,
37       const FieldTrialsView* field_trials) {
38     return nullptr;
39   }
40 };
41 
42 // Inductive case: Called with n + 1 template parameters; calls subroutines
43 // with n template parameters.
44 template <typename T, typename... Ts>
45 struct Helper<T, Ts...> {
46   static void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs) {
47     T::AppendSupportedDecoders(specs);
48     Helper<Ts...>::AppendSupportedDecoders(specs);
49   }
50   static bool IsSupportedDecoder(const SdpAudioFormat& format) {
51     auto opt_config = T::SdpToConfig(format);
52     static_assert(std::is_same<decltype(opt_config),
53                                absl::optional<typename T::Config>>::value,
54                   "T::SdpToConfig() must return a value of type "
55                   "absl::optional<T::Config>");
56     return opt_config ? true : Helper<Ts...>::IsSupportedDecoder(format);
57   }
58   static std::unique_ptr<AudioDecoder> MakeAudioDecoder(
59       const SdpAudioFormat& format,
60       absl::optional<AudioCodecPairId> codec_pair_id,
61       const FieldTrialsView* field_trials) {
62     auto opt_config = T::SdpToConfig(format);
63     return opt_config ? T::MakeAudioDecoder(*opt_config, codec_pair_id)
64                       : Helper<Ts...>::MakeAudioDecoder(format, codec_pair_id,
65                                                         field_trials);
66   }
67 };
68 
69 template <typename... Ts>
70 class AudioDecoderFactoryT : public AudioDecoderFactory {
71  public:
72   explicit AudioDecoderFactoryT(const FieldTrialsView* field_trials) {
73     field_trials_ = field_trials;
74   }
75 
76   std::vector<AudioCodecSpec> GetSupportedDecoders() override {
77     std::vector<AudioCodecSpec> specs;
78     Helper<Ts...>::AppendSupportedDecoders(&specs);
79     return specs;
80   }
81 
82   bool IsSupportedDecoder(const SdpAudioFormat& format) override {
83     return Helper<Ts...>::IsSupportedDecoder(format);
84   }
85 
86   std::unique_ptr<AudioDecoder> MakeAudioDecoder(
87       const SdpAudioFormat& format,
88       absl::optional<AudioCodecPairId> codec_pair_id) override {
89     return Helper<Ts...>::MakeAudioDecoder(format, codec_pair_id,
90                                            field_trials_);
91   }
92 
93   const FieldTrialsView* field_trials_;
94 };
95 
96 }  // namespace audio_decoder_factory_template_impl
97 
98 // Make an AudioDecoderFactory that can create instances of the given decoders.
99 //
100 // Each decoder type is given as a template argument to the function; it should
101 // be a struct with the following static member functions:
102 //
103 //   // Converts `audio_format` to a ConfigType instance. Returns an empty
104 //   // optional if `audio_format` doesn't correctly specify a decoder of our
105 //   // type.
106 //   absl::optional<ConfigType> SdpToConfig(const SdpAudioFormat& audio_format);
107 //
108 //   // Appends zero or more AudioCodecSpecs to the list that will be returned
109 //   // by AudioDecoderFactory::GetSupportedDecoders().
110 //   void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs);
111 //
112 //   // Creates an AudioDecoder for the specified format. Used to implement
113 //   // AudioDecoderFactory::MakeAudioDecoder().
114 //   std::unique_ptr<AudioDecoder> MakeAudioDecoder(
115 //       const ConfigType& config,
116 //       absl::optional<AudioCodecPairId> codec_pair_id);
117 //
118 // ConfigType should be a type that encapsulates all the settings needed to
119 // create an AudioDecoder. T::Config (where T is the decoder struct) should
120 // either be the config type, or an alias for it.
121 //
122 // Whenever it tries to do something, the new factory will try each of the
123 // decoder types in the order they were specified in the template argument
124 // list, stopping at the first one that claims to be able to do the job.
125 //
126 // TODO(kwiberg): Point at CreateBuiltinAudioDecoderFactory() for an example of
127 // how it is used.
128 template <typename... Ts>
129 rtc::scoped_refptr<AudioDecoderFactory> CreateAudioDecoderFactory(
130     const FieldTrialsView* field_trials = nullptr) {
131   // There's no technical reason we couldn't allow zero template parameters,
132   // but such a factory couldn't create any decoders, and callers can do this
133   // by mistake by simply forgetting the <> altogether. So we forbid it in
134   // order to prevent caller foot-shooting.
135   static_assert(sizeof...(Ts) >= 1,
136                 "Caller must give at least one template parameter");
137 
138   return rtc::make_ref_counted<
139       audio_decoder_factory_template_impl::AudioDecoderFactoryT<Ts...>>(
140       field_trials);
141 }
142 
143 }  // namespace webrtc
144 
145 #endif  // API_AUDIO_CODECS_AUDIO_DECODER_FACTORY_TEMPLATE_H_
146