blob: 3bc1464908fc006d480deccddf1fb6c1f8f011cd [file] [log] [blame]
kwibergbc8d75b2015-10-27 18:40:241/*
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
kjellander0c1546c2015-11-26 12:44:5411#include "webrtc/modules/audio_coding/acm2/rent_a_codec.h"
kwibergbc8d75b2015-10-27 18:40:2412
kwiberg82c16b02016-02-15 10:27:2213#include <memory>
kwibergacf06d62015-12-17 11:04:1514#include <utility>
15
kjellander@webrtc.org9592d2a2015-11-18 22:07:5716#include "webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.h"
17#include "webrtc/modules/audio_coding/codecs/g711/audio_encoder_pcm.h"
Edward Lemur76de83e2017-07-06 17:44:3418#include "webrtc/rtc_base/logging.h"
kwiberge8cf84f2015-11-10 12:05:1619#ifdef WEBRTC_CODEC_G722
kjellander@webrtc.org9592d2a2015-11-18 22:07:5720#include "webrtc/modules/audio_coding/codecs/g722/audio_encoder_g722.h"
kwiberge8cf84f2015-11-10 12:05:1621#endif
22#ifdef WEBRTC_CODEC_ILBC
kjellander@webrtc.org9592d2a2015-11-18 22:07:5723#include "webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h"
kwiberge8cf84f2015-11-10 12:05:1624#endif
25#ifdef WEBRTC_CODEC_ISACFX
kwiberg0bf3d9d2017-03-03 14:16:2826#include "webrtc/modules/audio_coding/codecs/isac/fix/include/audio_decoder_isacfix.h" // nogncheck
27#include "webrtc/modules/audio_coding/codecs/isac/fix/include/audio_encoder_isacfix.h" // nogncheck
kwiberge8cf84f2015-11-10 12:05:1628#endif
29#ifdef WEBRTC_CODEC_ISAC
kwiberg0bf3d9d2017-03-03 14:16:2830#include "webrtc/modules/audio_coding/codecs/isac/main/include/audio_decoder_isac.h" // nogncheck
31#include "webrtc/modules/audio_coding/codecs/isac/main/include/audio_encoder_isac.h" // nogncheck
kwiberge8cf84f2015-11-10 12:05:1632#endif
33#ifdef WEBRTC_CODEC_OPUS
kjellander@webrtc.org9592d2a2015-11-18 22:07:5734#include "webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.h"
kwiberge8cf84f2015-11-10 12:05:1635#endif
kjellander@webrtc.org9592d2a2015-11-18 22:07:5736#include "webrtc/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h"
kwiberg3c69ade2015-11-16 12:49:5437#ifdef WEBRTC_CODEC_RED
38#include "webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.h"
39#endif
kjellander0c1546c2015-11-26 12:44:5440#include "webrtc/modules/audio_coding/acm2/acm_codec_database.h"
kwibergbc8d75b2015-10-27 18:40:2441
kwibergd0e60102016-03-30 11:10:1142#if defined(WEBRTC_CODEC_ISACFX) || defined(WEBRTC_CODEC_ISAC)
43#include "webrtc/modules/audio_coding/codecs/isac/locked_bandwidth_info.h"
44#endif
45
kwibergbc8d75b2015-10-27 18:40:2446namespace webrtc {
47namespace acm2 {
48
Karl Wibergca8da3c2015-11-10 21:34:1849rtc::Optional<RentACodec::CodecId> RentACodec::CodecIdByParams(
kwibergbc8d75b2015-10-27 18:40:2450 const char* payload_name,
51 int sampling_freq_hz,
Peter Kasting80590d92016-01-13 00:26:3552 size_t channels) {
kwibergbc8d75b2015-10-27 18:40:2453 return CodecIdFromIndex(
54 ACMCodecDB::CodecId(payload_name, sampling_freq_hz, channels));
55}
56
Karl Wibergca8da3c2015-11-10 21:34:1857rtc::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>();
kwibergbc8d75b2015-10-27 18:40:2461}
62
Karl Wibergca8da3c2015-11-10 21:34:1863rtc::Optional<RentACodec::CodecId> RentACodec::CodecIdByInst(
kwiberg578e39a2015-11-06 22:28:0064 const CodecInst& codec_inst) {
65 return CodecIdFromIndex(ACMCodecDB::CodecNumber(codec_inst));
66}
67
Karl Wibergca8da3c2015-11-10 21:34:1868rtc::Optional<CodecInst> RentACodec::CodecInstByParams(const char* payload_name,
69 int sampling_freq_hz,
Peter Kasting80590d92016-01-13 00:26:3570 size_t channels) {
Karl Wibergca8da3c2015-11-10 21:34:1871 rtc::Optional<CodecId> codec_id =
kwibergbc8d75b2015-10-27 18:40:2472 CodecIdByParams(payload_name, sampling_freq_hz, channels);
73 if (!codec_id)
Karl Wibergca8da3c2015-11-10 21:34:1874 return rtc::Optional<CodecInst>();
75 rtc::Optional<CodecInst> ci = CodecInstById(*codec_id);
kwibergbc8d75b2015-10-27 18:40:2476 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 Wibergca8da3c2015-11-10 21:34:1889rtc::Optional<bool> RentACodec::IsSupportedNumChannels(CodecId codec_id,
Peter Kasting80590d92016-01-13 00:26:3590 size_t num_channels) {
kwibergc8b569e2015-11-03 13:46:0991 auto i = CodecIndexFromId(codec_id);
Karl Wibergca8da3c2015-11-10 21:34:1892 return i ? rtc::Optional<bool>(
93 ACMCodecDB::codec_settings_[*i].channel_support >=
94 num_channels)
95 : rtc::Optional<bool>();
kwibergc8b569e2015-11-03 13:46:0996}
97
kwibergbc8d75b2015-10-27 18:40:2498rtc::ArrayView<const CodecInst> RentACodec::Database() {
99 return rtc::ArrayView<const CodecInst>(ACMCodecDB::database_,
100 NumberOfCodecs());
101}
102
Karl Wibergca8da3c2015-11-10 21:34:18103rtc::Optional<NetEqDecoder> RentACodec::NetEqDecoderFromCodecId(
104 CodecId codec_id,
Peter Kasting80590d92016-01-13 00:26:35105 size_t num_channels) {
Karl Wibergca8da3c2015-11-10 21:34:18106 rtc::Optional<int> i = CodecIndexFromId(codec_id);
kwibergd3fdd5f2015-10-29 13:20:28107 if (!i)
Karl Wibergca8da3c2015-11-10 21:34:18108 return rtc::Optional<NetEqDecoder>();
kwibergd3fdd5f2015-10-29 13:20:28109 const NetEqDecoder ned = ACMCodecDB::neteq_decoders_[*i];
Karl Wibergca8da3c2015-11-10 21:34:18110 return rtc::Optional<NetEqDecoder>(
kwiberg6b9de622015-10-30 09:47:38111 (ned == NetEqDecoder::kDecoderOpus && num_channels == 2)
112 ? NetEqDecoder::kDecoderOpus_2ch
113 : ned);
kwibergd3fdd5f2015-10-29 13:20:28114}
115
kwiberg6c7e6c22015-11-18 15:32:49116RentACodec::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
kwiberge8cf84f2015-11-10 12:05:16147namespace {
148
149// Returns a new speech encoder, or null on error.
150// TODO(kwiberg): Don't handle errors here (bug 5033)
kwibergd0e60102016-03-30 11:10:11151std::unique_ptr<AudioEncoder> CreateEncoder(
152 const CodecInst& speech_inst,
153 const rtc::scoped_refptr<LockedIsacBandwidthInfo>& bwinfo) {
kwiberge8cf84f2015-11-10 12:05:16154#if defined(WEBRTC_CODEC_ISACFX)
155 if (STR_CASE_CMP(speech_inst.plname, "isac") == 0)
kwiberg82c16b02016-02-15 10:27:22156 return std::unique_ptr<AudioEncoder>(
kwibergebae5d12017-08-17 12:31:02157 new AudioEncoderIsacFixImpl(speech_inst, bwinfo));
kwiberge8cf84f2015-11-10 12:05:16158#endif
159#if defined(WEBRTC_CODEC_ISAC)
160 if (STR_CASE_CMP(speech_inst.plname, "isac") == 0)
kwiberg82c16b02016-02-15 10:27:22161 return std::unique_ptr<AudioEncoder>(
kwibergebae5d12017-08-17 12:31:02162 new AudioEncoderIsacFloatImpl(speech_inst, bwinfo));
kwiberge8cf84f2015-11-10 12:05:16163#endif
164#ifdef WEBRTC_CODEC_OPUS
165 if (STR_CASE_CMP(speech_inst.plname, "opus") == 0)
charujaine9cc1fe2017-06-18 09:38:58166 return std::unique_ptr<AudioEncoder>(new AudioEncoderOpus(speech_inst));
kwiberge8cf84f2015-11-10 12:05:16167#endif
168 if (STR_CASE_CMP(speech_inst.plname, "pcmu") == 0)
kwiberg82c16b02016-02-15 10:27:22169 return std::unique_ptr<AudioEncoder>(new AudioEncoderPcmU(speech_inst));
kwiberge8cf84f2015-11-10 12:05:16170 if (STR_CASE_CMP(speech_inst.plname, "pcma") == 0)
kwiberg82c16b02016-02-15 10:27:22171 return std::unique_ptr<AudioEncoder>(new AudioEncoderPcmA(speech_inst));
kwiberge8cf84f2015-11-10 12:05:16172 if (STR_CASE_CMP(speech_inst.plname, "l16") == 0)
kwiberg82c16b02016-02-15 10:27:22173 return std::unique_ptr<AudioEncoder>(new AudioEncoderPcm16B(speech_inst));
kwiberge8cf84f2015-11-10 12:05:16174#ifdef WEBRTC_CODEC_ILBC
175 if (STR_CASE_CMP(speech_inst.plname, "ilbc") == 0)
solenberg0a9e9202017-06-28 09:05:04176 return std::unique_ptr<AudioEncoder>(new AudioEncoderIlbcImpl(speech_inst));
kwiberge8cf84f2015-11-10 12:05:16177#endif
178#ifdef WEBRTC_CODEC_G722
179 if (STR_CASE_CMP(speech_inst.plname, "g722") == 0)
kwiberg4b9460d2017-06-18 00:41:59180 return std::unique_ptr<AudioEncoder>(new AudioEncoderG722Impl(speech_inst));
kwiberge8cf84f2015-11-10 12:05:16181#endif
182 LOG_F(LS_ERROR) << "Could not create encoder of type " << speech_inst.plname;
kwiberg82c16b02016-02-15 10:27:22183 return std::unique_ptr<AudioEncoder>();
kwiberge8cf84f2015-11-10 12:05:16184}
185
kwibergda728ea2016-03-08 14:01:31186std::unique_ptr<AudioEncoder> CreateRedEncoder(
187 std::unique_ptr<AudioEncoder> encoder,
188 int red_payload_type) {
kwiberg3c69ade2015-11-16 12:49:54189#ifdef WEBRTC_CODEC_RED
190 AudioEncoderCopyRed::Config config;
191 config.payload_type = red_payload_type;
kwibergda728ea2016-03-08 14:01:31192 config.speech_encoder = std::move(encoder);
193 return std::unique_ptr<AudioEncoder>(
194 new AudioEncoderCopyRed(std::move(config)));
kwiberg3c69ade2015-11-16 12:49:54195#else
kwiberg82c16b02016-02-15 10:27:22196 return std::unique_ptr<AudioEncoder>();
kwiberg3c69ade2015-11-16 12:49:54197#endif
198}
199
kwibergda728ea2016-03-08 14:01:31200std::unique_ptr<AudioEncoder> CreateCngEncoder(
201 std::unique_ptr<AudioEncoder> encoder,
202 int payload_type,
203 ACMVADMode vad_mode) {
kwiberg3c69ade2015-11-16 12:49:54204 AudioEncoderCng::Config config;
205 config.num_channels = encoder->NumChannels();
kwiberg0e2b7942015-11-23 12:30:52206 config.payload_type = payload_type;
kwibergda728ea2016-03-08 14:01:31207 config.speech_encoder = std::move(encoder);
kwiberg0e2b7942015-11-23 12:30:52208 switch (vad_mode) {
kwiberg3c69ade2015-11-16 12:49:54209 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 }
kwibergda728ea2016-03-08 14:01:31224 return std::unique_ptr<AudioEncoder>(new AudioEncoderCng(std::move(config)));
kwiberg3c69ade2015-11-16 12:49:54225}
226
kwiberg82c16b02016-02-15 10:27:22227std::unique_ptr<AudioDecoder> CreateIsacDecoder(
kwibergc9a54812016-06-02 09:58:59228 int sample_rate_hz,
kwibergd0e60102016-03-30 11:10:11229 const rtc::scoped_refptr<LockedIsacBandwidthInfo>& bwinfo) {
kwiberge8cf84f2015-11-10 12:05:16230#if defined(WEBRTC_CODEC_ISACFX)
kwibergc9a54812016-06-02 09:58:59231 return std::unique_ptr<AudioDecoder>(
kwibergebae5d12017-08-17 12:31:02232 new AudioDecoderIsacFixImpl(sample_rate_hz, bwinfo));
kwiberge8cf84f2015-11-10 12:05:16233#elif defined(WEBRTC_CODEC_ISAC)
kwibergc9a54812016-06-02 09:58:59234 return std::unique_ptr<AudioDecoder>(
kwibergebae5d12017-08-17 12:31:02235 new AudioDecoderIsacFloatImpl(sample_rate_hz, bwinfo));
kwiberge8cf84f2015-11-10 12:05:16236#else
237 FATAL() << "iSAC is not supported.";
kwiberg82c16b02016-02-15 10:27:22238 return std::unique_ptr<AudioDecoder>();
kwiberge8cf84f2015-11-10 12:05:16239#endif
240}
241
242} // namespace
243
kwibergd0e60102016-03-30 11:10:11244RentACodec::RentACodec() {
245#if defined(WEBRTC_CODEC_ISACFX) || defined(WEBRTC_CODEC_ISAC)
246 isac_bandwidth_info_ = new LockedIsacBandwidthInfo;
247#endif
248}
kwiberge8cf84f2015-11-10 12:05:16249RentACodec::~RentACodec() = default;
250
kwibergda728ea2016-03-08 14:01:31251std::unique_ptr<AudioEncoder> RentACodec::RentEncoder(
252 const CodecInst& codec_inst) {
kwibergd0e60102016-03-30 11:10:11253 return CreateEncoder(codec_inst, isac_bandwidth_info_);
kwiberg3c69ade2015-11-16 12:49:54254}
255
kwiberg0e2b7942015-11-23 12:30:52256RentACodec::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
kwibergda728ea2016-03-08 14:01:31266std::unique_ptr<AudioEncoder> RentACodec::RentEncoderStack(
267 StackParameters* param) {
kwiberg49ffac52016-04-06 19:22:38268 if (!param->speech_encoder)
269 return nullptr;
kwiberg0e2b7942015-11-23 12:30:52270
kwibergd5219022015-11-25 09:25:06271 if (param->use_codec_fec) {
272 // Switch FEC on. On failure, remember that FEC is off.
kwiberg0afb4962015-12-15 22:21:33273 if (!param->speech_encoder->SetFec(true))
kwibergd5219022015-11-25 09:25:06274 param->use_codec_fec = false;
275 } else {
276 // Switch FEC off. This shouldn't fail.
kwiberg0afb4962015-12-15 22:21:33277 const bool success = param->speech_encoder->SetFec(false);
kwibergd5219022015-11-25 09:25:06278 RTC_DCHECK(success);
279 }
280
kwiberg0afb4962015-12-15 22:21:33281 auto pt = [&param](const std::map<int, int>& m) {
282 auto it = m.find(param->speech_encoder->SampleRateHz());
kwiberg0e2b7942015-11-23 12:30:52283 return it == m.end() ? rtc::Optional<int>()
284 : rtc::Optional<int>(it->second);
285 };
286 auto cng_pt = pt(param->cng_payload_types);
kwiberg8af615d2015-11-25 09:19:13287 param->use_cng =
kwiberg0afb4962015-12-15 22:21:33288 param->use_cng && cng_pt && param->speech_encoder->NumChannels() == 1;
kwiberg0e2b7942015-11-23 12:30:52289 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) {
kwiberg3c69ade2015-11-16 12:49:54293 // 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.
kwiberg0afb4962015-12-15 22:21:33295 param->speech_encoder->Reset();
kwiberg3c69ade2015-11-16 12:49:54296 }
kwibergda728ea2016-03-08 14:01:31297 std::unique_ptr<AudioEncoder> encoder_stack =
298 std::move(param->speech_encoder);
kwiberg0e2b7942015-11-23 12:30:52299 if (param->use_red) {
kwibergda728ea2016-03-08 14:01:31300 encoder_stack = CreateRedEncoder(std::move(encoder_stack), *red_pt);
kwiberg3c69ade2015-11-16 12:49:54301 }
kwiberg0e2b7942015-11-23 12:30:52302 if (param->use_cng) {
kwibergda728ea2016-03-08 14:01:31303 encoder_stack =
304 CreateCngEncoder(std::move(encoder_stack), *cng_pt, param->vad_mode);
kwiberg3c69ade2015-11-16 12:49:54305 }
kwiberg9823ff62016-01-21 15:10:01306 return encoder_stack;
kwiberge8cf84f2015-11-10 12:05:16307}
308
kwibergc9a54812016-06-02 09:58:59309std::unique_ptr<AudioDecoder> RentACodec::RentIsacDecoder(int sample_rate_hz) {
310 return CreateIsacDecoder(sample_rate_hz, isac_bandwidth_info_);
kwiberge8cf84f2015-11-10 12:05:16311}
312
kwibergbc8d75b2015-10-27 18:40:24313} // namespace acm2
314} // namespace webrtc