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 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 38 VoECodecImpl::VoECodecImpl(voe::SharedData* shared) : _shared(shared) { 39 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1), 40 "VoECodecImpl() - ctor"); 41 } 42 43 VoECodecImpl::~VoECodecImpl() { 44 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1), 45 "~VoECodecImpl() - dtor"); 46 } 47 48 int VoECodecImpl::NumOfCodecs() { 49 // Number of supported codecs in the ACM 50 uint8_t nSupportedCodecs = AudioCodingModule::NumberOfCodecs(); 51 return (nSupportedCodecs); 52 } 53 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 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 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 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 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 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 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 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 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 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 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 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 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 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 380 RtcEventLog* VoECodecImpl::GetEventLog() { 381 return _shared->channel_manager().GetEventLog(); 382 } 383 384 #endif // WEBRTC_VOICE_ENGINE_CODEC_API 385 386 } // namespace webrtc 387