1 /*
2  *  Copyright (c) 2015 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 WEBRTC_MODULES_AUDIO_CODING_ACM2_RENT_A_CODEC_H_
12 #define WEBRTC_MODULES_AUDIO_CODING_ACM2_RENT_A_CODEC_H_
13 
14 #include <stddef.h>
15 #include <map>
16 
17 #include "webrtc/base/array_view.h"
18 #include "webrtc/base/constructormagic.h"
19 #include "webrtc/base/optional.h"
20 #include "webrtc/base/scoped_ptr.h"
21 #include "webrtc/modules/audio_coding/codecs/audio_decoder.h"
22 #include "webrtc/modules/audio_coding/codecs/audio_encoder.h"
23 #include "webrtc/modules/audio_coding/include/audio_coding_module_typedefs.h"
24 #include "webrtc/typedefs.h"
25 
26 #if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
27 #include "webrtc/modules/audio_coding/codecs/isac/locked_bandwidth_info.h"
28 #else
29 // Dummy implementation, for when we don't have iSAC.
30 namespace webrtc {
31 class LockedIsacBandwidthInfo {};
32 }
33 #endif
34 
35 namespace webrtc {
36 
37 struct CodecInst;
38 
39 namespace acm2 {
40 
41 class RentACodec {
42  public:
43   enum class CodecId {
44 #if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
45     kISAC,
46 #endif
47 #ifdef WEBRTC_CODEC_ISAC
48     kISACSWB,
49 #endif
50     // Mono
51     kPCM16B,
52     kPCM16Bwb,
53     kPCM16Bswb32kHz,
54     // Stereo
55     kPCM16B_2ch,
56     kPCM16Bwb_2ch,
57     kPCM16Bswb32kHz_2ch,
58     // Mono
59     kPCMU,
60     kPCMA,
61     // Stereo
62     kPCMU_2ch,
63     kPCMA_2ch,
64 #ifdef WEBRTC_CODEC_ILBC
65     kILBC,
66 #endif
67 #ifdef WEBRTC_CODEC_G722
68     kG722,      // Mono
69     kG722_2ch,  // Stereo
70 #endif
71 #ifdef WEBRTC_CODEC_OPUS
72     kOpus,  // Mono and stereo
73 #endif
74     kCNNB,
75     kCNWB,
76     kCNSWB,
77 #ifdef ENABLE_48000_HZ
78     kCNFB,
79 #endif
80     kAVT,
81 #ifdef WEBRTC_CODEC_RED
82     kRED,
83 #endif
84     kNumCodecs,  // Implementation detail. Don't use.
85 
86 // Set unsupported codecs to -1.
87 #if !defined(WEBRTC_CODEC_ISAC) && !defined(WEBRTC_CODEC_ISACFX)
88     kISAC = -1,
89 #endif
90 #ifndef WEBRTC_CODEC_ISAC
91     kISACSWB = -1,
92 #endif
93     // 48 kHz not supported, always set to -1.
94     kPCM16Bswb48kHz = -1,
95 #ifndef WEBRTC_CODEC_ILBC
96     kILBC = -1,
97 #endif
98 #ifndef WEBRTC_CODEC_G722
99     kG722 = -1,      // Mono
100     kG722_2ch = -1,  // Stereo
101 #endif
102 #ifndef WEBRTC_CODEC_OPUS
103     kOpus = -1,  // Mono and stereo
104 #endif
105 #ifndef WEBRTC_CODEC_RED
106     kRED = -1,
107 #endif
108 #ifndef ENABLE_48000_HZ
109     kCNFB = -1,
110 #endif
111 
112     kNone = -1
113   };
114 
115   enum class NetEqDecoder {
116     kDecoderPCMu,
117     kDecoderPCMa,
118     kDecoderPCMu_2ch,
119     kDecoderPCMa_2ch,
120     kDecoderILBC,
121     kDecoderISAC,
122     kDecoderISACswb,
123     kDecoderPCM16B,
124     kDecoderPCM16Bwb,
125     kDecoderPCM16Bswb32kHz,
126     kDecoderPCM16Bswb48kHz,
127     kDecoderPCM16B_2ch,
128     kDecoderPCM16Bwb_2ch,
129     kDecoderPCM16Bswb32kHz_2ch,
130     kDecoderPCM16Bswb48kHz_2ch,
131     kDecoderPCM16B_5ch,
132     kDecoderG722,
133     kDecoderG722_2ch,
134     kDecoderRED,
135     kDecoderAVT,
136     kDecoderCNGnb,
137     kDecoderCNGwb,
138     kDecoderCNGswb32kHz,
139     kDecoderCNGswb48kHz,
140     kDecoderArbitrary,
141     kDecoderOpus,
142     kDecoderOpus_2ch,
143   };
144 
NumberOfCodecs()145   static inline size_t NumberOfCodecs() {
146     return static_cast<size_t>(CodecId::kNumCodecs);
147   }
148 
CodecIndexFromId(CodecId codec_id)149   static inline rtc::Optional<int> CodecIndexFromId(CodecId codec_id) {
150     const int i = static_cast<int>(codec_id);
151     return i >= 0 && i < static_cast<int>(NumberOfCodecs())
152                ? rtc::Optional<int>(i)
153                : rtc::Optional<int>();
154   }
155 
CodecIdFromIndex(int codec_index)156   static inline rtc::Optional<CodecId> CodecIdFromIndex(int codec_index) {
157     return static_cast<size_t>(codec_index) < NumberOfCodecs()
158                ? rtc::Optional<RentACodec::CodecId>(
159                      static_cast<RentACodec::CodecId>(codec_index))
160                : rtc::Optional<RentACodec::CodecId>();
161   }
162 
163   static rtc::Optional<CodecId> CodecIdByParams(const char* payload_name,
164                                                 int sampling_freq_hz,
165                                                 size_t channels);
166   static rtc::Optional<CodecInst> CodecInstById(CodecId codec_id);
167   static rtc::Optional<CodecId> CodecIdByInst(const CodecInst& codec_inst);
168   static rtc::Optional<CodecInst> CodecInstByParams(const char* payload_name,
169                                                     int sampling_freq_hz,
170                                                     size_t channels);
171   static bool IsCodecValid(const CodecInst& codec_inst);
172 
IsPayloadTypeValid(int payload_type)173   static inline bool IsPayloadTypeValid(int payload_type) {
174     return payload_type >= 0 && payload_type <= 127;
175   }
176 
177   static rtc::ArrayView<const CodecInst> Database();
178 
179   static rtc::Optional<bool> IsSupportedNumChannels(CodecId codec_id,
180                                                     size_t num_channels);
181 
182   static rtc::Optional<NetEqDecoder> NetEqDecoderFromCodecId(
183       CodecId codec_id,
184       size_t num_channels);
185 
186   // Parse codec_inst and extract payload types. If the given CodecInst was for
187   // the wrong sort of codec, return kSkip; otherwise, if the rate was illegal,
188   // return kBadFreq; otherwise, update the given RTP timestamp rate (Hz) ->
189   // payload type map and return kOk.
190   enum class RegistrationResult { kOk, kSkip, kBadFreq };
191   static RegistrationResult RegisterCngPayloadType(std::map<int, int>* pt_map,
192                                                    const CodecInst& codec_inst);
193   static RegistrationResult RegisterRedPayloadType(std::map<int, int>* pt_map,
194                                                    const CodecInst& codec_inst);
195 
196   RentACodec();
197   ~RentACodec();
198 
199   // Creates and returns an audio encoder built to the given specification.
200   // Returns null in case of error. The returned encoder is live until the next
201   // successful call to this function, or until the Rent-A-Codec is destroyed.
202   AudioEncoder* RentEncoder(const CodecInst& codec_inst);
203 
204   struct StackParameters {
205     StackParameters();
206     ~StackParameters();
207 
208     AudioEncoder* speech_encoder = nullptr;
209     bool use_codec_fec = false;
210     bool use_red = false;
211     bool use_cng = false;
212     ACMVADMode vad_mode = VADNormal;
213 
214     // Maps from RTP timestamp rate (in Hz) to payload type.
215     std::map<int, int> cng_payload_types;
216     std::map<int, int> red_payload_types;
217   };
218 
219   // Creates and returns an audio encoder stack constructed to the given
220   // specification. If the specification isn't compatible with the encoder, it
221   // will be changed to match (things will be switched off). The returned
222   // encoder is live until the next successful call to this function, or until
223   // the Rent-A-Codec is destroyed.
224   AudioEncoder* RentEncoderStack(StackParameters* param);
225 
226   // The last return value of RentEncoderStack, or null if it hasn't been
227   // called.
GetEncoderStack()228   AudioEncoder* GetEncoderStack() const { return encoder_stack_; }
229 
230   // Creates and returns an iSAC decoder, which will remain live until the
231   // Rent-A-Codec is destroyed. Subsequent calls will simply return the same
232   // object.
233   AudioDecoder* RentIsacDecoder();
234 
235  private:
236   rtc::scoped_ptr<AudioEncoder> speech_encoder_;
237   rtc::scoped_ptr<AudioEncoder> cng_encoder_;
238   rtc::scoped_ptr<AudioEncoder> red_encoder_;
239   rtc::scoped_ptr<AudioDecoder> isac_decoder_;
240   AudioEncoder* encoder_stack_ = nullptr;
241   LockedIsacBandwidthInfo isac_bandwidth_info_;
242 
243   RTC_DISALLOW_COPY_AND_ASSIGN(RentACodec);
244 };
245 
246 }  // namespace acm2
247 }  // namespace webrtc
248 
249 #endif  // WEBRTC_MODULES_AUDIO_CODING_ACM2_RENT_A_CODEC_H_
250