1470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/*
2c80d9d9361ac22bbd277e8377a2dba93479ebff8mflodman@webrtc.org *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *
4470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  Use of this source code is governed by a BSD-style license
5470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  that can be found in the LICENSE file in the root of the source
6470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  tree. An additional intellectual property rights grant can be found
7470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  in the file PATENTS.  All contributing project authors may
8470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  be found in the AUTHORS file in the root of the source tree.
9470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */
10470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
11956aa7e0874f2e08c335a82a2c32f400fac8b031pbos@webrtc.org#include "webrtc/voice_engine/voe_codec_impl.h"
12470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
136955870806624479723addfae6dcf5d13968796cPeter Kasting#include "webrtc/base/format_macros.h"
143e6db2321ccdc8738c9cecbe9bdab13d4f0f658dkjellander#include "webrtc/modules/audio_coding/include/audio_coding_module.h"
1598f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
1698f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/trace.h"
17956aa7e0874f2e08c335a82a2c32f400fac8b031pbos@webrtc.org#include "webrtc/voice_engine/channel.h"
18956aa7e0874f2e08c335a82a2c32f400fac8b031pbos@webrtc.org#include "webrtc/voice_engine/include/voe_errors.h"
19956aa7e0874f2e08c335a82a2c32f400fac8b031pbos@webrtc.org#include "webrtc/voice_engine/voice_engine_impl.h"
20470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
210d266054acece70259fc1e85026194154f41e5a0Jelena Marusicnamespace webrtc {
22470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
230d266054acece70259fc1e85026194154f41e5a0Jelena MarusicVoECodec* VoECodec::GetInterface(VoiceEngine* voiceEngine) {
24470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifndef WEBRTC_VOICE_ENGINE_CODEC_API
250d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  return NULL;
26470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#else
270d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (NULL == voiceEngine) {
280d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return NULL;
290d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
300d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
310d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  s->AddRef();
320d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  return s;
33470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif
34470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
35470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
36470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifdef WEBRTC_VOICE_ENGINE_CODEC_API
37470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
380d266054acece70259fc1e85026194154f41e5a0Jelena MarusicVoECodecImpl::VoECodecImpl(voe::SharedData* shared) : _shared(shared) {
390d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
400d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               "VoECodecImpl() - ctor");
41470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
42470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
430d266054acece70259fc1e85026194154f41e5a0Jelena MarusicVoECodecImpl::~VoECodecImpl() {
440d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
450d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               "~VoECodecImpl() - dtor");
46470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
47470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
480d266054acece70259fc1e85026194154f41e5a0Jelena Marusicint VoECodecImpl::NumOfCodecs() {
490d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  // Number of supported codecs in the ACM
500d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  uint8_t nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
510d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  return (nSupportedCodecs);
52470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
53470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
540d266054acece70259fc1e85026194154f41e5a0Jelena Marusicint VoECodecImpl::GetCodec(int index, CodecInst& codec) {
5512e21a0d6ce70b86ffafec10a5004ef2b1826dbakwiberg  if (AudioCodingModule::Codec(index, &codec) == -1) {
560d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_INVALID_LISTNR, kTraceError,
570d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                          "GetCodec() invalid index");
580d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
590d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
600d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  return 0;
61470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
62470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
630d266054acece70259fc1e85026194154f41e5a0Jelena Marusicint VoECodecImpl::SetSendCodec(int channel, const CodecInst& codec) {
640d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
650d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               "SetSendCodec(channel=%d, codec)", channel);
660d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
670d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               "codec: plname=%s, pacsize=%d, plfreq=%d, pltype=%d, "
686955870806624479723addfae6dcf5d13968796cPeter Kasting               "channels=%" PRIuS ", rate=%d",
690d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               codec.plname, codec.pacsize, codec.plfreq, codec.pltype,
700d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               codec.channels, codec.rate);
710d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (!_shared->statistics().Initialized()) {
720d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_NOT_INITED, kTraceError);
730d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
740d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
750d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  // External sanity checks performed outside the ACM
7612e21a0d6ce70b86ffafec10a5004ef2b1826dbakwiberg  if ((STR_CASE_CMP(codec.plname, "L16") == 0) && (codec.pacsize >= 960)) {
770d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
780d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                          "SetSendCodec() invalid L16 packet size");
790d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
800d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
8112e21a0d6ce70b86ffafec10a5004ef2b1826dbakwiberg  if (!STR_CASE_CMP(codec.plname, "CN") ||
8212e21a0d6ce70b86ffafec10a5004ef2b1826dbakwiberg      !STR_CASE_CMP(codec.plname, "TELEPHONE-EVENT") ||
8312e21a0d6ce70b86ffafec10a5004ef2b1826dbakwiberg      !STR_CASE_CMP(codec.plname, "RED")) {
840d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
850d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                          "SetSendCodec() invalid codec name");
860d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
870d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
8812e21a0d6ce70b86ffafec10a5004ef2b1826dbakwiberg  if ((codec.channels != 1) && (codec.channels != 2)) {
890d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
900d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                          "SetSendCodec() invalid number of channels");
910d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
920d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
930d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
940d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  voe::Channel* channelPtr = ch.channel();
950d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (channelPtr == NULL) {
960d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
970d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                          "GetSendCodec() failed to locate channel");
980d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
990d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
10012e21a0d6ce70b86ffafec10a5004ef2b1826dbakwiberg  if (!AudioCodingModule::IsCodecValid(codec)) {
1010d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
1020d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                          "SetSendCodec() invalid codec");
1030d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
1040d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
10512e21a0d6ce70b86ffafec10a5004ef2b1826dbakwiberg  if (channelPtr->SetSendCodec(codec) != 0) {
1060d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_CANNOT_SET_SEND_CODEC, kTraceError,
1070d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                          "SetSendCodec() failed to set send codec");
1080d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
1090d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
110470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1110d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  return 0;
112470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
113470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1140d266054acece70259fc1e85026194154f41e5a0Jelena Marusicint VoECodecImpl::GetSendCodec(int channel, CodecInst& codec) {
1150d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (!_shared->statistics().Initialized()) {
1160d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_NOT_INITED, kTraceError);
1170d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
1180d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
1190d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
1200d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  voe::Channel* channelPtr = ch.channel();
1210d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (channelPtr == NULL) {
1220d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
1230d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                          "GetSendCodec() failed to locate channel");
1240d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
1250d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
12612e21a0d6ce70b86ffafec10a5004ef2b1826dbakwiberg  if (channelPtr->GetSendCodec(codec) != 0) {
1270d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_CANNOT_GET_SEND_CODEC, kTraceError,
1280d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                          "GetSendCodec() failed to get send codec");
1290d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
1300d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
1310d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  return 0;
132470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
133470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
134adf89b7e33cc54dab9365dddead687a46a074cf0Ivo Creusenint VoECodecImpl::SetBitRate(int channel, int bitrate_bps) {
135adf89b7e33cc54dab9365dddead687a46a074cf0Ivo Creusen  WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
136adf89b7e33cc54dab9365dddead687a46a074cf0Ivo Creusen               "SetBitRate(bitrate_bps=%d)", bitrate_bps);
137adf89b7e33cc54dab9365dddead687a46a074cf0Ivo Creusen  if (!_shared->statistics().Initialized()) {
138adf89b7e33cc54dab9365dddead687a46a074cf0Ivo Creusen    _shared->SetLastError(VE_NOT_INITED, kTraceError);
139adf89b7e33cc54dab9365dddead687a46a074cf0Ivo Creusen    return -1;
140adf89b7e33cc54dab9365dddead687a46a074cf0Ivo Creusen  }
141adf89b7e33cc54dab9365dddead687a46a074cf0Ivo Creusen  _shared->channel_manager().GetChannel(channel).channel()->SetBitRate(
142adf89b7e33cc54dab9365dddead687a46a074cf0Ivo Creusen      bitrate_bps);
143adf89b7e33cc54dab9365dddead687a46a074cf0Ivo Creusen  return 0;
144adf89b7e33cc54dab9365dddead687a46a074cf0Ivo Creusen}
145adf89b7e33cc54dab9365dddead687a46a074cf0Ivo Creusen
1460d266054acece70259fc1e85026194154f41e5a0Jelena Marusicint VoECodecImpl::GetRecCodec(int channel, CodecInst& codec) {
1470d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (!_shared->statistics().Initialized()) {
1480d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_NOT_INITED, kTraceError);
1490d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
1500d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
1510d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
1520d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  voe::Channel* channelPtr = ch.channel();
1530d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (channelPtr == NULL) {
1540d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
1550d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                          "GetRecCodec() failed to locate channel");
1560d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
1570d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
15812e21a0d6ce70b86ffafec10a5004ef2b1826dbakwiberg  return channelPtr->GetRecCodec(codec);
159470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
160470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1610d266054acece70259fc1e85026194154f41e5a0Jelena Marusicint VoECodecImpl::SetRecPayloadType(int channel, const CodecInst& codec) {
1620d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
1630d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               "SetRecPayloadType(channel=%d, codec)", channel);
1640d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
1656955870806624479723addfae6dcf5d13968796cPeter Kasting               "codec: plname=%s, plfreq=%d, pltype=%d, channels=%" PRIuS ", "
1660d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               "pacsize=%d, rate=%d",
1670d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               codec.plname, codec.plfreq, codec.pltype, codec.channels,
1680d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               codec.pacsize, codec.rate);
1690d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (!_shared->statistics().Initialized()) {
1700d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_NOT_INITED, kTraceError);
1710d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
1720d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
1730d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
1740d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  voe::Channel* channelPtr = ch.channel();
1750d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (channelPtr == NULL) {
1760d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
1770d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                          "GetRecPayloadType() failed to locate channel");
1780d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
1790d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
1800d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  return channelPtr->SetRecPayloadType(codec);
181470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
182470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1830d266054acece70259fc1e85026194154f41e5a0Jelena Marusicint VoECodecImpl::GetRecPayloadType(int channel, CodecInst& codec) {
1840d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (!_shared->statistics().Initialized()) {
1850d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_NOT_INITED, kTraceError);
1860d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
1870d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
1880d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
1890d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  voe::Channel* channelPtr = ch.channel();
1900d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (channelPtr == NULL) {
1910d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
1920d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                          "GetRecPayloadType() failed to locate channel");
1930d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
1940d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
1950d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  return channelPtr->GetRecPayloadType(codec);
196470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
197470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1980d266054acece70259fc1e85026194154f41e5a0Jelena Marusicint VoECodecImpl::SetSendCNPayloadType(int channel,
1990d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                                       int type,
2000d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                                       PayloadFrequencies frequency) {
2010d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
2020d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               "SetSendCNPayloadType(channel=%d, type=%d, frequency=%d)",
2030d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               channel, type, frequency);
2040d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (!_shared->statistics().Initialized()) {
2050d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_NOT_INITED, kTraceError);
2060d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
2070d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
2080d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (type < 96 || type > 127) {
2090d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    // Only allow dynamic range: 96 to 127
2100d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_INVALID_PLTYPE, kTraceError,
2110d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                          "SetSendCNPayloadType() invalid payload type");
2120d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
2130d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
2140d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if ((frequency != kFreq16000Hz) && (frequency != kFreq32000Hz)) {
2150d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    // It is not possible to modify the payload type for CN/8000.
2160d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    // We only allow modification of the CN payload type for CN/16000
2170d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    // and CN/32000.
2180d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_INVALID_PLFREQ, kTraceError,
2190d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                          "SetSendCNPayloadType() invalid payload frequency");
2200d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
2210d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
2220d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
2230d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  voe::Channel* channelPtr = ch.channel();
2240d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (channelPtr == NULL) {
2250d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
2260d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                          "SetSendCNPayloadType() failed to locate channel");
2270d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
2280d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
2290d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  return channelPtr->SetSendCNPayloadType(type, frequency);
230470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
231470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
232c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.orgint VoECodecImpl::SetFECStatus(int channel, bool enable) {
233c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org  WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
234c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org               "SetCodecFECStatus(channel=%d, enable=%d)", channel, enable);
235c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org  if (!_shared->statistics().Initialized()) {
236c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org    _shared->SetLastError(VE_NOT_INITED, kTraceError);
237c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org    return -1;
238c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org  }
239c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org  voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
240c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org  voe::Channel* channelPtr = ch.channel();
241c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org  if (channelPtr == NULL) {
242c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org    _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
243c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org                          "SetCodecFECStatus() failed to locate channel");
244c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org    return -1;
245c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org  }
246c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org  return channelPtr->SetCodecFECStatus(enable);
247c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org}
248c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org
249c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.orgint VoECodecImpl::GetFECStatus(int channel, bool& enabled) {
250c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org  if (!_shared->statistics().Initialized()) {
251c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org    _shared->SetLastError(VE_NOT_INITED, kTraceError);
252c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org    return -1;
253c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org  }
254c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org  voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
255c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org  voe::Channel* channelPtr = ch.channel();
256c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org  if (channelPtr == NULL) {
257c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org    _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
258c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org                          "GetFECStatus() failed to locate channel");
259c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org    return -1;
260c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org  }
261c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org  enabled = channelPtr->GetCodecFECStatus();
262c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org  return 0;
263c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org}
264c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org
2650d266054acece70259fc1e85026194154f41e5a0Jelena Marusicint VoECodecImpl::SetVADStatus(int channel,
2660d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                               bool enable,
2670d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                               VadModes mode,
2680d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                               bool disableDTX) {
2690d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
2700d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               "SetVADStatus(channel=%i, enable=%i, mode=%i, disableDTX=%i)",
2710d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               channel, enable, mode, disableDTX);
272470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2730d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (!_shared->statistics().Initialized()) {
2740d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_NOT_INITED, kTraceError);
2750d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
2760d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
2770d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
2780d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  voe::Channel* channelPtr = ch.channel();
2790d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (channelPtr == NULL) {
2800d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
2810d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                          "SetVADStatus failed to locate channel");
2820d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
2830d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
2840d266054acece70259fc1e85026194154f41e5a0Jelena Marusic
2850d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  ACMVADMode vadMode(VADNormal);
2860d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  switch (mode) {
2870d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    case kVadConventional:
2880d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      vadMode = VADNormal;
2890d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      break;
2900d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    case kVadAggressiveLow:
2910d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      vadMode = VADLowBitrate;
2920d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      break;
2930d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    case kVadAggressiveMid:
2940d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      vadMode = VADAggr;
2950d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      break;
2960d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    case kVadAggressiveHigh:
2970d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      vadMode = VADVeryAggr;
2980d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      break;
2990d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
3000d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  return channelPtr->SetVADStatus(enable, vadMode, disableDTX);
301470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
302470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3030d266054acece70259fc1e85026194154f41e5a0Jelena Marusicint VoECodecImpl::GetVADStatus(int channel,
3040d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                               bool& enabled,
3050d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                               VadModes& mode,
3060d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                               bool& disabledDTX) {
3070d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (!_shared->statistics().Initialized()) {
3080d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_NOT_INITED, kTraceError);
3090d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
3100d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
3110d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
3120d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  voe::Channel* channelPtr = ch.channel();
3130d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (channelPtr == NULL) {
3140d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
3150d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                          "GetVADStatus failed to locate channel");
3160d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
3170d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
318470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3190d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  ACMVADMode vadMode;
3200d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  int ret = channelPtr->GetVADStatus(enabled, vadMode, disabledDTX);
321470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3220d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (ret != 0) {
3230d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    _shared->SetLastError(VE_INVALID_OPERATION, kTraceError,
3240d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                          "GetVADStatus failed to get VAD mode");
3250d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
3260d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
3270d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  switch (vadMode) {
3280d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    case VADNormal:
3290d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      mode = kVadConventional;
3300d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      break;
3310d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    case VADLowBitrate:
3320d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      mode = kVadAggressiveLow;
3330d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      break;
3340d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    case VADAggr:
3350d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      mode = kVadAggressiveMid;
3360d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      break;
3370d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    case VADVeryAggr:
3380d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      mode = kVadAggressiveHigh;
3390d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      break;
3400d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
341470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3420d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  return 0;
343470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
344470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
345adee8f924224e116f041564ddde83c979880e35fminyue@webrtc.orgint VoECodecImpl::SetOpusMaxPlaybackRate(int channel, int frequency_hz) {
3466aac93bd9c3da92e92b016d83c8f84c65aae65b6minyue@webrtc.org  WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
347adee8f924224e116f041564ddde83c979880e35fminyue@webrtc.org               "SetOpusMaxPlaybackRate(channel=%d, frequency_hz=%d)", channel,
348adee8f924224e116f041564ddde83c979880e35fminyue@webrtc.org               frequency_hz);
3496aac93bd9c3da92e92b016d83c8f84c65aae65b6minyue@webrtc.org  if (!_shared->statistics().Initialized()) {
3506aac93bd9c3da92e92b016d83c8f84c65aae65b6minyue@webrtc.org    _shared->SetLastError(VE_NOT_INITED, kTraceError);
3516aac93bd9c3da92e92b016d83c8f84c65aae65b6minyue@webrtc.org    return -1;
3526aac93bd9c3da92e92b016d83c8f84c65aae65b6minyue@webrtc.org  }
3536aac93bd9c3da92e92b016d83c8f84c65aae65b6minyue@webrtc.org  voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
3546aac93bd9c3da92e92b016d83c8f84c65aae65b6minyue@webrtc.org  voe::Channel* channelPtr = ch.channel();
3556aac93bd9c3da92e92b016d83c8f84c65aae65b6minyue@webrtc.org  if (channelPtr == NULL) {
3566aac93bd9c3da92e92b016d83c8f84c65aae65b6minyue@webrtc.org    _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
357adee8f924224e116f041564ddde83c979880e35fminyue@webrtc.org                          "SetOpusMaxPlaybackRate failed to locate channel");
3586aac93bd9c3da92e92b016d83c8f84c65aae65b6minyue@webrtc.org    return -1;
3596aac93bd9c3da92e92b016d83c8f84c65aae65b6minyue@webrtc.org  }
360adee8f924224e116f041564ddde83c979880e35fminyue@webrtc.org  return channelPtr->SetOpusMaxPlaybackRate(frequency_hz);
3616aac93bd9c3da92e92b016d83c8f84c65aae65b6minyue@webrtc.org}
3626aac93bd9c3da92e92b016d83c8f84c65aae65b6minyue@webrtc.org
3639b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.orgint VoECodecImpl::SetOpusDtx(int channel, bool enable_dtx) {
3649b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org  WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
3659b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org               "SetOpusDtx(channel=%d, enable_dtx=%d)", channel, enable_dtx);
3669b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org  if (!_shared->statistics().Initialized()) {
3679b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org    _shared->SetLastError(VE_NOT_INITED, kTraceError);
3689b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org    return -1;
3699b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org  }
3709b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org  voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
3719b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org  voe::Channel* channelPtr = ch.channel();
3729b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org  if (channelPtr == NULL) {
3739b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org    _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
3749b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org                          "SetOpusDtx failed to locate channel");
3759b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org    return -1;
3769b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org  }
3779b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org  return channelPtr->SetOpusDtx(enable_dtx);
3789b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org}
3799b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org
380b04965ccf83c2bc6e2758abab9bea0c18551a54civocRtcEventLog* VoECodecImpl::GetEventLog() {
381b04965ccf83c2bc6e2758abab9bea0c18551a54civoc  return _shared->channel_manager().GetEventLog();
382b04965ccf83c2bc6e2758abab9bea0c18551a54civoc}
383b04965ccf83c2bc6e2758abab9bea0c18551a54civoc
384470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif  // WEBRTC_VOICE_ENGINE_CODEC_API
385470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
386d900e8bea84c474696bf0219aed1353ce65ffd8epbos@webrtc.org}  // namespace webrtc
387