Line data Source code
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 : #include "webrtc/modules/audio_coding/acm2/rent_a_codec.h"
12 :
13 : #include <memory>
14 : #include <utility>
15 :
16 : #include "webrtc/base/logging.h"
17 : #include "webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.h"
18 : #include "webrtc/modules/audio_coding/codecs/g711/audio_encoder_pcm.h"
19 : #ifdef WEBRTC_CODEC_G722
20 : #include "webrtc/modules/audio_coding/codecs/g722/audio_encoder_g722.h"
21 : #endif
22 : #ifdef WEBRTC_CODEC_ILBC
23 : #include "webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h"
24 : #endif
25 : #ifdef WEBRTC_CODEC_ISACFX
26 : #include "webrtc/modules/audio_coding/codecs/isac/fix/include/audio_decoder_isacfix.h"
27 : #include "webrtc/modules/audio_coding/codecs/isac/fix/include/audio_encoder_isacfix.h"
28 : #endif
29 : #ifdef WEBRTC_CODEC_ISAC
30 : #include "webrtc/modules/audio_coding/codecs/isac/main/include/audio_decoder_isac.h"
31 : #include "webrtc/modules/audio_coding/codecs/isac/main/include/audio_encoder_isac.h"
32 : #endif
33 : #ifdef WEBRTC_CODEC_OPUS
34 : #include "webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.h"
35 : #endif
36 : #include "webrtc/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h"
37 : #ifdef WEBRTC_CODEC_RED
38 : #include "webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.h"
39 : #endif
40 : #include "webrtc/modules/audio_coding/acm2/acm_codec_database.h"
41 : #include "webrtc/modules/audio_coding/acm2/acm_common_defs.h"
42 :
43 : #if defined(WEBRTC_CODEC_ISACFX) || defined(WEBRTC_CODEC_ISAC)
44 : #include "webrtc/modules/audio_coding/codecs/isac/locked_bandwidth_info.h"
45 : #endif
46 :
47 : namespace webrtc {
48 : namespace acm2 {
49 :
50 0 : rtc::Optional<SdpAudioFormat> RentACodec::NetEqDecoderToSdpAudioFormat(
51 : NetEqDecoder nd) {
52 0 : switch (nd) {
53 : case NetEqDecoder::kDecoderPCMu:
54 0 : return rtc::Optional<SdpAudioFormat>(SdpAudioFormat("pcmu", 8000, 1));
55 : case NetEqDecoder::kDecoderPCMa:
56 0 : return rtc::Optional<SdpAudioFormat>(SdpAudioFormat("pcma", 8000, 1));
57 : case NetEqDecoder::kDecoderPCMu_2ch:
58 0 : return rtc::Optional<SdpAudioFormat>(SdpAudioFormat("pcmu", 8000, 2));
59 : case NetEqDecoder::kDecoderPCMa_2ch:
60 0 : return rtc::Optional<SdpAudioFormat>(SdpAudioFormat("pcma", 8000, 2));
61 : case NetEqDecoder::kDecoderILBC:
62 0 : return rtc::Optional<SdpAudioFormat>(SdpAudioFormat("ilbc", 8000, 1));
63 : case NetEqDecoder::kDecoderISAC:
64 0 : return rtc::Optional<SdpAudioFormat>(SdpAudioFormat("isac", 16000, 1));
65 : case NetEqDecoder::kDecoderISACswb:
66 0 : return rtc::Optional<SdpAudioFormat>(SdpAudioFormat("isac", 32000, 1));
67 : case NetEqDecoder::kDecoderPCM16B:
68 0 : return rtc::Optional<SdpAudioFormat>(SdpAudioFormat("l16", 8000, 1));
69 : case NetEqDecoder::kDecoderPCM16Bwb:
70 0 : return rtc::Optional<SdpAudioFormat>(SdpAudioFormat("l16", 16000, 1));
71 : case NetEqDecoder::kDecoderPCM16Bswb32kHz:
72 0 : return rtc::Optional<SdpAudioFormat>(SdpAudioFormat("l16", 32000, 1));
73 : case NetEqDecoder::kDecoderPCM16Bswb48kHz:
74 0 : return rtc::Optional<SdpAudioFormat>(SdpAudioFormat("l16", 48000, 1));
75 : case NetEqDecoder::kDecoderPCM16B_2ch:
76 0 : return rtc::Optional<SdpAudioFormat>(SdpAudioFormat("l16", 8000, 2));
77 : case NetEqDecoder::kDecoderPCM16Bwb_2ch:
78 0 : return rtc::Optional<SdpAudioFormat>(SdpAudioFormat("l16", 16000, 2));
79 : case NetEqDecoder::kDecoderPCM16Bswb32kHz_2ch:
80 0 : return rtc::Optional<SdpAudioFormat>(SdpAudioFormat("l16", 32000, 2));
81 : case NetEqDecoder::kDecoderPCM16Bswb48kHz_2ch:
82 0 : return rtc::Optional<SdpAudioFormat>(SdpAudioFormat("l16", 48000, 2));
83 : case NetEqDecoder::kDecoderPCM16B_5ch:
84 0 : return rtc::Optional<SdpAudioFormat>(SdpAudioFormat("l16", 8000, 5));
85 : case NetEqDecoder::kDecoderG722:
86 0 : return rtc::Optional<SdpAudioFormat>(SdpAudioFormat("g722", 8000, 1));
87 : case NetEqDecoder::kDecoderG722_2ch:
88 0 : return rtc::Optional<SdpAudioFormat>(SdpAudioFormat("g722", 8000, 2));
89 : case NetEqDecoder::kDecoderOpus:
90 : return rtc::Optional<SdpAudioFormat>(
91 0 : SdpAudioFormat("opus", 48000, 2,
92 0 : std::map<std::string, std::string>{{"stereo", "0"}}));
93 : case NetEqDecoder::kDecoderOpus_2ch:
94 : return rtc::Optional<SdpAudioFormat>(
95 0 : SdpAudioFormat("opus", 48000, 2,
96 0 : std::map<std::string, std::string>{{"stereo", "1"}}));
97 : case NetEqDecoder::kDecoderRED:
98 0 : return rtc::Optional<SdpAudioFormat>(SdpAudioFormat("red", 8000, 1));
99 : case NetEqDecoder::kDecoderAVT:
100 : return rtc::Optional<SdpAudioFormat>(
101 0 : SdpAudioFormat("telephone-event", 8000, 1));
102 : case NetEqDecoder::kDecoderAVT16kHz:
103 : return rtc::Optional<SdpAudioFormat>(
104 0 : SdpAudioFormat("telephone-event", 16000, 1));
105 : case NetEqDecoder::kDecoderAVT32kHz:
106 : return rtc::Optional<SdpAudioFormat>(
107 0 : SdpAudioFormat("telephone-event", 32000, 1));
108 : case NetEqDecoder::kDecoderAVT48kHz:
109 : return rtc::Optional<SdpAudioFormat>(
110 0 : SdpAudioFormat("telephone-event", 48000, 1));
111 : case NetEqDecoder::kDecoderCNGnb:
112 0 : return rtc::Optional<SdpAudioFormat>(SdpAudioFormat("cn", 8000, 1));
113 : case NetEqDecoder::kDecoderCNGwb:
114 0 : return rtc::Optional<SdpAudioFormat>(SdpAudioFormat("cn", 16000, 1));
115 : case NetEqDecoder::kDecoderCNGswb32kHz:
116 0 : return rtc::Optional<SdpAudioFormat>(SdpAudioFormat("cn", 32000, 1));
117 : case NetEqDecoder::kDecoderCNGswb48kHz:
118 0 : return rtc::Optional<SdpAudioFormat>(SdpAudioFormat("cn", 48000, 1));
119 : default:
120 0 : return rtc::Optional<SdpAudioFormat>();
121 : }
122 : }
123 :
124 0 : rtc::Optional<RentACodec::CodecId> RentACodec::CodecIdByParams(
125 : const char* payload_name,
126 : int sampling_freq_hz,
127 : size_t channels) {
128 : return CodecIdFromIndex(
129 0 : ACMCodecDB::CodecId(payload_name, sampling_freq_hz, channels));
130 : }
131 :
132 0 : rtc::Optional<CodecInst> RentACodec::CodecInstById(CodecId codec_id) {
133 0 : rtc::Optional<int> mi = CodecIndexFromId(codec_id);
134 0 : return mi ? rtc::Optional<CodecInst>(Database()[*mi])
135 0 : : rtc::Optional<CodecInst>();
136 : }
137 :
138 0 : rtc::Optional<RentACodec::CodecId> RentACodec::CodecIdByInst(
139 : const CodecInst& codec_inst) {
140 0 : return CodecIdFromIndex(ACMCodecDB::CodecNumber(codec_inst));
141 : }
142 :
143 0 : rtc::Optional<CodecInst> RentACodec::CodecInstByParams(const char* payload_name,
144 : int sampling_freq_hz,
145 : size_t channels) {
146 : rtc::Optional<CodecId> codec_id =
147 0 : CodecIdByParams(payload_name, sampling_freq_hz, channels);
148 0 : if (!codec_id)
149 0 : return rtc::Optional<CodecInst>();
150 0 : rtc::Optional<CodecInst> ci = CodecInstById(*codec_id);
151 0 : RTC_DCHECK(ci);
152 :
153 : // Keep the number of channels from the function call. For most codecs it
154 : // will be the same value as in default codec settings, but not for all.
155 0 : ci->channels = channels;
156 :
157 0 : return ci;
158 : }
159 :
160 0 : bool RentACodec::IsCodecValid(const CodecInst& codec_inst) {
161 0 : return ACMCodecDB::CodecNumber(codec_inst) >= 0;
162 : }
163 :
164 0 : rtc::Optional<bool> RentACodec::IsSupportedNumChannels(CodecId codec_id,
165 : size_t num_channels) {
166 0 : auto i = CodecIndexFromId(codec_id);
167 : return i ? rtc::Optional<bool>(
168 0 : ACMCodecDB::codec_settings_[*i].channel_support >=
169 : num_channels)
170 0 : : rtc::Optional<bool>();
171 : }
172 :
173 0 : rtc::ArrayView<const CodecInst> RentACodec::Database() {
174 0 : return rtc::ArrayView<const CodecInst>(ACMCodecDB::database_,
175 0 : NumberOfCodecs());
176 : }
177 :
178 0 : rtc::Optional<NetEqDecoder> RentACodec::NetEqDecoderFromCodecId(
179 : CodecId codec_id,
180 : size_t num_channels) {
181 0 : rtc::Optional<int> i = CodecIndexFromId(codec_id);
182 0 : if (!i)
183 0 : return rtc::Optional<NetEqDecoder>();
184 0 : const NetEqDecoder ned = ACMCodecDB::neteq_decoders_[*i];
185 : return rtc::Optional<NetEqDecoder>(
186 0 : (ned == NetEqDecoder::kDecoderOpus && num_channels == 2)
187 0 : ? NetEqDecoder::kDecoderOpus_2ch
188 0 : : ned);
189 : }
190 :
191 0 : RentACodec::RegistrationResult RentACodec::RegisterCngPayloadType(
192 : std::map<int, int>* pt_map,
193 : const CodecInst& codec_inst) {
194 0 : if (STR_CASE_CMP(codec_inst.plname, "CN") != 0)
195 0 : return RegistrationResult::kSkip;
196 0 : switch (codec_inst.plfreq) {
197 : case 8000:
198 : case 16000:
199 : case 32000:
200 : case 48000:
201 0 : (*pt_map)[codec_inst.plfreq] = codec_inst.pltype;
202 0 : return RegistrationResult::kOk;
203 : default:
204 0 : return RegistrationResult::kBadFreq;
205 : }
206 : }
207 :
208 0 : RentACodec::RegistrationResult RentACodec::RegisterRedPayloadType(
209 : std::map<int, int>* pt_map,
210 : const CodecInst& codec_inst) {
211 0 : if (STR_CASE_CMP(codec_inst.plname, "RED") != 0)
212 0 : return RegistrationResult::kSkip;
213 0 : switch (codec_inst.plfreq) {
214 : case 8000:
215 0 : (*pt_map)[codec_inst.plfreq] = codec_inst.pltype;
216 0 : return RegistrationResult::kOk;
217 : default:
218 0 : return RegistrationResult::kBadFreq;
219 : }
220 : }
221 :
222 : namespace {
223 :
224 : // Returns a new speech encoder, or null on error.
225 : // TODO(kwiberg): Don't handle errors here (bug 5033)
226 0 : std::unique_ptr<AudioEncoder> CreateEncoder(
227 : const CodecInst& speech_inst,
228 : const rtc::scoped_refptr<LockedIsacBandwidthInfo>& bwinfo) {
229 : #if defined(WEBRTC_CODEC_ISACFX)
230 : if (STR_CASE_CMP(speech_inst.plname, "isac") == 0)
231 : return std::unique_ptr<AudioEncoder>(
232 : new AudioEncoderIsacFix(speech_inst, bwinfo));
233 : #endif
234 : #if defined(WEBRTC_CODEC_ISAC)
235 : if (STR_CASE_CMP(speech_inst.plname, "isac") == 0)
236 : return std::unique_ptr<AudioEncoder>(
237 : new AudioEncoderIsac(speech_inst, bwinfo));
238 : #endif
239 : #ifdef WEBRTC_CODEC_OPUS
240 0 : if (STR_CASE_CMP(speech_inst.plname, "opus") == 0)
241 0 : return std::unique_ptr<AudioEncoder>(new AudioEncoderOpus(speech_inst));
242 : #endif
243 0 : if (STR_CASE_CMP(speech_inst.plname, "pcmu") == 0)
244 0 : return std::unique_ptr<AudioEncoder>(new AudioEncoderPcmU(speech_inst));
245 0 : if (STR_CASE_CMP(speech_inst.plname, "pcma") == 0)
246 0 : return std::unique_ptr<AudioEncoder>(new AudioEncoderPcmA(speech_inst));
247 0 : if (STR_CASE_CMP(speech_inst.plname, "l16") == 0)
248 0 : return std::unique_ptr<AudioEncoder>(new AudioEncoderPcm16B(speech_inst));
249 : #ifdef WEBRTC_CODEC_ILBC
250 : if (STR_CASE_CMP(speech_inst.plname, "ilbc") == 0)
251 : return std::unique_ptr<AudioEncoder>(new AudioEncoderIlbc(speech_inst));
252 : #endif
253 : #ifdef WEBRTC_CODEC_G722
254 : if (STR_CASE_CMP(speech_inst.plname, "g722") == 0)
255 : return std::unique_ptr<AudioEncoder>(new AudioEncoderG722(speech_inst));
256 : #endif
257 0 : LOG_F(LS_ERROR) << "Could not create encoder of type " << speech_inst.plname;
258 0 : return std::unique_ptr<AudioEncoder>();
259 : }
260 :
261 0 : std::unique_ptr<AudioEncoder> CreateRedEncoder(
262 : std::unique_ptr<AudioEncoder> encoder,
263 : int red_payload_type) {
264 : #ifdef WEBRTC_CODEC_RED
265 : AudioEncoderCopyRed::Config config;
266 : config.payload_type = red_payload_type;
267 : config.speech_encoder = std::move(encoder);
268 : return std::unique_ptr<AudioEncoder>(
269 : new AudioEncoderCopyRed(std::move(config)));
270 : #else
271 0 : return std::unique_ptr<AudioEncoder>();
272 : #endif
273 : }
274 :
275 0 : std::unique_ptr<AudioEncoder> CreateCngEncoder(
276 : std::unique_ptr<AudioEncoder> encoder,
277 : int payload_type,
278 : ACMVADMode vad_mode) {
279 0 : AudioEncoderCng::Config config;
280 0 : config.num_channels = encoder->NumChannels();
281 0 : config.payload_type = payload_type;
282 0 : config.speech_encoder = std::move(encoder);
283 0 : switch (vad_mode) {
284 : case VADNormal:
285 0 : config.vad_mode = Vad::kVadNormal;
286 0 : break;
287 : case VADLowBitrate:
288 0 : config.vad_mode = Vad::kVadLowBitrate;
289 0 : break;
290 : case VADAggr:
291 0 : config.vad_mode = Vad::kVadAggressive;
292 0 : break;
293 : case VADVeryAggr:
294 0 : config.vad_mode = Vad::kVadVeryAggressive;
295 0 : break;
296 : default:
297 0 : FATAL();
298 : }
299 0 : return std::unique_ptr<AudioEncoder>(new AudioEncoderCng(std::move(config)));
300 : }
301 :
302 0 : std::unique_ptr<AudioDecoder> CreateIsacDecoder(
303 : int sample_rate_hz,
304 : const rtc::scoped_refptr<LockedIsacBandwidthInfo>& bwinfo) {
305 : #if defined(WEBRTC_CODEC_ISACFX)
306 : return std::unique_ptr<AudioDecoder>(
307 : new AudioDecoderIsacFix(sample_rate_hz, bwinfo));
308 : #elif defined(WEBRTC_CODEC_ISAC)
309 : return std::unique_ptr<AudioDecoder>(
310 : new AudioDecoderIsac(sample_rate_hz, bwinfo));
311 : #else
312 0 : FATAL() << "iSAC is not supported.";
313 : return std::unique_ptr<AudioDecoder>();
314 : #endif
315 : }
316 :
317 : } // namespace
318 :
319 0 : RentACodec::RentACodec() {
320 : #if defined(WEBRTC_CODEC_ISACFX) || defined(WEBRTC_CODEC_ISAC)
321 : isac_bandwidth_info_ = new LockedIsacBandwidthInfo;
322 : #endif
323 0 : }
324 : RentACodec::~RentACodec() = default;
325 :
326 0 : std::unique_ptr<AudioEncoder> RentACodec::RentEncoder(
327 : const CodecInst& codec_inst) {
328 0 : return CreateEncoder(codec_inst, isac_bandwidth_info_);
329 : }
330 :
331 0 : RentACodec::StackParameters::StackParameters() {
332 : // Register the default payload types for RED and CNG.
333 0 : for (const CodecInst& ci : RentACodec::Database()) {
334 0 : RentACodec::RegisterCngPayloadType(&cng_payload_types, ci);
335 0 : RentACodec::RegisterRedPayloadType(&red_payload_types, ci);
336 : }
337 0 : }
338 :
339 : RentACodec::StackParameters::~StackParameters() = default;
340 :
341 0 : std::unique_ptr<AudioEncoder> RentACodec::RentEncoderStack(
342 : StackParameters* param) {
343 0 : if (!param->speech_encoder)
344 0 : return nullptr;
345 :
346 0 : if (param->use_codec_fec) {
347 : // Switch FEC on. On failure, remember that FEC is off.
348 0 : if (!param->speech_encoder->SetFec(true))
349 0 : param->use_codec_fec = false;
350 : } else {
351 : // Switch FEC off. This shouldn't fail.
352 0 : const bool success = param->speech_encoder->SetFec(false);
353 0 : RTC_DCHECK(success);
354 : }
355 :
356 0 : auto pt = [¶m](const std::map<int, int>& m) {
357 0 : auto it = m.find(param->speech_encoder->SampleRateHz());
358 0 : return it == m.end() ? rtc::Optional<int>()
359 0 : : rtc::Optional<int>(it->second);
360 0 : };
361 0 : auto cng_pt = pt(param->cng_payload_types);
362 0 : param->use_cng =
363 0 : param->use_cng && cng_pt && param->speech_encoder->NumChannels() == 1;
364 0 : auto red_pt = pt(param->red_payload_types);
365 0 : param->use_red = param->use_red && red_pt;
366 :
367 0 : if (param->use_cng || param->use_red) {
368 : // The RED and CNG encoders need to be in sync with the speech encoder, so
369 : // reset the latter to ensure its buffer is empty.
370 0 : param->speech_encoder->Reset();
371 : }
372 : std::unique_ptr<AudioEncoder> encoder_stack =
373 0 : std::move(param->speech_encoder);
374 0 : if (param->use_red) {
375 0 : encoder_stack = CreateRedEncoder(std::move(encoder_stack), *red_pt);
376 : }
377 0 : if (param->use_cng) {
378 : encoder_stack =
379 0 : CreateCngEncoder(std::move(encoder_stack), *cng_pt, param->vad_mode);
380 : }
381 0 : return encoder_stack;
382 : }
383 :
384 0 : std::unique_ptr<AudioDecoder> RentACodec::RentIsacDecoder(int sample_rate_hz) {
385 0 : return CreateIsacDecoder(sample_rate_hz, isac_bandwidth_info_);
386 : }
387 :
388 : } // namespace acm2
389 : } // namespace webrtc
|