blob: ff6689028a3b622c5eb8c39de45ba44dc89a123a [file] [log] [blame]
kwibergfce4a942015-10-27 11:40:24 -07001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_coding/acm2/rent_a_codec.h"
kwibergfce4a942015-10-27 11:40:24 -070012
kwiberg16c5a962016-02-15 02:27:22 -080013#include <memory>
kwiberg0eb15ed2015-12-17 03:04:15 -080014#include <utility>
15
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "modules/audio_coding/codecs/cng/audio_encoder_cng.h"
17#include "modules/audio_coding/codecs/g711/audio_encoder_pcm.h"
18#include "rtc_base/logging.h"
kwiberg805fc712015-11-10 04:05:16 -080019#ifdef WEBRTC_CODEC_G722
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "modules/audio_coding/codecs/g722/audio_encoder_g722.h"
kwiberg805fc712015-11-10 04:05:16 -080021#endif
22#ifdef WEBRTC_CODEC_ILBC
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020023#include "modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h"
kwiberg805fc712015-11-10 04:05:16 -080024#endif
25#ifdef WEBRTC_CODEC_ISACFX
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020026#include "modules/audio_coding/codecs/isac/fix/include/audio_decoder_isacfix.h" // nogncheck
27#include "modules/audio_coding/codecs/isac/fix/include/audio_encoder_isacfix.h" // nogncheck
kwiberg805fc712015-11-10 04:05:16 -080028#endif
29#ifdef WEBRTC_CODEC_ISAC
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020030#include "modules/audio_coding/codecs/isac/main/include/audio_decoder_isac.h" // nogncheck
31#include "modules/audio_coding/codecs/isac/main/include/audio_encoder_isac.h" // nogncheck
kwiberg805fc712015-11-10 04:05:16 -080032#endif
33#ifdef WEBRTC_CODEC_OPUS
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020034#include "modules/audio_coding/codecs/opus/audio_encoder_opus.h"
kwiberg805fc712015-11-10 04:05:16 -080035#endif
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020036#include "modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h"
kwiberge155ae62015-11-16 04:49:54 -080037#ifdef WEBRTC_CODEC_RED
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020038#include "modules/audio_coding/codecs/red/audio_encoder_copy_red.h"
kwiberge155ae62015-11-16 04:49:54 -080039#endif
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020040#include "modules/audio_coding/acm2/acm_codec_database.h"
kwibergfce4a942015-10-27 11:40:24 -070041
kwiberg0d05da72016-03-30 04:10:11 -070042#if defined(WEBRTC_CODEC_ISACFX) || defined(WEBRTC_CODEC_ISAC)
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020043#include "modules/audio_coding/codecs/isac/locked_bandwidth_info.h"
kwiberg0d05da72016-03-30 04:10:11 -070044#endif
45
kwibergfce4a942015-10-27 11:40:24 -070046namespace webrtc {
47namespace acm2 {
48
Karl Wibergbe579832015-11-10 22:34:18 +010049rtc::Optional<RentACodec::CodecId> RentACodec::CodecIdByParams(
kwibergfce4a942015-10-27 11:40:24 -070050 const char* payload_name,
51 int sampling_freq_hz,
Peter Kasting69558702016-01-12 16:26:35 -080052 size_t channels) {
kwibergfce4a942015-10-27 11:40:24 -070053 return CodecIdFromIndex(
54 ACMCodecDB::CodecId(payload_name, sampling_freq_hz, channels));
55}
56
Karl Wibergbe579832015-11-10 22:34:18 +010057rtc::Optional<CodecInst> RentACodec::CodecInstById(CodecId codec_id) {
58 rtc::Optional<int> mi = CodecIndexFromId(codec_id);
59 return mi ? rtc::Optional<CodecInst>(Database()[*mi])
60 : rtc::Optional<CodecInst>();
kwibergfce4a942015-10-27 11:40:24 -070061}
62
Karl Wibergbe579832015-11-10 22:34:18 +010063rtc::Optional<RentACodec::CodecId> RentACodec::CodecIdByInst(
kwibergd6c0f8c2015-11-06 14:28:00 -080064 const CodecInst& codec_inst) {
65 return CodecIdFromIndex(ACMCodecDB::CodecNumber(codec_inst));
66}
67
Karl Wibergbe579832015-11-10 22:34:18 +010068rtc::Optional<CodecInst> RentACodec::CodecInstByParams(const char* payload_name,
69 int sampling_freq_hz,
Peter Kasting69558702016-01-12 16:26:35 -080070 size_t channels) {
Karl Wibergbe579832015-11-10 22:34:18 +010071 rtc::Optional<CodecId> codec_id =
kwibergfce4a942015-10-27 11:40:24 -070072 CodecIdByParams(payload_name, sampling_freq_hz, channels);
73 if (!codec_id)
Karl Wibergbe579832015-11-10 22:34:18 +010074 return rtc::Optional<CodecInst>();
75 rtc::Optional<CodecInst> ci = CodecInstById(*codec_id);
kwibergfce4a942015-10-27 11:40:24 -070076 RTC_DCHECK(ci);
77
78 // Keep the number of channels from the function call. For most codecs it
79 // will be the same value as in default codec settings, but not for all.
80 ci->channels = channels;
81
82 return ci;
83}
84
85bool RentACodec::IsCodecValid(const CodecInst& codec_inst) {
86 return ACMCodecDB::CodecNumber(codec_inst) >= 0;
87}
88
Karl Wibergbe579832015-11-10 22:34:18 +010089rtc::Optional<bool> RentACodec::IsSupportedNumChannels(CodecId codec_id,
Peter Kasting69558702016-01-12 16:26:35 -080090 size_t num_channels) {
kwibergde94d082015-11-03 05:46:09 -080091 auto i = CodecIndexFromId(codec_id);
Karl Wibergbe579832015-11-10 22:34:18 +010092 return i ? rtc::Optional<bool>(
93 ACMCodecDB::codec_settings_[*i].channel_support >=
94 num_channels)
95 : rtc::Optional<bool>();
kwibergde94d082015-11-03 05:46:09 -080096}
97
kwibergfce4a942015-10-27 11:40:24 -070098rtc::ArrayView<const CodecInst> RentACodec::Database() {
99 return rtc::ArrayView<const CodecInst>(ACMCodecDB::database_,
100 NumberOfCodecs());
101}
102
Karl Wibergbe579832015-11-10 22:34:18 +0100103rtc::Optional<NetEqDecoder> RentACodec::NetEqDecoderFromCodecId(
104 CodecId codec_id,
Peter Kasting69558702016-01-12 16:26:35 -0800105 size_t num_channels) {
Karl Wibergbe579832015-11-10 22:34:18 +0100106 rtc::Optional<int> i = CodecIndexFromId(codec_id);
kwibergee1879c2015-10-29 06:20:28 -0700107 if (!i)
Karl Wibergbe579832015-11-10 22:34:18 +0100108 return rtc::Optional<NetEqDecoder>();
kwibergee1879c2015-10-29 06:20:28 -0700109 const NetEqDecoder ned = ACMCodecDB::neteq_decoders_[*i];
Karl Wibergbe579832015-11-10 22:34:18 +0100110 return rtc::Optional<NetEqDecoder>(
kwiberg102c6a62015-10-30 02:47:38 -0700111 (ned == NetEqDecoder::kDecoderOpus && num_channels == 2)
112 ? NetEqDecoder::kDecoderOpus_2ch
113 : ned);
kwibergee1879c2015-10-29 06:20:28 -0700114}
115
kwiberge1a27d42015-11-18 07:32:49 -0800116RentACodec::RegistrationResult RentACodec::RegisterCngPayloadType(
117 std::map<int, int>* pt_map,
118 const CodecInst& codec_inst) {
119 if (STR_CASE_CMP(codec_inst.plname, "CN") != 0)
120 return RegistrationResult::kSkip;
121 switch (codec_inst.plfreq) {
122 case 8000:
123 case 16000:
124 case 32000:
125 case 48000:
126 (*pt_map)[codec_inst.plfreq] = codec_inst.pltype;
127 return RegistrationResult::kOk;
128 default:
129 return RegistrationResult::kBadFreq;
130 }
131}
132
133RentACodec::RegistrationResult RentACodec::RegisterRedPayloadType(
134 std::map<int, int>* pt_map,
135 const CodecInst& codec_inst) {
136 if (STR_CASE_CMP(codec_inst.plname, "RED") != 0)
137 return RegistrationResult::kSkip;
138 switch (codec_inst.plfreq) {
139 case 8000:
140 (*pt_map)[codec_inst.plfreq] = codec_inst.pltype;
141 return RegistrationResult::kOk;
142 default:
143 return RegistrationResult::kBadFreq;
144 }
145}
146
kwiberg805fc712015-11-10 04:05:16 -0800147namespace {
148
149// Returns a new speech encoder, or null on error.
150// TODO(kwiberg): Don't handle errors here (bug 5033)
kwiberg0d05da72016-03-30 04:10:11 -0700151std::unique_ptr<AudioEncoder> CreateEncoder(
152 const CodecInst& speech_inst,
153 const rtc::scoped_refptr<LockedIsacBandwidthInfo>& bwinfo) {
kwiberg805fc712015-11-10 04:05:16 -0800154#if defined(WEBRTC_CODEC_ISACFX)
155 if (STR_CASE_CMP(speech_inst.plname, "isac") == 0)
kwiberg16c5a962016-02-15 02:27:22 -0800156 return std::unique_ptr<AudioEncoder>(
kwiberg6ff045f2017-08-17 05:31:02 -0700157 new AudioEncoderIsacFixImpl(speech_inst, bwinfo));
kwiberg805fc712015-11-10 04:05:16 -0800158#endif
159#if defined(WEBRTC_CODEC_ISAC)
160 if (STR_CASE_CMP(speech_inst.plname, "isac") == 0)
kwiberg16c5a962016-02-15 02:27:22 -0800161 return std::unique_ptr<AudioEncoder>(
kwiberg6ff045f2017-08-17 05:31:02 -0700162 new AudioEncoderIsacFloatImpl(speech_inst, bwinfo));
kwiberg805fc712015-11-10 04:05:16 -0800163#endif
164#ifdef WEBRTC_CODEC_OPUS
165 if (STR_CASE_CMP(speech_inst.plname, "opus") == 0)
Karl Wiberg7275e182017-10-25 09:57:40 +0200166 return std::unique_ptr<AudioEncoder>(new AudioEncoderOpusImpl(speech_inst));
kwiberg805fc712015-11-10 04:05:16 -0800167#endif
168 if (STR_CASE_CMP(speech_inst.plname, "pcmu") == 0)
kwiberg16c5a962016-02-15 02:27:22 -0800169 return std::unique_ptr<AudioEncoder>(new AudioEncoderPcmU(speech_inst));
kwiberg805fc712015-11-10 04:05:16 -0800170 if (STR_CASE_CMP(speech_inst.plname, "pcma") == 0)
kwiberg16c5a962016-02-15 02:27:22 -0800171 return std::unique_ptr<AudioEncoder>(new AudioEncoderPcmA(speech_inst));
kwiberg805fc712015-11-10 04:05:16 -0800172 if (STR_CASE_CMP(speech_inst.plname, "l16") == 0)
kwiberg16c5a962016-02-15 02:27:22 -0800173 return std::unique_ptr<AudioEncoder>(new AudioEncoderPcm16B(speech_inst));
kwiberg805fc712015-11-10 04:05:16 -0800174#ifdef WEBRTC_CODEC_ILBC
175 if (STR_CASE_CMP(speech_inst.plname, "ilbc") == 0)
solenbergdb3c9b02017-06-28 02:05:04 -0700176 return std::unique_ptr<AudioEncoder>(new AudioEncoderIlbcImpl(speech_inst));
kwiberg805fc712015-11-10 04:05:16 -0800177#endif
178#ifdef WEBRTC_CODEC_G722
179 if (STR_CASE_CMP(speech_inst.plname, "g722") == 0)
kwibergb8727ae2017-06-17 17:41:59 -0700180 return std::unique_ptr<AudioEncoder>(new AudioEncoderG722Impl(speech_inst));
kwiberg805fc712015-11-10 04:05:16 -0800181#endif
182 LOG_F(LS_ERROR) << "Could not create encoder of type " << speech_inst.plname;
kwiberg16c5a962016-02-15 02:27:22 -0800183 return std::unique_ptr<AudioEncoder>();
kwiberg805fc712015-11-10 04:05:16 -0800184}
185
kwiberg6030a122016-03-08 06:01:31 -0800186std::unique_ptr<AudioEncoder> CreateRedEncoder(
187 std::unique_ptr<AudioEncoder> encoder,
188 int red_payload_type) {
kwiberge155ae62015-11-16 04:49:54 -0800189#ifdef WEBRTC_CODEC_RED
190 AudioEncoderCopyRed::Config config;
191 config.payload_type = red_payload_type;
kwiberg6030a122016-03-08 06:01:31 -0800192 config.speech_encoder = std::move(encoder);
193 return std::unique_ptr<AudioEncoder>(
194 new AudioEncoderCopyRed(std::move(config)));
kwiberge155ae62015-11-16 04:49:54 -0800195#else
kwiberg16c5a962016-02-15 02:27:22 -0800196 return std::unique_ptr<AudioEncoder>();
kwiberge155ae62015-11-16 04:49:54 -0800197#endif
198}
199
kwiberg6030a122016-03-08 06:01:31 -0800200std::unique_ptr<AudioEncoder> CreateCngEncoder(
201 std::unique_ptr<AudioEncoder> encoder,
202 int payload_type,
203 ACMVADMode vad_mode) {
kwiberge155ae62015-11-16 04:49:54 -0800204 AudioEncoderCng::Config config;
205 config.num_channels = encoder->NumChannels();
kwiberg1379f1f2015-11-23 04:30:52 -0800206 config.payload_type = payload_type;
kwiberg6030a122016-03-08 06:01:31 -0800207 config.speech_encoder = std::move(encoder);
kwiberg1379f1f2015-11-23 04:30:52 -0800208 switch (vad_mode) {
kwiberge155ae62015-11-16 04:49:54 -0800209 case VADNormal:
210 config.vad_mode = Vad::kVadNormal;
211 break;
212 case VADLowBitrate:
213 config.vad_mode = Vad::kVadLowBitrate;
214 break;
215 case VADAggr:
216 config.vad_mode = Vad::kVadAggressive;
217 break;
218 case VADVeryAggr:
219 config.vad_mode = Vad::kVadVeryAggressive;
220 break;
221 default:
222 FATAL();
223 }
kwiberg6030a122016-03-08 06:01:31 -0800224 return std::unique_ptr<AudioEncoder>(new AudioEncoderCng(std::move(config)));
kwiberge155ae62015-11-16 04:49:54 -0800225}
226
kwiberg16c5a962016-02-15 02:27:22 -0800227std::unique_ptr<AudioDecoder> CreateIsacDecoder(
kwibergabe95ba2016-06-02 02:58:59 -0700228 int sample_rate_hz,
kwiberg0d05da72016-03-30 04:10:11 -0700229 const rtc::scoped_refptr<LockedIsacBandwidthInfo>& bwinfo) {
kwiberg805fc712015-11-10 04:05:16 -0800230#if defined(WEBRTC_CODEC_ISACFX)
kwibergabe95ba2016-06-02 02:58:59 -0700231 return std::unique_ptr<AudioDecoder>(
kwiberg6ff045f2017-08-17 05:31:02 -0700232 new AudioDecoderIsacFixImpl(sample_rate_hz, bwinfo));
kwiberg805fc712015-11-10 04:05:16 -0800233#elif defined(WEBRTC_CODEC_ISAC)
kwibergabe95ba2016-06-02 02:58:59 -0700234 return std::unique_ptr<AudioDecoder>(
kwiberg6ff045f2017-08-17 05:31:02 -0700235 new AudioDecoderIsacFloatImpl(sample_rate_hz, bwinfo));
kwiberg805fc712015-11-10 04:05:16 -0800236#else
237 FATAL() << "iSAC is not supported.";
kwiberg16c5a962016-02-15 02:27:22 -0800238 return std::unique_ptr<AudioDecoder>();
kwiberg805fc712015-11-10 04:05:16 -0800239#endif
240}
241
242} // namespace
243
kwiberg0d05da72016-03-30 04:10:11 -0700244RentACodec::RentACodec() {
245#if defined(WEBRTC_CODEC_ISACFX) || defined(WEBRTC_CODEC_ISAC)
246 isac_bandwidth_info_ = new LockedIsacBandwidthInfo;
247#endif
248}
kwiberg805fc712015-11-10 04:05:16 -0800249RentACodec::~RentACodec() = default;
250
kwiberg6030a122016-03-08 06:01:31 -0800251std::unique_ptr<AudioEncoder> RentACodec::RentEncoder(
252 const CodecInst& codec_inst) {
kwiberg0d05da72016-03-30 04:10:11 -0700253 return CreateEncoder(codec_inst, isac_bandwidth_info_);
kwiberge155ae62015-11-16 04:49:54 -0800254}
255
kwiberg1379f1f2015-11-23 04:30:52 -0800256RentACodec::StackParameters::StackParameters() {
257 // Register the default payload types for RED and CNG.
258 for (const CodecInst& ci : RentACodec::Database()) {
259 RentACodec::RegisterCngPayloadType(&cng_payload_types, ci);
260 RentACodec::RegisterRedPayloadType(&red_payload_types, ci);
261 }
262}
263
264RentACodec::StackParameters::~StackParameters() = default;
265
kwiberg6030a122016-03-08 06:01:31 -0800266std::unique_ptr<AudioEncoder> RentACodec::RentEncoderStack(
267 StackParameters* param) {
kwibergc8d071e2016-04-06 12:22:38 -0700268 if (!param->speech_encoder)
269 return nullptr;
kwiberg1379f1f2015-11-23 04:30:52 -0800270
kwiberg9cd5c8c2015-11-25 01:25:06 -0800271 if (param->use_codec_fec) {
272 // Switch FEC on. On failure, remember that FEC is off.
kwiberg95d98512015-12-15 14:21:33 -0800273 if (!param->speech_encoder->SetFec(true))
kwiberg9cd5c8c2015-11-25 01:25:06 -0800274 param->use_codec_fec = false;
275 } else {
276 // Switch FEC off. This shouldn't fail.
kwiberg95d98512015-12-15 14:21:33 -0800277 const bool success = param->speech_encoder->SetFec(false);
kwiberg9cd5c8c2015-11-25 01:25:06 -0800278 RTC_DCHECK(success);
279 }
280
kwiberg95d98512015-12-15 14:21:33 -0800281 auto pt = [&param](const std::map<int, int>& m) {
282 auto it = m.find(param->speech_encoder->SampleRateHz());
kwiberg1379f1f2015-11-23 04:30:52 -0800283 return it == m.end() ? rtc::Optional<int>()
284 : rtc::Optional<int>(it->second);
285 };
286 auto cng_pt = pt(param->cng_payload_types);
kwiberg989b4ab2015-11-25 01:19:13 -0800287 param->use_cng =
kwiberg95d98512015-12-15 14:21:33 -0800288 param->use_cng && cng_pt && param->speech_encoder->NumChannels() == 1;
kwiberg1379f1f2015-11-23 04:30:52 -0800289 auto red_pt = pt(param->red_payload_types);
290 param->use_red = param->use_red && red_pt;
291
292 if (param->use_cng || param->use_red) {
kwiberge155ae62015-11-16 04:49:54 -0800293 // The RED and CNG encoders need to be in sync with the speech encoder, so
294 // reset the latter to ensure its buffer is empty.
kwiberg95d98512015-12-15 14:21:33 -0800295 param->speech_encoder->Reset();
kwiberge155ae62015-11-16 04:49:54 -0800296 }
kwiberg6030a122016-03-08 06:01:31 -0800297 std::unique_ptr<AudioEncoder> encoder_stack =
298 std::move(param->speech_encoder);
kwiberg1379f1f2015-11-23 04:30:52 -0800299 if (param->use_red) {
kwiberg6030a122016-03-08 06:01:31 -0800300 encoder_stack = CreateRedEncoder(std::move(encoder_stack), *red_pt);
kwiberge155ae62015-11-16 04:49:54 -0800301 }
kwiberg1379f1f2015-11-23 04:30:52 -0800302 if (param->use_cng) {
kwiberg6030a122016-03-08 06:01:31 -0800303 encoder_stack =
304 CreateCngEncoder(std::move(encoder_stack), *cng_pt, param->vad_mode);
kwiberge155ae62015-11-16 04:49:54 -0800305 }
kwiberg32be07b2016-01-21 07:10:01 -0800306 return encoder_stack;
kwiberg805fc712015-11-10 04:05:16 -0800307}
308
kwibergabe95ba2016-06-02 02:58:59 -0700309std::unique_ptr<AudioDecoder> RentACodec::RentIsacDecoder(int sample_rate_hz) {
310 return CreateIsacDecoder(sample_rate_hz, isac_bandwidth_info_);
kwiberg805fc712015-11-10 04:05:16 -0800311}
312
kwibergfce4a942015-10-27 11:40:24 -0700313} // namespace acm2
314} // namespace webrtc