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 20namespace webrtc 21{ 22 23VoECodec* 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 40VoECodecImpl::VoECodecImpl(voe::SharedData* shared) : _shared(shared) 41{ 42 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1), 43 "VoECodecImpl() - ctor"); 44} 45 46VoECodecImpl::~VoECodecImpl() 47{ 48 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1), 49 "~VoECodecImpl() - dtor"); 50} 51 52int 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 66int 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 87int 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 150int 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 183int 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 216int 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 240int 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 260int 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 298int 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 315int 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 333int 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 373int 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 421int 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 439void 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 478void 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 517int 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 577int 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 607int 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