blob: bc507dd8c7debf614b0263eedaa09c256e081bde [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
kjellander3e6db232015-11-26 04:44:54 -080011#include "webrtc/modules/audio_coding/acm2/codec_manager.h"
Henrik Lundin45c64492015-03-30 19:00:44 +020012
13#include "webrtc/base/checks.h"
Karl Wibergbd1bc472015-05-18 12:18:54 +020014#include "webrtc/engine_configurations.h"
kjellander3e6db232015-11-26 04:44:54 -080015#include "webrtc/modules/audio_coding/acm2/rent_a_codec.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010016#include "webrtc/system_wrappers/include/trace.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 int dummy_id = 0;
26 if ((send_codec.channels != 1) && (send_codec.channels != 2)) {
27 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
28 "Wrong number of channels (%d, only mono and stereo are "
kwiberg223692a2015-11-18 08:27:51 -080029 "supported)",
30 send_codec.channels);
Henrik Lundin45c64492015-03-30 19:00:44 +020031 return -1;
32 }
33
kwibergd6c0f8c2015-11-06 14:28:00 -080034 auto maybe_codec_id = RentACodec::CodecIdByInst(send_codec);
35 if (!maybe_codec_id) {
Henrik Lundin45c64492015-03-30 19:00:44 +020036 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
37 "Invalid codec setting for the send codec.");
38 return -1;
39 }
40
Henrik Lundin45c64492015-03-30 19:00:44 +020041 // Telephone-event cannot be a send codec.
42 if (!STR_CASE_CMP(send_codec.plname, "telephone-event")) {
43 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
44 "telephone-event cannot be a send codec");
Henrik Lundin45c64492015-03-30 19:00:44 +020045 return -1;
46 }
47
kwibergd6c0f8c2015-11-06 14:28:00 -080048 if (!RentACodec::IsSupportedNumChannels(*maybe_codec_id, send_codec.channels)
49 .value_or(false)) {
Henrik Lundin45c64492015-03-30 19:00:44 +020050 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
51 "%d number of channels not supportedn for %s.",
52 send_codec.channels, send_codec.plname);
Henrik Lundin45c64492015-03-30 19:00:44 +020053 return -1;
54 }
kwibergd6c0f8c2015-11-06 14:28:00 -080055 return RentACodec::CodecIndexFromId(*maybe_codec_id).value_or(-1);
Henrik Lundin45c64492015-03-30 19:00:44 +020056}
57
Karl Wiberg2ea71c32015-05-07 15:49:23 +020058bool IsOpus(const CodecInst& codec) {
59 return
60#ifdef WEBRTC_CODEC_OPUS
61 !STR_CASE_CMP(codec.plname, "opus") ||
62#endif
63 false;
64}
65
Henrik Lundin45c64492015-03-30 19:00:44 +020066} // namespace
67
kwiberga6db4952015-12-16 04:19:08 -080068CodecManager::CodecManager() {
Henrik Lundin45c64492015-03-30 19:00:44 +020069 thread_checker_.DetachFromThread();
70}
71
Henrik Lundin93ef1d82015-04-13 09:31:16 +020072CodecManager::~CodecManager() = default;
Henrik Lundin45c64492015-03-30 19:00:44 +020073
kwiberga6db4952015-12-16 04:19:08 -080074bool CodecManager::RegisterEncoder(const CodecInst& send_codec) {
henrikg91d6ede2015-09-17 00:24:34 -070075 RTC_DCHECK(thread_checker_.CalledOnValidThread());
kwiberg223692a2015-11-18 08:27:51 -080076 int codec_id = IsValidSendCodec(send_codec);
Henrik Lundin45c64492015-03-30 19:00:44 +020077
78 // Check for reported errors from function IsValidSendCodec().
79 if (codec_id < 0) {
kwiberga6db4952015-12-16 04:19:08 -080080 return false;
Henrik Lundin45c64492015-03-30 19:00:44 +020081 }
82
83 int dummy_id = 0;
kwiberg1379f1f2015-11-23 04:30:52 -080084 switch (RentACodec::RegisterRedPayloadType(
85 &codec_stack_params_.red_payload_types, send_codec)) {
kwiberge1a27d42015-11-18 07:32:49 -080086 case RentACodec::RegistrationResult::kOk:
kwiberga6db4952015-12-16 04:19:08 -080087 return true;
kwiberge1a27d42015-11-18 07:32:49 -080088 case RentACodec::RegistrationResult::kBadFreq:
Henrik Lundin45c64492015-03-30 19:00:44 +020089 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
kwiberge1a27d42015-11-18 07:32:49 -080090 "RegisterSendCodec() failed, invalid frequency for RED"
91 " registration");
kwiberga6db4952015-12-16 04:19:08 -080092 return false;
kwiberge1a27d42015-11-18 07:32:49 -080093 case RentACodec::RegistrationResult::kSkip:
94 break;
Henrik Lundin45c64492015-03-30 19:00:44 +020095 }
kwiberg1379f1f2015-11-23 04:30:52 -080096 switch (RentACodec::RegisterCngPayloadType(
97 &codec_stack_params_.cng_payload_types, send_codec)) {
kwiberge1a27d42015-11-18 07:32:49 -080098 case RentACodec::RegistrationResult::kOk:
kwiberga6db4952015-12-16 04:19:08 -080099 return true;
kwiberge1a27d42015-11-18 07:32:49 -0800100 case RentACodec::RegistrationResult::kBadFreq:
101 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
102 "RegisterSendCodec() failed, invalid frequency for CNG"
103 " registration");
kwiberga6db4952015-12-16 04:19:08 -0800104 return false;
kwiberge1a27d42015-11-18 07:32:49 -0800105 case RentACodec::RegistrationResult::kSkip:
106 break;
Henrik Lundin45c64492015-03-30 19:00:44 +0200107 }
108
kwiberga6db4952015-12-16 04:19:08 -0800109 if (IsOpus(send_codec)) {
kwibergdfbb3a42015-12-01 04:45:04 -0800110 // VAD/DTX not supported.
111 codec_stack_params_.use_cng = false;
Henrik Lundin45c64492015-03-30 19:00:44 +0200112 }
Karl Wiberg2ea71c32015-05-07 15:49:23 +0200113
kwiberga6db4952015-12-16 04:19:08 -0800114 send_codec_inst_ = rtc::Optional<CodecInst>(send_codec);
115 codec_stack_params_.speech_encoder = nullptr; // Caller must recreate it.
116 return true;
Henrik Lundin45c64492015-03-30 19:00:44 +0200117}
118
kwiberga6db4952015-12-16 04:19:08 -0800119CodecInst CodecManager::ForgeCodecInst(
120 const AudioEncoder* external_speech_encoder) {
121 CodecInst ci;
122 ci.channels = external_speech_encoder->NumChannels();
123 ci.plfreq = external_speech_encoder->SampleRateHz();
124 ci.pacsize = rtc::CheckedDivExact(
Peter Kastingdce40cf2015-08-24 14:52:23 -0700125 static_cast<int>(external_speech_encoder->Max10MsFramesInAPacket() *
kwiberga6db4952015-12-16 04:19:08 -0800126 ci.plfreq),
Peter Kastingdce40cf2015-08-24 14:52:23 -0700127 100);
kwiberga6db4952015-12-16 04:19:08 -0800128 ci.pltype = -1; // Not valid.
129 ci.rate = -1; // Not valid.
Karl Wiberg7e0c7d42015-05-18 14:52:29 +0200130 static const char kName[] = "external";
kwiberga6db4952015-12-16 04:19:08 -0800131 memcpy(ci.plname, kName, sizeof(kName));
132 return ci;
Henrik Lundin45c64492015-03-30 19:00:44 +0200133}
134
Henrik Lundin45c64492015-03-30 19:00:44 +0200135bool CodecManager::SetCopyRed(bool enable) {
kwiberg1379f1f2015-11-23 04:30:52 -0800136 if (enable && codec_stack_params_.use_codec_fec) {
Henrik Lundin45c64492015-03-30 19:00:44 +0200137 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, 0,
138 "Codec internal FEC and RED cannot be co-enabled.");
139 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) {
Karl Wiberg2ea71c32015-05-07 15:49:23 +0200144 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, 0,
kwiberga6db4952015-12-16 04:19:08 -0800145 "Cannot enable RED at %i Hz.", send_codec_inst_->plfreq);
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) {
Henrik Lundin45c64492015-03-30 19:00:44 +0200164 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, 0,
165 "VAD/DTX not supported for stereo sending");
kwiberga6db4952015-12-16 04:19:08 -0800166 return false;
Henrik Lundin45c64492015-03-30 19:00:44 +0200167 }
168
kwiberga6db4952015-12-16 04:19:08 -0800169 if (CurrentEncoderIsOpus()) {
170 // VAD/DTX not supported, but don't fail.
171 enable = false;
Karl Wiberg2ea71c32015-05-07 15:49:23 +0200172 }
173
kwiberga6db4952015-12-16 04:19:08 -0800174 codec_stack_params_.use_cng = enable;
175 codec_stack_params_.vad_mode = mode;
176 return true;
Henrik Lundin45c64492015-03-30 19:00:44 +0200177}
178
kwiberga6db4952015-12-16 04:19:08 -0800179bool CodecManager::SetCodecFEC(bool enable_codec_fec) {
kwiberg1379f1f2015-11-23 04:30:52 -0800180 if (enable_codec_fec && codec_stack_params_.use_red) {
Henrik Lundin45c64492015-03-30 19:00:44 +0200181 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, 0,
182 "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
kwiberga6db4952015-12-16 04:19:08 -0800190bool CodecManager::CurrentEncoderIsOpus() const {
191 return send_codec_inst_ ? IsOpus(*send_codec_inst_) : false;
Henrik Lundin45c64492015-03-30 19:00:44 +0200192}
193
Henrik Lundin45c64492015-03-30 19:00:44 +0200194} // namespace acm2
195} // namespace webrtc