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/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"
     19 
     20 namespace webrtc
     21 {
     22 
     23 VoECodec* VoECodec::GetInterface(VoiceEngine* voiceEngine)
     24 {
     25 #ifndef WEBRTC_VOICE_ENGINE_CODEC_API
     26     return NULL;
     27 #else
     28     if (NULL == voiceEngine)
     29     {
     30         return NULL;
     31     }
     32     VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
     33     s->AddRef();
     34     return s;
     35 #endif
     36 }
     37 
     38 #ifdef WEBRTC_VOICE_ENGINE_CODEC_API
     39 
     40 VoECodecImpl::VoECodecImpl(voe::SharedData* shared) : _shared(shared)
     41 {
     42     WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
     43                  "VoECodecImpl() - ctor");
     44 }
     45 
     46 VoECodecImpl::~VoECodecImpl()
     47 {
     48     WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
     49                  "~VoECodecImpl() - dtor");
     50 }
     51 
     52 int VoECodecImpl::NumOfCodecs()
     53 {
     54     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
     55                  "NumOfCodecs()");
     56 
     57     // Number of supported codecs in the ACM
     58     uint8_t nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
     59 
     60     WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
     61         VoEId(_shared->instance_id(), -1),
     62         "NumOfCodecs() => %u", nSupportedCodecs);
     63     return (nSupportedCodecs);
     64 }
     65 
     66 int VoECodecImpl::GetCodec(int index, CodecInst& codec)
     67 {
     68     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
     69                  "GetCodec(index=%d, codec=?)", index);
     70     CodecInst acmCodec;
     71     if (AudioCodingModule::Codec(index, &acmCodec)
     72             == -1)
     73     {
     74         _shared->SetLastError(VE_INVALID_LISTNR, kTraceError,
     75             "GetCodec() invalid index");
     76         return -1;
     77     }
     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);
     84     return 0;
     85 }
     86 
     87 int VoECodecImpl::SetSendCodec(int channel, const CodecInst& codec)
     88 {
     89     CodecInst copyCodec;
     90     ExternalToACMCodecRepresentation(copyCodec, codec);
     91 
     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())
     99     {
    100         _shared->SetLastError(VE_NOT_INITED, kTraceError);
    101         return -1;
    102     }
    103     // External sanity checks performed outside the ACM
    104     if ((STR_CASE_CMP(copyCodec.plname, "L16") == 0) &&
    105             (copyCodec.pacsize >= 960))
    106     {
    107         _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
    108             "SetSendCodec() invalid L16 packet size");
    109         return -1;
    110     }
    111     if (!STR_CASE_CMP(copyCodec.plname, "CN")
    112             || !STR_CASE_CMP(copyCodec.plname, "TELEPHONE-EVENT")
    113             || !STR_CASE_CMP(copyCodec.plname, "RED"))
    114     {
    115         _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
    116             "SetSendCodec() invalid codec name");
    117         return -1;
    118     }
    119     if ((copyCodec.channels != 1) && (copyCodec.channels != 2))
    120     {
    121         _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
    122             "SetSendCodec() invalid number of channels");
    123         return -1;
    124     }
    125     voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
    126     voe::Channel* channelPtr = ch.channel();
    127     if (channelPtr == NULL)
    128     {
    129         _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
    130             "GetSendCodec() failed to locate channel");
    131         return -1;
    132     }
    133     if (!AudioCodingModule::IsCodecValid(
    134             (CodecInst&) copyCodec))
    135     {
    136         _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
    137             "SetSendCodec() invalid codec");
    138         return -1;
    139     }
    140     if (channelPtr->SetSendCodec(copyCodec) != 0)
    141     {
    142         _shared->SetLastError(VE_CANNOT_SET_SEND_CODEC, kTraceError,
    143             "SetSendCodec() failed to set send codec");
    144         return -1;
    145     }
    146 
    147     return 0;
    148 }
    149 
    150 int VoECodecImpl::GetSendCodec(int channel, CodecInst& codec)
    151 {
    152     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
    153                  "GetSendCodec(channel=%d, codec=?)", channel);
    154     if (!_shared->statistics().Initialized())
    155     {
    156         _shared->SetLastError(VE_NOT_INITED, kTraceError);
    157         return -1;
    158     }
    159     voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
    160     voe::Channel* channelPtr = ch.channel();
    161     if (channelPtr == NULL)
    162     {
    163         _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
    164             "GetSendCodec() failed to locate channel");
    165         return -1;
    166     }
    167     CodecInst acmCodec;
    168     if (channelPtr->GetSendCodec(acmCodec) != 0)
    169     {
    170         _shared->SetLastError(VE_CANNOT_GET_SEND_CODEC, kTraceError,
    171             "GetSendCodec() failed to get send codec");
    172         return -1;
    173     }
    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);
    180     return 0;
    181 }
    182 
    183 int VoECodecImpl::GetRecCodec(int channel, CodecInst& codec)
    184 {
    185     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
    186                  "GetRecCodec(channel=%d, codec=?)", channel);
    187     if (!_shared->statistics().Initialized())
    188     {
    189         _shared->SetLastError(VE_NOT_INITED, kTraceError);
    190         return -1;
    191     }
    192     voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
    193     voe::Channel* channelPtr = ch.channel();
    194     if (channelPtr == NULL)
    195     {
    196         _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
    197             "GetRecCodec() failed to locate channel");
    198         return -1;
    199     }
    200     CodecInst acmCodec;
    201     if (channelPtr->GetRecCodec(acmCodec) != 0)
    202     {
    203         _shared->SetLastError(VE_CANNOT_GET_REC_CODEC, kTraceError,
    204             "GetRecCodec() failed to get received codec");
    205         return -1;
    206     }
    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);
    213     return 0;
    214 }
    215 
    216 int VoECodecImpl::SetRecPayloadType(int channel, const CodecInst& codec)
    217 {
    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())
    225     {
    226         _shared->SetLastError(VE_NOT_INITED, kTraceError);
    227         return -1;
    228     }
    229     voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
    230     voe::Channel* channelPtr = ch.channel();
    231     if (channelPtr == NULL)
    232     {
    233         _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
    234             "GetRecPayloadType() failed to locate channel");
    235         return -1;
    236     }
    237     return channelPtr->SetRecPayloadType(codec);
    238 }
    239 
    240 int VoECodecImpl::GetRecPayloadType(int channel, CodecInst& codec)
    241 {
    242     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
    243                  "GetRecPayloadType(channel=%d, codec)", channel);
    244     if (!_shared->statistics().Initialized())
    245     {
    246         _shared->SetLastError(VE_NOT_INITED, kTraceError);
    247         return -1;
    248     }
    249     voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
    250     voe::Channel* channelPtr = ch.channel();
    251     if (channelPtr == NULL)
    252     {
    253         _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
    254             "GetRecPayloadType() failed to locate channel");
    255         return -1;
    256     }
    257     return channelPtr->GetRecPayloadType(codec);
    258 }
    259 
    260 int VoECodecImpl::SetSendCNPayloadType(int channel, int type,
    261                                        PayloadFrequencies frequency)
    262 {
    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())
    267     {
    268         _shared->SetLastError(VE_NOT_INITED, kTraceError);
    269         return -1;
    270     }
    271     if (type < 96 || type > 127)
    272     {
    273         // Only allow dynamic range: 96 to 127
    274         _shared->SetLastError(VE_INVALID_PLTYPE, kTraceError,
    275             "SetSendCNPayloadType() invalid payload type");
    276         return -1;
    277     }
    278     if ((frequency != kFreq16000Hz) && (frequency != kFreq32000Hz))
    279     {
    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
    282         // and CN/32000.
    283         _shared->SetLastError(VE_INVALID_PLFREQ, kTraceError,
    284             "SetSendCNPayloadType() invalid payload frequency");
    285         return -1;
    286     }
    287     voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
    288     voe::Channel* channelPtr = ch.channel();
    289     if (channelPtr == NULL)
    290     {
    291         _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
    292             "SetSendCNPayloadType() failed to locate channel");
    293         return -1;
    294     }
    295     return channelPtr->SetSendCNPayloadType(type, frequency);
    296 }
    297 
    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);
    303     return -1;
    304   }
    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");
    310     return -1;
    311   }
    312   return channelPtr->SetCodecFECStatus(enable);
    313 }
    314 
    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);
    320     return -1;
    321   }
    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");
    327     return -1;
    328   }
    329   enabled = channelPtr->GetCodecFECStatus();
    330   return 0;
    331 }
    332 
    333 int VoECodecImpl::SetVADStatus(int channel, bool enable, VadModes mode,
    334                                bool disableDTX)
    335 {
    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);
    339 
    340     if (!_shared->statistics().Initialized())
    341     {
    342         _shared->SetLastError(VE_NOT_INITED, kTraceError);
    343         return -1;
    344     }
    345     voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
    346     voe::Channel* channelPtr = ch.channel();
    347     if (channelPtr == NULL)
    348     {
    349         _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
    350             "SetVADStatus failed to locate channel");
    351         return -1;
    352     }
    353 
    354     ACMVADMode vadMode(VADNormal);
    355     switch (mode)
    356     {
    357         case kVadConventional:
    358             vadMode = VADNormal;
    359             break;
    360         case kVadAggressiveLow:
    361             vadMode = VADLowBitrate;
    362             break;
    363         case kVadAggressiveMid:
    364             vadMode = VADAggr;
    365             break;
    366         case kVadAggressiveHigh:
    367             vadMode = VADVeryAggr;
    368             break;
    369     }
    370     return channelPtr->SetVADStatus(enable, vadMode, disableDTX);
    371 }
    372 
    373 int VoECodecImpl::GetVADStatus(int channel, bool& enabled, VadModes& mode,
    374                                bool& disabledDTX)
    375 {
    376     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
    377                  "GetVADStatus(channel=%i)", channel);
    378 
    379     if (!_shared->statistics().Initialized())
    380     {
    381         _shared->SetLastError(VE_NOT_INITED, kTraceError);
    382         return -1;
    383     }
    384     voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
    385     voe::Channel* channelPtr = ch.channel();
    386     if (channelPtr == NULL)
    387     {
    388         _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
    389             "GetVADStatus failed to locate channel");
    390         return -1;
    391     }
    392 
    393     ACMVADMode vadMode;
    394     int ret = channelPtr->GetVADStatus(enabled, vadMode, disabledDTX);
    395 
    396     if (ret != 0)
    397     {
    398         _shared->SetLastError(VE_INVALID_OPERATION, kTraceError,
    399             "GetVADStatus failed to get VAD mode");
    400         return -1;
    401     }
    402     switch (vadMode)
    403     {
    404         case VADNormal:
    405             mode = kVadConventional;
    406             break;
    407         case VADLowBitrate:
    408             mode = kVadAggressiveLow;
    409             break;
    410         case VADAggr:
    411             mode = kVadAggressiveMid;
    412             break;
    413         case VADVeryAggr:
    414             mode = kVadAggressiveHigh;
    415             break;
    416     }
    417 
    418     return 0;
    419 }
    420 
    421 int VoECodecImpl::SetOpusMaxPlaybackRate(int channel, int frequency_hz) {
    422   WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
    423                "SetOpusMaxPlaybackRate(channel=%d, frequency_hz=%d)", channel,
    424                frequency_hz);
    425   if (!_shared->statistics().Initialized()) {
    426     _shared->SetLastError(VE_NOT_INITED, kTraceError);
    427     return -1;
    428   }
    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                           "SetOpusMaxPlaybackRate failed to locate channel");
    434     return -1;
    435   }
    436   return channelPtr->SetOpusMaxPlaybackRate(frequency_hz);
    437 }
    438 
    439 void VoECodecImpl::ACMToExternalCodecRepresentation(CodecInst& toInst,
    440                                                     const CodecInst& fromInst)
    441 {
    442     toInst = fromInst;
    443     if (STR_CASE_CMP(fromInst.plname,"SILK") == 0)
    444     {
    445         if (fromInst.plfreq == 12000)
    446         {
    447             if (fromInst.pacsize == 320)
    448             {
    449                 toInst.pacsize = 240;
    450             }
    451             else if (fromInst.pacsize == 640)
    452             {
    453                 toInst.pacsize = 480;
    454             }
    455             else if (fromInst.pacsize == 960)
    456             {
    457                 toInst.pacsize = 720;
    458             }
    459         }
    460         else if (fromInst.plfreq == 24000)
    461         {
    462             if (fromInst.pacsize == 640)
    463             {
    464                 toInst.pacsize = 480;
    465             }
    466             else if (fromInst.pacsize == 1280)
    467             {
    468                 toInst.pacsize = 960;
    469             }
    470             else if (fromInst.pacsize == 1920)
    471             {
    472                 toInst.pacsize = 1440;
    473             }
    474         }
    475     }
    476 }
    477 
    478 void VoECodecImpl::ExternalToACMCodecRepresentation(CodecInst& toInst,
    479                                                     const CodecInst& fromInst)
    480 {
    481     toInst = fromInst;
    482     if (STR_CASE_CMP(fromInst.plname,"SILK") == 0)
    483     {
    484         if (fromInst.plfreq == 12000)
    485         {
    486             if (fromInst.pacsize == 240)
    487             {
    488                 toInst.pacsize = 320;
    489             }
    490             else if (fromInst.pacsize == 480)
    491             {
    492                 toInst.pacsize = 640;
    493             }
    494             else if (fromInst.pacsize == 720)
    495             {
    496                 toInst.pacsize = 960;
    497             }
    498         }
    499         else if (fromInst.plfreq == 24000)
    500         {
    501             if (fromInst.pacsize == 480)
    502             {
    503                 toInst.pacsize = 640;
    504             }
    505             else if (fromInst.pacsize == 960)
    506             {
    507                 toInst.pacsize = 1280;
    508             }
    509             else if (fromInst.pacsize == 1440)
    510             {
    511                 toInst.pacsize = 1920;
    512             }
    513         }
    514     }
    515 }
    516 
    517 int VoECodecImpl::SetSecondarySendCodec(int channel, const CodecInst& codec,
    518                                         int red_payload_type) {
    519   CodecInst copy_codec;
    520   ExternalToACMCodecRepresentation(copy_codec, codec);
    521 
    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);
    530     return -1;
    531   }
    532 
    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");
    538     return -1;
    539   }
    540 
    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");
    547     return -1;
    548   }
    549 
    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");
    554     return -1;
    555   }
    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");
    561     return -1;
    562   }
    563   if (!AudioCodingModule::IsCodecValid(copy_codec)) {
    564     _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
    565                           "SetSecondarySendCodec() invalid codec");
    566     return -1;
    567   }
    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 "
    571                           "send codec");
    572     return -1;
    573   }
    574   return 0;
    575 }
    576 
    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);
    582     return -1;
    583   }
    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");
    589     return -1;
    590   }
    591   CodecInst acm_codec;
    592   if (channelPtr->GetSecondarySendCodec(&acm_codec) != 0) {
    593     _shared->SetLastError(VE_CANNOT_GET_SECONDARY_SEND_CODEC, kTraceError,
    594                           "GetSecondarySendCodec() failed to get secondary "
    595                           "send codec");
    596     return -1;
    597   }
    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);
    604   return 0;
    605 }
    606 
    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 "
    615                           "channel");
    616     return -1;
    617   }
    618   channelPtr->RemoveSecondarySendCodec();
    619   return 0;
    620 }
    621 
    622 #endif  // WEBRTC_VOICE_ENGINE_CODEC_API
    623 
    624 }  // namespace webrtc
    625