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