blob: cdd2403e8c052cd86ae022ff80fc4c7b8b34a40f [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
mflodman@webrtc.orgc80d9d92012-02-06 10:11:25 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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
pbos@webrtc.org956aa7e2013-05-21 13:52:32 +000011#include "webrtc/voice_engine/voe_codec_impl.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
kjellander3e6db232015-11-26 04:44:54 -080013#include "webrtc/modules/audio_coding/include/audio_coding_module.h"
kjellanderc3771cc2017-06-30 13:42:44 -070014#include "webrtc/rtc_base/format_macros.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010015#include "webrtc/system_wrappers/include/trace.h"
pbos@webrtc.org956aa7e2013-05-21 13:52:32 +000016#include "webrtc/voice_engine/channel.h"
17#include "webrtc/voice_engine/include/voe_errors.h"
18#include "webrtc/voice_engine/voice_engine_impl.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000019
Jelena Marusic0d266052015-05-04 14:15:32 +020020namespace webrtc {
niklase@google.com470e71d2011-07-07 08:21:25 +000021
Jelena Marusic0d266052015-05-04 14:15:32 +020022VoECodec* VoECodec::GetInterface(VoiceEngine* voiceEngine) {
Jelena Marusic0d266052015-05-04 14:15:32 +020023 if (NULL == voiceEngine) {
24 return NULL;
25 }
26 VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
27 s->AddRef();
28 return s;
niklase@google.com470e71d2011-07-07 08:21:25 +000029}
30
Jelena Marusic0d266052015-05-04 14:15:32 +020031VoECodecImpl::VoECodecImpl(voe::SharedData* shared) : _shared(shared) {
32 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
33 "VoECodecImpl() - ctor");
niklase@google.com470e71d2011-07-07 08:21:25 +000034}
35
Jelena Marusic0d266052015-05-04 14:15:32 +020036VoECodecImpl::~VoECodecImpl() {
37 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
38 "~VoECodecImpl() - dtor");
niklase@google.com470e71d2011-07-07 08:21:25 +000039}
40
Jelena Marusic0d266052015-05-04 14:15:32 +020041int VoECodecImpl::NumOfCodecs() {
Jelena Marusic0d266052015-05-04 14:15:32 +020042 // Number of supported codecs in the ACM
43 uint8_t nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
Jelena Marusic0d266052015-05-04 14:15:32 +020044 return (nSupportedCodecs);
niklase@google.com470e71d2011-07-07 08:21:25 +000045}
46
Jelena Marusic0d266052015-05-04 14:15:32 +020047int VoECodecImpl::GetCodec(int index, CodecInst& codec) {
kwiberg12e21a02015-11-19 11:08:29 -080048 if (AudioCodingModule::Codec(index, &codec) == -1) {
Jelena Marusic0d266052015-05-04 14:15:32 +020049 _shared->SetLastError(VE_INVALID_LISTNR, kTraceError,
50 "GetCodec() invalid index");
51 return -1;
52 }
Jelena Marusic0d266052015-05-04 14:15:32 +020053 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +000054}
55
Jelena Marusic0d266052015-05-04 14:15:32 +020056int VoECodecImpl::SetSendCodec(int channel, const CodecInst& codec) {
Jelena Marusic0d266052015-05-04 14:15:32 +020057 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
58 "SetSendCodec(channel=%d, codec)", channel);
59 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
60 "codec: plname=%s, pacsize=%d, plfreq=%d, pltype=%d, "
Peter Kasting69558702016-01-12 16:26:35 -080061 "channels=%" PRIuS ", rate=%d",
Jelena Marusic0d266052015-05-04 14:15:32 +020062 codec.plname, codec.pacsize, codec.plfreq, codec.pltype,
63 codec.channels, codec.rate);
64 if (!_shared->statistics().Initialized()) {
65 _shared->SetLastError(VE_NOT_INITED, kTraceError);
66 return -1;
67 }
68 // External sanity checks performed outside the ACM
kwiberg12e21a02015-11-19 11:08:29 -080069 if ((STR_CASE_CMP(codec.plname, "L16") == 0) && (codec.pacsize >= 960)) {
Jelena Marusic0d266052015-05-04 14:15:32 +020070 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
71 "SetSendCodec() invalid L16 packet size");
72 return -1;
73 }
kwiberg12e21a02015-11-19 11:08:29 -080074 if (!STR_CASE_CMP(codec.plname, "CN") ||
75 !STR_CASE_CMP(codec.plname, "TELEPHONE-EVENT") ||
76 !STR_CASE_CMP(codec.plname, "RED")) {
Jelena Marusic0d266052015-05-04 14:15:32 +020077 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
78 "SetSendCodec() invalid codec name");
79 return -1;
80 }
kwiberg12e21a02015-11-19 11:08:29 -080081 if ((codec.channels != 1) && (codec.channels != 2)) {
Jelena Marusic0d266052015-05-04 14:15:32 +020082 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
83 "SetSendCodec() invalid number of channels");
84 return -1;
85 }
86 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
87 voe::Channel* channelPtr = ch.channel();
88 if (channelPtr == NULL) {
89 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
90 "GetSendCodec() failed to locate channel");
91 return -1;
92 }
kwiberg12e21a02015-11-19 11:08:29 -080093 if (!AudioCodingModule::IsCodecValid(codec)) {
Jelena Marusic0d266052015-05-04 14:15:32 +020094 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
95 "SetSendCodec() invalid codec");
96 return -1;
97 }
kwiberg12e21a02015-11-19 11:08:29 -080098 if (channelPtr->SetSendCodec(codec) != 0) {
Jelena Marusic0d266052015-05-04 14:15:32 +020099 _shared->SetLastError(VE_CANNOT_SET_SEND_CODEC, kTraceError,
100 "SetSendCodec() failed to set send codec");
101 return -1;
102 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000103
Jelena Marusic0d266052015-05-04 14:15:32 +0200104 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000105}
106
Jelena Marusic0d266052015-05-04 14:15:32 +0200107int VoECodecImpl::GetSendCodec(int channel, CodecInst& codec) {
Jelena Marusic0d266052015-05-04 14:15:32 +0200108 if (!_shared->statistics().Initialized()) {
109 _shared->SetLastError(VE_NOT_INITED, kTraceError);
110 return -1;
111 }
112 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
113 voe::Channel* channelPtr = ch.channel();
114 if (channelPtr == NULL) {
115 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
116 "GetSendCodec() failed to locate channel");
117 return -1;
118 }
kwiberg12e21a02015-11-19 11:08:29 -0800119 if (channelPtr->GetSendCodec(codec) != 0) {
Jelena Marusic0d266052015-05-04 14:15:32 +0200120 _shared->SetLastError(VE_CANNOT_GET_SEND_CODEC, kTraceError,
121 "GetSendCodec() failed to get send codec");
122 return -1;
123 }
Jelena Marusic0d266052015-05-04 14:15:32 +0200124 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000125}
126
Ivo Creusenadf89b72015-04-29 16:03:33 +0200127int VoECodecImpl::SetBitRate(int channel, int bitrate_bps) {
128 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
129 "SetBitRate(bitrate_bps=%d)", bitrate_bps);
130 if (!_shared->statistics().Initialized()) {
131 _shared->SetLastError(VE_NOT_INITED, kTraceError);
132 return -1;
133 }
minyue78b4d562016-11-30 04:47:39 -0800134 constexpr int64_t kDefaultProbingIntervalMs = 3000;
Ivo Creusenadf89b72015-04-29 16:03:33 +0200135 _shared->channel_manager().GetChannel(channel).channel()->SetBitRate(
minyue78b4d562016-11-30 04:47:39 -0800136 bitrate_bps, kDefaultProbingIntervalMs);
Ivo Creusenadf89b72015-04-29 16:03:33 +0200137 return 0;
138}
139
Jelena Marusic0d266052015-05-04 14:15:32 +0200140int VoECodecImpl::GetRecCodec(int channel, CodecInst& codec) {
Jelena Marusic0d266052015-05-04 14:15:32 +0200141 if (!_shared->statistics().Initialized()) {
142 _shared->SetLastError(VE_NOT_INITED, kTraceError);
143 return -1;
144 }
145 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
146 voe::Channel* channelPtr = ch.channel();
147 if (channelPtr == NULL) {
148 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
149 "GetRecCodec() failed to locate channel");
150 return -1;
151 }
kwiberg12e21a02015-11-19 11:08:29 -0800152 return channelPtr->GetRecCodec(codec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000153}
154
Jelena Marusic0d266052015-05-04 14:15:32 +0200155int VoECodecImpl::SetRecPayloadType(int channel, const CodecInst& codec) {
156 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
157 "SetRecPayloadType(channel=%d, codec)", channel);
158 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
Peter Kasting69558702016-01-12 16:26:35 -0800159 "codec: plname=%s, plfreq=%d, pltype=%d, channels=%" PRIuS ", "
Jelena Marusic0d266052015-05-04 14:15:32 +0200160 "pacsize=%d, rate=%d",
161 codec.plname, codec.plfreq, codec.pltype, codec.channels,
162 codec.pacsize, codec.rate);
163 if (!_shared->statistics().Initialized()) {
164 _shared->SetLastError(VE_NOT_INITED, kTraceError);
165 return -1;
166 }
167 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
168 voe::Channel* channelPtr = ch.channel();
169 if (channelPtr == NULL) {
170 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
171 "GetRecPayloadType() failed to locate channel");
172 return -1;
173 }
174 return channelPtr->SetRecPayloadType(codec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000175}
176
Jelena Marusic0d266052015-05-04 14:15:32 +0200177int VoECodecImpl::GetRecPayloadType(int channel, CodecInst& codec) {
Jelena Marusic0d266052015-05-04 14:15:32 +0200178 if (!_shared->statistics().Initialized()) {
179 _shared->SetLastError(VE_NOT_INITED, kTraceError);
180 return -1;
181 }
182 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
183 voe::Channel* channelPtr = ch.channel();
184 if (channelPtr == NULL) {
185 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
186 "GetRecPayloadType() failed to locate channel");
187 return -1;
188 }
189 return channelPtr->GetRecPayloadType(codec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000190}
191
Jelena Marusic0d266052015-05-04 14:15:32 +0200192int VoECodecImpl::SetSendCNPayloadType(int channel,
193 int type,
194 PayloadFrequencies frequency) {
195 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
196 "SetSendCNPayloadType(channel=%d, type=%d, frequency=%d)",
197 channel, type, frequency);
198 if (!_shared->statistics().Initialized()) {
199 _shared->SetLastError(VE_NOT_INITED, kTraceError);
200 return -1;
201 }
202 if (type < 96 || type > 127) {
203 // Only allow dynamic range: 96 to 127
204 _shared->SetLastError(VE_INVALID_PLTYPE, kTraceError,
205 "SetSendCNPayloadType() invalid payload type");
206 return -1;
207 }
208 if ((frequency != kFreq16000Hz) && (frequency != kFreq32000Hz)) {
209 // It is not possible to modify the payload type for CN/8000.
210 // We only allow modification of the CN payload type for CN/16000
211 // and CN/32000.
212 _shared->SetLastError(VE_INVALID_PLFREQ, kTraceError,
213 "SetSendCNPayloadType() invalid payload frequency");
214 return -1;
215 }
216 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
217 voe::Channel* channelPtr = ch.channel();
218 if (channelPtr == NULL) {
219 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
220 "SetSendCNPayloadType() failed to locate channel");
221 return -1;
222 }
223 return channelPtr->SetSendCNPayloadType(type, frequency);
niklase@google.com470e71d2011-07-07 08:21:25 +0000224}
225
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +0000226int VoECodecImpl::SetFECStatus(int channel, bool enable) {
227 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
228 "SetCodecFECStatus(channel=%d, enable=%d)", channel, enable);
229 if (!_shared->statistics().Initialized()) {
230 _shared->SetLastError(VE_NOT_INITED, kTraceError);
231 return -1;
232 }
233 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
234 voe::Channel* channelPtr = ch.channel();
235 if (channelPtr == NULL) {
236 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
237 "SetCodecFECStatus() failed to locate channel");
238 return -1;
239 }
240 return channelPtr->SetCodecFECStatus(enable);
241}
242
243int VoECodecImpl::GetFECStatus(int channel, bool& enabled) {
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +0000244 if (!_shared->statistics().Initialized()) {
245 _shared->SetLastError(VE_NOT_INITED, kTraceError);
246 return -1;
247 }
248 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
249 voe::Channel* channelPtr = ch.channel();
250 if (channelPtr == NULL) {
251 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
252 "GetFECStatus() failed to locate channel");
253 return -1;
254 }
255 enabled = channelPtr->GetCodecFECStatus();
256 return 0;
257}
258
Jelena Marusic0d266052015-05-04 14:15:32 +0200259int VoECodecImpl::SetVADStatus(int channel,
260 bool enable,
261 VadModes mode,
262 bool disableDTX) {
263 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
264 "SetVADStatus(channel=%i, enable=%i, mode=%i, disableDTX=%i)",
265 channel, enable, mode, disableDTX);
niklase@google.com470e71d2011-07-07 08:21:25 +0000266
Jelena Marusic0d266052015-05-04 14:15:32 +0200267 if (!_shared->statistics().Initialized()) {
268 _shared->SetLastError(VE_NOT_INITED, kTraceError);
269 return -1;
270 }
271 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
272 voe::Channel* channelPtr = ch.channel();
273 if (channelPtr == NULL) {
274 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
275 "SetVADStatus failed to locate channel");
276 return -1;
277 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000278
Jelena Marusic0d266052015-05-04 14:15:32 +0200279 ACMVADMode vadMode(VADNormal);
280 switch (mode) {
281 case kVadConventional:
282 vadMode = VADNormal;
283 break;
284 case kVadAggressiveLow:
285 vadMode = VADLowBitrate;
286 break;
287 case kVadAggressiveMid:
288 vadMode = VADAggr;
289 break;
290 case kVadAggressiveHigh:
291 vadMode = VADVeryAggr;
292 break;
293 }
294 return channelPtr->SetVADStatus(enable, vadMode, disableDTX);
niklase@google.com470e71d2011-07-07 08:21:25 +0000295}
296
Jelena Marusic0d266052015-05-04 14:15:32 +0200297int VoECodecImpl::GetVADStatus(int channel,
298 bool& enabled,
299 VadModes& mode,
300 bool& disabledDTX) {
Jelena Marusic0d266052015-05-04 14:15:32 +0200301 if (!_shared->statistics().Initialized()) {
302 _shared->SetLastError(VE_NOT_INITED, kTraceError);
303 return -1;
304 }
305 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
306 voe::Channel* channelPtr = ch.channel();
307 if (channelPtr == NULL) {
308 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
309 "GetVADStatus failed to locate channel");
310 return -1;
311 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000312
Jelena Marusic0d266052015-05-04 14:15:32 +0200313 ACMVADMode vadMode;
314 int ret = channelPtr->GetVADStatus(enabled, vadMode, disabledDTX);
niklase@google.com470e71d2011-07-07 08:21:25 +0000315
Jelena Marusic0d266052015-05-04 14:15:32 +0200316 if (ret != 0) {
317 _shared->SetLastError(VE_INVALID_OPERATION, kTraceError,
318 "GetVADStatus failed to get VAD mode");
319 return -1;
320 }
321 switch (vadMode) {
322 case VADNormal:
323 mode = kVadConventional;
324 break;
325 case VADLowBitrate:
326 mode = kVadAggressiveLow;
327 break;
328 case VADAggr:
329 mode = kVadAggressiveMid;
330 break;
331 case VADVeryAggr:
332 mode = kVadAggressiveHigh;
333 break;
334 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000335
Jelena Marusic0d266052015-05-04 14:15:32 +0200336 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000337}
338
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000339int VoECodecImpl::SetOpusMaxPlaybackRate(int channel, int frequency_hz) {
minyue@webrtc.org6aac93b2014-08-12 08:13:33 +0000340 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000341 "SetOpusMaxPlaybackRate(channel=%d, frequency_hz=%d)", channel,
342 frequency_hz);
minyue@webrtc.org6aac93b2014-08-12 08:13:33 +0000343 if (!_shared->statistics().Initialized()) {
344 _shared->SetLastError(VE_NOT_INITED, kTraceError);
345 return -1;
346 }
347 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
348 voe::Channel* channelPtr = ch.channel();
349 if (channelPtr == NULL) {
350 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000351 "SetOpusMaxPlaybackRate failed to locate channel");
minyue@webrtc.org6aac93b2014-08-12 08:13:33 +0000352 return -1;
353 }
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000354 return channelPtr->SetOpusMaxPlaybackRate(frequency_hz);
minyue@webrtc.org6aac93b2014-08-12 08:13:33 +0000355}
356
minyue@webrtc.org9b2e1142015-03-13 09:38:07 +0000357int VoECodecImpl::SetOpusDtx(int channel, bool enable_dtx) {
358 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
359 "SetOpusDtx(channel=%d, enable_dtx=%d)", channel, enable_dtx);
360 if (!_shared->statistics().Initialized()) {
361 _shared->SetLastError(VE_NOT_INITED, kTraceError);
362 return -1;
363 }
364 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
365 voe::Channel* channelPtr = ch.channel();
366 if (channelPtr == NULL) {
367 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
368 "SetOpusDtx failed to locate channel");
369 return -1;
370 }
371 return channelPtr->SetOpusDtx(enable_dtx);
372}
373
ivoc85228d62016-07-27 04:53:47 -0700374int VoECodecImpl::GetOpusDtxStatus(int channel, bool* enabled) {
375 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
376 "GetOpusDtx(channel=%d)", channel);
377 if (!_shared->statistics().Initialized()) {
378 _shared->SetLastError(VE_NOT_INITED, kTraceError);
379 return -1;
380 }
381 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
382 voe::Channel* channelPtr = ch.channel();
383 if (channelPtr == NULL) {
384 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
385 "GetOpusDtx failed to locate channel");
386 return -1;
387 }
388 return channelPtr->GetOpusDtx(enabled);
389}
390
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000391} // namespace webrtc