blob: 63f0244752ca94a13cf904374b397ed8b58997fc [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"
17#include "typedefs.h"
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)) {
Alex Loiko300ec8c2017-05-30 17:23:28 +020027 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) {
Alex Loiko300ec8c2017-05-30 17:23:28 +020034 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")) {
Alex Loiko300ec8c2017-05-30 17:23:28 +020040 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)) {
Alex Loiko300ec8c2017-05-30 17:23:28 +020046 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:
Alex Loiko300ec8c2017-05-30 17:23:28 +020084 LOG(LS_ERROR) << "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:
Alex Loiko300ec8c2017-05-30 17:23:28 +020095 LOG(LS_ERROR) << "RegisterSendCodec() failed, invalid frequency for CNG"
96 " registration";
kwiberga6db4952015-12-16 04:19:08 -080097 return false;
kwiberge1a27d42015-11-18 07:32:49 -080098 case RentACodec::RegistrationResult::kSkip:
99 break;
Henrik Lundin45c64492015-03-30 19:00:44 +0200100 }
101
kwiberga6db4952015-12-16 04:19:08 -0800102 if (IsOpus(send_codec)) {
kwibergdfbb3a42015-12-01 04:45:04 -0800103 // VAD/DTX not supported.
104 codec_stack_params_.use_cng = false;
Henrik Lundin45c64492015-03-30 19:00:44 +0200105 }
Karl Wiberg2ea71c32015-05-07 15:49:23 +0200106
kwiberga6db4952015-12-16 04:19:08 -0800107 send_codec_inst_ = rtc::Optional<CodecInst>(send_codec);
kwiberg3f81fcd2016-06-23 03:58:36 -0700108 recreate_encoder_ = true; // Caller must recreate it.
kwiberga6db4952015-12-16 04:19:08 -0800109 return true;
Henrik Lundin45c64492015-03-30 19:00:44 +0200110}
111
kwiberga6db4952015-12-16 04:19:08 -0800112CodecInst CodecManager::ForgeCodecInst(
113 const AudioEncoder* external_speech_encoder) {
114 CodecInst ci;
115 ci.channels = external_speech_encoder->NumChannels();
116 ci.plfreq = external_speech_encoder->SampleRateHz();
117 ci.pacsize = rtc::CheckedDivExact(
Peter Kastingdce40cf2015-08-24 14:52:23 -0700118 static_cast<int>(external_speech_encoder->Max10MsFramesInAPacket() *
kwiberga6db4952015-12-16 04:19:08 -0800119 ci.plfreq),
Peter Kastingdce40cf2015-08-24 14:52:23 -0700120 100);
kwiberga6db4952015-12-16 04:19:08 -0800121 ci.pltype = -1; // Not valid.
122 ci.rate = -1; // Not valid.
Karl Wiberg7e0c7d42015-05-18 14:52:29 +0200123 static const char kName[] = "external";
kwiberga6db4952015-12-16 04:19:08 -0800124 memcpy(ci.plname, kName, sizeof(kName));
125 return ci;
Henrik Lundin45c64492015-03-30 19:00:44 +0200126}
127
Henrik Lundin45c64492015-03-30 19:00:44 +0200128bool CodecManager::SetCopyRed(bool enable) {
kwiberg1379f1f2015-11-23 04:30:52 -0800129 if (enable && codec_stack_params_.use_codec_fec) {
Alex Loiko300ec8c2017-05-30 17:23:28 +0200130 LOG(LS_WARNING) << "Codec internal FEC and RED cannot be co-enabled.";
Henrik Lundin45c64492015-03-30 19:00:44 +0200131 return false;
132 }
kwiberga6db4952015-12-16 04:19:08 -0800133 if (enable && send_codec_inst_ &&
134 codec_stack_params_.red_payload_types.count(send_codec_inst_->plfreq) <
kwiberg1379f1f2015-11-23 04:30:52 -0800135 1) {
Alex Loiko300ec8c2017-05-30 17:23:28 +0200136 LOG(LS_WARNING) << "Cannot enable RED at " << send_codec_inst_->plfreq
137 << " Hz.";
Henrik Lundin45c64492015-03-30 19:00:44 +0200138 return false;
139 }
kwiberga6db4952015-12-16 04:19:08 -0800140 codec_stack_params_.use_red = enable;
Henrik Lundin45c64492015-03-30 19:00:44 +0200141 return true;
142}
143
kwiberga6db4952015-12-16 04:19:08 -0800144bool CodecManager::SetVAD(bool enable, ACMVADMode mode) {
Henrik Lundin45c64492015-03-30 19:00:44 +0200145 // Sanity check of the mode.
henrikg91d6ede2015-09-17 00:24:34 -0700146 RTC_DCHECK(mode == VADNormal || mode == VADLowBitrate || mode == VADAggr ||
147 mode == VADVeryAggr);
Henrik Lundin45c64492015-03-30 19:00:44 +0200148
149 // Check that the send codec is mono. We don't support VAD/DTX for stereo
150 // sending.
kwiberg95d98512015-12-15 14:21:33 -0800151 const bool stereo_send =
152 codec_stack_params_.speech_encoder
153 ? (codec_stack_params_.speech_encoder->NumChannels() != 1)
154 : false;
kwiberged8275a2015-11-10 09:47:36 -0800155 if (enable && stereo_send) {
Alex Loiko300ec8c2017-05-30 17:23:28 +0200156 LOG(LS_ERROR) << "VAD/DTX not supported for stereo sending";
kwiberga6db4952015-12-16 04:19:08 -0800157 return false;
Henrik Lundin45c64492015-03-30 19:00:44 +0200158 }
159
kwiberg44307632015-12-16 06:24:05 -0800160 // TODO(kwiberg): This doesn't protect Opus when injected as an external
161 // encoder.
162 if (send_codec_inst_ && IsOpus(*send_codec_inst_)) {
kwiberga6db4952015-12-16 04:19:08 -0800163 // VAD/DTX not supported, but don't fail.
164 enable = false;
Karl Wiberg2ea71c32015-05-07 15:49:23 +0200165 }
166
kwiberga6db4952015-12-16 04:19:08 -0800167 codec_stack_params_.use_cng = enable;
168 codec_stack_params_.vad_mode = mode;
169 return true;
Henrik Lundin45c64492015-03-30 19:00:44 +0200170}
171
kwiberga6db4952015-12-16 04:19:08 -0800172bool CodecManager::SetCodecFEC(bool enable_codec_fec) {
kwiberg1379f1f2015-11-23 04:30:52 -0800173 if (enable_codec_fec && codec_stack_params_.use_red) {
Alex Loiko300ec8c2017-05-30 17:23:28 +0200174 LOG(LS_WARNING) << "Codec internal FEC and RED cannot be co-enabled.";
kwiberga6db4952015-12-16 04:19:08 -0800175 return false;
Henrik Lundin45c64492015-03-30 19:00:44 +0200176 }
177
kwiberga6db4952015-12-16 04:19:08 -0800178 codec_stack_params_.use_codec_fec = enable_codec_fec;
179 return true;
Henrik Lundin45c64492015-03-30 19:00:44 +0200180}
181
kwiberg3f81fcd2016-06-23 03:58:36 -0700182bool CodecManager::MakeEncoder(RentACodec* rac, AudioCodingModule* acm) {
183 RTC_DCHECK(rac);
184 RTC_DCHECK(acm);
185
186 if (!recreate_encoder_) {
187 bool error = false;
188 // Try to re-use the speech encoder we've given to the ACM.
189 acm->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
190 if (!*encoder) {
191 // There is no existing encoder.
192 recreate_encoder_ = true;
193 return;
194 }
195
196 // Extract the speech encoder from the ACM.
197 std::unique_ptr<AudioEncoder> enc = std::move(*encoder);
198 while (true) {
199 auto sub_enc = enc->ReclaimContainedEncoders();
200 if (sub_enc.empty()) {
201 break;
202 }
kwibergaf476c72016-11-28 15:21:39 -0800203 RTC_CHECK_EQ(1, sub_enc.size());
kwiberg3f81fcd2016-06-23 03:58:36 -0700204
205 // Replace enc with its sub encoder. We need to put the sub encoder in
206 // a temporary first, since otherwise the old value of enc would be
207 // destroyed before the new value got assigned, which would be bad
208 // since the new value is a part of the old value.
209 auto tmp_enc = std::move(sub_enc[0]);
210 enc = std::move(tmp_enc);
211 }
212
213 // Wrap it in a new encoder stack and put it back.
214 codec_stack_params_.speech_encoder = std::move(enc);
215 *encoder = rac->RentEncoderStack(&codec_stack_params_);
216 if (!*encoder) {
217 error = true;
218 }
219 });
220 if (error) {
221 return false;
222 }
223 if (!recreate_encoder_) {
224 return true;
225 }
226 }
227
228 if (!send_codec_inst_) {
229 // We don't have the information we need to create a new speech encoder.
230 // (This is not an error.)
231 return true;
232 }
233
234 codec_stack_params_.speech_encoder = rac->RentEncoder(*send_codec_inst_);
235 auto stack = rac->RentEncoderStack(&codec_stack_params_);
236 if (!stack) {
237 return false;
238 }
239 acm->SetEncoder(std::move(stack));
240 recreate_encoder_ = false;
241 return true;
242}
243
Henrik Lundin45c64492015-03-30 19:00:44 +0200244} // namespace acm2
245} // namespace webrtc