blob: a7735bb03102209073f4239203559914aea7fcc9 [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
pbos@webrtc.org956aa7e2013-05-21 13:52:32 +000013#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
14#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
15#include "webrtc/system_wrappers/interface/trace.h"
16#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
20namespace webrtc
21{
22
23VoECodec* VoECodec::GetInterface(VoiceEngine* voiceEngine)
24{
25#ifndef WEBRTC_VOICE_ENGINE_CODEC_API
26 return NULL;
27#else
28 if (NULL == voiceEngine)
29 {
30 return NULL;
31 }
tommi@webrtc.org0989fb72013-02-15 15:07:32 +000032 VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
tommi@webrtc.orga990e122012-04-26 15:28:22 +000033 s->AddRef();
34 return s;
niklase@google.com470e71d2011-07-07 08:21:25 +000035#endif
36}
37
38#ifdef WEBRTC_VOICE_ENGINE_CODEC_API
39
tommi@webrtc.org851becd2012-04-04 14:57:19 +000040VoECodecImpl::VoECodecImpl(voe::SharedData* shared) : _shared(shared)
niklase@google.com470e71d2011-07-07 08:21:25 +000041{
tommi@webrtc.org851becd2012-04-04 14:57:19 +000042 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +000043 "VoECodecImpl() - ctor");
44}
45
46VoECodecImpl::~VoECodecImpl()
47{
tommi@webrtc.org851becd2012-04-04 14:57:19 +000048 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +000049 "~VoECodecImpl() - dtor");
50}
51
niklase@google.com470e71d2011-07-07 08:21:25 +000052int VoECodecImpl::NumOfCodecs()
53{
tommi@webrtc.org851becd2012-04-04 14:57:19 +000054 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +000055 "NumOfCodecs()");
56
57 // Number of supported codecs in the ACM
pbos@webrtc.org6141e132013-04-09 10:09:10 +000058 uint8_t nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
niklase@google.com470e71d2011-07-07 08:21:25 +000059
tommi@webrtc.org851becd2012-04-04 14:57:19 +000060 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
61 VoEId(_shared->instance_id(), -1),
62 "NumOfCodecs() => %u", nSupportedCodecs);
niklase@google.com470e71d2011-07-07 08:21:25 +000063 return (nSupportedCodecs);
64}
65
66int VoECodecImpl::GetCodec(int index, CodecInst& codec)
67{
tommi@webrtc.org851becd2012-04-04 14:57:19 +000068 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +000069 "GetCodec(index=%d, codec=?)", index);
70 CodecInst acmCodec;
tina.legrand@webrtc.org7a7a0082013-02-21 10:27:48 +000071 if (AudioCodingModule::Codec(index, &acmCodec)
niklase@google.com470e71d2011-07-07 08:21:25 +000072 == -1)
73 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +000074 _shared->SetLastError(VE_INVALID_LISTNR, kTraceError,
75 "GetCodec() invalid index");
niklase@google.com470e71d2011-07-07 08:21:25 +000076 return -1;
77 }
78 ACMToExternalCodecRepresentation(codec, acmCodec);
tommi@webrtc.org851becd2012-04-04 14:57:19 +000079 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
80 VoEId(_shared->instance_id(), -1),
81 "GetCodec() => plname=%s, pacsize=%d, plfreq=%d, pltype=%d, "
82 "channels=%d, rate=%d", codec.plname, codec.pacsize,
83 codec.plfreq, codec.pltype, codec.channels, codec.rate);
niklase@google.com470e71d2011-07-07 08:21:25 +000084 return 0;
85}
86
87int VoECodecImpl::SetSendCodec(int channel, const CodecInst& codec)
88{
89 CodecInst copyCodec;
90 ExternalToACMCodecRepresentation(copyCodec, codec);
91
tommi@webrtc.org851becd2012-04-04 14:57:19 +000092 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +000093 "SetSendCodec(channel=%d, codec)", channel);
tommi@webrtc.org851becd2012-04-04 14:57:19 +000094 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +000095 "codec: plname=%s, pacsize=%d, plfreq=%d, pltype=%d, "
96 "channels=%d, rate=%d", codec.plname, codec.pacsize,
97 codec.plfreq, codec.pltype, codec.channels, codec.rate);
tommi@webrtc.org851becd2012-04-04 14:57:19 +000098 if (!_shared->statistics().Initialized())
niklase@google.com470e71d2011-07-07 08:21:25 +000099 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000100 _shared->SetLastError(VE_NOT_INITED, kTraceError);
niklase@google.com470e71d2011-07-07 08:21:25 +0000101 return -1;
102 }
103 // External sanity checks performed outside the ACM
104 if ((STR_CASE_CMP(copyCodec.plname, "L16") == 0) &&
105 (copyCodec.pacsize >= 960))
106 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000107 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
108 "SetSendCodec() invalid L16 packet size");
niklase@google.com470e71d2011-07-07 08:21:25 +0000109 return -1;
110 }
111 if (!STR_CASE_CMP(copyCodec.plname, "CN")
112 || !STR_CASE_CMP(copyCodec.plname, "TELEPHONE-EVENT")
113 || !STR_CASE_CMP(copyCodec.plname, "RED"))
114 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000115 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
116 "SetSendCodec() invalid codec name");
niklase@google.com470e71d2011-07-07 08:21:25 +0000117 return -1;
118 }
niklas.enbom@webrtc.orge33a1022011-11-16 10:33:53 +0000119 if ((copyCodec.channels != 1) && (copyCodec.channels != 2))
niklase@google.com470e71d2011-07-07 08:21:25 +0000120 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000121 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
122 "SetSendCodec() invalid number of channels");
niklase@google.com470e71d2011-07-07 08:21:25 +0000123 return -1;
124 }
pbos@webrtc.org676ff1e2013-08-07 17:57:36 +0000125 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
126 voe::Channel* channelPtr = ch.channel();
niklase@google.com470e71d2011-07-07 08:21:25 +0000127 if (channelPtr == NULL)
128 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000129 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
130 "GetSendCodec() failed to locate channel");
niklase@google.com470e71d2011-07-07 08:21:25 +0000131 return -1;
132 }
133 if (!AudioCodingModule::IsCodecValid(
134 (CodecInst&) copyCodec))
135 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000136 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
137 "SetSendCodec() invalid codec");
niklase@google.com470e71d2011-07-07 08:21:25 +0000138 return -1;
139 }
140 if (channelPtr->SetSendCodec(copyCodec) != 0)
141 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000142 _shared->SetLastError(VE_CANNOT_SET_SEND_CODEC, kTraceError,
143 "SetSendCodec() failed to set send codec");
niklase@google.com470e71d2011-07-07 08:21:25 +0000144 return -1;
145 }
146
niklase@google.com470e71d2011-07-07 08:21:25 +0000147 return 0;
148}
149
150int VoECodecImpl::GetSendCodec(int channel, CodecInst& codec)
151{
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000152 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000153 "GetSendCodec(channel=%d, codec=?)", channel);
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000154 if (!_shared->statistics().Initialized())
niklase@google.com470e71d2011-07-07 08:21:25 +0000155 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000156 _shared->SetLastError(VE_NOT_INITED, kTraceError);
niklase@google.com470e71d2011-07-07 08:21:25 +0000157 return -1;
158 }
pbos@webrtc.org676ff1e2013-08-07 17:57:36 +0000159 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
160 voe::Channel* channelPtr = ch.channel();
niklase@google.com470e71d2011-07-07 08:21:25 +0000161 if (channelPtr == NULL)
162 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000163 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
164 "GetSendCodec() failed to locate channel");
niklase@google.com470e71d2011-07-07 08:21:25 +0000165 return -1;
166 }
167 CodecInst acmCodec;
168 if (channelPtr->GetSendCodec(acmCodec) != 0)
169 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000170 _shared->SetLastError(VE_CANNOT_GET_SEND_CODEC, kTraceError,
171 "GetSendCodec() failed to get send codec");
niklase@google.com470e71d2011-07-07 08:21:25 +0000172 return -1;
173 }
174 ACMToExternalCodecRepresentation(codec, acmCodec);
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000175 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
176 VoEId(_shared->instance_id(), -1),
177 "GetSendCodec() => plname=%s, pacsize=%d, plfreq=%d, "
178 "channels=%d, rate=%d", codec.plname, codec.pacsize,
179 codec.plfreq, codec.channels, codec.rate);
niklase@google.com470e71d2011-07-07 08:21:25 +0000180 return 0;
181}
182
183int VoECodecImpl::GetRecCodec(int channel, CodecInst& codec)
184{
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000185 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000186 "GetRecCodec(channel=%d, codec=?)", channel);
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000187 if (!_shared->statistics().Initialized())
niklase@google.com470e71d2011-07-07 08:21:25 +0000188 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000189 _shared->SetLastError(VE_NOT_INITED, kTraceError);
niklase@google.com470e71d2011-07-07 08:21:25 +0000190 return -1;
191 }
pbos@webrtc.org676ff1e2013-08-07 17:57:36 +0000192 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
193 voe::Channel* channelPtr = ch.channel();
niklase@google.com470e71d2011-07-07 08:21:25 +0000194 if (channelPtr == NULL)
195 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000196 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
197 "GetRecCodec() failed to locate channel");
niklase@google.com470e71d2011-07-07 08:21:25 +0000198 return -1;
199 }
200 CodecInst acmCodec;
201 if (channelPtr->GetRecCodec(acmCodec) != 0)
202 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000203 _shared->SetLastError(VE_CANNOT_GET_REC_CODEC, kTraceError,
204 "GetRecCodec() failed to get received codec");
niklase@google.com470e71d2011-07-07 08:21:25 +0000205 return -1;
206 }
207 ACMToExternalCodecRepresentation(codec, acmCodec);
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000208 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
209 VoEId(_shared->instance_id(), -1),
210 "GetRecCodec() => plname=%s, pacsize=%d, plfreq=%d, "
211 "channels=%d, rate=%d", codec.plname, codec.pacsize,
212 codec.plfreq, codec.channels, codec.rate);
niklase@google.com470e71d2011-07-07 08:21:25 +0000213 return 0;
214}
215
niklase@google.com470e71d2011-07-07 08:21:25 +0000216int VoECodecImpl::SetRecPayloadType(int channel, const CodecInst& codec)
217{
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000218 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000219 "SetRecPayloadType(channel=%d, codec)", channel);
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000220 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000221 "codec: plname=%s, plfreq=%d, pltype=%d, channels=%u, "
222 "pacsize=%d, rate=%d", codec.plname, codec.plfreq, codec.pltype,
223 codec.channels, codec.pacsize, codec.rate);
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000224 if (!_shared->statistics().Initialized())
niklase@google.com470e71d2011-07-07 08:21:25 +0000225 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000226 _shared->SetLastError(VE_NOT_INITED, kTraceError);
niklase@google.com470e71d2011-07-07 08:21:25 +0000227 return -1;
228 }
pbos@webrtc.org676ff1e2013-08-07 17:57:36 +0000229 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
230 voe::Channel* channelPtr = ch.channel();
niklase@google.com470e71d2011-07-07 08:21:25 +0000231 if (channelPtr == NULL)
232 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000233 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
234 "GetRecPayloadType() failed to locate channel");
niklase@google.com470e71d2011-07-07 08:21:25 +0000235 return -1;
236 }
237 return channelPtr->SetRecPayloadType(codec);
238}
239
240int VoECodecImpl::GetRecPayloadType(int channel, CodecInst& codec)
241{
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000242 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000243 "GetRecPayloadType(channel=%d, codec)", channel);
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000244 if (!_shared->statistics().Initialized())
niklase@google.com470e71d2011-07-07 08:21:25 +0000245 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000246 _shared->SetLastError(VE_NOT_INITED, kTraceError);
niklase@google.com470e71d2011-07-07 08:21:25 +0000247 return -1;
248 }
pbos@webrtc.org676ff1e2013-08-07 17:57:36 +0000249 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
250 voe::Channel* channelPtr = ch.channel();
niklase@google.com470e71d2011-07-07 08:21:25 +0000251 if (channelPtr == NULL)
252 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000253 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
254 "GetRecPayloadType() failed to locate channel");
niklase@google.com470e71d2011-07-07 08:21:25 +0000255 return -1;
256 }
257 return channelPtr->GetRecPayloadType(codec);
258}
259
260int VoECodecImpl::SetSendCNPayloadType(int channel, int type,
261 PayloadFrequencies frequency)
262{
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000263 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000264 "SetSendCNPayloadType(channel=%d, type=%d, frequency=%d)",
265 channel, type, frequency);
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000266 if (!_shared->statistics().Initialized())
niklase@google.com470e71d2011-07-07 08:21:25 +0000267 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000268 _shared->SetLastError(VE_NOT_INITED, kTraceError);
niklase@google.com470e71d2011-07-07 08:21:25 +0000269 return -1;
270 }
271 if (type < 96 || type > 127)
272 {
273 // Only allow dynamic range: 96 to 127
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000274 _shared->SetLastError(VE_INVALID_PLTYPE, kTraceError,
275 "SetSendCNPayloadType() invalid payload type");
niklase@google.com470e71d2011-07-07 08:21:25 +0000276 return -1;
277 }
278 if ((frequency != kFreq16000Hz) && (frequency != kFreq32000Hz))
279 {
280 // It is not possible to modify the payload type for CN/8000.
281 // We only allow modification of the CN payload type for CN/16000
282 // and CN/32000.
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000283 _shared->SetLastError(VE_INVALID_PLFREQ, kTraceError,
284 "SetSendCNPayloadType() invalid payload frequency");
niklase@google.com470e71d2011-07-07 08:21:25 +0000285 return -1;
286 }
pbos@webrtc.org676ff1e2013-08-07 17:57:36 +0000287 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
288 voe::Channel* channelPtr = ch.channel();
niklase@google.com470e71d2011-07-07 08:21:25 +0000289 if (channelPtr == NULL)
290 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000291 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
292 "SetSendCNPayloadType() failed to locate channel");
niklase@google.com470e71d2011-07-07 08:21:25 +0000293 return -1;
294 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000295 return channelPtr->SetSendCNPayloadType(type, frequency);
296}
297
niklase@google.com470e71d2011-07-07 08:21:25 +0000298int VoECodecImpl::SetVADStatus(int channel, bool enable, VadModes mode,
299 bool disableDTX)
300{
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000301 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000302 "SetVADStatus(channel=%i, enable=%i, mode=%i, disableDTX=%i)",
303 channel, enable, mode, disableDTX);
304
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000305 if (!_shared->statistics().Initialized())
niklase@google.com470e71d2011-07-07 08:21:25 +0000306 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000307 _shared->SetLastError(VE_NOT_INITED, kTraceError);
niklase@google.com470e71d2011-07-07 08:21:25 +0000308 return -1;
309 }
pbos@webrtc.org676ff1e2013-08-07 17:57:36 +0000310 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
311 voe::Channel* channelPtr = ch.channel();
niklase@google.com470e71d2011-07-07 08:21:25 +0000312 if (channelPtr == NULL)
313 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000314 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
315 "SetVADStatus failed to locate channel");
niklase@google.com470e71d2011-07-07 08:21:25 +0000316 return -1;
317 }
318
319 ACMVADMode vadMode(VADNormal);
320 switch (mode)
321 {
322 case kVadConventional:
323 vadMode = VADNormal;
324 break;
325 case kVadAggressiveLow:
326 vadMode = VADLowBitrate;
327 break;
328 case kVadAggressiveMid:
329 vadMode = VADAggr;
330 break;
331 case kVadAggressiveHigh:
332 vadMode = VADVeryAggr;
333 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000334 }
335 return channelPtr->SetVADStatus(enable, vadMode, disableDTX);
336}
337
338int VoECodecImpl::GetVADStatus(int channel, bool& enabled, VadModes& mode,
339 bool& disabledDTX)
340{
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000341 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000342 "GetVADStatus(channel=%i)", channel);
343
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000344 if (!_shared->statistics().Initialized())
niklase@google.com470e71d2011-07-07 08:21:25 +0000345 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000346 _shared->SetLastError(VE_NOT_INITED, kTraceError);
niklase@google.com470e71d2011-07-07 08:21:25 +0000347 return -1;
348 }
pbos@webrtc.org676ff1e2013-08-07 17:57:36 +0000349 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
350 voe::Channel* channelPtr = ch.channel();
niklase@google.com470e71d2011-07-07 08:21:25 +0000351 if (channelPtr == NULL)
352 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000353 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
354 "GetVADStatus failed to locate channel");
niklase@google.com470e71d2011-07-07 08:21:25 +0000355 return -1;
356 }
357
358 ACMVADMode vadMode;
359 int ret = channelPtr->GetVADStatus(enabled, vadMode, disabledDTX);
360
361 if (ret != 0)
362 {
tommi@webrtc.org851becd2012-04-04 14:57:19 +0000363 _shared->SetLastError(VE_INVALID_OPERATION, kTraceError,
364 "GetVADStatus failed to get VAD mode");
niklase@google.com470e71d2011-07-07 08:21:25 +0000365 return -1;
366 }
367 switch (vadMode)
368 {
369 case VADNormal:
370 mode = kVadConventional;
371 break;
372 case VADLowBitrate:
373 mode = kVadAggressiveLow;
374 break;
375 case VADAggr:
376 mode = kVadAggressiveMid;
377 break;
378 case VADVeryAggr:
379 mode = kVadAggressiveHigh;
380 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000381 }
382
383 return 0;
384}
385
386void VoECodecImpl::ACMToExternalCodecRepresentation(CodecInst& toInst,
387 const CodecInst& fromInst)
388{
389 toInst = fromInst;
390 if (STR_CASE_CMP(fromInst.plname,"SILK") == 0)
391 {
392 if (fromInst.plfreq == 12000)
393 {
394 if (fromInst.pacsize == 320)
395 {
396 toInst.pacsize = 240;
397 }
398 else if (fromInst.pacsize == 640)
399 {
400 toInst.pacsize = 480;
401 }
402 else if (fromInst.pacsize == 960)
403 {
404 toInst.pacsize = 720;
405 }
406 }
407 else if (fromInst.plfreq == 24000)
408 {
409 if (fromInst.pacsize == 640)
410 {
411 toInst.pacsize = 480;
412 }
413 else if (fromInst.pacsize == 1280)
414 {
415 toInst.pacsize = 960;
416 }
417 else if (fromInst.pacsize == 1920)
418 {
419 toInst.pacsize = 1440;
420 }
421 }
422 }
423}
424
425void VoECodecImpl::ExternalToACMCodecRepresentation(CodecInst& toInst,
426 const CodecInst& fromInst)
427{
428 toInst = fromInst;
429 if (STR_CASE_CMP(fromInst.plname,"SILK") == 0)
430 {
431 if (fromInst.plfreq == 12000)
432 {
433 if (fromInst.pacsize == 240)
434 {
435 toInst.pacsize = 320;
436 }
437 else if (fromInst.pacsize == 480)
438 {
439 toInst.pacsize = 640;
440 }
441 else if (fromInst.pacsize == 720)
442 {
443 toInst.pacsize = 960;
444 }
445 }
446 else if (fromInst.plfreq == 24000)
447 {
448 if (fromInst.pacsize == 480)
449 {
450 toInst.pacsize = 640;
451 }
452 else if (fromInst.pacsize == 960)
453 {
454 toInst.pacsize = 1280;
455 }
456 else if (fromInst.pacsize == 1440)
457 {
458 toInst.pacsize = 1920;
459 }
460 }
461 }
462}
463
turaj@webrtc.org42259e72012-12-11 02:15:12 +0000464int VoECodecImpl::SetSecondarySendCodec(int channel, const CodecInst& codec,
465 int red_payload_type) {
466 CodecInst copy_codec;
467 ExternalToACMCodecRepresentation(copy_codec, codec);
468
469 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
470 "SetSecondarySendCodec(channel=%d, codec)", channel);
471 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
472 "codec: plname=%s, pacsize=%d, plfreq=%d, pltype=%d, "
473 "channels=%d, rate=%d", codec.plname, codec.pacsize,
474 codec.plfreq, codec.pltype, codec.channels, codec.rate);
475 if (!_shared->statistics().Initialized()) {
476 _shared->SetLastError(VE_NOT_INITED, kTraceError);
477 return -1;
478 }
479
480 // External sanity checks performed outside the ACM
481 if ((STR_CASE_CMP(copy_codec.plname, "L16") == 0) &&
482 (copy_codec.pacsize >= 960)) {
483 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
484 "SetSecondarySendCodec() invalid L16 packet size");
485 return -1;
486 }
487
488 // None of the following codecs can be registered as the secondary encoder.
489 if (!STR_CASE_CMP(copy_codec.plname, "CN") ||
490 !STR_CASE_CMP(copy_codec.plname, "TELEPHONE-EVENT") ||
491 !STR_CASE_CMP(copy_codec.plname, "RED")) {
492 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
493 "SetSecondarySendCodec() invalid codec name");
494 return -1;
495 }
496
497 // Only mono and stereo are supported.
498 if ((copy_codec.channels != 1) && (copy_codec.channels != 2)) {
499 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
500 "SetSecondarySendCodec() invalid number of channels");
501 return -1;
502 }
pbos@webrtc.org676ff1e2013-08-07 17:57:36 +0000503 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
504 voe::Channel* channelPtr = ch.channel();
turaj@webrtc.org42259e72012-12-11 02:15:12 +0000505 if (channelPtr == NULL) {
506 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
507 "SetSecondarySendCodec() failed to locate channel");
508 return -1;
509 }
510 if (!AudioCodingModule::IsCodecValid(copy_codec)) {
511 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
512 "SetSecondarySendCodec() invalid codec");
513 return -1;
514 }
515 if (channelPtr->SetSecondarySendCodec(copy_codec, red_payload_type) != 0) {
516 _shared->SetLastError(VE_CANNOT_SET_SECONDARY_SEND_CODEC, kTraceError,
517 "SetSecondarySendCodec() failed to set secondary "
518 "send codec");
519 return -1;
520 }
521 return 0;
522}
523
524int VoECodecImpl::GetSecondarySendCodec(int channel, CodecInst& codec) {
525 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
526 "GetSecondarySendCodec(channel=%d, codec=?)", channel);
527 if (!_shared->statistics().Initialized()) {
528 _shared->SetLastError(VE_NOT_INITED, kTraceError);
529 return -1;
530 }
pbos@webrtc.org676ff1e2013-08-07 17:57:36 +0000531 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
532 voe::Channel* channelPtr = ch.channel();
turaj@webrtc.org42259e72012-12-11 02:15:12 +0000533 if (channelPtr == NULL) {
534 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
535 "GetSecondarySendCodec() failed to locate channel");
536 return -1;
537 }
538 CodecInst acm_codec;
539 if (channelPtr->GetSecondarySendCodec(&acm_codec) != 0) {
540 _shared->SetLastError(VE_CANNOT_GET_SECONDARY_SEND_CODEC, kTraceError,
541 "GetSecondarySendCodec() failed to get secondary "
542 "send codec");
543 return -1;
544 }
545 ACMToExternalCodecRepresentation(codec, acm_codec);
546 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
547 VoEId(_shared->instance_id(), -1),
548 "GetSecondarySendCodec() => plname=%s, pacsize=%d, plfreq=%d, "
549 "channels=%d, rate=%d", codec.plname, codec.pacsize,
550 codec.plfreq, codec.channels, codec.rate);
551 return 0;
552}
553
554int VoECodecImpl::RemoveSecondarySendCodec(int channel) {
555 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
556 "RemoveSecondarySendCodec(channel=%d)", channel);
pbos@webrtc.org676ff1e2013-08-07 17:57:36 +0000557 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
558 voe::Channel* channelPtr = ch.channel();
turaj@webrtc.org42259e72012-12-11 02:15:12 +0000559 if (channelPtr == NULL) {
560 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
561 "RemoveSecondarySendCodec() failed to locate "
562 "channel");
563 return -1;
564 }
565 channelPtr->RemoveSecondarySendCodec();
566 return 0;
567}
568
niklase@google.com470e71d2011-07-07 08:21:25 +0000569#endif // WEBRTC_VOICE_ENGINE_CODEC_API
570
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000571} // namespace webrtc