blob: f29e0f1a1e27b90cc9054d8377eb2f85b4dcd504 [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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020013#include "rtc_base/checks.h"
14//#include "rtc_base/format_macros.h"
15#include "modules/audio_coding/acm2/rent_a_codec.h"
16#include "rtc_base/logging.h"
Henrik Lundin45c64492015-03-30 19:00:44 +020017
18namespace webrtc {
19namespace acm2 {
20
21namespace {
Henrik Lundin45c64492015-03-30 19:00:44 +020022
Henrik Lundin45c64492015-03-30 19:00:44 +020023// Check if the given codec is a valid to be registered as send codec.
kwiberg223692a2015-11-18 08:27:51 -080024int IsValidSendCodec(const CodecInst& send_codec) {
Henrik Lundin45c64492015-03-30 19:00:44 +020025 if ((send_codec.channels != 1) && (send_codec.channels != 2)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010026 RTC_LOG(LS_ERROR) << "Wrong number of channels (" << send_codec.channels
27 << "), only mono and stereo are supported)";
Henrik Lundin45c64492015-03-30 19:00:44 +020028 return -1;
29 }
30
kwibergd6c0f8c2015-11-06 14:28:00 -080031 auto maybe_codec_id = RentACodec::CodecIdByInst(send_codec);
32 if (!maybe_codec_id) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010033 RTC_LOG(LS_ERROR) << "Invalid codec setting for the send codec.";
Henrik Lundin45c64492015-03-30 19:00:44 +020034 return -1;
35 }
36
Henrik Lundin45c64492015-03-30 19:00:44 +020037 // Telephone-event cannot be a send codec.
38 if (!STR_CASE_CMP(send_codec.plname, "telephone-event")) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010039 RTC_LOG(LS_ERROR) << "telephone-event cannot be a send codec";
Henrik Lundin45c64492015-03-30 19:00:44 +020040 return -1;
41 }
42
kwibergd6c0f8c2015-11-06 14:28:00 -080043 if (!RentACodec::IsSupportedNumChannels(*maybe_codec_id, send_codec.channels)
44 .value_or(false)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010045 RTC_LOG(LS_ERROR) << send_codec.channels
46 << " number of channels not supported for "
47 << send_codec.plname << ".";
Henrik Lundin45c64492015-03-30 19:00:44 +020048 return -1;
49 }
kwibergd6c0f8c2015-11-06 14:28:00 -080050 return RentACodec::CodecIndexFromId(*maybe_codec_id).value_or(-1);
Henrik Lundin45c64492015-03-30 19:00:44 +020051}
52
Karl Wiberg2ea71c32015-05-07 15:49:23 +020053bool IsOpus(const CodecInst& codec) {
54 return
55#ifdef WEBRTC_CODEC_OPUS
56 !STR_CASE_CMP(codec.plname, "opus") ||
57#endif
58 false;
59}
60
Henrik Lundin45c64492015-03-30 19:00:44 +020061} // namespace
62
kwiberga6db4952015-12-16 04:19:08 -080063CodecManager::CodecManager() {
Henrik Lundin45c64492015-03-30 19:00:44 +020064 thread_checker_.DetachFromThread();
65}
66
Henrik Lundin93ef1d82015-04-13 09:31:16 +020067CodecManager::~CodecManager() = default;
Henrik Lundin45c64492015-03-30 19:00:44 +020068
kwiberga6db4952015-12-16 04:19:08 -080069bool CodecManager::RegisterEncoder(const CodecInst& send_codec) {
henrikg91d6ede2015-09-17 00:24:34 -070070 RTC_DCHECK(thread_checker_.CalledOnValidThread());
kwiberg223692a2015-11-18 08:27:51 -080071 int codec_id = IsValidSendCodec(send_codec);
Henrik Lundin45c64492015-03-30 19:00:44 +020072
73 // Check for reported errors from function IsValidSendCodec().
74 if (codec_id < 0) {
kwiberga6db4952015-12-16 04:19:08 -080075 return false;
Henrik Lundin45c64492015-03-30 19:00:44 +020076 }
77
kwiberg1379f1f2015-11-23 04:30:52 -080078 switch (RentACodec::RegisterRedPayloadType(
79 &codec_stack_params_.red_payload_types, send_codec)) {
kwiberge1a27d42015-11-18 07:32:49 -080080 case RentACodec::RegistrationResult::kOk:
kwiberga6db4952015-12-16 04:19:08 -080081 return true;
kwiberge1a27d42015-11-18 07:32:49 -080082 case RentACodec::RegistrationResult::kBadFreq:
Mirko Bonadei675513b2017-11-09 11:09:25 +010083 RTC_LOG(LS_ERROR)
84 << "RegisterSendCodec() failed, invalid frequency for RED"
85 " registration";
kwiberga6db4952015-12-16 04:19:08 -080086 return false;
kwiberge1a27d42015-11-18 07:32:49 -080087 case RentACodec::RegistrationResult::kSkip:
88 break;
Henrik Lundin45c64492015-03-30 19:00:44 +020089 }
kwiberg1379f1f2015-11-23 04:30:52 -080090 switch (RentACodec::RegisterCngPayloadType(
91 &codec_stack_params_.cng_payload_types, send_codec)) {
kwiberge1a27d42015-11-18 07:32:49 -080092 case RentACodec::RegistrationResult::kOk:
kwiberga6db4952015-12-16 04:19:08 -080093 return true;
kwiberge1a27d42015-11-18 07:32:49 -080094 case RentACodec::RegistrationResult::kBadFreq:
Mirko Bonadei675513b2017-11-09 11:09:25 +010095 RTC_LOG(LS_ERROR)
96 << "RegisterSendCodec() failed, invalid frequency for CNG"
97 " registration";
kwiberga6db4952015-12-16 04:19:08 -080098 return false;
kwiberge1a27d42015-11-18 07:32:49 -080099 case RentACodec::RegistrationResult::kSkip:
100 break;
Henrik Lundin45c64492015-03-30 19:00:44 +0200101 }
102
kwiberga6db4952015-12-16 04:19:08 -0800103 if (IsOpus(send_codec)) {
kwibergdfbb3a42015-12-01 04:45:04 -0800104 // VAD/DTX not supported.
105 codec_stack_params_.use_cng = false;
Henrik Lundin45c64492015-03-30 19:00:44 +0200106 }
Karl Wiberg2ea71c32015-05-07 15:49:23 +0200107
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100108 send_codec_inst_ = send_codec;
kwiberg3f81fcd2016-06-23 03:58:36 -0700109 recreate_encoder_ = true; // Caller must recreate it.
kwiberga6db4952015-12-16 04:19:08 -0800110 return true;
Henrik Lundin45c64492015-03-30 19:00:44 +0200111}
112
kwiberga6db4952015-12-16 04:19:08 -0800113CodecInst CodecManager::ForgeCodecInst(
114 const AudioEncoder* external_speech_encoder) {
115 CodecInst ci;
116 ci.channels = external_speech_encoder->NumChannels();
117 ci.plfreq = external_speech_encoder->SampleRateHz();
118 ci.pacsize = rtc::CheckedDivExact(
Peter Kastingdce40cf2015-08-24 14:52:23 -0700119 static_cast<int>(external_speech_encoder->Max10MsFramesInAPacket() *
kwiberga6db4952015-12-16 04:19:08 -0800120 ci.plfreq),
Peter Kastingdce40cf2015-08-24 14:52:23 -0700121 100);
kwiberga6db4952015-12-16 04:19:08 -0800122 ci.pltype = -1; // Not valid.
123 ci.rate = -1; // Not valid.
Karl Wiberg7e0c7d42015-05-18 14:52:29 +0200124 static const char kName[] = "external";
kwiberga6db4952015-12-16 04:19:08 -0800125 memcpy(ci.plname, kName, sizeof(kName));
126 return ci;
Henrik Lundin45c64492015-03-30 19:00:44 +0200127}
128
Henrik Lundin45c64492015-03-30 19:00:44 +0200129bool CodecManager::SetCopyRed(bool enable) {
kwiberg1379f1f2015-11-23 04:30:52 -0800130 if (enable && codec_stack_params_.use_codec_fec) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100131 RTC_LOG(LS_WARNING) << "Codec internal FEC and RED cannot be co-enabled.";
Henrik Lundin45c64492015-03-30 19:00:44 +0200132 return false;
133 }
kwiberga6db4952015-12-16 04:19:08 -0800134 if (enable && send_codec_inst_ &&
135 codec_stack_params_.red_payload_types.count(send_codec_inst_->plfreq) <
kwiberg1379f1f2015-11-23 04:30:52 -0800136 1) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100137 RTC_LOG(LS_WARNING) << "Cannot enable RED at " << send_codec_inst_->plfreq
138 << " Hz.";
Henrik Lundin45c64492015-03-30 19:00:44 +0200139 return false;
140 }
kwiberga6db4952015-12-16 04:19:08 -0800141 codec_stack_params_.use_red = enable;
Henrik Lundin45c64492015-03-30 19:00:44 +0200142 return true;
143}
144
kwiberga6db4952015-12-16 04:19:08 -0800145bool CodecManager::SetVAD(bool enable, ACMVADMode mode) {
Henrik Lundin45c64492015-03-30 19:00:44 +0200146 // Sanity check of the mode.
henrikg91d6ede2015-09-17 00:24:34 -0700147 RTC_DCHECK(mode == VADNormal || mode == VADLowBitrate || mode == VADAggr ||
148 mode == VADVeryAggr);
Henrik Lundin45c64492015-03-30 19:00:44 +0200149
150 // Check that the send codec is mono. We don't support VAD/DTX for stereo
151 // sending.
kwiberg95d98512015-12-15 14:21:33 -0800152 const bool stereo_send =
153 codec_stack_params_.speech_encoder
154 ? (codec_stack_params_.speech_encoder->NumChannels() != 1)
155 : false;
kwiberged8275a2015-11-10 09:47:36 -0800156 if (enable && stereo_send) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100157 RTC_LOG(LS_ERROR) << "VAD/DTX not supported for stereo sending";
kwiberga6db4952015-12-16 04:19:08 -0800158 return false;
Henrik Lundin45c64492015-03-30 19:00:44 +0200159 }
160
kwiberg44307632015-12-16 06:24:05 -0800161 // TODO(kwiberg): This doesn't protect Opus when injected as an external
162 // encoder.
163 if (send_codec_inst_ && IsOpus(*send_codec_inst_)) {
kwiberga6db4952015-12-16 04:19:08 -0800164 // VAD/DTX not supported, but don't fail.
165 enable = false;
Karl Wiberg2ea71c32015-05-07 15:49:23 +0200166 }
167
kwiberga6db4952015-12-16 04:19:08 -0800168 codec_stack_params_.use_cng = enable;
169 codec_stack_params_.vad_mode = mode;
170 return true;
Henrik Lundin45c64492015-03-30 19:00:44 +0200171}
172
kwiberga6db4952015-12-16 04:19:08 -0800173bool CodecManager::SetCodecFEC(bool enable_codec_fec) {
kwiberg1379f1f2015-11-23 04:30:52 -0800174 if (enable_codec_fec && codec_stack_params_.use_red) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100175 RTC_LOG(LS_WARNING) << "Codec internal FEC and RED cannot be co-enabled.";
kwiberga6db4952015-12-16 04:19:08 -0800176 return false;
Henrik Lundin45c64492015-03-30 19:00:44 +0200177 }
178
kwiberga6db4952015-12-16 04:19:08 -0800179 codec_stack_params_.use_codec_fec = enable_codec_fec;
180 return true;
Henrik Lundin45c64492015-03-30 19:00:44 +0200181}
182
kwiberg3f81fcd2016-06-23 03:58:36 -0700183bool CodecManager::MakeEncoder(RentACodec* rac, AudioCodingModule* acm) {
184 RTC_DCHECK(rac);
185 RTC_DCHECK(acm);
186
187 if (!recreate_encoder_) {
188 bool error = false;
189 // Try to re-use the speech encoder we've given to the ACM.
190 acm->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
191 if (!*encoder) {
192 // There is no existing encoder.
193 recreate_encoder_ = true;
194 return;
195 }
196
197 // Extract the speech encoder from the ACM.
198 std::unique_ptr<AudioEncoder> enc = std::move(*encoder);
199 while (true) {
200 auto sub_enc = enc->ReclaimContainedEncoders();
201 if (sub_enc.empty()) {
202 break;
203 }
kwibergaf476c72016-11-28 15:21:39 -0800204 RTC_CHECK_EQ(1, sub_enc.size());
kwiberg3f81fcd2016-06-23 03:58:36 -0700205
206 // Replace enc with its sub encoder. We need to put the sub encoder in
207 // a temporary first, since otherwise the old value of enc would be
208 // destroyed before the new value got assigned, which would be bad
209 // since the new value is a part of the old value.
210 auto tmp_enc = std::move(sub_enc[0]);
211 enc = std::move(tmp_enc);
212 }
213
214 // Wrap it in a new encoder stack and put it back.
215 codec_stack_params_.speech_encoder = std::move(enc);
216 *encoder = rac->RentEncoderStack(&codec_stack_params_);
217 if (!*encoder) {
218 error = true;
219 }
220 });
221 if (error) {
222 return false;
223 }
224 if (!recreate_encoder_) {
225 return true;
226 }
227 }
228
229 if (!send_codec_inst_) {
230 // We don't have the information we need to create a new speech encoder.
231 // (This is not an error.)
232 return true;
233 }
234
235 codec_stack_params_.speech_encoder = rac->RentEncoder(*send_codec_inst_);
236 auto stack = rac->RentEncoderStack(&codec_stack_params_);
237 if (!stack) {
238 return false;
239 }
240 acm->SetEncoder(std::move(stack));
241 recreate_encoder_ = false;
242 return true;
243}
244
Henrik Lundin45c64492015-03-30 19:00:44 +0200245} // namespace acm2
246} // namespace webrtc