blob: 0a9ce117e2bd743747e08b71135d3ca460988353 [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 Bonadei01cd8532018-09-04 10:47:15 +020021#include "modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h" // nogncheck
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 Bonadei01cd8532018-09-04 10:47:15 +020036#include "modules/audio_coding/codecs/red/audio_encoder_copy_red.h" // nogncheck
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
Danil Chapovalovb6021232018-06-19 13:26:36 +020047absl::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
Danil Chapovalovb6021232018-06-19 13:26:36 +020055absl::optional<CodecInst> RentACodec::CodecInstById(CodecId codec_id) {
56 absl::optional<int> mi = CodecIndexFromId(codec_id);
57 return mi ? absl::optional<CodecInst>(Database()[*mi]) : absl::nullopt;
kwibergfce4a942015-10-27 11:40:24 -070058}
59
Danil Chapovalovb6021232018-06-19 13:26:36 +020060absl::optional<RentACodec::CodecId> RentACodec::CodecIdByInst(
kwibergd6c0f8c2015-11-06 14:28:00 -080061 const CodecInst& codec_inst) {
62 return CodecIdFromIndex(ACMCodecDB::CodecNumber(codec_inst));
63}
64
Danil Chapovalovb6021232018-06-19 13:26:36 +020065absl::optional<CodecInst> RentACodec::CodecInstByParams(
66 const char* payload_name,
67 int sampling_freq_hz,
68 size_t channels) {
69 absl::optional<CodecId> codec_id =
kwibergfce4a942015-10-27 11:40:24 -070070 CodecIdByParams(payload_name, sampling_freq_hz, channels);
71 if (!codec_id)
Danil Chapovalovb6021232018-06-19 13:26:36 +020072 return absl::nullopt;
73 absl::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
Danil Chapovalovb6021232018-06-19 13:26:36 +020083absl::optional<bool> RentACodec::IsSupportedNumChannels(CodecId codec_id,
84 size_t num_channels) {
kwibergde94d082015-11-03 05:46:09 -080085 auto i = CodecIndexFromId(codec_id);
Danil Chapovalovb6021232018-06-19 13:26:36 +020086 return i ? absl::optional<bool>(
Karl Wibergbe579832015-11-10 22:34:18 +010087 ACMCodecDB::codec_settings_[*i].channel_support >=
88 num_channels)
Danil Chapovalovb6021232018-06-19 13:26:36 +020089 : absl::nullopt;
kwibergde94d082015-11-03 05:46:09 -080090}
91
kwibergfce4a942015-10-27 11:40:24 -070092rtc::ArrayView<const CodecInst> RentACodec::Database() {
93 return rtc::ArrayView<const CodecInst>(ACMCodecDB::database_,
94 NumberOfCodecs());
95}
96
Danil Chapovalovb6021232018-06-19 13:26:36 +020097absl::optional<NetEqDecoder> RentACodec::NetEqDecoderFromCodecId(
Karl Wibergbe579832015-11-10 22:34:18 +010098 CodecId codec_id,
Peter Kasting69558702016-01-12 16:26:35 -080099 size_t num_channels) {
Danil Chapovalovb6021232018-06-19 13:26:36 +0200100 absl::optional<int> i = CodecIndexFromId(codec_id);
kwibergee1879c2015-10-29 06:20:28 -0700101 if (!i)
Danil Chapovalovb6021232018-06-19 13:26:36 +0200102 return absl::nullopt;
kwibergee1879c2015-10-29 06:20:28 -0700103 const NetEqDecoder ned = ACMCodecDB::neteq_decoders_[*i];
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100104 return (ned == NetEqDecoder::kDecoderOpus && num_channels == 2)
105 ? NetEqDecoder::kDecoderOpus_2ch
106 : ned;
kwibergee1879c2015-10-29 06:20:28 -0700107}
108
kwiberge1a27d42015-11-18 07:32:49 -0800109RentACodec::RegistrationResult RentACodec::RegisterCngPayloadType(
110 std::map<int, int>* pt_map,
111 const CodecInst& codec_inst) {
112 if (STR_CASE_CMP(codec_inst.plname, "CN") != 0)
113 return RegistrationResult::kSkip;
114 switch (codec_inst.plfreq) {
115 case 8000:
116 case 16000:
117 case 32000:
118 case 48000:
119 (*pt_map)[codec_inst.plfreq] = codec_inst.pltype;
120 return RegistrationResult::kOk;
121 default:
122 return RegistrationResult::kBadFreq;
123 }
124}
125
126RentACodec::RegistrationResult RentACodec::RegisterRedPayloadType(
127 std::map<int, int>* pt_map,
128 const CodecInst& codec_inst) {
129 if (STR_CASE_CMP(codec_inst.plname, "RED") != 0)
130 return RegistrationResult::kSkip;
131 switch (codec_inst.plfreq) {
132 case 8000:
133 (*pt_map)[codec_inst.plfreq] = codec_inst.pltype;
134 return RegistrationResult::kOk;
135 default:
136 return RegistrationResult::kBadFreq;
137 }
138}
139
kwiberg805fc712015-11-10 04:05:16 -0800140namespace {
141
142// Returns a new speech encoder, or null on error.
143// TODO(kwiberg): Don't handle errors here (bug 5033)
kwiberg0d05da72016-03-30 04:10:11 -0700144std::unique_ptr<AudioEncoder> CreateEncoder(
145 const CodecInst& speech_inst,
146 const rtc::scoped_refptr<LockedIsacBandwidthInfo>& bwinfo) {
kwiberg805fc712015-11-10 04:05:16 -0800147#if defined(WEBRTC_CODEC_ISACFX)
148 if (STR_CASE_CMP(speech_inst.plname, "isac") == 0)
kwiberg16c5a962016-02-15 02:27:22 -0800149 return std::unique_ptr<AudioEncoder>(
kwiberg6ff045f2017-08-17 05:31:02 -0700150 new AudioEncoderIsacFixImpl(speech_inst, bwinfo));
kwiberg805fc712015-11-10 04:05:16 -0800151#endif
152#if defined(WEBRTC_CODEC_ISAC)
153 if (STR_CASE_CMP(speech_inst.plname, "isac") == 0)
kwiberg16c5a962016-02-15 02:27:22 -0800154 return std::unique_ptr<AudioEncoder>(
kwiberg6ff045f2017-08-17 05:31:02 -0700155 new AudioEncoderIsacFloatImpl(speech_inst, bwinfo));
kwiberg805fc712015-11-10 04:05:16 -0800156#endif
157#ifdef WEBRTC_CODEC_OPUS
158 if (STR_CASE_CMP(speech_inst.plname, "opus") == 0)
Karl Wiberg7275e182017-10-25 09:57:40 +0200159 return std::unique_ptr<AudioEncoder>(new AudioEncoderOpusImpl(speech_inst));
kwiberg805fc712015-11-10 04:05:16 -0800160#endif
161 if (STR_CASE_CMP(speech_inst.plname, "pcmu") == 0)
kwiberg16c5a962016-02-15 02:27:22 -0800162 return std::unique_ptr<AudioEncoder>(new AudioEncoderPcmU(speech_inst));
kwiberg805fc712015-11-10 04:05:16 -0800163 if (STR_CASE_CMP(speech_inst.plname, "pcma") == 0)
kwiberg16c5a962016-02-15 02:27:22 -0800164 return std::unique_ptr<AudioEncoder>(new AudioEncoderPcmA(speech_inst));
kwiberg805fc712015-11-10 04:05:16 -0800165 if (STR_CASE_CMP(speech_inst.plname, "l16") == 0)
kwiberg16c5a962016-02-15 02:27:22 -0800166 return std::unique_ptr<AudioEncoder>(new AudioEncoderPcm16B(speech_inst));
kwiberg805fc712015-11-10 04:05:16 -0800167#ifdef WEBRTC_CODEC_ILBC
168 if (STR_CASE_CMP(speech_inst.plname, "ilbc") == 0)
solenbergdb3c9b02017-06-28 02:05:04 -0700169 return std::unique_ptr<AudioEncoder>(new AudioEncoderIlbcImpl(speech_inst));
kwiberg805fc712015-11-10 04:05:16 -0800170#endif
kwiberg805fc712015-11-10 04:05:16 -0800171 if (STR_CASE_CMP(speech_inst.plname, "g722") == 0)
kwibergb8727ae2017-06-17 17:41:59 -0700172 return std::unique_ptr<AudioEncoder>(new AudioEncoderG722Impl(speech_inst));
Mirko Bonadei675513b2017-11-09 11:09:25 +0100173 RTC_LOG_F(LS_ERROR) << "Could not create encoder of type "
174 << speech_inst.plname;
kwiberg16c5a962016-02-15 02:27:22 -0800175 return std::unique_ptr<AudioEncoder>();
kwiberg805fc712015-11-10 04:05:16 -0800176}
177
kwiberg6030a122016-03-08 06:01:31 -0800178std::unique_ptr<AudioEncoder> CreateRedEncoder(
179 std::unique_ptr<AudioEncoder> encoder,
180 int red_payload_type) {
kwiberge155ae62015-11-16 04:49:54 -0800181#ifdef WEBRTC_CODEC_RED
182 AudioEncoderCopyRed::Config config;
183 config.payload_type = red_payload_type;
kwiberg6030a122016-03-08 06:01:31 -0800184 config.speech_encoder = std::move(encoder);
185 return std::unique_ptr<AudioEncoder>(
186 new AudioEncoderCopyRed(std::move(config)));
kwiberge155ae62015-11-16 04:49:54 -0800187#else
kwiberg16c5a962016-02-15 02:27:22 -0800188 return std::unique_ptr<AudioEncoder>();
kwiberge155ae62015-11-16 04:49:54 -0800189#endif
190}
191
kwiberg6030a122016-03-08 06:01:31 -0800192std::unique_ptr<AudioEncoder> CreateCngEncoder(
193 std::unique_ptr<AudioEncoder> encoder,
194 int payload_type,
195 ACMVADMode vad_mode) {
kwiberge155ae62015-11-16 04:49:54 -0800196 AudioEncoderCng::Config config;
197 config.num_channels = encoder->NumChannels();
kwiberg1379f1f2015-11-23 04:30:52 -0800198 config.payload_type = payload_type;
kwiberg6030a122016-03-08 06:01:31 -0800199 config.speech_encoder = std::move(encoder);
kwiberg1379f1f2015-11-23 04:30:52 -0800200 switch (vad_mode) {
kwiberge155ae62015-11-16 04:49:54 -0800201 case VADNormal:
202 config.vad_mode = Vad::kVadNormal;
203 break;
204 case VADLowBitrate:
205 config.vad_mode = Vad::kVadLowBitrate;
206 break;
207 case VADAggr:
208 config.vad_mode = Vad::kVadAggressive;
209 break;
210 case VADVeryAggr:
211 config.vad_mode = Vad::kVadVeryAggressive;
212 break;
213 default:
214 FATAL();
215 }
kwiberg6030a122016-03-08 06:01:31 -0800216 return std::unique_ptr<AudioEncoder>(new AudioEncoderCng(std::move(config)));
kwiberge155ae62015-11-16 04:49:54 -0800217}
218
kwiberg16c5a962016-02-15 02:27:22 -0800219std::unique_ptr<AudioDecoder> CreateIsacDecoder(
kwibergabe95ba2016-06-02 02:58:59 -0700220 int sample_rate_hz,
kwiberg0d05da72016-03-30 04:10:11 -0700221 const rtc::scoped_refptr<LockedIsacBandwidthInfo>& bwinfo) {
kwiberg805fc712015-11-10 04:05:16 -0800222#if defined(WEBRTC_CODEC_ISACFX)
kwibergabe95ba2016-06-02 02:58:59 -0700223 return std::unique_ptr<AudioDecoder>(
kwiberg6ff045f2017-08-17 05:31:02 -0700224 new AudioDecoderIsacFixImpl(sample_rate_hz, bwinfo));
kwiberg805fc712015-11-10 04:05:16 -0800225#elif defined(WEBRTC_CODEC_ISAC)
kwibergabe95ba2016-06-02 02:58:59 -0700226 return std::unique_ptr<AudioDecoder>(
kwiberg6ff045f2017-08-17 05:31:02 -0700227 new AudioDecoderIsacFloatImpl(sample_rate_hz, bwinfo));
kwiberg805fc712015-11-10 04:05:16 -0800228#else
229 FATAL() << "iSAC is not supported.";
kwiberg16c5a962016-02-15 02:27:22 -0800230 return std::unique_ptr<AudioDecoder>();
kwiberg805fc712015-11-10 04:05:16 -0800231#endif
232}
233
234} // namespace
235
kwiberg0d05da72016-03-30 04:10:11 -0700236RentACodec::RentACodec() {
237#if defined(WEBRTC_CODEC_ISACFX) || defined(WEBRTC_CODEC_ISAC)
238 isac_bandwidth_info_ = new LockedIsacBandwidthInfo;
239#endif
240}
kwiberg805fc712015-11-10 04:05:16 -0800241RentACodec::~RentACodec() = default;
242
kwiberg6030a122016-03-08 06:01:31 -0800243std::unique_ptr<AudioEncoder> RentACodec::RentEncoder(
244 const CodecInst& codec_inst) {
kwiberg0d05da72016-03-30 04:10:11 -0700245 return CreateEncoder(codec_inst, isac_bandwidth_info_);
kwiberge155ae62015-11-16 04:49:54 -0800246}
247
kwiberg1379f1f2015-11-23 04:30:52 -0800248RentACodec::StackParameters::StackParameters() {
249 // Register the default payload types for RED and CNG.
250 for (const CodecInst& ci : RentACodec::Database()) {
251 RentACodec::RegisterCngPayloadType(&cng_payload_types, ci);
252 RentACodec::RegisterRedPayloadType(&red_payload_types, ci);
253 }
254}
255
256RentACodec::StackParameters::~StackParameters() = default;
257
kwiberg6030a122016-03-08 06:01:31 -0800258std::unique_ptr<AudioEncoder> RentACodec::RentEncoderStack(
259 StackParameters* param) {
kwibergc8d071e2016-04-06 12:22:38 -0700260 if (!param->speech_encoder)
261 return nullptr;
kwiberg1379f1f2015-11-23 04:30:52 -0800262
kwiberg9cd5c8c2015-11-25 01:25:06 -0800263 if (param->use_codec_fec) {
264 // Switch FEC on. On failure, remember that FEC is off.
kwiberg95d98512015-12-15 14:21:33 -0800265 if (!param->speech_encoder->SetFec(true))
kwiberg9cd5c8c2015-11-25 01:25:06 -0800266 param->use_codec_fec = false;
267 } else {
268 // Switch FEC off. This shouldn't fail.
kwiberg95d98512015-12-15 14:21:33 -0800269 const bool success = param->speech_encoder->SetFec(false);
kwiberg9cd5c8c2015-11-25 01:25:06 -0800270 RTC_DCHECK(success);
271 }
272
kwiberg95d98512015-12-15 14:21:33 -0800273 auto pt = [&param](const std::map<int, int>& m) {
274 auto it = m.find(param->speech_encoder->SampleRateHz());
Danil Chapovalovb6021232018-06-19 13:26:36 +0200275 return it == m.end() ? absl::nullopt : absl::optional<int>(it->second);
kwiberg1379f1f2015-11-23 04:30:52 -0800276 };
277 auto cng_pt = pt(param->cng_payload_types);
kwiberg989b4ab2015-11-25 01:19:13 -0800278 param->use_cng =
kwiberg95d98512015-12-15 14:21:33 -0800279 param->use_cng && cng_pt && param->speech_encoder->NumChannels() == 1;
kwiberg1379f1f2015-11-23 04:30:52 -0800280 auto red_pt = pt(param->red_payload_types);
281 param->use_red = param->use_red && red_pt;
282
283 if (param->use_cng || param->use_red) {
kwiberge155ae62015-11-16 04:49:54 -0800284 // The RED and CNG encoders need to be in sync with the speech encoder, so
285 // reset the latter to ensure its buffer is empty.
kwiberg95d98512015-12-15 14:21:33 -0800286 param->speech_encoder->Reset();
kwiberge155ae62015-11-16 04:49:54 -0800287 }
kwiberg6030a122016-03-08 06:01:31 -0800288 std::unique_ptr<AudioEncoder> encoder_stack =
289 std::move(param->speech_encoder);
kwiberg1379f1f2015-11-23 04:30:52 -0800290 if (param->use_red) {
kwiberg6030a122016-03-08 06:01:31 -0800291 encoder_stack = CreateRedEncoder(std::move(encoder_stack), *red_pt);
kwiberge155ae62015-11-16 04:49:54 -0800292 }
kwiberg1379f1f2015-11-23 04:30:52 -0800293 if (param->use_cng) {
kwiberg6030a122016-03-08 06:01:31 -0800294 encoder_stack =
295 CreateCngEncoder(std::move(encoder_stack), *cng_pt, param->vad_mode);
kwiberge155ae62015-11-16 04:49:54 -0800296 }
kwiberg32be07b2016-01-21 07:10:01 -0800297 return encoder_stack;
kwiberg805fc712015-11-10 04:05:16 -0800298}
299
kwibergabe95ba2016-06-02 02:58:59 -0700300std::unique_ptr<AudioDecoder> RentACodec::RentIsacDecoder(int sample_rate_hz) {
301 return CreateIsacDecoder(sample_rate_hz, isac_bandwidth_info_);
kwiberg805fc712015-11-10 04:05:16 -0800302}
303
kwibergfce4a942015-10-27 11:40:24 -0700304} // namespace acm2
305} // namespace webrtc