blob: 162f1c2efb9bc7fc0253ea52232137a74903dc4d [file] [log] [blame]
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/voice_engine/voe_codec_impl.h"
#include "webrtc/modules/audio_coding/include/audio_coding_module.h"
#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
#include "webrtc/system_wrappers/include/trace.h"
#include "webrtc/voice_engine/channel.h"
#include "webrtc/voice_engine/include/voe_errors.h"
#include "webrtc/voice_engine/voice_engine_impl.h"
namespace webrtc {
VoECodec* VoECodec::GetInterface(VoiceEngine* voiceEngine) {
#ifndef WEBRTC_VOICE_ENGINE_CODEC_API
return NULL;
#else
if (NULL == voiceEngine) {
return NULL;
}
VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
s->AddRef();
return s;
#endif
}
#ifdef WEBRTC_VOICE_ENGINE_CODEC_API
VoECodecImpl::VoECodecImpl(voe::SharedData* shared) : _shared(shared) {
WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
"VoECodecImpl() - ctor");
}
VoECodecImpl::~VoECodecImpl() {
WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
"~VoECodecImpl() - dtor");
}
int VoECodecImpl::NumOfCodecs() {
// Number of supported codecs in the ACM
uint8_t nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
return (nSupportedCodecs);
}
int VoECodecImpl::GetCodec(int index, CodecInst& codec) {
if (AudioCodingModule::Codec(index, &codec) == -1) {
_shared->SetLastError(VE_INVALID_LISTNR, kTraceError,
"GetCodec() invalid index");
return -1;
}
return 0;
}
int VoECodecImpl::SetSendCodec(int channel, const CodecInst& codec) {
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"SetSendCodec(channel=%d, codec)", channel);
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
"codec: plname=%s, pacsize=%d, plfreq=%d, pltype=%d, "
"channels=%d, rate=%d",
codec.plname, codec.pacsize, codec.plfreq, codec.pltype,
codec.channels, codec.rate);
if (!_shared->statistics().Initialized()) {
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
// External sanity checks performed outside the ACM
if ((STR_CASE_CMP(codec.plname, "L16") == 0) && (codec.pacsize >= 960)) {
_shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
"SetSendCodec() invalid L16 packet size");
return -1;
}
if (!STR_CASE_CMP(codec.plname, "CN") ||
!STR_CASE_CMP(codec.plname, "TELEPHONE-EVENT") ||
!STR_CASE_CMP(codec.plname, "RED")) {
_shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
"SetSendCodec() invalid codec name");
return -1;
}
if ((codec.channels != 1) && (codec.channels != 2)) {
_shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
"SetSendCodec() invalid number of channels");
return -1;
}
voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
voe::Channel* channelPtr = ch.channel();
if (channelPtr == NULL) {
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"GetSendCodec() failed to locate channel");
return -1;
}
if (!AudioCodingModule::IsCodecValid(codec)) {
_shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
"SetSendCodec() invalid codec");
return -1;
}
if (channelPtr->SetSendCodec(codec) != 0) {
_shared->SetLastError(VE_CANNOT_SET_SEND_CODEC, kTraceError,
"SetSendCodec() failed to set send codec");
return -1;
}
return 0;
}
int VoECodecImpl::GetSendCodec(int channel, CodecInst& codec) {
if (!_shared->statistics().Initialized()) {
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
voe::Channel* channelPtr = ch.channel();
if (channelPtr == NULL) {
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"GetSendCodec() failed to locate channel");
return -1;
}
if (channelPtr->GetSendCodec(codec) != 0) {
_shared->SetLastError(VE_CANNOT_GET_SEND_CODEC, kTraceError,
"GetSendCodec() failed to get send codec");
return -1;
}
return 0;
}
int VoECodecImpl::SetBitRate(int channel, int bitrate_bps) {
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"SetBitRate(bitrate_bps=%d)", bitrate_bps);
if (!_shared->statistics().Initialized()) {
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
_shared->channel_manager().GetChannel(channel).channel()->SetBitRate(
bitrate_bps);
return 0;
}
int VoECodecImpl::GetRecCodec(int channel, CodecInst& codec) {
if (!_shared->statistics().Initialized()) {
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
voe::Channel* channelPtr = ch.channel();
if (channelPtr == NULL) {
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"GetRecCodec() failed to locate channel");
return -1;
}
return channelPtr->GetRecCodec(codec);
}
int VoECodecImpl::SetRecPayloadType(int channel, const CodecInst& codec) {
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"SetRecPayloadType(channel=%d, codec)", channel);
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
"codec: plname=%s, plfreq=%d, pltype=%d, channels=%u, "
"pacsize=%d, rate=%d",
codec.plname, codec.plfreq, codec.pltype, codec.channels,
codec.pacsize, codec.rate);
if (!_shared->statistics().Initialized()) {
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
voe::Channel* channelPtr = ch.channel();
if (channelPtr == NULL) {
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"GetRecPayloadType() failed to locate channel");
return -1;
}
return channelPtr->SetRecPayloadType(codec);
}
int VoECodecImpl::GetRecPayloadType(int channel, CodecInst& codec) {
if (!_shared->statistics().Initialized()) {
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
voe::Channel* channelPtr = ch.channel();
if (channelPtr == NULL) {
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"GetRecPayloadType() failed to locate channel");
return -1;
}
return channelPtr->GetRecPayloadType(codec);
}
int VoECodecImpl::SetSendCNPayloadType(int channel,
int type,
PayloadFrequencies frequency) {
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"SetSendCNPayloadType(channel=%d, type=%d, frequency=%d)",
channel, type, frequency);
if (!_shared->statistics().Initialized()) {
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
if (type < 96 || type > 127) {
// Only allow dynamic range: 96 to 127
_shared->SetLastError(VE_INVALID_PLTYPE, kTraceError,
"SetSendCNPayloadType() invalid payload type");
return -1;
}
if ((frequency != kFreq16000Hz) && (frequency != kFreq32000Hz)) {
// It is not possible to modify the payload type for CN/8000.
// We only allow modification of the CN payload type for CN/16000
// and CN/32000.
_shared->SetLastError(VE_INVALID_PLFREQ, kTraceError,
"SetSendCNPayloadType() invalid payload frequency");
return -1;
}
voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
voe::Channel* channelPtr = ch.channel();
if (channelPtr == NULL) {
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"SetSendCNPayloadType() failed to locate channel");
return -1;
}
return channelPtr->SetSendCNPayloadType(type, frequency);
}
int VoECodecImpl::SetFECStatus(int channel, bool enable) {
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"SetCodecFECStatus(channel=%d, enable=%d)", channel, enable);
if (!_shared->statistics().Initialized()) {
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
voe::Channel* channelPtr = ch.channel();
if (channelPtr == NULL) {
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"SetCodecFECStatus() failed to locate channel");
return -1;
}
return channelPtr->SetCodecFECStatus(enable);
}
int VoECodecImpl::GetFECStatus(int channel, bool& enabled) {
if (!_shared->statistics().Initialized()) {
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
voe::Channel* channelPtr = ch.channel();
if (channelPtr == NULL) {
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"GetFECStatus() failed to locate channel");
return -1;
}
enabled = channelPtr->GetCodecFECStatus();
return 0;
}
int VoECodecImpl::SetVADStatus(int channel,
bool enable,
VadModes mode,
bool disableDTX) {
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"SetVADStatus(channel=%i, enable=%i, mode=%i, disableDTX=%i)",
channel, enable, mode, disableDTX);
if (!_shared->statistics().Initialized()) {
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
voe::Channel* channelPtr = ch.channel();
if (channelPtr == NULL) {
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"SetVADStatus failed to locate channel");
return -1;
}
ACMVADMode vadMode(VADNormal);
switch (mode) {
case kVadConventional:
vadMode = VADNormal;
break;
case kVadAggressiveLow:
vadMode = VADLowBitrate;
break;
case kVadAggressiveMid:
vadMode = VADAggr;
break;
case kVadAggressiveHigh:
vadMode = VADVeryAggr;
break;
}
return channelPtr->SetVADStatus(enable, vadMode, disableDTX);
}
int VoECodecImpl::GetVADStatus(int channel,
bool& enabled,
VadModes& mode,
bool& disabledDTX) {
if (!_shared->statistics().Initialized()) {
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
voe::Channel* channelPtr = ch.channel();
if (channelPtr == NULL) {
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"GetVADStatus failed to locate channel");
return -1;
}
ACMVADMode vadMode;
int ret = channelPtr->GetVADStatus(enabled, vadMode, disabledDTX);
if (ret != 0) {
_shared->SetLastError(VE_INVALID_OPERATION, kTraceError,
"GetVADStatus failed to get VAD mode");
return -1;
}
switch (vadMode) {
case VADNormal:
mode = kVadConventional;
break;
case VADLowBitrate:
mode = kVadAggressiveLow;
break;
case VADAggr:
mode = kVadAggressiveMid;
break;
case VADVeryAggr:
mode = kVadAggressiveHigh;
break;
}
return 0;
}
int VoECodecImpl::SetOpusMaxPlaybackRate(int channel, int frequency_hz) {
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"SetOpusMaxPlaybackRate(channel=%d, frequency_hz=%d)", channel,
frequency_hz);
if (!_shared->statistics().Initialized()) {
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
voe::Channel* channelPtr = ch.channel();
if (channelPtr == NULL) {
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"SetOpusMaxPlaybackRate failed to locate channel");
return -1;
}
return channelPtr->SetOpusMaxPlaybackRate(frequency_hz);
}
int VoECodecImpl::SetOpusDtx(int channel, bool enable_dtx) {
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"SetOpusDtx(channel=%d, enable_dtx=%d)", channel, enable_dtx);
if (!_shared->statistics().Initialized()) {
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
voe::Channel* channelPtr = ch.channel();
if (channelPtr == NULL) {
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"SetOpusDtx failed to locate channel");
return -1;
}
return channelPtr->SetOpusDtx(enable_dtx);
}
RtcEventLog* VoECodecImpl::GetEventLog() {
return _shared->channel_manager().GetEventLog();
}
#endif // WEBRTC_VOICE_ENGINE_CODEC_API
} // namespace webrtc