blob: 78db38dad60b5efbb9b1965f62a9dbf17041055b [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"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "modules/audio_coding/codecs/g722/audio_encoder_g722.h"
kwiberg805fc712015-11-10 04:05:16 -080020#ifdef WEBRTC_CODEC_ILBC
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h"
kwiberg805fc712015-11-10 04:05:16 -080022#endif
23#ifdef WEBRTC_CODEC_ISACFX
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020024#include "modules/audio_coding/codecs/isac/fix/include/audio_decoder_isacfix.h" // nogncheck
25#include "modules/audio_coding/codecs/isac/fix/include/audio_encoder_isacfix.h" // nogncheck
kwiberg805fc712015-11-10 04:05:16 -080026#endif
27#ifdef WEBRTC_CODEC_ISAC
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020028#include "modules/audio_coding/codecs/isac/main/include/audio_decoder_isac.h" // nogncheck
29#include "modules/audio_coding/codecs/isac/main/include/audio_encoder_isac.h" // nogncheck
kwiberg805fc712015-11-10 04:05:16 -080030#endif
31#ifdef WEBRTC_CODEC_OPUS
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020032#include "modules/audio_coding/codecs/opus/audio_encoder_opus.h"
kwiberg805fc712015-11-10 04:05:16 -080033#endif
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020034#include "modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h"
kwiberge155ae62015-11-16 04:49:54 -080035#ifdef WEBRTC_CODEC_RED
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020036#include "modules/audio_coding/codecs/red/audio_encoder_copy_red.h"
kwiberge155ae62015-11-16 04:49:54 -080037#endif
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020038#include "modules/audio_coding/acm2/acm_codec_database.h"
kwibergfce4a942015-10-27 11:40:24 -070039
kwiberg0d05da72016-03-30 04:10:11 -070040#if defined(WEBRTC_CODEC_ISACFX) || defined(WEBRTC_CODEC_ISAC)
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020041#include "modules/audio_coding/codecs/isac/locked_bandwidth_info.h"
kwiberg0d05da72016-03-30 04:10:11 -070042#endif
43
kwibergfce4a942015-10-27 11:40:24 -070044namespace webrtc {
45namespace acm2 {
46
Karl Wibergbe579832015-11-10 22:34:18 +010047rtc::Optional<RentACodec::CodecId> RentACodec::CodecIdByParams(
kwibergfce4a942015-10-27 11:40:24 -070048 const char* payload_name,
49 int sampling_freq_hz,
Peter Kasting69558702016-01-12 16:26:35 -080050 size_t channels) {
kwibergfce4a942015-10-27 11:40:24 -070051 return CodecIdFromIndex(
52 ACMCodecDB::CodecId(payload_name, sampling_freq_hz, channels));
53}
54
Karl Wibergbe579832015-11-10 22:34:18 +010055rtc::Optional<CodecInst> RentACodec::CodecInstById(CodecId codec_id) {
56 rtc::Optional<int> mi = CodecIndexFromId(codec_id);
57 return mi ? rtc::Optional<CodecInst>(Database()[*mi])
Oskar Sundbom12ab00b2017-11-16 15:31:38 +010058 : rtc::nullopt;
kwibergfce4a942015-10-27 11:40:24 -070059}
60
Karl Wibergbe579832015-11-10 22:34:18 +010061rtc::Optional<RentACodec::CodecId> RentACodec::CodecIdByInst(
kwibergd6c0f8c2015-11-06 14:28:00 -080062 const CodecInst& codec_inst) {
63 return CodecIdFromIndex(ACMCodecDB::CodecNumber(codec_inst));
64}
65
Karl Wibergbe579832015-11-10 22:34:18 +010066rtc::Optional<CodecInst> RentACodec::CodecInstByParams(const char* payload_name,
67 int sampling_freq_hz,
Peter Kasting69558702016-01-12 16:26:35 -080068 size_t channels) {
Karl Wibergbe579832015-11-10 22:34:18 +010069 rtc::Optional<CodecId> codec_id =
kwibergfce4a942015-10-27 11:40:24 -070070 CodecIdByParams(payload_name, sampling_freq_hz, channels);
71 if (!codec_id)
Oskar Sundbom12ab00b2017-11-16 15:31:38 +010072 return rtc::nullopt;
Karl Wibergbe579832015-11-10 22:34:18 +010073 rtc::Optional<CodecInst> ci = CodecInstById(*codec_id);
kwibergfce4a942015-10-27 11:40:24 -070074 RTC_DCHECK(ci);
75
76 // Keep the number of channels from the function call. For most codecs it
77 // will be the same value as in default codec settings, but not for all.
78 ci->channels = channels;
79
80 return ci;
81}
82
83bool RentACodec::IsCodecValid(const CodecInst& codec_inst) {
84 return ACMCodecDB::CodecNumber(codec_inst) >= 0;
85}
86
Karl Wibergbe579832015-11-10 22:34:18 +010087rtc::Optional<bool> RentACodec::IsSupportedNumChannels(CodecId codec_id,
Peter Kasting69558702016-01-12 16:26:35 -080088 size_t num_channels) {
kwibergde94d082015-11-03 05:46:09 -080089 auto i = CodecIndexFromId(codec_id);
Karl Wibergbe579832015-11-10 22:34:18 +010090 return i ? rtc::Optional<bool>(
91 ACMCodecDB::codec_settings_[*i].channel_support >=
92 num_channels)
Oskar Sundbom12ab00b2017-11-16 15:31:38 +010093 : rtc::nullopt;
kwibergde94d082015-11-03 05:46:09 -080094}
95
kwibergfce4a942015-10-27 11:40:24 -070096rtc::ArrayView<const CodecInst> RentACodec::Database() {
97 return rtc::ArrayView<const CodecInst>(ACMCodecDB::database_,
98 NumberOfCodecs());
99}
100
Karl Wibergbe579832015-11-10 22:34:18 +0100101rtc::Optional<NetEqDecoder> RentACodec::NetEqDecoderFromCodecId(
102 CodecId codec_id,
Peter Kasting69558702016-01-12 16:26:35 -0800103 size_t num_channels) {
Karl Wibergbe579832015-11-10 22:34:18 +0100104 rtc::Optional<int> i = CodecIndexFromId(codec_id);
kwibergee1879c2015-10-29 06:20:28 -0700105 if (!i)
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100106 return rtc::nullopt;
kwibergee1879c2015-10-29 06:20:28 -0700107 const NetEqDecoder ned = ACMCodecDB::neteq_decoders_[*i];
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100108 return (ned == NetEqDecoder::kDecoderOpus && num_channels == 2)
109 ? NetEqDecoder::kDecoderOpus_2ch
110 : ned;
kwibergee1879c2015-10-29 06:20:28 -0700111}
112
kwiberge1a27d42015-11-18 07:32:49 -0800113RentACodec::RegistrationResult RentACodec::RegisterCngPayloadType(
114 std::map<int, int>* pt_map,
115 const CodecInst& codec_inst) {
116 if (STR_CASE_CMP(codec_inst.plname, "CN") != 0)
117 return RegistrationResult::kSkip;
118 switch (codec_inst.plfreq) {
119 case 8000:
120 case 16000:
121 case 32000:
122 case 48000:
123 (*pt_map)[codec_inst.plfreq] = codec_inst.pltype;
124 return RegistrationResult::kOk;
125 default:
126 return RegistrationResult::kBadFreq;
127 }
128}
129
130RentACodec::RegistrationResult RentACodec::RegisterRedPayloadType(
131 std::map<int, int>* pt_map,
132 const CodecInst& codec_inst) {
133 if (STR_CASE_CMP(codec_inst.plname, "RED") != 0)
134 return RegistrationResult::kSkip;
135 switch (codec_inst.plfreq) {
136 case 8000:
137 (*pt_map)[codec_inst.plfreq] = codec_inst.pltype;
138 return RegistrationResult::kOk;
139 default:
140 return RegistrationResult::kBadFreq;
141 }
142}
143
kwiberg805fc712015-11-10 04:05:16 -0800144namespace {
145
146// Returns a new speech encoder, or null on error.
147// TODO(kwiberg): Don't handle errors here (bug 5033)
kwiberg0d05da72016-03-30 04:10:11 -0700148std::unique_ptr<AudioEncoder> CreateEncoder(
149 const CodecInst& speech_inst,
150 const rtc::scoped_refptr<LockedIsacBandwidthInfo>& bwinfo) {
kwiberg805fc712015-11-10 04:05:16 -0800151#if defined(WEBRTC_CODEC_ISACFX)
152 if (STR_CASE_CMP(speech_inst.plname, "isac") == 0)
kwiberg16c5a962016-02-15 02:27:22 -0800153 return std::unique_ptr<AudioEncoder>(
kwiberg6ff045f2017-08-17 05:31:02 -0700154 new AudioEncoderIsacFixImpl(speech_inst, bwinfo));
kwiberg805fc712015-11-10 04:05:16 -0800155#endif
156#if defined(WEBRTC_CODEC_ISAC)
157 if (STR_CASE_CMP(speech_inst.plname, "isac") == 0)
kwiberg16c5a962016-02-15 02:27:22 -0800158 return std::unique_ptr<AudioEncoder>(
kwiberg6ff045f2017-08-17 05:31:02 -0700159 new AudioEncoderIsacFloatImpl(speech_inst, bwinfo));
kwiberg805fc712015-11-10 04:05:16 -0800160#endif
161#ifdef WEBRTC_CODEC_OPUS
162 if (STR_CASE_CMP(speech_inst.plname, "opus") == 0)
Karl Wiberg7275e182017-10-25 09:57:40 +0200163 return std::unique_ptr<AudioEncoder>(new AudioEncoderOpusImpl(speech_inst));
kwiberg805fc712015-11-10 04:05:16 -0800164#endif
165 if (STR_CASE_CMP(speech_inst.plname, "pcmu") == 0)
kwiberg16c5a962016-02-15 02:27:22 -0800166 return std::unique_ptr<AudioEncoder>(new AudioEncoderPcmU(speech_inst));
kwiberg805fc712015-11-10 04:05:16 -0800167 if (STR_CASE_CMP(speech_inst.plname, "pcma") == 0)
kwiberg16c5a962016-02-15 02:27:22 -0800168 return std::unique_ptr<AudioEncoder>(new AudioEncoderPcmA(speech_inst));
kwiberg805fc712015-11-10 04:05:16 -0800169 if (STR_CASE_CMP(speech_inst.plname, "l16") == 0)
kwiberg16c5a962016-02-15 02:27:22 -0800170 return std::unique_ptr<AudioEncoder>(new AudioEncoderPcm16B(speech_inst));
kwiberg805fc712015-11-10 04:05:16 -0800171#ifdef WEBRTC_CODEC_ILBC
172 if (STR_CASE_CMP(speech_inst.plname, "ilbc") == 0)
solenbergdb3c9b02017-06-28 02:05:04 -0700173 return std::unique_ptr<AudioEncoder>(new AudioEncoderIlbcImpl(speech_inst));
kwiberg805fc712015-11-10 04:05:16 -0800174#endif
kwiberg805fc712015-11-10 04:05:16 -0800175 if (STR_CASE_CMP(speech_inst.plname, "g722") == 0)
kwibergb8727ae2017-06-17 17:41:59 -0700176 return std::unique_ptr<AudioEncoder>(new AudioEncoderG722Impl(speech_inst));
Mirko Bonadei675513b2017-11-09 11:09:25 +0100177 RTC_LOG_F(LS_ERROR) << "Could not create encoder of type "
178 << speech_inst.plname;
kwiberg16c5a962016-02-15 02:27:22 -0800179 return std::unique_ptr<AudioEncoder>();
kwiberg805fc712015-11-10 04:05:16 -0800180}
181
kwiberg6030a122016-03-08 06:01:31 -0800182std::unique_ptr<AudioEncoder> CreateRedEncoder(
183 std::unique_ptr<AudioEncoder> encoder,
184 int red_payload_type) {
kwiberge155ae62015-11-16 04:49:54 -0800185#ifdef WEBRTC_CODEC_RED
186 AudioEncoderCopyRed::Config config;
187 config.payload_type = red_payload_type;
kwiberg6030a122016-03-08 06:01:31 -0800188 config.speech_encoder = std::move(encoder);
189 return std::unique_ptr<AudioEncoder>(
190 new AudioEncoderCopyRed(std::move(config)));
kwiberge155ae62015-11-16 04:49:54 -0800191#else
kwiberg16c5a962016-02-15 02:27:22 -0800192 return std::unique_ptr<AudioEncoder>();
kwiberge155ae62015-11-16 04:49:54 -0800193#endif
194}
195
kwiberg6030a122016-03-08 06:01:31 -0800196std::unique_ptr<AudioEncoder> CreateCngEncoder(
197 std::unique_ptr<AudioEncoder> encoder,
198 int payload_type,
199 ACMVADMode vad_mode) {
kwiberge155ae62015-11-16 04:49:54 -0800200 AudioEncoderCng::Config config;
201 config.num_channels = encoder->NumChannels();
kwiberg1379f1f2015-11-23 04:30:52 -0800202 config.payload_type = payload_type;
kwiberg6030a122016-03-08 06:01:31 -0800203 config.speech_encoder = std::move(encoder);
kwiberg1379f1f2015-11-23 04:30:52 -0800204 switch (vad_mode) {
kwiberge155ae62015-11-16 04:49:54 -0800205 case VADNormal:
206 config.vad_mode = Vad::kVadNormal;
207 break;
208 case VADLowBitrate:
209 config.vad_mode = Vad::kVadLowBitrate;
210 break;
211 case VADAggr:
212 config.vad_mode = Vad::kVadAggressive;
213 break;
214 case VADVeryAggr:
215 config.vad_mode = Vad::kVadVeryAggressive;
216 break;
217 default:
218 FATAL();
219 }
kwiberg6030a122016-03-08 06:01:31 -0800220 return std::unique_ptr<AudioEncoder>(new AudioEncoderCng(std::move(config)));
kwiberge155ae62015-11-16 04:49:54 -0800221}
222
kwiberg16c5a962016-02-15 02:27:22 -0800223std::unique_ptr<AudioDecoder> CreateIsacDecoder(
kwibergabe95ba2016-06-02 02:58:59 -0700224 int sample_rate_hz,
kwiberg0d05da72016-03-30 04:10:11 -0700225 const rtc::scoped_refptr<LockedIsacBandwidthInfo>& bwinfo) {
kwiberg805fc712015-11-10 04:05:16 -0800226#if defined(WEBRTC_CODEC_ISACFX)
kwibergabe95ba2016-06-02 02:58:59 -0700227 return std::unique_ptr<AudioDecoder>(
kwiberg6ff045f2017-08-17 05:31:02 -0700228 new AudioDecoderIsacFixImpl(sample_rate_hz, bwinfo));
kwiberg805fc712015-11-10 04:05:16 -0800229#elif defined(WEBRTC_CODEC_ISAC)
kwibergabe95ba2016-06-02 02:58:59 -0700230 return std::unique_ptr<AudioDecoder>(
kwiberg6ff045f2017-08-17 05:31:02 -0700231 new AudioDecoderIsacFloatImpl(sample_rate_hz, bwinfo));
kwiberg805fc712015-11-10 04:05:16 -0800232#else
233 FATAL() << "iSAC is not supported.";
kwiberg16c5a962016-02-15 02:27:22 -0800234 return std::unique_ptr<AudioDecoder>();
kwiberg805fc712015-11-10 04:05:16 -0800235#endif
236}
237
238} // namespace
239
kwiberg0d05da72016-03-30 04:10:11 -0700240RentACodec::RentACodec() {
241#if defined(WEBRTC_CODEC_ISACFX) || defined(WEBRTC_CODEC_ISAC)
242 isac_bandwidth_info_ = new LockedIsacBandwidthInfo;
243#endif
244}
kwiberg805fc712015-11-10 04:05:16 -0800245RentACodec::~RentACodec() = default;
246
kwiberg6030a122016-03-08 06:01:31 -0800247std::unique_ptr<AudioEncoder> RentACodec::RentEncoder(
248 const CodecInst& codec_inst) {
kwiberg0d05da72016-03-30 04:10:11 -0700249 return CreateEncoder(codec_inst, isac_bandwidth_info_);
kwiberge155ae62015-11-16 04:49:54 -0800250}
251
kwiberg1379f1f2015-11-23 04:30:52 -0800252RentACodec::StackParameters::StackParameters() {
253 // Register the default payload types for RED and CNG.
254 for (const CodecInst& ci : RentACodec::Database()) {
255 RentACodec::RegisterCngPayloadType(&cng_payload_types, ci);
256 RentACodec::RegisterRedPayloadType(&red_payload_types, ci);
257 }
258}
259
260RentACodec::StackParameters::~StackParameters() = default;
261
kwiberg6030a122016-03-08 06:01:31 -0800262std::unique_ptr<AudioEncoder> RentACodec::RentEncoderStack(
263 StackParameters* param) {
kwibergc8d071e2016-04-06 12:22:38 -0700264 if (!param->speech_encoder)
265 return nullptr;
kwiberg1379f1f2015-11-23 04:30:52 -0800266
kwiberg9cd5c8c2015-11-25 01:25:06 -0800267 if (param->use_codec_fec) {
268 // Switch FEC on. On failure, remember that FEC is off.
kwiberg95d98512015-12-15 14:21:33 -0800269 if (!param->speech_encoder->SetFec(true))
kwiberg9cd5c8c2015-11-25 01:25:06 -0800270 param->use_codec_fec = false;
271 } else {
272 // Switch FEC off. This shouldn't fail.
kwiberg95d98512015-12-15 14:21:33 -0800273 const bool success = param->speech_encoder->SetFec(false);
kwiberg9cd5c8c2015-11-25 01:25:06 -0800274 RTC_DCHECK(success);
275 }
276
kwiberg95d98512015-12-15 14:21:33 -0800277 auto pt = [&param](const std::map<int, int>& m) {
278 auto it = m.find(param->speech_encoder->SampleRateHz());
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100279 return it == m.end() ? rtc::nullopt
kwiberg1379f1f2015-11-23 04:30:52 -0800280 : rtc::Optional<int>(it->second);
281 };
282 auto cng_pt = pt(param->cng_payload_types);
kwiberg989b4ab2015-11-25 01:19:13 -0800283 param->use_cng =
kwiberg95d98512015-12-15 14:21:33 -0800284 param->use_cng && cng_pt && param->speech_encoder->NumChannels() == 1;
kwiberg1379f1f2015-11-23 04:30:52 -0800285 auto red_pt = pt(param->red_payload_types);
286 param->use_red = param->use_red && red_pt;
287
288 if (param->use_cng || param->use_red) {
kwiberge155ae62015-11-16 04:49:54 -0800289 // The RED and CNG encoders need to be in sync with the speech encoder, so
290 // reset the latter to ensure its buffer is empty.
kwiberg95d98512015-12-15 14:21:33 -0800291 param->speech_encoder->Reset();
kwiberge155ae62015-11-16 04:49:54 -0800292 }
kwiberg6030a122016-03-08 06:01:31 -0800293 std::unique_ptr<AudioEncoder> encoder_stack =
294 std::move(param->speech_encoder);
kwiberg1379f1f2015-11-23 04:30:52 -0800295 if (param->use_red) {
kwiberg6030a122016-03-08 06:01:31 -0800296 encoder_stack = CreateRedEncoder(std::move(encoder_stack), *red_pt);
kwiberge155ae62015-11-16 04:49:54 -0800297 }
kwiberg1379f1f2015-11-23 04:30:52 -0800298 if (param->use_cng) {
kwiberg6030a122016-03-08 06:01:31 -0800299 encoder_stack =
300 CreateCngEncoder(std::move(encoder_stack), *cng_pt, param->vad_mode);
kwiberge155ae62015-11-16 04:49:54 -0800301 }
kwiberg32be07b2016-01-21 07:10:01 -0800302 return encoder_stack;
kwiberg805fc712015-11-10 04:05:16 -0800303}
304
kwibergabe95ba2016-06-02 02:58:59 -0700305std::unique_ptr<AudioDecoder> RentACodec::RentIsacDecoder(int sample_rate_hz) {
306 return CreateIsacDecoder(sample_rate_hz, isac_bandwidth_info_);
kwiberg805fc712015-11-10 04:05:16 -0800307}
308
kwibergfce4a942015-10-27 11:40:24 -0700309} // namespace acm2
310} // namespace webrtc