blob: 19891bc39fae52399f23e224db25342fd6642f37 [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 }
140 _shared->channel_manager().GetChannel(channel).channel()->SetBitRate(
141 bitrate_bps);
142 return 0;
143}
144
Jelena Marusic0d266052015-05-04 14:15:32 +0200145int VoECodecImpl::GetRecCodec(int channel, CodecInst& codec) {
Jelena Marusic0d266052015-05-04 14:15:32 +0200146 if (!_shared->statistics().Initialized()) {
147 _shared->SetLastError(VE_NOT_INITED, kTraceError);
148 return -1;
149 }
150 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
151 voe::Channel* channelPtr = ch.channel();
152 if (channelPtr == NULL) {
153 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
154 "GetRecCodec() failed to locate channel");
155 return -1;
156 }
kwiberg12e21a02015-11-19 11:08:29 -0800157 return channelPtr->GetRecCodec(codec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000158}
159
Jelena Marusic0d266052015-05-04 14:15:32 +0200160int VoECodecImpl::SetRecPayloadType(int channel, const CodecInst& codec) {
161 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
162 "SetRecPayloadType(channel=%d, codec)", channel);
163 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
Peter Kasting69558702016-01-12 16:26:35 -0800164 "codec: plname=%s, plfreq=%d, pltype=%d, channels=%" PRIuS ", "
Jelena Marusic0d266052015-05-04 14:15:32 +0200165 "pacsize=%d, rate=%d",
166 codec.plname, codec.plfreq, codec.pltype, codec.channels,
167 codec.pacsize, codec.rate);
168 if (!_shared->statistics().Initialized()) {
169 _shared->SetLastError(VE_NOT_INITED, kTraceError);
170 return -1;
171 }
172 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
173 voe::Channel* channelPtr = ch.channel();
174 if (channelPtr == NULL) {
175 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
176 "GetRecPayloadType() failed to locate channel");
177 return -1;
178 }
179 return channelPtr->SetRecPayloadType(codec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000180}
181
Jelena Marusic0d266052015-05-04 14:15:32 +0200182int VoECodecImpl::GetRecPayloadType(int channel, CodecInst& codec) {
Jelena Marusic0d266052015-05-04 14:15:32 +0200183 if (!_shared->statistics().Initialized()) {
184 _shared->SetLastError(VE_NOT_INITED, kTraceError);
185 return -1;
186 }
187 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
188 voe::Channel* channelPtr = ch.channel();
189 if (channelPtr == NULL) {
190 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
191 "GetRecPayloadType() failed to locate channel");
192 return -1;
193 }
194 return channelPtr->GetRecPayloadType(codec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000195}
196
Jelena Marusic0d266052015-05-04 14:15:32 +0200197int VoECodecImpl::SetSendCNPayloadType(int channel,
198 int type,
199 PayloadFrequencies frequency) {
200 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
201 "SetSendCNPayloadType(channel=%d, type=%d, frequency=%d)",
202 channel, type, frequency);
203 if (!_shared->statistics().Initialized()) {
204 _shared->SetLastError(VE_NOT_INITED, kTraceError);
205 return -1;
206 }
207 if (type < 96 || type > 127) {
208 // Only allow dynamic range: 96 to 127
209 _shared->SetLastError(VE_INVALID_PLTYPE, kTraceError,
210 "SetSendCNPayloadType() invalid payload type");
211 return -1;
212 }
213 if ((frequency != kFreq16000Hz) && (frequency != kFreq32000Hz)) {
214 // It is not possible to modify the payload type for CN/8000.
215 // We only allow modification of the CN payload type for CN/16000
216 // and CN/32000.
217 _shared->SetLastError(VE_INVALID_PLFREQ, kTraceError,
218 "SetSendCNPayloadType() invalid payload frequency");
219 return -1;
220 }
221 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
222 voe::Channel* channelPtr = ch.channel();
223 if (channelPtr == NULL) {
224 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
225 "SetSendCNPayloadType() failed to locate channel");
226 return -1;
227 }
228 return channelPtr->SetSendCNPayloadType(type, frequency);
niklase@google.com470e71d2011-07-07 08:21:25 +0000229}
230
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +0000231int VoECodecImpl::SetFECStatus(int channel, bool enable) {
232 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
233 "SetCodecFECStatus(channel=%d, enable=%d)", channel, enable);
234 if (!_shared->statistics().Initialized()) {
235 _shared->SetLastError(VE_NOT_INITED, kTraceError);
236 return -1;
237 }
238 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
239 voe::Channel* channelPtr = ch.channel();
240 if (channelPtr == NULL) {
241 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
242 "SetCodecFECStatus() failed to locate channel");
243 return -1;
244 }
245 return channelPtr->SetCodecFECStatus(enable);
246}
247
248int VoECodecImpl::GetFECStatus(int channel, bool& enabled) {
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +0000249 if (!_shared->statistics().Initialized()) {
250 _shared->SetLastError(VE_NOT_INITED, kTraceError);
251 return -1;
252 }
253 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
254 voe::Channel* channelPtr = ch.channel();
255 if (channelPtr == NULL) {
256 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
257 "GetFECStatus() failed to locate channel");
258 return -1;
259 }
260 enabled = channelPtr->GetCodecFECStatus();
261 return 0;
262}
263
Jelena Marusic0d266052015-05-04 14:15:32 +0200264int VoECodecImpl::SetVADStatus(int channel,
265 bool enable,
266 VadModes mode,
267 bool disableDTX) {
268 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
269 "SetVADStatus(channel=%i, enable=%i, mode=%i, disableDTX=%i)",
270 channel, enable, mode, disableDTX);
niklase@google.com470e71d2011-07-07 08:21:25 +0000271
Jelena Marusic0d266052015-05-04 14:15:32 +0200272 if (!_shared->statistics().Initialized()) {
273 _shared->SetLastError(VE_NOT_INITED, kTraceError);
274 return -1;
275 }
276 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
277 voe::Channel* channelPtr = ch.channel();
278 if (channelPtr == NULL) {
279 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
280 "SetVADStatus failed to locate channel");
281 return -1;
282 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000283
Jelena Marusic0d266052015-05-04 14:15:32 +0200284 ACMVADMode vadMode(VADNormal);
285 switch (mode) {
286 case kVadConventional:
287 vadMode = VADNormal;
288 break;
289 case kVadAggressiveLow:
290 vadMode = VADLowBitrate;
291 break;
292 case kVadAggressiveMid:
293 vadMode = VADAggr;
294 break;
295 case kVadAggressiveHigh:
296 vadMode = VADVeryAggr;
297 break;
298 }
299 return channelPtr->SetVADStatus(enable, vadMode, disableDTX);
niklase@google.com470e71d2011-07-07 08:21:25 +0000300}
301
Jelena Marusic0d266052015-05-04 14:15:32 +0200302int VoECodecImpl::GetVADStatus(int channel,
303 bool& enabled,
304 VadModes& mode,
305 bool& disabledDTX) {
Jelena Marusic0d266052015-05-04 14:15:32 +0200306 if (!_shared->statistics().Initialized()) {
307 _shared->SetLastError(VE_NOT_INITED, kTraceError);
308 return -1;
309 }
310 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
311 voe::Channel* channelPtr = ch.channel();
312 if (channelPtr == NULL) {
313 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
314 "GetVADStatus failed to locate channel");
315 return -1;
316 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000317
Jelena Marusic0d266052015-05-04 14:15:32 +0200318 ACMVADMode vadMode;
319 int ret = channelPtr->GetVADStatus(enabled, vadMode, disabledDTX);
niklase@google.com470e71d2011-07-07 08:21:25 +0000320
Jelena Marusic0d266052015-05-04 14:15:32 +0200321 if (ret != 0) {
322 _shared->SetLastError(VE_INVALID_OPERATION, kTraceError,
323 "GetVADStatus failed to get VAD mode");
324 return -1;
325 }
326 switch (vadMode) {
327 case VADNormal:
328 mode = kVadConventional;
329 break;
330 case VADLowBitrate:
331 mode = kVadAggressiveLow;
332 break;
333 case VADAggr:
334 mode = kVadAggressiveMid;
335 break;
336 case VADVeryAggr:
337 mode = kVadAggressiveHigh;
338 break;
339 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000340
Jelena Marusic0d266052015-05-04 14:15:32 +0200341 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000342}
343
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000344int VoECodecImpl::SetOpusMaxPlaybackRate(int channel, int frequency_hz) {
minyue@webrtc.org6aac93b2014-08-12 08:13:33 +0000345 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000346 "SetOpusMaxPlaybackRate(channel=%d, frequency_hz=%d)", channel,
347 frequency_hz);
minyue@webrtc.org6aac93b2014-08-12 08:13:33 +0000348 if (!_shared->statistics().Initialized()) {
349 _shared->SetLastError(VE_NOT_INITED, kTraceError);
350 return -1;
351 }
352 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
353 voe::Channel* channelPtr = ch.channel();
354 if (channelPtr == NULL) {
355 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000356 "SetOpusMaxPlaybackRate failed to locate channel");
minyue@webrtc.org6aac93b2014-08-12 08:13:33 +0000357 return -1;
358 }
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +0000359 return channelPtr->SetOpusMaxPlaybackRate(frequency_hz);
minyue@webrtc.org6aac93b2014-08-12 08:13:33 +0000360}
361
minyue@webrtc.org9b2e1142015-03-13 09:38:07 +0000362int VoECodecImpl::SetOpusDtx(int channel, bool enable_dtx) {
363 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
364 "SetOpusDtx(channel=%d, enable_dtx=%d)", channel, enable_dtx);
365 if (!_shared->statistics().Initialized()) {
366 _shared->SetLastError(VE_NOT_INITED, kTraceError);
367 return -1;
368 }
369 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
370 voe::Channel* channelPtr = ch.channel();
371 if (channelPtr == NULL) {
372 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
373 "SetOpusDtx failed to locate channel");
374 return -1;
375 }
376 return channelPtr->SetOpusDtx(enable_dtx);
377}
378
niklase@google.com470e71d2011-07-07 08:21:25 +0000379#endif // WEBRTC_VOICE_ENGINE_CODEC_API
380
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000381} // namespace webrtc