Home | History | Annotate | Download | only in voice_engine
      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