blob: eda65550625c3a24f795bd8dfa69d9776d46b003 [file] [log] [blame]
Henrik Lundin45c64492015-03-30 19:00:44 +02001/*
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/codec_manager.h"
Henrik Lundin45c64492015-03-30 19:00:44 +020012
Yves Gerey988cc082018-10-23 12:03:01 +020013#include <string.h>
14#include <map>
15#include <memory>
16#include <utility>
17
Niels Möller2edab4c2018-10-22 09:48:08 +020018#include "absl/strings/match.h"
Yves Gerey988cc082018-10-23 12:03:01 +020019#include "api/array_view.h"
20#include "api/audio_codecs/audio_encoder.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "modules/audio_coding/acm2/rent_a_codec.h"
Yves Gerey988cc082018-10-23 12:03:01 +020022#include "rtc_base/checks.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020023#include "rtc_base/logging.h"
Henrik Lundin45c64492015-03-30 19:00:44 +020024
25namespace webrtc {
26namespace acm2 {
27
28namespace {
Henrik Lundin45c64492015-03-30 19:00:44 +020029
Henrik Lundin45c64492015-03-30 19:00:44 +020030// Check if the given codec is a valid to be registered as send codec.
kwiberg223692a2015-11-18 08:27:51 -080031int IsValidSendCodec(const CodecInst& send_codec) {
Henrik Lundin45c64492015-03-30 19:00:44 +020032 if ((send_codec.channels != 1) && (send_codec.channels != 2)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010033 RTC_LOG(LS_ERROR) << "Wrong number of channels (" << send_codec.channels
34 << "), only mono and stereo are supported)";
Henrik Lundin45c64492015-03-30 19:00:44 +020035 return -1;
36 }
37
kwibergd6c0f8c2015-11-06 14:28:00 -080038 auto maybe_codec_id = RentACodec::CodecIdByInst(send_codec);
39 if (!maybe_codec_id) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010040 RTC_LOG(LS_ERROR) << "Invalid codec setting for the send codec.";
Henrik Lundin45c64492015-03-30 19:00:44 +020041 return -1;
42 }
43
Henrik Lundin45c64492015-03-30 19:00:44 +020044 // Telephone-event cannot be a send codec.
Niels Möller2edab4c2018-10-22 09:48:08 +020045 if (absl::EqualsIgnoreCase(send_codec.plname, "telephone-event")) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010046 RTC_LOG(LS_ERROR) << "telephone-event cannot be a send codec";
Henrik Lundin45c64492015-03-30 19:00:44 +020047 return -1;
48 }
49
kwibergd6c0f8c2015-11-06 14:28:00 -080050 if (!RentACodec::IsSupportedNumChannels(*maybe_codec_id, send_codec.channels)
51 .value_or(false)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010052 RTC_LOG(LS_ERROR) << send_codec.channels
53 << " number of channels not supported for "
54 << send_codec.plname << ".";
Henrik Lundin45c64492015-03-30 19:00:44 +020055 return -1;
56 }
kwibergd6c0f8c2015-11-06 14:28:00 -080057 return RentACodec::CodecIndexFromId(*maybe_codec_id).value_or(-1);
Henrik Lundin45c64492015-03-30 19:00:44 +020058}
59
Karl Wiberg2ea71c32015-05-07 15:49:23 +020060bool IsOpus(const CodecInst& codec) {
61 return
62#ifdef WEBRTC_CODEC_OPUS
Niels Möller2edab4c2018-10-22 09:48:08 +020063 absl::EqualsIgnoreCase(codec.plname, "opus") ||
Karl Wiberg2ea71c32015-05-07 15:49:23 +020064#endif
65 false;
66}
67
Henrik Lundin45c64492015-03-30 19:00:44 +020068} // namespace
69
kwiberga6db4952015-12-16 04:19:08 -080070CodecManager::CodecManager() {
Henrik Lundin45c64492015-03-30 19:00:44 +020071 thread_checker_.DetachFromThread();
72}
73
Henrik Lundin93ef1d82015-04-13 09:31:16 +020074CodecManager::~CodecManager() = default;
Henrik Lundin45c64492015-03-30 19:00:44 +020075
kwiberga6db4952015-12-16 04:19:08 -080076bool CodecManager::RegisterEncoder(const CodecInst& send_codec) {
henrikg91d6ede2015-09-17 00:24:34 -070077 RTC_DCHECK(thread_checker_.CalledOnValidThread());
kwiberg223692a2015-11-18 08:27:51 -080078 int codec_id = IsValidSendCodec(send_codec);
Henrik Lundin45c64492015-03-30 19:00:44 +020079
80 // Check for reported errors from function IsValidSendCodec().
81 if (codec_id < 0) {
kwiberga6db4952015-12-16 04:19:08 -080082 return false;
Henrik Lundin45c64492015-03-30 19:00:44 +020083 }
84
kwiberg1379f1f2015-11-23 04:30:52 -080085 switch (RentACodec::RegisterRedPayloadType(
86 &codec_stack_params_.red_payload_types, send_codec)) {
kwiberge1a27d42015-11-18 07:32:49 -080087 case RentACodec::RegistrationResult::kOk:
kwiberga6db4952015-12-16 04:19:08 -080088 return true;
kwiberge1a27d42015-11-18 07:32:49 -080089 case RentACodec::RegistrationResult::kBadFreq:
Mirko Bonadei675513b2017-11-09 11:09:25 +010090 RTC_LOG(LS_ERROR)
91 << "RegisterSendCodec() failed, invalid frequency for RED"
92 " registration";
kwiberga6db4952015-12-16 04:19:08 -080093 return false;
kwiberge1a27d42015-11-18 07:32:49 -080094 case RentACodec::RegistrationResult::kSkip:
95 break;
Henrik Lundin45c64492015-03-30 19:00:44 +020096 }
kwiberg1379f1f2015-11-23 04:30:52 -080097 switch (RentACodec::RegisterCngPayloadType(
98 &codec_stack_params_.cng_payload_types, send_codec)) {
kwiberge1a27d42015-11-18 07:32:49 -080099 case RentACodec::RegistrationResult::kOk:
kwiberga6db4952015-12-16 04:19:08 -0800100 return true;
kwiberge1a27d42015-11-18 07:32:49 -0800101 case RentACodec::RegistrationResult::kBadFreq:
Mirko Bonadei675513b2017-11-09 11:09:25 +0100102 RTC_LOG(LS_ERROR)
103 << "RegisterSendCodec() failed, invalid frequency for CNG"
104 " registration";
kwiberga6db4952015-12-16 04:19:08 -0800105 return false;
kwiberge1a27d42015-11-18 07:32:49 -0800106 case RentACodec::RegistrationResult::kSkip:
107 break;
Henrik Lundin45c64492015-03-30 19:00:44 +0200108 }
109
kwiberga6db4952015-12-16 04:19:08 -0800110 if (IsOpus(send_codec)) {
kwibergdfbb3a42015-12-01 04:45:04 -0800111 // VAD/DTX not supported.
112 codec_stack_params_.use_cng = false;
Henrik Lundin45c64492015-03-30 19:00:44 +0200113 }
Karl Wiberg2ea71c32015-05-07 15:49:23 +0200114
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100115 send_codec_inst_ = send_codec;
kwiberg3f81fcd2016-06-23 03:58:36 -0700116 recreate_encoder_ = true; // Caller must recreate it.
kwiberga6db4952015-12-16 04:19:08 -0800117 return true;
Henrik Lundin45c64492015-03-30 19:00:44 +0200118}
119
kwiberga6db4952015-12-16 04:19:08 -0800120CodecInst CodecManager::ForgeCodecInst(
121 const AudioEncoder* external_speech_encoder) {
122 CodecInst ci;
123 ci.channels = external_speech_encoder->NumChannels();
124 ci.plfreq = external_speech_encoder->SampleRateHz();
125 ci.pacsize = rtc::CheckedDivExact(
Peter Kastingdce40cf2015-08-24 14:52:23 -0700126 static_cast<int>(external_speech_encoder->Max10MsFramesInAPacket() *
kwiberga6db4952015-12-16 04:19:08 -0800127 ci.plfreq),
Peter Kastingdce40cf2015-08-24 14:52:23 -0700128 100);
kwiberga6db4952015-12-16 04:19:08 -0800129 ci.pltype = -1; // Not valid.
130 ci.rate = -1; // Not valid.
Karl Wiberg7e0c7d42015-05-18 14:52:29 +0200131 static const char kName[] = "external";
kwiberga6db4952015-12-16 04:19:08 -0800132 memcpy(ci.plname, kName, sizeof(kName));
133 return ci;
Henrik Lundin45c64492015-03-30 19:00:44 +0200134}
135
Henrik Lundin45c64492015-03-30 19:00:44 +0200136bool CodecManager::SetCopyRed(bool enable) {
kwiberg1379f1f2015-11-23 04:30:52 -0800137 if (enable && codec_stack_params_.use_codec_fec) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100138 RTC_LOG(LS_WARNING) << "Codec internal FEC and RED cannot be co-enabled.";
Henrik Lundin45c64492015-03-30 19:00:44 +0200139 return false;
140 }
kwiberga6db4952015-12-16 04:19:08 -0800141 if (enable && send_codec_inst_ &&
142 codec_stack_params_.red_payload_types.count(send_codec_inst_->plfreq) <
kwiberg1379f1f2015-11-23 04:30:52 -0800143 1) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100144 RTC_LOG(LS_WARNING) << "Cannot enable RED at " << send_codec_inst_->plfreq
145 << " Hz.";
Henrik Lundin45c64492015-03-30 19:00:44 +0200146 return false;
147 }
kwiberga6db4952015-12-16 04:19:08 -0800148 codec_stack_params_.use_red = enable;
Henrik Lundin45c64492015-03-30 19:00:44 +0200149 return true;
150}
151
kwiberga6db4952015-12-16 04:19:08 -0800152bool CodecManager::SetVAD(bool enable, ACMVADMode mode) {
Henrik Lundin45c64492015-03-30 19:00:44 +0200153 // Sanity check of the mode.
henrikg91d6ede2015-09-17 00:24:34 -0700154 RTC_DCHECK(mode == VADNormal || mode == VADLowBitrate || mode == VADAggr ||
155 mode == VADVeryAggr);
Henrik Lundin45c64492015-03-30 19:00:44 +0200156
157 // Check that the send codec is mono. We don't support VAD/DTX for stereo
158 // sending.
kwiberg95d98512015-12-15 14:21:33 -0800159 const bool stereo_send =
160 codec_stack_params_.speech_encoder
161 ? (codec_stack_params_.speech_encoder->NumChannels() != 1)
162 : false;
kwiberged8275a2015-11-10 09:47:36 -0800163 if (enable && stereo_send) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100164 RTC_LOG(LS_ERROR) << "VAD/DTX not supported for stereo sending";
kwiberga6db4952015-12-16 04:19:08 -0800165 return false;
Henrik Lundin45c64492015-03-30 19:00:44 +0200166 }
167
kwiberg44307632015-12-16 06:24:05 -0800168 // TODO(kwiberg): This doesn't protect Opus when injected as an external
169 // encoder.
170 if (send_codec_inst_ && IsOpus(*send_codec_inst_)) {
kwiberga6db4952015-12-16 04:19:08 -0800171 // VAD/DTX not supported, but don't fail.
172 enable = false;
Karl Wiberg2ea71c32015-05-07 15:49:23 +0200173 }
174
kwiberga6db4952015-12-16 04:19:08 -0800175 codec_stack_params_.use_cng = enable;
176 codec_stack_params_.vad_mode = mode;
177 return true;
Henrik Lundin45c64492015-03-30 19:00:44 +0200178}
179
kwiberga6db4952015-12-16 04:19:08 -0800180bool CodecManager::SetCodecFEC(bool enable_codec_fec) {
kwiberg1379f1f2015-11-23 04:30:52 -0800181 if (enable_codec_fec && codec_stack_params_.use_red) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100182 RTC_LOG(LS_WARNING) << "Codec internal FEC and RED cannot be co-enabled.";
kwiberga6db4952015-12-16 04:19:08 -0800183 return false;
Henrik Lundin45c64492015-03-30 19:00:44 +0200184 }
185
kwiberga6db4952015-12-16 04:19:08 -0800186 codec_stack_params_.use_codec_fec = enable_codec_fec;
187 return true;
Henrik Lundin45c64492015-03-30 19:00:44 +0200188}
189
kwiberg3f81fcd2016-06-23 03:58:36 -0700190bool CodecManager::MakeEncoder(RentACodec* rac, AudioCodingModule* acm) {
191 RTC_DCHECK(rac);
192 RTC_DCHECK(acm);
193
194 if (!recreate_encoder_) {
195 bool error = false;
196 // Try to re-use the speech encoder we've given to the ACM.
197 acm->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
198 if (!*encoder) {
199 // There is no existing encoder.
200 recreate_encoder_ = true;
201 return;
202 }
203
204 // Extract the speech encoder from the ACM.
205 std::unique_ptr<AudioEncoder> enc = std::move(*encoder);
206 while (true) {
207 auto sub_enc = enc->ReclaimContainedEncoders();
208 if (sub_enc.empty()) {
209 break;
210 }
kwibergaf476c72016-11-28 15:21:39 -0800211 RTC_CHECK_EQ(1, sub_enc.size());
kwiberg3f81fcd2016-06-23 03:58:36 -0700212
213 // Replace enc with its sub encoder. We need to put the sub encoder in
214 // a temporary first, since otherwise the old value of enc would be
215 // destroyed before the new value got assigned, which would be bad
216 // since the new value is a part of the old value.
217 auto tmp_enc = std::move(sub_enc[0]);
218 enc = std::move(tmp_enc);
219 }
220
221 // Wrap it in a new encoder stack and put it back.
222 codec_stack_params_.speech_encoder = std::move(enc);
223 *encoder = rac->RentEncoderStack(&codec_stack_params_);
224 if (!*encoder) {
225 error = true;
226 }
227 });
228 if (error) {
229 return false;
230 }
231 if (!recreate_encoder_) {
232 return true;
233 }
234 }
235
236 if (!send_codec_inst_) {
237 // We don't have the information we need to create a new speech encoder.
238 // (This is not an error.)
239 return true;
240 }
241
242 codec_stack_params_.speech_encoder = rac->RentEncoder(*send_codec_inst_);
243 auto stack = rac->RentEncoderStack(&codec_stack_params_);
244 if (!stack) {
245 return false;
246 }
247 acm->SetEncoder(std::move(stack));
248 recreate_encoder_ = false;
249 return true;
250}
251
Henrik Lundin45c64492015-03-30 19:00:44 +0200252} // namespace acm2
253} // namespace webrtc