blob: 8a70ba22681df0e26d1330d5c555ddf62edcf1fc [file] [log] [blame]
kwiberg65315832017-06-16 17:42:051/*
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
Mirko Bonadei92ea95e2017-09-15 04:47:3111#ifndef API_AUDIO_CODECS_AUDIO_ENCODER_FACTORY_TEMPLATE_H_
12#define API_AUDIO_CODECS_AUDIO_ENCODER_FACTORY_TEMPLATE_H_
kwiberg65315832017-06-16 17:42:0513
14#include <memory>
15#include <vector>
16
Mirko Bonadei92ea95e2017-09-15 04:47:3117#include "api/audio_codecs/audio_encoder_factory.h"
Jonas Orelande62c2f22022-03-29 09:04:4818#include "api/field_trials_view.h"
Niels Möller7c8c4db2022-06-13 08:36:3819#include "api/make_ref_counted.h"
Mirko Bonadeid9708072019-01-25 19:26:4820#include "api/scoped_refptr.h"
kwiberg65315832017-06-16 17:42:0521
22namespace webrtc {
23
24namespace audio_encoder_factory_template_impl {
25
26template <typename... Ts>
27struct Helper;
28
29// Base case: 0 template parameters.
30template <>
31struct Helper<> {
32 static void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs) {}
Danil Chapovalov0bc58cf2018-06-21 11:32:5633 static absl::optional<AudioCodecInfo> QueryAudioEncoder(
kwiberg65315832017-06-16 17:42:0534 const SdpAudioFormat& format) {
Danil Chapovalov0bc58cf2018-06-21 11:32:5635 return absl::nullopt;
kwiberg65315832017-06-16 17:42:0536 }
37 static std::unique_ptr<AudioEncoder> MakeAudioEncoder(
38 int payload_type,
Karl Wiberg6b542282018-03-05 19:24:5739 const SdpAudioFormat& format,
Jonas Oreland6e2b9e22022-03-15 13:29:0040 absl::optional<AudioCodecPairId> codec_pair_id,
Jonas Orelande62c2f22022-03-29 09:04:4841 const FieldTrialsView* field_trials) {
kwiberg65315832017-06-16 17:42:0542 return nullptr;
43 }
44};
45
46// Inductive case: Called with n + 1 template parameters; calls subroutines
47// with n template parameters.
48template <typename T, typename... Ts>
49struct Helper<T, Ts...> {
50 static void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs) {
51 T::AppendSupportedEncoders(specs);
52 Helper<Ts...>::AppendSupportedEncoders(specs);
53 }
Danil Chapovalov0bc58cf2018-06-21 11:32:5654 static absl::optional<AudioCodecInfo> QueryAudioEncoder(
kwiberg65315832017-06-16 17:42:0555 const SdpAudioFormat& format) {
56 auto opt_config = T::SdpToConfig(format);
Karl Wiberg7eaf2f92017-11-24 13:17:2757 static_assert(std::is_same<decltype(opt_config),
Danil Chapovalov0bc58cf2018-06-21 11:32:5658 absl::optional<typename T::Config>>::value,
Karl Wiberg7eaf2f92017-11-24 13:17:2759 "T::SdpToConfig() must return a value of type "
Danil Chapovalov0bc58cf2018-06-21 11:32:5660 "absl::optional<T::Config>");
61 return opt_config ? absl::optional<AudioCodecInfo>(
kwiberg65315832017-06-16 17:42:0562 T::QueryAudioEncoder(*opt_config))
63 : Helper<Ts...>::QueryAudioEncoder(format);
64 }
65 static std::unique_ptr<AudioEncoder> MakeAudioEncoder(
66 int payload_type,
Karl Wiberg6b542282018-03-05 19:24:5767 const SdpAudioFormat& format,
Jonas Oreland6e2b9e22022-03-15 13:29:0068 absl::optional<AudioCodecPairId> codec_pair_id,
Jonas Orelande62c2f22022-03-29 09:04:4869 const FieldTrialsView* field_trials) {
kwiberg65315832017-06-16 17:42:0570 auto opt_config = T::SdpToConfig(format);
71 if (opt_config) {
Karl Wibergf1c470e2018-06-01 09:24:5572 return T::MakeAudioEncoder(*opt_config, payload_type, codec_pair_id);
kwiberg65315832017-06-16 17:42:0573 } else {
Karl Wiberg6b542282018-03-05 19:24:5774 return Helper<Ts...>::MakeAudioEncoder(payload_type, format,
Jonas Oreland6e2b9e22022-03-15 13:29:0075 codec_pair_id, field_trials);
kwiberg65315832017-06-16 17:42:0576 }
77 }
78};
79
80template <typename... Ts>
81class AudioEncoderFactoryT : public AudioEncoderFactory {
82 public:
Jonas Orelande62c2f22022-03-29 09:04:4883 explicit AudioEncoderFactoryT(const FieldTrialsView* field_trials) {
Jonas Oreland6e2b9e22022-03-15 13:29:0084 field_trials_ = field_trials;
85 }
86
kwiberg65315832017-06-16 17:42:0587 std::vector<AudioCodecSpec> GetSupportedEncoders() override {
88 std::vector<AudioCodecSpec> specs;
89 Helper<Ts...>::AppendSupportedEncoders(&specs);
90 return specs;
91 }
92
Danil Chapovalov0bc58cf2018-06-21 11:32:5693 absl::optional<AudioCodecInfo> QueryAudioEncoder(
kwiberg65315832017-06-16 17:42:0594 const SdpAudioFormat& format) override {
95 return Helper<Ts...>::QueryAudioEncoder(format);
96 }
97
98 std::unique_ptr<AudioEncoder> MakeAudioEncoder(
99 int payload_type,
Karl Wiberg6b542282018-03-05 19:24:57100 const SdpAudioFormat& format,
Danil Chapovalov0bc58cf2018-06-21 11:32:56101 absl::optional<AudioCodecPairId> codec_pair_id) override {
Jonas Oreland6e2b9e22022-03-15 13:29:00102 return Helper<Ts...>::MakeAudioEncoder(payload_type, format, codec_pair_id,
103 field_trials_);
kwiberg65315832017-06-16 17:42:05104 }
Jonas Oreland6e2b9e22022-03-15 13:29:00105
Jonas Orelande62c2f22022-03-29 09:04:48106 const FieldTrialsView* field_trials_;
kwiberg65315832017-06-16 17:42:05107};
108
109} // namespace audio_encoder_factory_template_impl
110
111// Make an AudioEncoderFactory that can create instances of the given encoders.
112//
113// Each encoder type is given as a template argument to the function; it should
114// be a struct with the following static member functions:
115//
Artem Titov0e61fdd2021-07-25 19:50:14116// // Converts `audio_format` to a ConfigType instance. Returns an empty
117// // optional if `audio_format` doesn't correctly specify an encoder of our
kwiberg65315832017-06-16 17:42:05118// // type.
Danil Chapovalov0bc58cf2018-06-21 11:32:56119// absl::optional<ConfigType> SdpToConfig(const SdpAudioFormat& audio_format);
kwiberg65315832017-06-16 17:42:05120//
121// // Appends zero or more AudioCodecSpecs to the list that will be returned
122// // by AudioEncoderFactory::GetSupportedEncoders().
123// void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs);
124//
125// // Returns information about how this format would be encoded. Used to
126// // implement AudioEncoderFactory::QueryAudioEncoder().
127// AudioCodecInfo QueryAudioEncoder(const ConfigType& config);
128//
129// // Creates an AudioEncoder for the specified format. Used to implement
130// // AudioEncoderFactory::MakeAudioEncoder().
Karl Wiberg6b542282018-03-05 19:24:57131// std::unique_ptr<AudioDecoder> MakeAudioEncoder(
132// const ConfigType& config,
133// int payload_type,
Danil Chapovalov0bc58cf2018-06-21 11:32:56134// absl::optional<AudioCodecPairId> codec_pair_id);
kwiberg65315832017-06-16 17:42:05135//
136// ConfigType should be a type that encapsulates all the settings needed to
Karl Wiberg7eaf2f92017-11-24 13:17:27137// create an AudioEncoder. T::Config (where T is the encoder struct) should
138// either be the config type, or an alias for it.
kwiberg65315832017-06-16 17:42:05139//
140// Whenever it tries to do something, the new factory will try each of the
141// encoders in the order they were specified in the template argument list,
142// stopping at the first one that claims to be able to do the job.
143//
kwiberg65315832017-06-16 17:42:05144// TODO(kwiberg): Point at CreateBuiltinAudioEncoderFactory() for an example of
145// how it is used.
146template <typename... Ts>
Jonas Oreland6e2b9e22022-03-15 13:29:00147rtc::scoped_refptr<AudioEncoderFactory> CreateAudioEncoderFactory(
Jonas Orelande62c2f22022-03-29 09:04:48148 const FieldTrialsView* field_trials = nullptr) {
kwiberg65315832017-06-16 17:42:05149 // There's no technical reason we couldn't allow zero template parameters,
150 // but such a factory couldn't create any encoders, and callers can do this
151 // by mistake by simply forgetting the <> altogether. So we forbid it in
152 // order to prevent caller foot-shooting.
153 static_assert(sizeof...(Ts) >= 1,
154 "Caller must give at least one template parameter");
155
Tomas Gunnarssonc1d58912021-04-22 17:21:43156 return rtc::make_ref_counted<
Jonas Oreland6e2b9e22022-03-15 13:29:00157 audio_encoder_factory_template_impl::AudioEncoderFactoryT<Ts...>>(
158 field_trials);
kwiberg65315832017-06-16 17:42:05159}
160
161} // namespace webrtc
162
Mirko Bonadei92ea95e2017-09-15 04:47:31163#endif // API_AUDIO_CODECS_AUDIO_ENCODER_FACTORY_TEMPLATE_H_