blob: 74cb053425f5138aab54750455e0bd960206079d [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"
Mirko Bonadeid9708072019-01-25 19:26:4818#include "api/scoped_refptr.h"
Steve Anton10542f22019-01-11 17:11:0019#include "rtc_base/ref_counted_object.h"
kwiberg65315832017-06-16 17:42:0520
21namespace webrtc {
22
23namespace audio_encoder_factory_template_impl {
24
25template <typename... Ts>
26struct Helper;
27
28// Base case: 0 template parameters.
29template <>
30struct Helper<> {
31 static void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs) {}
Danil Chapovalov0bc58cf2018-06-21 11:32:5632 static absl::optional<AudioCodecInfo> QueryAudioEncoder(
kwiberg65315832017-06-16 17:42:0533 const SdpAudioFormat& format) {
Danil Chapovalov0bc58cf2018-06-21 11:32:5634 return absl::nullopt;
kwiberg65315832017-06-16 17:42:0535 }
36 static std::unique_ptr<AudioEncoder> MakeAudioEncoder(
37 int payload_type,
Karl Wiberg6b542282018-03-05 19:24:5738 const SdpAudioFormat& format,
Danil Chapovalov0bc58cf2018-06-21 11:32:5639 absl::optional<AudioCodecPairId> codec_pair_id) {
kwiberg65315832017-06-16 17:42:0540 return nullptr;
41 }
42};
43
44// Inductive case: Called with n + 1 template parameters; calls subroutines
45// with n template parameters.
46template <typename T, typename... Ts>
47struct Helper<T, Ts...> {
48 static void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs) {
49 T::AppendSupportedEncoders(specs);
50 Helper<Ts...>::AppendSupportedEncoders(specs);
51 }
Danil Chapovalov0bc58cf2018-06-21 11:32:5652 static absl::optional<AudioCodecInfo> QueryAudioEncoder(
kwiberg65315832017-06-16 17:42:0553 const SdpAudioFormat& format) {
54 auto opt_config = T::SdpToConfig(format);
Karl Wiberg7eaf2f92017-11-24 13:17:2755 static_assert(std::is_same<decltype(opt_config),
Danil Chapovalov0bc58cf2018-06-21 11:32:5656 absl::optional<typename T::Config>>::value,
Karl Wiberg7eaf2f92017-11-24 13:17:2757 "T::SdpToConfig() must return a value of type "
Danil Chapovalov0bc58cf2018-06-21 11:32:5658 "absl::optional<T::Config>");
59 return opt_config ? absl::optional<AudioCodecInfo>(
kwiberg65315832017-06-16 17:42:0560 T::QueryAudioEncoder(*opt_config))
61 : Helper<Ts...>::QueryAudioEncoder(format);
62 }
63 static std::unique_ptr<AudioEncoder> MakeAudioEncoder(
64 int payload_type,
Karl Wiberg6b542282018-03-05 19:24:5765 const SdpAudioFormat& format,
Danil Chapovalov0bc58cf2018-06-21 11:32:5666 absl::optional<AudioCodecPairId> codec_pair_id) {
kwiberg65315832017-06-16 17:42:0567 auto opt_config = T::SdpToConfig(format);
68 if (opt_config) {
Karl Wibergf1c470e2018-06-01 09:24:5569 return T::MakeAudioEncoder(*opt_config, payload_type, codec_pair_id);
kwiberg65315832017-06-16 17:42:0570 } else {
Karl Wiberg6b542282018-03-05 19:24:5771 return Helper<Ts...>::MakeAudioEncoder(payload_type, format,
72 codec_pair_id);
kwiberg65315832017-06-16 17:42:0573 }
74 }
75};
76
77template <typename... Ts>
78class AudioEncoderFactoryT : public AudioEncoderFactory {
79 public:
80 std::vector<AudioCodecSpec> GetSupportedEncoders() override {
81 std::vector<AudioCodecSpec> specs;
82 Helper<Ts...>::AppendSupportedEncoders(&specs);
83 return specs;
84 }
85
Danil Chapovalov0bc58cf2018-06-21 11:32:5686 absl::optional<AudioCodecInfo> QueryAudioEncoder(
kwiberg65315832017-06-16 17:42:0587 const SdpAudioFormat& format) override {
88 return Helper<Ts...>::QueryAudioEncoder(format);
89 }
90
91 std::unique_ptr<AudioEncoder> MakeAudioEncoder(
92 int payload_type,
Karl Wiberg6b542282018-03-05 19:24:5793 const SdpAudioFormat& format,
Danil Chapovalov0bc58cf2018-06-21 11:32:5694 absl::optional<AudioCodecPairId> codec_pair_id) override {
Karl Wiberg6b542282018-03-05 19:24:5795 return Helper<Ts...>::MakeAudioEncoder(payload_type, format, codec_pair_id);
kwiberg65315832017-06-16 17:42:0596 }
97};
98
99} // namespace audio_encoder_factory_template_impl
100
101// Make an AudioEncoderFactory that can create instances of the given encoders.
102//
103// Each encoder type is given as a template argument to the function; it should
104// be a struct with the following static member functions:
105//
106// // Converts |audio_format| to a ConfigType instance. Returns an empty
107// // optional if |audio_format| doesn't correctly specify an encoder of our
108// // type.
Danil Chapovalov0bc58cf2018-06-21 11:32:56109// absl::optional<ConfigType> SdpToConfig(const SdpAudioFormat& audio_format);
kwiberg65315832017-06-16 17:42:05110//
111// // Appends zero or more AudioCodecSpecs to the list that will be returned
112// // by AudioEncoderFactory::GetSupportedEncoders().
113// void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs);
114//
115// // Returns information about how this format would be encoded. Used to
116// // implement AudioEncoderFactory::QueryAudioEncoder().
117// AudioCodecInfo QueryAudioEncoder(const ConfigType& config);
118//
119// // Creates an AudioEncoder for the specified format. Used to implement
120// // AudioEncoderFactory::MakeAudioEncoder().
Karl Wiberg6b542282018-03-05 19:24:57121// std::unique_ptr<AudioDecoder> MakeAudioEncoder(
122// const ConfigType& config,
123// int payload_type,
Danil Chapovalov0bc58cf2018-06-21 11:32:56124// absl::optional<AudioCodecPairId> codec_pair_id);
kwiberg65315832017-06-16 17:42:05125//
126// ConfigType should be a type that encapsulates all the settings needed to
Karl Wiberg7eaf2f92017-11-24 13:17:27127// create an AudioEncoder. T::Config (where T is the encoder struct) should
128// either be the config type, or an alias for it.
kwiberg65315832017-06-16 17:42:05129//
130// Whenever it tries to do something, the new factory will try each of the
131// encoders in the order they were specified in the template argument list,
132// stopping at the first one that claims to be able to do the job.
133//
kwiberg65315832017-06-16 17:42:05134// TODO(kwiberg): Point at CreateBuiltinAudioEncoderFactory() for an example of
135// how it is used.
136template <typename... Ts>
137rtc::scoped_refptr<AudioEncoderFactory> CreateAudioEncoderFactory() {
138 // There's no technical reason we couldn't allow zero template parameters,
139 // but such a factory couldn't create any encoders, and callers can do this
140 // by mistake by simply forgetting the <> altogether. So we forbid it in
141 // order to prevent caller foot-shooting.
142 static_assert(sizeof...(Ts) >= 1,
143 "Caller must give at least one template parameter");
144
145 return rtc::scoped_refptr<AudioEncoderFactory>(
146 new rtc::RefCountedObject<
147 audio_encoder_factory_template_impl::AudioEncoderFactoryT<Ts...>>());
148}
149
150} // namespace webrtc
151
Mirko Bonadei92ea95e2017-09-15 04:47:31152#endif // API_AUDIO_CODECS_AUDIO_ENCODER_FACTORY_TEMPLATE_H_