1 /*
2 * Copyright (c) 2012 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
11 #include "webrtc/voice_engine/voe_codec_impl.h"
12
13 #include "webrtc/base/format_macros.h"
14 #include "webrtc/modules/audio_coding/include/audio_coding_module.h"
15 #include "webrtc/system_wrappers/include/critical_section_wrapper.h"
16 #include "webrtc/system_wrappers/include/trace.h"
17 #include "webrtc/voice_engine/channel.h"
18 #include "webrtc/voice_engine/include/voe_errors.h"
19 #include "webrtc/voice_engine/voice_engine_impl.h"
20
21 namespace webrtc {
22
GetInterface(VoiceEngine * voiceEngine)23 VoECodec* VoECodec::GetInterface(VoiceEngine* voiceEngine) {
24 #ifndef WEBRTC_VOICE_ENGINE_CODEC_API
25 return NULL;
26 #else
27 if (NULL == voiceEngine) {
28 return NULL;
29 }
30 VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
31 s->AddRef();
32 return s;
33 #endif
34 }
35
36 #ifdef WEBRTC_VOICE_ENGINE_CODEC_API
37
VoECodecImpl(voe::SharedData * shared)38 VoECodecImpl::VoECodecImpl(voe::SharedData* shared) : _shared(shared) {
39 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
40 "VoECodecImpl() - ctor");
41 }
42
~VoECodecImpl()43 VoECodecImpl::~VoECodecImpl() {
44 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
45 "~VoECodecImpl() - dtor");
46 }
47
NumOfCodecs()48 int VoECodecImpl::NumOfCodecs() {
49 // Number of supported codecs in the ACM
50 uint8_t nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
51 return (nSupportedCodecs);
52 }
53
GetCodec(int index,CodecInst & codec)54 int VoECodecImpl::GetCodec(int index, CodecInst& codec) {
55 if (AudioCodingModule::Codec(index, &codec) == -1) {
56 _shared->SetLastError(VE_INVALID_LISTNR, kTraceError,
57 "GetCodec() invalid index");
58 return -1;
59 }
60 return 0;
61 }
62
SetSendCodec(int channel,const CodecInst & codec)63 int VoECodecImpl::SetSendCodec(int channel, const CodecInst& codec) {
64 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
65 "SetSendCodec(channel=%d, codec)", channel);
66 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
67 "codec: plname=%s, pacsize=%d, plfreq=%d, pltype=%d, "
68 "channels=%" PRIuS ", rate=%d",
69 codec.plname, codec.pacsize, codec.plfreq, codec.pltype,
70 codec.channels, codec.rate);
71 if (!_shared->statistics().Initialized()) {
72 _shared->SetLastError(VE_NOT_INITED, kTraceError);
73 return -1;
74 }
75 // External sanity checks performed outside the ACM
76 if ((STR_CASE_CMP(codec.plname, "L16") == 0) && (codec.pacsize >= 960)) {
77 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
78 "SetSendCodec() invalid L16 packet size");
79 return -1;
80 }
81 if (!STR_CASE_CMP(codec.plname, "CN") ||
82 !STR_CASE_CMP(codec.plname, "TELEPHONE-EVENT") ||
83 !STR_CASE_CMP(codec.plname, "RED")) {
84 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
85 "SetSendCodec() invalid codec name");
86 return -1;
87 }
88 if ((codec.channels != 1) && (codec.channels != 2)) {
89 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
90 "SetSendCodec() invalid number of channels");
91 return -1;
92 }
93 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
94 voe::Channel* channelPtr = ch.channel();
95 if (channelPtr == NULL) {
96 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
97 "GetSendCodec() failed to locate channel");
98 return -1;
99 }
100 if (!AudioCodingModule::IsCodecValid(codec)) {
101 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
102 "SetSendCodec() invalid codec");
103 return -1;
104 }
105 if (channelPtr->SetSendCodec(codec) != 0) {
106 _shared->SetLastError(VE_CANNOT_SET_SEND_CODEC, kTraceError,
107 "SetSendCodec() failed to set send codec");
108 return -1;
109 }
110
111 return 0;
112 }
113
GetSendCodec(int channel,CodecInst & codec)114 int VoECodecImpl::GetSendCodec(int channel, CodecInst& codec) {
115 if (!_shared->statistics().Initialized()) {
116 _shared->SetLastError(VE_NOT_INITED, kTraceError);
117 return -1;
118 }
119 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
120 voe::Channel* channelPtr = ch.channel();
121 if (channelPtr == NULL) {
122 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
123 "GetSendCodec() failed to locate channel");
124 return -1;
125 }
126 if (channelPtr->GetSendCodec(codec) != 0) {
127 _shared->SetLastError(VE_CANNOT_GET_SEND_CODEC, kTraceError,
128 "GetSendCodec() failed to get send codec");
129 return -1;
130 }
131 return 0;
132 }
133
SetBitRate(int channel,int bitrate_bps)134 int VoECodecImpl::SetBitRate(int channel, int bitrate_bps) {
135 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
136 "SetBitRate(bitrate_bps=%d)", bitrate_bps);
137 if (!_shared->statistics().Initialized()) {
138 _shared->SetLastError(VE_NOT_INITED, kTraceError);
139 return -1;
140 }
141 _shared->channel_manager().GetChannel(channel).channel()->SetBitRate(
142 bitrate_bps);
143 return 0;
144 }
145
GetRecCodec(int channel,CodecInst & codec)146 int VoECodecImpl::GetRecCodec(int channel, CodecInst& codec) {
147 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 }
158 return channelPtr->GetRecCodec(codec);
159 }
160
SetRecPayloadType(int channel,const CodecInst & codec)161 int 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),
165 "codec: plname=%s, plfreq=%d, pltype=%d, channels=%" PRIuS ", "
166 "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);
181 }
182
GetRecPayloadType(int channel,CodecInst & codec)183 int VoECodecImpl::GetRecPayloadType(int channel, CodecInst& codec) {
184 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);
196 }
197
SetSendCNPayloadType(int channel,int type,PayloadFrequencies frequency)198 int 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);
230 }
231
SetFECStatus(int channel,bool enable)232 int 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
GetFECStatus(int channel,bool & enabled)249 int VoECodecImpl::GetFECStatus(int channel, bool& enabled) {
250 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
SetVADStatus(int channel,bool enable,VadModes mode,bool disableDTX)265 int 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);
272
273 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 }
284
285 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);
301 }
302
GetVADStatus(int channel,bool & enabled,VadModes & mode,bool & disabledDTX)303 int VoECodecImpl::GetVADStatus(int channel,
304 bool& enabled,
305 VadModes& mode,
306 bool& disabledDTX) {
307 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 }
318
319 ACMVADMode vadMode;
320 int ret = channelPtr->GetVADStatus(enabled, vadMode, disabledDTX);
321
322 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 }
341
342 return 0;
343 }
344
SetOpusMaxPlaybackRate(int channel,int frequency_hz)345 int VoECodecImpl::SetOpusMaxPlaybackRate(int channel, int frequency_hz) {
346 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
347 "SetOpusMaxPlaybackRate(channel=%d, frequency_hz=%d)", channel,
348 frequency_hz);
349 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,
357 "SetOpusMaxPlaybackRate failed to locate channel");
358 return -1;
359 }
360 return channelPtr->SetOpusMaxPlaybackRate(frequency_hz);
361 }
362
SetOpusDtx(int channel,bool enable_dtx)363 int 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
GetEventLog()380 RtcEventLog* VoECodecImpl::GetEventLog() {
381 return _shared->channel_manager().GetEventLog();
382 }
383
384 #endif // WEBRTC_VOICE_ENGINE_CODEC_API
385
386 } // namespace webrtc
387