blob: 50ef9efa4b6a087a88911cd39a21bf0f48ae82cc [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"
Mirko Bonadei71207422017-09-15 13:58:09 +020017#include "typedefs.h" // NOLINT(build/include)
Henrik Lundin45c64492015-03-30 19:00:44 +020018
19namespace webrtc {
20namespace acm2 {
21
22namespace {
Henrik Lundin45c64492015-03-30 19:00:44 +020023
Henrik Lundin45c64492015-03-30 19:00:44 +020024// Check if the given codec is a valid to be registered as send codec.
kwiberg223692a2015-11-18 08:27:51 -080025int IsValidSendCodec(const CodecInst& send_codec) {
Henrik Lundin45c64492015-03-30 19:00:44 +020026 if ((send_codec.channels != 1) && (send_codec.channels != 2)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010027 RTC_LOG(LS_ERROR) << "Wrong number of channels (" << send_codec.channels
28 << "), only mono and stereo are supported)";
Henrik Lundin45c64492015-03-30 19:00:44 +020029 return -1;
30 }
31
kwibergd6c0f8c2015-11-06 14:28:00 -080032 auto maybe_codec_id = RentACodec::CodecIdByInst(send_codec);
33 if (!maybe_codec_id) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010034 RTC_LOG(LS_ERROR) << "Invalid codec setting for the send codec.";
Henrik Lundin45c64492015-03-30 19:00:44 +020035 return -1;
36 }
37
Henrik Lundin45c64492015-03-30 19:00:44 +020038 // Telephone-event cannot be a send codec.
39 if (!STR_CASE_CMP(send_codec.plname, "telephone-event")) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010040 RTC_LOG(LS_ERROR) << "telephone-event cannot be a send codec";
Henrik Lundin45c64492015-03-30 19:00:44 +020041 return -1;
42 }
43
kwibergd6c0f8c2015-11-06 14:28:00 -080044 if (!RentACodec::IsSupportedNumChannels(*maybe_codec_id, send_codec.channels)
45 .value_or(false)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010046 RTC_LOG(LS_ERROR) << send_codec.channels
47 << " number of channels not supported for "
48 << send_codec.plname << ".";
Henrik Lundin45c64492015-03-30 19:00:44 +020049 return -1;
50 }
kwibergd6c0f8c2015-11-06 14:28:00 -080051 return RentACodec::CodecIndexFromId(*maybe_codec_id).value_or(-1);
Henrik Lundin45c64492015-03-30 19:00:44 +020052}
53
Karl Wiberg2ea71c32015-05-07 15:49:23 +020054bool IsOpus(const CodecInst& codec) {
55 return
56#ifdef WEBRTC_CODEC_OPUS
57 !STR_CASE_CMP(codec.plname, "opus") ||
58#endif
59 false;
60}
61
Henrik Lundin45c64492015-03-30 19:00:44 +020062} // namespace
63
kwiberga6db4952015-12-16 04:19:08 -080064CodecManager::CodecManager() {
Henrik Lundin45c64492015-03-30 19:00:44 +020065 thread_checker_.DetachFromThread();
66}
67
Henrik Lundin93ef1d82015-04-13 09:31:16 +020068CodecManager::~CodecManager() = default;
Henrik Lundin45c64492015-03-30 19:00:44 +020069
kwiberga6db4952015-12-16 04:19:08 -080070bool CodecManager::RegisterEncoder(const CodecInst& send_codec) {
henrikg91d6ede2015-09-17 00:24:34 -070071 RTC_DCHECK(thread_checker_.CalledOnValidThread());
kwiberg223692a2015-11-18 08:27:51 -080072 int codec_id = IsValidSendCodec(send_codec);
Henrik Lundin45c64492015-03-30 19:00:44 +020073
74 // Check for reported errors from function IsValidSendCodec().
75 if (codec_id < 0) {
kwiberga6db4952015-12-16 04:19:08 -080076 return false;
Henrik Lundin45c64492015-03-30 19:00:44 +020077 }
78
kwiberg1379f1f2015-11-23 04:30:52 -080079 switch (RentACodec::RegisterRedPayloadType(
80 &codec_stack_params_.red_payload_types, send_codec)) {
kwiberge1a27d42015-11-18 07:32:49 -080081 case RentACodec::RegistrationResult::kOk:
kwiberga6db4952015-12-16 04:19:08 -080082 return true;
kwiberge1a27d42015-11-18 07:32:49 -080083 case RentACodec::RegistrationResult::kBadFreq:
Mirko Bonadei675513b2017-11-09 11:09:25 +010084 RTC_LOG(LS_ERROR)
85 << "RegisterSendCodec() failed, invalid frequency for RED"
86 " registration";
kwiberga6db4952015-12-16 04:19:08 -080087 return false;
kwiberge1a27d42015-11-18 07:32:49 -080088 case RentACodec::RegistrationResult::kSkip:
89 break;
Henrik Lundin45c64492015-03-30 19:00:44 +020090 }
kwiberg1379f1f2015-11-23 04:30:52 -080091 switch (RentACodec::RegisterCngPayloadType(
92 &codec_stack_params_.cng_payload_types, send_codec)) {
kwiberge1a27d42015-11-18 07:32:49 -080093 case RentACodec::RegistrationResult::kOk:
kwiberga6db4952015-12-16 04:19:08 -080094 return true;
kwiberge1a27d42015-11-18 07:32:49 -080095 case RentACodec::RegistrationResult::kBadFreq:
Mirko Bonadei675513b2017-11-09 11:09:25 +010096 RTC_LOG(LS_ERROR)
97 << "RegisterSendCodec() failed, invalid frequency for CNG"
98 " registration";
kwiberga6db4952015-12-16 04:19:08 -080099 return false;
kwiberge1a27d42015-11-18 07:32:49 -0800100 case RentACodec::RegistrationResult::kSkip:
101 break;
Henrik Lundin45c64492015-03-30 19:00:44 +0200102 }
103
kwiberga6db4952015-12-16 04:19:08 -0800104 if (IsOpus(send_codec)) {
kwibergdfbb3a42015-12-01 04:45:04 -0800105 // VAD/DTX not supported.
106 codec_stack_params_.use_cng = false;
Henrik Lundin45c64492015-03-30 19:00:44 +0200107 }
Karl Wiberg2ea71c32015-05-07 15:49:23 +0200108
kwiberga6db4952015-12-16 04:19:08 -0800109 send_codec_inst_ = rtc::Optional<CodecInst>(send_codec);
kwiberg3f81fcd2016-06-23 03:58:36 -0700110 recreate_encoder_ = true; // Caller must recreate it.
kwiberga6db4952015-12-16 04:19:08 -0800111 return true;
Henrik Lundin45c64492015-03-30 19:00:44 +0200112}
113
kwiberga6db4952015-12-16 04:19:08 -0800114CodecInst CodecManager::ForgeCodecInst(
115 const AudioEncoder* external_speech_encoder) {
116 CodecInst ci;
117 ci.channels = external_speech_encoder->NumChannels();
118 ci.plfreq = external_speech_encoder->SampleRateHz();
119 ci.pacsize = rtc::CheckedDivExact(
Peter Kastingdce40cf2015-08-24 14:52:23 -0700120 static_cast<int>(external_speech_encoder->Max10MsFramesInAPacket() *
kwiberga6db4952015-12-16 04:19:08 -0800121 ci.plfreq),
Peter Kastingdce40cf2015-08-24 14:52:23 -0700122 100);
kwiberga6db4952015-12-16 04:19:08 -0800123 ci.pltype = -1; // Not valid.
124 ci.rate = -1; // Not valid.
Karl Wiberg7e0c7d42015-05-18 14:52:29 +0200125 static const char kName[] = "external";
kwiberga6db4952015-12-16 04:19:08 -0800126 memcpy(ci.plname, kName, sizeof(kName));
127 return ci;
Henrik Lundin45c64492015-03-30 19:00:44 +0200128}
129
Henrik Lundin45c64492015-03-30 19:00:44 +0200130bool CodecManager::SetCopyRed(bool enable) {
kwiberg1379f1f2015-11-23 04:30:52 -0800131 if (enable && codec_stack_params_.use_codec_fec) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100132 RTC_LOG(LS_WARNING) << "Codec internal FEC and RED cannot be co-enabled.";
Henrik Lundin45c64492015-03-30 19:00:44 +0200133 return false;
134 }
kwiberga6db4952015-12-16 04:19:08 -0800135 if (enable && send_codec_inst_ &&
136 codec_stack_params_.red_payload_types.count(send_codec_inst_->plfreq) <
kwiberg1379f1f2015-11-23 04:30:52 -0800137 1) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100138 RTC_LOG(LS_WARNING) << "Cannot enable RED at " << send_codec_inst_->plfreq
139 << " Hz.";
Henrik Lundin45c64492015-03-30 19:00:44 +0200140 return false;
141 }
kwiberga6db4952015-12-16 04:19:08 -0800142 codec_stack_params_.use_red = enable;
Henrik Lundin45c64492015-03-30 19:00:44 +0200143 return true;
144}
145
kwiberga6db4952015-12-16 04:19:08 -0800146bool CodecManager::SetVAD(bool enable, ACMVADMode mode) {
Henrik Lundin45c64492015-03-30 19:00:44 +0200147 // Sanity check of the mode.
henrikg91d6ede2015-09-17 00:24:34 -0700148 RTC_DCHECK(mode == VADNormal || mode == VADLowBitrate || mode == VADAggr ||
149 mode == VADVeryAggr);
Henrik Lundin45c64492015-03-30 19:00:44 +0200150
151 // Check that the send codec is mono. We don't support VAD/DTX for stereo
152 // sending.
kwiberg95d98512015-12-15 14:21:33 -0800153 const bool stereo_send =
154 codec_stack_params_.speech_encoder
155 ? (codec_stack_params_.speech_encoder->NumChannels() != 1)
156 : false;
kwiberged8275a2015-11-10 09:47:36 -0800157 if (enable && stereo_send) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100158 RTC_LOG(LS_ERROR) << "VAD/DTX not supported for stereo sending";
kwiberga6db4952015-12-16 04:19:08 -0800159 return false;
Henrik Lundin45c64492015-03-30 19:00:44 +0200160 }
161
kwiberg44307632015-12-16 06:24:05 -0800162 // TODO(kwiberg): This doesn't protect Opus when injected as an external
163 // encoder.
164 if (send_codec_inst_ && IsOpus(*send_codec_inst_)) {
kwiberga6db4952015-12-16 04:19:08 -0800165 // VAD/DTX not supported, but don't fail.
166 enable = false;
Karl Wiberg2ea71c32015-05-07 15:49:23 +0200167 }
168
kwiberga6db4952015-12-16 04:19:08 -0800169 codec_stack_params_.use_cng = enable;
170 codec_stack_params_.vad_mode = mode;
171 return true;
Henrik Lundin45c64492015-03-30 19:00:44 +0200172}
173
kwiberga6db4952015-12-16 04:19:08 -0800174bool CodecManager::SetCodecFEC(bool enable_codec_fec) {
kwiberg1379f1f2015-11-23 04:30:52 -0800175 if (enable_codec_fec && codec_stack_params_.use_red) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100176 RTC_LOG(LS_WARNING) << "Codec internal FEC and RED cannot be co-enabled.";
kwiberga6db4952015-12-16 04:19:08 -0800177 return false;
Henrik Lundin45c64492015-03-30 19:00:44 +0200178 }
179
kwiberga6db4952015-12-16 04:19:08 -0800180 codec_stack_params_.use_codec_fec = enable_codec_fec;
181 return true;
Henrik Lundin45c64492015-03-30 19:00:44 +0200182}
183
kwiberg3f81fcd2016-06-23 03:58:36 -0700184bool CodecManager::MakeEncoder(RentACodec* rac, AudioCodingModule* acm) {
185 RTC_DCHECK(rac);
186 RTC_DCHECK(acm);
187
188 if (!recreate_encoder_) {
189 bool error = false;
190 // Try to re-use the speech encoder we've given to the ACM.
191 acm->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
192 if (!*encoder) {
193 // There is no existing encoder.
194 recreate_encoder_ = true;
195 return;
196 }
197
198 // Extract the speech encoder from the ACM.
199 std::unique_ptr<AudioEncoder> enc = std::move(*encoder);
200 while (true) {
201 auto sub_enc = enc->ReclaimContainedEncoders();
202 if (sub_enc.empty()) {
203 break;
204 }
kwibergaf476c72016-11-28 15:21:39 -0800205 RTC_CHECK_EQ(1, sub_enc.size());
kwiberg3f81fcd2016-06-23 03:58:36 -0700206
207 // Replace enc with its sub encoder. We need to put the sub encoder in
208 // a temporary first, since otherwise the old value of enc would be
209 // destroyed before the new value got assigned, which would be bad
210 // since the new value is a part of the old value.
211 auto tmp_enc = std::move(sub_enc[0]);
212 enc = std::move(tmp_enc);
213 }
214
215 // Wrap it in a new encoder stack and put it back.
216 codec_stack_params_.speech_encoder = std::move(enc);
217 *encoder = rac->RentEncoderStack(&codec_stack_params_);
218 if (!*encoder) {
219 error = true;
220 }
221 });
222 if (error) {
223 return false;
224 }
225 if (!recreate_encoder_) {
226 return true;
227 }
228 }
229
230 if (!send_codec_inst_) {
231 // We don't have the information we need to create a new speech encoder.
232 // (This is not an error.)
233 return true;
234 }
235
236 codec_stack_params_.speech_encoder = rac->RentEncoder(*send_codec_inst_);
237 auto stack = rac->RentEncoderStack(&codec_stack_params_);
238 if (!stack) {
239 return false;
240 }
241 acm->SetEncoder(std::move(stack));
242 recreate_encoder_ = false;
243 return true;
244}
245
Henrik Lundin45c64492015-03-30 19:00:44 +0200246} // namespace acm2
247} // namespace webrtc