2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
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.
11 #include "webrtc/voice_engine/voe_codec_impl.h"
13 #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"
23 VoECodec* VoECodec::GetInterface(VoiceEngine* voiceEngine)
25 #ifndef WEBRTC_VOICE_ENGINE_CODEC_API
28 if (NULL == voiceEngine)
32 VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
38 #ifdef WEBRTC_VOICE_ENGINE_CODEC_API
40 VoECodecImpl::VoECodecImpl(voe::SharedData* shared) : _shared(shared)
42 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
43 "VoECodecImpl() - ctor");
46 VoECodecImpl::~VoECodecImpl()
48 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
49 "~VoECodecImpl() - dtor");
52 int VoECodecImpl::NumOfCodecs()
54 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
57 // Number of supported codecs in the ACM
58 uint8_t nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
60 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
61 VoEId(_shared->instance_id(), -1),
62 "NumOfCodecs() => %u", nSupportedCodecs);
63 return (nSupportedCodecs);
66 int VoECodecImpl::GetCodec(int index, CodecInst& codec)
68 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
69 "GetCodec(index=%d, codec=?)", index);
71 if (AudioCodingModule::Codec(index, &acmCodec)
74 _shared->SetLastError(VE_INVALID_LISTNR, kTraceError,
75 "GetCodec() invalid index");
78 ACMToExternalCodecRepresentation(codec, acmCodec);
79 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);
87 int VoECodecImpl::SetSendCodec(int channel, const CodecInst& codec)
90 ExternalToACMCodecRepresentation(copyCodec, codec);
92 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
93 "SetSendCodec(channel=%d, codec)", channel);
94 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
95 "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);
98 if (!_shared->statistics().Initialized())
100 _shared->SetLastError(VE_NOT_INITED, kTraceError);
103 // External sanity checks performed outside the ACM
104 if ((STR_CASE_CMP(copyCodec.plname, "L16") == 0) &&
105 (copyCodec.pacsize >= 960))
107 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
108 "SetSendCodec() invalid L16 packet size");
111 if (!STR_CASE_CMP(copyCodec.plname, "CN")
112 || !STR_CASE_CMP(copyCodec.plname, "TELEPHONE-EVENT")
113 || !STR_CASE_CMP(copyCodec.plname, "RED"))
115 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
116 "SetSendCodec() invalid codec name");
119 if ((copyCodec.channels != 1) && (copyCodec.channels != 2))
121 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
122 "SetSendCodec() invalid number of channels");
125 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
126 voe::Channel* channelPtr = ch.channel();
127 if (channelPtr == NULL)
129 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
130 "GetSendCodec() failed to locate channel");
133 if (!AudioCodingModule::IsCodecValid(
134 (CodecInst&) copyCodec))
136 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
137 "SetSendCodec() invalid codec");
140 if (channelPtr->SetSendCodec(copyCodec) != 0)
142 _shared->SetLastError(VE_CANNOT_SET_SEND_CODEC, kTraceError,
143 "SetSendCodec() failed to set send codec");
150 int VoECodecImpl::GetSendCodec(int channel, CodecInst& codec)
152 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
153 "GetSendCodec(channel=%d, codec=?)", channel);
154 if (!_shared->statistics().Initialized())
156 _shared->SetLastError(VE_NOT_INITED, kTraceError);
159 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
160 voe::Channel* channelPtr = ch.channel();
161 if (channelPtr == NULL)
163 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
164 "GetSendCodec() failed to locate channel");
168 if (channelPtr->GetSendCodec(acmCodec) != 0)
170 _shared->SetLastError(VE_CANNOT_GET_SEND_CODEC, kTraceError,
171 "GetSendCodec() failed to get send codec");
174 ACMToExternalCodecRepresentation(codec, acmCodec);
175 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);
183 int VoECodecImpl::GetRecCodec(int channel, CodecInst& codec)
185 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
186 "GetRecCodec(channel=%d, codec=?)", channel);
187 if (!_shared->statistics().Initialized())
189 _shared->SetLastError(VE_NOT_INITED, kTraceError);
192 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
193 voe::Channel* channelPtr = ch.channel();
194 if (channelPtr == NULL)
196 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
197 "GetRecCodec() failed to locate channel");
201 if (channelPtr->GetRecCodec(acmCodec) != 0)
203 _shared->SetLastError(VE_CANNOT_GET_REC_CODEC, kTraceError,
204 "GetRecCodec() failed to get received codec");
207 ACMToExternalCodecRepresentation(codec, acmCodec);
208 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);
216 int VoECodecImpl::SetRecPayloadType(int channel, const CodecInst& codec)
218 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
219 "SetRecPayloadType(channel=%d, codec)", channel);
220 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
221 "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);
224 if (!_shared->statistics().Initialized())
226 _shared->SetLastError(VE_NOT_INITED, kTraceError);
229 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
230 voe::Channel* channelPtr = ch.channel();
231 if (channelPtr == NULL)
233 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
234 "GetRecPayloadType() failed to locate channel");
237 return channelPtr->SetRecPayloadType(codec);
240 int VoECodecImpl::GetRecPayloadType(int channel, CodecInst& codec)
242 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
243 "GetRecPayloadType(channel=%d, codec)", channel);
244 if (!_shared->statistics().Initialized())
246 _shared->SetLastError(VE_NOT_INITED, kTraceError);
249 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
250 voe::Channel* channelPtr = ch.channel();
251 if (channelPtr == NULL)
253 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
254 "GetRecPayloadType() failed to locate channel");
257 return channelPtr->GetRecPayloadType(codec);
260 int VoECodecImpl::SetSendCNPayloadType(int channel, int type,
261 PayloadFrequencies frequency)
263 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
264 "SetSendCNPayloadType(channel=%d, type=%d, frequency=%d)",
265 channel, type, frequency);
266 if (!_shared->statistics().Initialized())
268 _shared->SetLastError(VE_NOT_INITED, kTraceError);
271 if (type < 96 || type > 127)
273 // Only allow dynamic range: 96 to 127
274 _shared->SetLastError(VE_INVALID_PLTYPE, kTraceError,
275 "SetSendCNPayloadType() invalid payload type");
278 if ((frequency != kFreq16000Hz) && (frequency != kFreq32000Hz))
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
283 _shared->SetLastError(VE_INVALID_PLFREQ, kTraceError,
284 "SetSendCNPayloadType() invalid payload frequency");
287 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
288 voe::Channel* channelPtr = ch.channel();
289 if (channelPtr == NULL)
291 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
292 "SetSendCNPayloadType() failed to locate channel");
295 return channelPtr->SetSendCNPayloadType(type, frequency);
298 int VoECodecImpl::SetFECStatus(int channel, bool enable) {
299 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
300 "SetCodecFECStatus(channel=%d, enable=%d)", channel, enable);
301 if (!_shared->statistics().Initialized()) {
302 _shared->SetLastError(VE_NOT_INITED, kTraceError);
305 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
306 voe::Channel* channelPtr = ch.channel();
307 if (channelPtr == NULL) {
308 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
309 "SetCodecFECStatus() failed to locate channel");
312 return channelPtr->SetCodecFECStatus(enable);
315 int VoECodecImpl::GetFECStatus(int channel, bool& enabled) {
316 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
317 "GetCodecFECStatus(channel=%d)", channel);
318 if (!_shared->statistics().Initialized()) {
319 _shared->SetLastError(VE_NOT_INITED, kTraceError);
322 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
323 voe::Channel* channelPtr = ch.channel();
324 if (channelPtr == NULL) {
325 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
326 "GetFECStatus() failed to locate channel");
329 enabled = channelPtr->GetCodecFECStatus();
333 int VoECodecImpl::SetVADStatus(int channel, bool enable, VadModes mode,
336 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
337 "SetVADStatus(channel=%i, enable=%i, mode=%i, disableDTX=%i)",
338 channel, enable, mode, disableDTX);
340 if (!_shared->statistics().Initialized())
342 _shared->SetLastError(VE_NOT_INITED, kTraceError);
345 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
346 voe::Channel* channelPtr = ch.channel();
347 if (channelPtr == NULL)
349 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
350 "SetVADStatus failed to locate channel");
354 ACMVADMode vadMode(VADNormal);
357 case kVadConventional:
360 case kVadAggressiveLow:
361 vadMode = VADLowBitrate;
363 case kVadAggressiveMid:
366 case kVadAggressiveHigh:
367 vadMode = VADVeryAggr;
370 return channelPtr->SetVADStatus(enable, vadMode, disableDTX);
373 int VoECodecImpl::GetVADStatus(int channel, bool& enabled, VadModes& mode,
376 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
377 "GetVADStatus(channel=%i)", channel);
379 if (!_shared->statistics().Initialized())
381 _shared->SetLastError(VE_NOT_INITED, kTraceError);
384 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
385 voe::Channel* channelPtr = ch.channel();
386 if (channelPtr == NULL)
388 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
389 "GetVADStatus failed to locate channel");
394 int ret = channelPtr->GetVADStatus(enabled, vadMode, disabledDTX);
398 _shared->SetLastError(VE_INVALID_OPERATION, kTraceError,
399 "GetVADStatus failed to get VAD mode");
405 mode = kVadConventional;
408 mode = kVadAggressiveLow;
411 mode = kVadAggressiveMid;
414 mode = kVadAggressiveHigh;
421 int VoECodecImpl::SetOpusMaxBandwidth(int channel, int bandwidth_hz) {
422 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
423 "SetOpusMaxBandwidth(channel=%d, bandwidth_hz=%d)", channel,
425 if (!_shared->statistics().Initialized()) {
426 _shared->SetLastError(VE_NOT_INITED, kTraceError);
429 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
430 voe::Channel* channelPtr = ch.channel();
431 if (channelPtr == NULL) {
432 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
433 "SetOpusMaxBandwidth failed to locate channel");
436 return channelPtr->SetOpusMaxBandwidth(bandwidth_hz);
439 void VoECodecImpl::ACMToExternalCodecRepresentation(CodecInst& toInst,
440 const CodecInst& fromInst)
443 if (STR_CASE_CMP(fromInst.plname,"SILK") == 0)
445 if (fromInst.plfreq == 12000)
447 if (fromInst.pacsize == 320)
449 toInst.pacsize = 240;
451 else if (fromInst.pacsize == 640)
453 toInst.pacsize = 480;
455 else if (fromInst.pacsize == 960)
457 toInst.pacsize = 720;
460 else if (fromInst.plfreq == 24000)
462 if (fromInst.pacsize == 640)
464 toInst.pacsize = 480;
466 else if (fromInst.pacsize == 1280)
468 toInst.pacsize = 960;
470 else if (fromInst.pacsize == 1920)
472 toInst.pacsize = 1440;
478 void VoECodecImpl::ExternalToACMCodecRepresentation(CodecInst& toInst,
479 const CodecInst& fromInst)
482 if (STR_CASE_CMP(fromInst.plname,"SILK") == 0)
484 if (fromInst.plfreq == 12000)
486 if (fromInst.pacsize == 240)
488 toInst.pacsize = 320;
490 else if (fromInst.pacsize == 480)
492 toInst.pacsize = 640;
494 else if (fromInst.pacsize == 720)
496 toInst.pacsize = 960;
499 else if (fromInst.plfreq == 24000)
501 if (fromInst.pacsize == 480)
503 toInst.pacsize = 640;
505 else if (fromInst.pacsize == 960)
507 toInst.pacsize = 1280;
509 else if (fromInst.pacsize == 1440)
511 toInst.pacsize = 1920;
517 int VoECodecImpl::SetSecondarySendCodec(int channel, const CodecInst& codec,
518 int red_payload_type) {
519 CodecInst copy_codec;
520 ExternalToACMCodecRepresentation(copy_codec, codec);
522 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
523 "SetSecondarySendCodec(channel=%d, codec)", channel);
524 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
525 "codec: plname=%s, pacsize=%d, plfreq=%d, pltype=%d, "
526 "channels=%d, rate=%d", codec.plname, codec.pacsize,
527 codec.plfreq, codec.pltype, codec.channels, codec.rate);
528 if (!_shared->statistics().Initialized()) {
529 _shared->SetLastError(VE_NOT_INITED, kTraceError);
533 // External sanity checks performed outside the ACM
534 if ((STR_CASE_CMP(copy_codec.plname, "L16") == 0) &&
535 (copy_codec.pacsize >= 960)) {
536 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
537 "SetSecondarySendCodec() invalid L16 packet size");
541 // None of the following codecs can be registered as the secondary encoder.
542 if (!STR_CASE_CMP(copy_codec.plname, "CN") ||
543 !STR_CASE_CMP(copy_codec.plname, "TELEPHONE-EVENT") ||
544 !STR_CASE_CMP(copy_codec.plname, "RED")) {
545 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
546 "SetSecondarySendCodec() invalid codec name");
550 // Only mono and stereo are supported.
551 if ((copy_codec.channels != 1) && (copy_codec.channels != 2)) {
552 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
553 "SetSecondarySendCodec() invalid number of channels");
556 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
557 voe::Channel* channelPtr = ch.channel();
558 if (channelPtr == NULL) {
559 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
560 "SetSecondarySendCodec() failed to locate channel");
563 if (!AudioCodingModule::IsCodecValid(copy_codec)) {
564 _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
565 "SetSecondarySendCodec() invalid codec");
568 if (channelPtr->SetSecondarySendCodec(copy_codec, red_payload_type) != 0) {
569 _shared->SetLastError(VE_CANNOT_SET_SECONDARY_SEND_CODEC, kTraceError,
570 "SetSecondarySendCodec() failed to set secondary "
577 int VoECodecImpl::GetSecondarySendCodec(int channel, CodecInst& codec) {
578 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
579 "GetSecondarySendCodec(channel=%d, codec=?)", channel);
580 if (!_shared->statistics().Initialized()) {
581 _shared->SetLastError(VE_NOT_INITED, kTraceError);
584 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
585 voe::Channel* channelPtr = ch.channel();
586 if (channelPtr == NULL) {
587 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
588 "GetSecondarySendCodec() failed to locate channel");
592 if (channelPtr->GetSecondarySendCodec(&acm_codec) != 0) {
593 _shared->SetLastError(VE_CANNOT_GET_SECONDARY_SEND_CODEC, kTraceError,
594 "GetSecondarySendCodec() failed to get secondary "
598 ACMToExternalCodecRepresentation(codec, acm_codec);
599 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
600 VoEId(_shared->instance_id(), -1),
601 "GetSecondarySendCodec() => plname=%s, pacsize=%d, plfreq=%d, "
602 "channels=%d, rate=%d", codec.plname, codec.pacsize,
603 codec.plfreq, codec.channels, codec.rate);
607 int VoECodecImpl::RemoveSecondarySendCodec(int channel) {
608 WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
609 "RemoveSecondarySendCodec(channel=%d)", channel);
610 voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
611 voe::Channel* channelPtr = ch.channel();
612 if (channelPtr == NULL) {
613 _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
614 "RemoveSecondarySendCodec() failed to locate "
618 channelPtr->RemoveSecondarySendCodec();
622 #endif // WEBRTC_VOICE_ENGINE_CODEC_API
624 } // namespace webrtc