• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GetInterface(VoiceEngine * voiceEngine)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 
VoECodecImpl(voe::SharedData * shared)40 VoECodecImpl::VoECodecImpl(voe::SharedData* shared) : _shared(shared)
41 {
42     WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
43                  "VoECodecImpl() - ctor");
44 }
45 
~VoECodecImpl()46 VoECodecImpl::~VoECodecImpl()
47 {
48     WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
49                  "~VoECodecImpl() - dtor");
50 }
51 
NumOfCodecs()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 
GetCodec(int index,CodecInst & codec)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 
SetSendCodec(int channel,const CodecInst & codec)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 
GetSendCodec(int channel,CodecInst & codec)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 
GetRecCodec(int channel,CodecInst & codec)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 
SetRecPayloadType(int channel,const CodecInst & codec)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 
GetRecPayloadType(int channel,CodecInst & codec)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 
SetSendCNPayloadType(int channel,int type,PayloadFrequencies frequency)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 
SetFECStatus(int channel,bool enable)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 
GetFECStatus(int channel,bool & enabled)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 
SetVADStatus(int channel,bool enable,VadModes mode,bool disableDTX)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 
GetVADStatus(int channel,bool & enabled,VadModes & mode,bool & disabledDTX)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 
ACMToExternalCodecRepresentation(CodecInst & toInst,const CodecInst & fromInst)421 void VoECodecImpl::ACMToExternalCodecRepresentation(CodecInst& toInst,
422                                                     const CodecInst& fromInst)
423 {
424     toInst = fromInst;
425     if (STR_CASE_CMP(fromInst.plname,"SILK") == 0)
426     {
427         if (fromInst.plfreq == 12000)
428         {
429             if (fromInst.pacsize == 320)
430             {
431                 toInst.pacsize = 240;
432             }
433             else if (fromInst.pacsize == 640)
434             {
435                 toInst.pacsize = 480;
436             }
437             else if (fromInst.pacsize == 960)
438             {
439                 toInst.pacsize = 720;
440             }
441         }
442         else if (fromInst.plfreq == 24000)
443         {
444             if (fromInst.pacsize == 640)
445             {
446                 toInst.pacsize = 480;
447             }
448             else if (fromInst.pacsize == 1280)
449             {
450                 toInst.pacsize = 960;
451             }
452             else if (fromInst.pacsize == 1920)
453             {
454                 toInst.pacsize = 1440;
455             }
456         }
457     }
458 }
459 
ExternalToACMCodecRepresentation(CodecInst & toInst,const CodecInst & fromInst)460 void VoECodecImpl::ExternalToACMCodecRepresentation(CodecInst& toInst,
461                                                     const CodecInst& fromInst)
462 {
463     toInst = fromInst;
464     if (STR_CASE_CMP(fromInst.plname,"SILK") == 0)
465     {
466         if (fromInst.plfreq == 12000)
467         {
468             if (fromInst.pacsize == 240)
469             {
470                 toInst.pacsize = 320;
471             }
472             else if (fromInst.pacsize == 480)
473             {
474                 toInst.pacsize = 640;
475             }
476             else if (fromInst.pacsize == 720)
477             {
478                 toInst.pacsize = 960;
479             }
480         }
481         else if (fromInst.plfreq == 24000)
482         {
483             if (fromInst.pacsize == 480)
484             {
485                 toInst.pacsize = 640;
486             }
487             else if (fromInst.pacsize == 960)
488             {
489                 toInst.pacsize = 1280;
490             }
491             else if (fromInst.pacsize == 1440)
492             {
493                 toInst.pacsize = 1920;
494             }
495         }
496     }
497 }
498 
SetSecondarySendCodec(int channel,const CodecInst & codec,int red_payload_type)499 int VoECodecImpl::SetSecondarySendCodec(int channel, const CodecInst& codec,
500                                         int red_payload_type) {
501   CodecInst copy_codec;
502   ExternalToACMCodecRepresentation(copy_codec, codec);
503 
504   WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
505                "SetSecondarySendCodec(channel=%d, codec)", channel);
506   WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
507                "codec: plname=%s, pacsize=%d, plfreq=%d, pltype=%d, "
508                "channels=%d, rate=%d", codec.plname, codec.pacsize,
509                codec.plfreq, codec.pltype, codec.channels, codec.rate);
510   if (!_shared->statistics().Initialized()) {
511     _shared->SetLastError(VE_NOT_INITED, kTraceError);
512     return -1;
513   }
514 
515   // External sanity checks performed outside the ACM
516   if ((STR_CASE_CMP(copy_codec.plname, "L16") == 0) &&
517       (copy_codec.pacsize >= 960)) {
518     _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
519                           "SetSecondarySendCodec() invalid L16 packet size");
520     return -1;
521   }
522 
523   // None of the following codecs can be registered as the secondary encoder.
524   if (!STR_CASE_CMP(copy_codec.plname, "CN") ||
525       !STR_CASE_CMP(copy_codec.plname, "TELEPHONE-EVENT") ||
526       !STR_CASE_CMP(copy_codec.plname, "RED"))  {
527     _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
528                           "SetSecondarySendCodec() invalid codec name");
529     return -1;
530   }
531 
532   // Only mono and stereo are supported.
533   if ((copy_codec.channels != 1) && (copy_codec.channels != 2)) {
534     _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
535                           "SetSecondarySendCodec() invalid number of channels");
536     return -1;
537   }
538   voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
539   voe::Channel* channelPtr = ch.channel();
540   if (channelPtr == NULL) {
541     _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
542                           "SetSecondarySendCodec() failed to locate channel");
543     return -1;
544   }
545   if (!AudioCodingModule::IsCodecValid(copy_codec)) {
546     _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
547                           "SetSecondarySendCodec() invalid codec");
548     return -1;
549   }
550   if (channelPtr->SetSecondarySendCodec(copy_codec, red_payload_type) != 0) {
551     _shared->SetLastError(VE_CANNOT_SET_SECONDARY_SEND_CODEC, kTraceError,
552                           "SetSecondarySendCodec() failed to set secondary "
553                           "send codec");
554     return -1;
555   }
556   return 0;
557 }
558 
GetSecondarySendCodec(int channel,CodecInst & codec)559 int VoECodecImpl::GetSecondarySendCodec(int channel, CodecInst& codec) {
560   WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
561                "GetSecondarySendCodec(channel=%d, codec=?)", channel);
562   if (!_shared->statistics().Initialized()) {
563     _shared->SetLastError(VE_NOT_INITED, kTraceError);
564     return -1;
565   }
566   voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
567   voe::Channel* channelPtr = ch.channel();
568   if (channelPtr == NULL) {
569     _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
570                           "GetSecondarySendCodec() failed to locate channel");
571     return -1;
572   }
573   CodecInst acm_codec;
574   if (channelPtr->GetSecondarySendCodec(&acm_codec) != 0) {
575     _shared->SetLastError(VE_CANNOT_GET_SECONDARY_SEND_CODEC, kTraceError,
576                           "GetSecondarySendCodec() failed to get secondary "
577                           "send codec");
578     return -1;
579   }
580   ACMToExternalCodecRepresentation(codec, acm_codec);
581   WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
582                VoEId(_shared->instance_id(), -1),
583                "GetSecondarySendCodec() => plname=%s, pacsize=%d, plfreq=%d, "
584                "channels=%d, rate=%d", codec.plname, codec.pacsize,
585                codec.plfreq, codec.channels, codec.rate);
586   return 0;
587 }
588 
RemoveSecondarySendCodec(int channel)589 int VoECodecImpl::RemoveSecondarySendCodec(int channel) {
590   WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
591                "RemoveSecondarySendCodec(channel=%d)", channel);
592   voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
593   voe::Channel* channelPtr = ch.channel();
594   if (channelPtr == NULL) {
595     _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
596                           "RemoveSecondarySendCodec() failed to locate "
597                           "channel");
598     return -1;
599   }
600   channelPtr->RemoveSecondarySendCodec();
601   return 0;
602 }
603 
604 #endif  // WEBRTC_VOICE_ENGINE_CODEC_API
605 
606 }  // namespace webrtc
607