Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / voice_engine / voe_codec_impl.cc
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::SetOpusMaxBandwidth(int channel, int bandwidth_hz) {
422   WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
423                "SetOpusMaxBandwidth(channel=%d, bandwidth_hz=%d)", channel,
424                bandwidth_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                           "SetOpusMaxBandwidth failed to locate channel");
434     return -1;
435   }
436   return channelPtr->SetOpusMaxBandwidth(bandwidth_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