blob: b2fd08d599b60cb17cf793cea53aca5cdb0c90b5 [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
Peter Kasting69558702016-01-12 16:26:35 -080013#include "webrtc/base/format_macros.h"
kjellander3e6db232015-11-26 04:44:54 -080014#include "webrtc/modules/audio_coding/include/audio_coding_module.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) {
niklase@google.com470e71d2011-07-07 08:21:25 +000023#ifndef WEBRTC_VOICE_ENGINE_CODEC_API
Jelena Marusic0d266052015-05-04 14:15:32 +020024 return NULL;
niklase@google.com470e71d2011-07-07 08:21:25 +000025#else
Jelena Marusic0d266052015-05-04 14:15:32 +020026 if (NULL == voiceEngine) {
27 return NULL;
28 }
29 VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
30 s->AddRef();
31 return s;
niklase@google.com470e71d2011-07-07 08:21:25 +000032#endif
33}
34
35#ifdef WEBRTC_VOICE_ENGINE_CODEC_API
36
Jelena Marusic0d266052015-05-04 14:15:32 +020037VoECodecImpl::VoECodecImpl(voe::SharedData* shared) : _shared(shared) {
38 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
39 "VoECodecImpl() - ctor");
niklase@google.com470e71d2011-07-07 08:21:25 +000040}
41
Jelena Marusic0d266052015-05-04 14:15:32 +020042VoECodecImpl::~VoECodecImpl() {
43 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
44 "~VoECodecImpl() - dtor");
niklase@google.com470e71d2011-07-07 08:21:25 +000045}
46
Jelena Marusic0d266052015-05-04 14:15:32 +020047int VoECodecImpl::NumOfCodecs() {
Jelena Marusic0d266052015-05-04 14:15:32 +020048 // Number of supported codecs in the ACM
49 uint8_t nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
Jelena Marusic0d266052015-05-04 14:15:32 +020050 return (nSupportedCodecs);
niklase@google.com470e71d2011-07-07 08:21:25 +000051}
52
Jelena Marusic0d266052015-05-04 14:15:32 +020053int VoECodecImpl::GetCodec(int index, CodecInst& codec) {
kwiberg12e21a02015-11-19 11:08:29 -080054 if (AudioCodingModule::Codec(index, &codec) == -1) {
Jelena Marusic0d266052015-05-04 14:15:32 +020055 _shared->SetLastError(VE_INVALID_LISTNR, kTraceError,
56 "GetCodec() invalid index");
57 return -1;
58 }
Jelena Marusic0d266052015-05-04 14:15:32 +020059 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +000060}
61
Jelena Marusic0d266052015-05-04 14:15:32 +020062int VoECodecImpl::SetSendCodec(int channel, const CodecInst& codec) {
Jelena Marusic0d266052015-05-04 14:15:32 +020063 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
64 "SetSendCodec(channel=%d, codec)", channel);
65 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
66 "codec: plname=%s, pacsize=%d, plfreq=%d, pltype=%d, "
Peter Kasting69558702016-01-12 16:26:35 -080067 "channels=%" PRIuS ", rate=%d",
Jelena Marusic0d266052015-05-04 14:15:32 +020068 codec.plname, codec.pacsize, codec.plfreq, codec.pltype,
69 codec.channels, codec.rate);
70 if (!_shared->statistics().Initialized()) {
71 _shared->SetLastError(VE_NOT_INITED, kTraceError);
72 return -1;
73 }
74 // External sanity checks performed outside the ACM
kwiberg12e21a02015-11-19 11:08:29 -080075 if ((STR_CASE_CMP(codec.plname, "L16") == 0) && (codec.pacsize >= 960)) {
Jelena Marusic0d266052015-05-04 14:15:32 +020076 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
77 "SetSendCodec() invalid L16 packet size");
78 return -1;
79 }
kwiberg12e21a02015-11-19 11:08:29 -080080 if (!STR_CASE_CMP(codec.plname, "CN") ||
81 !STR_CASE_CMP(codec.plname, "TELEPHONE-EVENT") ||
82 !STR_CASE_CMP(codec.plname, "RED")) {
Jelena Marusic0d266052015-05-04 14:15:32 +020083 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
84 "SetSendCodec() invalid codec name");
85 return -1;
86 }
kwiberg12e21a02015-11-19 11:08:29 -080087 if ((codec.channels != 1) && (codec.channels != 2)) {
Jelena Marusic0d266052015-05-04 14:15:32 +020088 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
89 "SetSendCodec() invalid number of channels");
90 return -1;
91 }
92 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
93 voe::Channel* channelPtr = ch.channel();
94 if (channelPtr == NULL) {
95 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
96 "GetSendCodec() failed to locate channel");
97 return -1;
98 }
kwiberg12e21a02015-11-19 11:08:29 -080099 if (!AudioCodingModule::IsCodecValid(codec)) {
Jelena Marusic0d266052015-05-04 14:15:32 +0200100 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
101 "SetSendCodec() invalid codec");
102 return -1;
103 }
kwiberg12e21a02015-11-19 11:08:29 -0800104 if (channelPtr->SetSendCodec(codec) != 0) {
Jelena Marusic0d266052015-05-04 14:15:32 +0200105 _shared->SetLastError(VE_CANNOT_SET_SEND_CODEC, kTraceError,
106 "SetSendCodec() failed to set send codec");
107 return -1;
108 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000109
Jelena Marusic0d266052015-05-04 14:15:32 +0200110 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000111}
112
Jelena Marusic0d266052015-05-04 14:15:32 +0200113int VoECodecImpl::GetSendCodec(int channel, CodecInst& codec) {
Jelena Marusic0d266052015-05-04 14:15:32 +0200114 if (!_shared->statistics().Initialized()) {
115 _shared->SetLastError(VE_NOT_INITED, kTraceError);
116 return -1;
117 }
118 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
119 voe::Channel* channelPtr = ch.channel();
120 if (channelPtr == NULL) {
121 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
122 "GetSendCodec() failed to locate channel");
123 return -1;
124 }
kwiberg12e21a02015-11-19 11:08:29 -0800125 if (channelPtr->GetSendCodec(codec) != 0) {
Jelena Marusic0d266052015-05-04 14:15:32 +0200126 _shared->SetLastError(VE_CANNOT_GET_SEND_CODEC, kTraceError,
127 "GetSendCodec() failed to get send codec");
128 return -1;
129 }
Jelena Marusic0d266052015-05-04 14:15:32 +0200130 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000131}
132
Ivo Creusenadf89b72015-04-29 16:03:33 +0200133int VoECodecImpl::SetBitRate(int channel, int bitrate_bps) {
134 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
135 "SetBitRate(bitrate_bps=%d)", bitrate_bps);
136 if (!_shared->statistics().Initialized()) {
137 _shared->SetLastError(VE_NOT_INITED, kTraceError);
138 return -1;
139 }
michaelt9abbf5a2016-11-28 07:00:18 -0800140 constexpr int64_t kDefaultProbingIntervalMs = 3000;
Ivo Creusenadf89b72015-04-29 16:03:33 +0200141 _shared->channel_manager().GetChannel(channel).channel()->SetBitRate(
michaelt9abbf5a2016-11-28 07:00:18 -0800142 bitrate_bps, kDefaultProbingIntervalMs);
Ivo Creusenadf89b72015-04-29 16:03:33 +0200143 return 0;
144}
145
Jelena Marusic0d266052015-05-04 14:15:32 +0200146int VoECodecImpl::GetRecCodec(int channel, CodecInst& codec) {
Jelena Marusic0d266052015-05-04 14:15:32 +0200147 if (!_shared->statistics().Initialized()) {
148 _shared->SetLastError(VE_NOT_INITED, kTraceError);
149 return -1;
150 }
151 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
152 voe::Channel* channelPtr = ch.channel();
153 if (channelPtr == NULL) {
154 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
155 "GetRecCodec() failed to locate channel");
156 return -1;
157 }
kwiberg12e21a02015-11-19 11:08:29 -0800158 return channelPtr->GetRecCodec(codec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000159}
160
Jelena Marusic0d266052015-05-04 14:15:32 +0200161int VoECodecImpl::SetRecPayloadType(int channel, const CodecInst& codec) {
162 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
163 "SetRecPayloadType(channel=%d, codec)", channel);
164 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
Peter Kasting69558702016-01-12 16:26:35 -0800165 "codec: plname=%s, plfreq=%d, pltype=%d, channels=%" PRIuS ", "
Jelena Marusic0d266052015-05-04 14:15:32 +0200166 "pacsize=%d, rate=%d",
167 codec.plname, codec.plfreq, codec.pltype, codec.channels,
168 codec.pacsize, codec.rate);
169 if (!_shared->statistics().Initialized()) {
170 _shared->SetLastError(VE_NOT_INITED, kTraceError);
171 return -1;
172 }
173 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
174 voe::Channel* channelPtr = ch.channel();
175 if (channelPtr == NULL) {
176 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
177 "GetRecPayloadType() failed to locate channel");
178 return -1;
179 }
180 return channelPtr->SetRecPayloadType(codec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000181}
182
Jelena Marusic0d266052015-05-04 14:15:32 +0200183int VoECodecImpl::GetRecPayloadType(int channel, CodecInst& codec) {
Jelena Marusic0d266052015-05-04 14:15:32 +0200184 if (!_shared->statistics().Initialized()) {
185 _shared->SetLastError(VE_NOT_INITED, kTraceError);
186 return -1;
187 }
188 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
189 voe::Channel* channelPtr = ch.channel();
190 if (channelPtr == NULL) {
191 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
192 "GetRecPayloadType() failed to locate channel");
193 return -1;
194 }
195 return channelPtr->GetRecPayloadType(codec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000196}
197
Jelena Marusic0d266052015-05-04 14:15:32 +0200198int VoECodecImpl::SetSendCNPayloadType(int channel,
199 int type,
200 PayloadFrequencies frequency) {
201 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
202 "SetSendCNPayloadType(channel=%d, type=%d, frequency=%d)",
203 channel, type, frequency);
204 if (!_shared->statistics().Initialized()) {
205 _shared->SetLastError(VE_NOT_INITED, kTraceError);
206 return -1;
207 }
208 if (type < 96 || type > 127) {
209 // Only allow dynamic range: 96 to 127
210 _shared->SetLastError(VE_INVALID_PLTYPE, kTraceError,
211 "SetSendCNPayloadType() invalid payload type");
212 return -1;
213 }
214 if ((frequency != kFreq16000Hz) && (frequency != kFreq32000Hz)) {
215 // It is not possible to modify the payload type for CN/8000.
216 // We only allow modification of the CN payload type for CN/16000
217 // and CN/32000.
218 _shared->SetLastError(VE_INVALID_PLFREQ, kTraceError,
219 "SetSendCNPayloadType() invalid payload frequency");
220 return -1;
221 }
222 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
223 voe::Channel* channelPtr = ch.channel();
224 if (channelPtr == NULL) {
225 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
226 "SetSendCNPayloadType() failed to locate channel");
227 return -1;
228 }
229 return channelPtr->SetSendCNPayloadType(type, frequency);
niklase@google.com470e71d2011-07-07 08:21:25 +0000230}
231
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +0000232int VoECodecImpl::SetFECStatus(int channel, bool enable) {
233 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
234 "SetCodecFECStatus(channel=%d, enable=%d)", channel, enable);
235 if (!_shared->statistics().Initialized()) {
236 _shared->SetLastError(VE_NOT_INITED, kTraceError);
237 return -1;
238 }
239 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
240 voe::Channel* channelPtr = ch.channel();
241 if (channelPtr == NULL) {
242 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
243 "SetCodecFECStatus() failed to locate channel");
244 return -1;
245 }
246 return channelPtr->SetCodecFECStatus(enable);
247}
248
249int VoECodecImpl::GetFECStatus(int channel, bool& enabled) {
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +0000250 if (!_shared->statistics().Initialized()) {
251 _shared->SetLastError(VE_NOT_INITED, kTraceError);
252 return -1;
253 }
254 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
255 voe::Channel* channelPtr = ch.channel();
256 if (channelPtr == NULL) {
257 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
258 "GetFECStatus() failed to locate channel");
259 return -1;
260 }
261 enabled = channelPtr->GetCodecFECStatus();
262 return 0;
263}
264
Jelena Marusic0d266052015-05-04 14:15:32 +0200265int VoECodecImpl::SetVADStatus(int channel,
266 bool enable,
267 VadModes mode,
268 bool disableDTX) {
269 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
270 "SetVADStatus(channel=%i, enable=%i, mode=%i, disableDTX=%i)",
271 channel, enable, mode, disableDTX);
niklase@google.com470e71d2011-07-07 08:21:25 +0000272
Jelena Marusic0d266052015-05-04 14:15:32 +0200273 if (!_shared->statistics().Initialized()) {
274 _shared->SetLastError(VE_NOT_INITED, kTraceError);
275 return -1;
276 }
277 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
278 voe::Channel* channelPtr = ch.channel();
279 if (channelPtr == NULL) {
280 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
281 "SetVADStatus failed to locate channel");
282 return -1;
283 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000284
Jelena Marusic0d266052015-05-04 14:15:32 +0200285 ACMVADMode vadMode(VADNormal);
286 switch (mode) {
287 case kVadConventional:
288 vadMode = VADNormal;
289 break;
290 case kVadAggressiveLow:
291 vadMode = VADLowBitrate;
292 break;
293 case kVadAggressiveMid:
294 vadMode = VADAggr;
295 break;
296 case kVadAggressiveHigh:
297 vadMode = VADVeryAggr;
298 break;
299 }
300 return channelPtr->SetVADStatus(enable, vadMode, disableDTX);
niklase@google.com470e71d2011-07-07 08:21:25 +0000301}
302
Jelena Marusic0d266052015-05-04 14:15:32 +0200303int VoECodecImpl::GetVADStatus(int channel,
304 bool& enabled,
305 VadModes& mode,
306 bool& disabledDTX) {
Jelena Marusic0d266052015-05-04 14:15:32 +0200307 if (!_shared->statistics().Initialized()) {
308 _shared->SetLastError(VE_NOT_INITED, kTraceError);
309 return -1;
310 }
311 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
312 voe::Channel* channelPtr = ch.channel();
313 if (channelPtr == NULL) {
314 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
315 "GetVADStatus failed to locate channel");
316 return -1;
317 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000318
Jelena Marusic0d266052015-05-04 14:15:32 +0200319 ACMVADMode vadMode;
320 int ret = channelPtr->GetVADStatus(enabled, vadMode, disabledDTX);
niklase@google.com470e71d2011-07-07 08:21:25 +0000321
Jelena Marusic0d266052015-05-04 14:15:32 +0200322 if (ret != 0) {
323 _shared->SetLastError(VE_INVALID_OPERATION, kTraceError,
324 "GetVADStatus failed to get VAD mode");
325 return -1;
326 }
327 switch (vadMode) {
328 case VADNormal:
329 mode = kVadConventional;
330 break;
331 case VADLowBitrate:
332 mode = kVadAggressiveLow;
333 break;
334 case VADAggr:
335 mode = kVadAggressiveMid;
336 break;
337 case VADVeryAggr:
338 mode = kVadAggressiveHigh;
339 break;
340 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000341
Jelena Marusic0d266052015-05-04 14:15:32 +0200342 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000343}
344
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000345int VoECodecImpl::SetOpusMaxPlaybackRate(int channel, int frequency_hz) {
minyue@webrtc.org6aac93b2014-08-12 08:13:33 +0000346 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000347 "SetOpusMaxPlaybackRate(channel=%d, frequency_hz=%d)", channel,
348 frequency_hz);
minyue@webrtc.org6aac93b2014-08-12 08:13:33 +0000349 if (!_shared->statistics().Initialized()) {
350 _shared->SetLastError(VE_NOT_INITED, kTraceError);
351 return -1;
352 }
353 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
354 voe::Channel* channelPtr = ch.channel();
355 if (channelPtr == NULL) {
356 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000357 "SetOpusMaxPlaybackRate failed to locate channel");
minyue@webrtc.org6aac93b2014-08-12 08:13:33 +0000358 return -1;
359 }
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000360 return channelPtr->SetOpusMaxPlaybackRate(frequency_hz);
minyue@webrtc.org6aac93b2014-08-12 08:13:33 +0000361}
362
minyue@webrtc.org9b2e1142015-03-13 09:38:07 +0000363int VoECodecImpl::SetOpusDtx(int channel, bool enable_dtx) {
364 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
365 "SetOpusDtx(channel=%d, enable_dtx=%d)", channel, enable_dtx);
366 if (!_shared->statistics().Initialized()) {
367 _shared->SetLastError(VE_NOT_INITED, kTraceError);
368 return -1;
369 }
370 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
371 voe::Channel* channelPtr = ch.channel();
372 if (channelPtr == NULL) {
373 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
374 "SetOpusDtx failed to locate channel");
375 return -1;
376 }
377 return channelPtr->SetOpusDtx(enable_dtx);
378}
379
ivoc85228d62016-07-27 04:53:47 -0700380int VoECodecImpl::GetOpusDtxStatus(int channel, bool* enabled) {
381 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
382 "GetOpusDtx(channel=%d)", channel);
383 if (!_shared->statistics().Initialized()) {
384 _shared->SetLastError(VE_NOT_INITED, kTraceError);
385 return -1;
386 }
387 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
388 voe::Channel* channelPtr = ch.channel();
389 if (channelPtr == NULL) {
390 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
391 "GetOpusDtx failed to locate channel");
392 return -1;
393 }
394 return channelPtr->GetOpusDtx(enabled);
395}
396
niklase@google.com470e71d2011-07-07 08:21:25 +0000397#endif // WEBRTC_VOICE_ENGINE_CODEC_API
398
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000399} // namespace webrtc