386 lines
14 KiB
C++
386 lines
14 KiB
C++
|
/*
|
||
|
* 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/base/format_macros.h"
|
||
|
#include "webrtc/modules/audio_coding/include/audio_coding_module.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=%" PRIuS ", 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=%" PRIuS ", "
|
||
|
"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
|