2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
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.
20 #include "gflags/gflags.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22 #include "webrtc/engine_configurations.h"
23 #include "webrtc/modules/audio_processing/include/audio_processing.h"
24 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
25 #include "webrtc/test/channel_transport/include/channel_transport.h"
26 #include "webrtc/test/testsupport/fileutils.h"
27 #include "webrtc/test/testsupport/trace_to_stderr.h"
28 #include "webrtc/voice_engine/include/voe_audio_processing.h"
29 #include "webrtc/voice_engine/include/voe_base.h"
30 #include "webrtc/voice_engine/include/voe_codec.h"
31 #include "webrtc/voice_engine/include/voe_dtmf.h"
32 #include "webrtc/voice_engine/include/voe_errors.h"
33 #include "webrtc/voice_engine/include/voe_external_media.h"
34 #include "webrtc/voice_engine/include/voe_file.h"
35 #include "webrtc/voice_engine/include/voe_hardware.h"
36 #include "webrtc/voice_engine/include/voe_neteq_stats.h"
37 #include "webrtc/voice_engine/include/voe_network.h"
38 #include "webrtc/voice_engine/include/voe_rtp_rtcp.h"
39 #include "webrtc/voice_engine/include/voe_video_sync.h"
40 #include "webrtc/voice_engine/include/voe_volume_control.h"
42 DEFINE_bool(use_log_file, false,
43 "Output logs to a file; by default they will be printed to stderr.");
45 using namespace webrtc;
50 printf("*** Error at line %i \n", __LINE__); \
51 printf("*** Error code = %i \n", base1->LastError()); \
54 VoiceEngine* m_voe = NULL;
55 VoEBase* base1 = NULL;
56 VoECodec* codec = NULL;
57 VoEVolumeControl* volume = NULL;
59 VoERTP_RTCP* rtp_rtcp = NULL;
60 VoEAudioProcessing* apm = NULL;
61 VoENetwork* netw = NULL;
63 VoEVideoSync* vsync = NULL;
64 VoEHardware* hardware = NULL;
65 VoEExternalMedia* xmedia = NULL;
66 VoENetEqStats* neteqst = NULL;
68 void RunTest(std::string out_path);
70 class MyObserver : public VoiceEngineObserver {
72 virtual void CallbackOnError(int channel, int err_code);
75 void MyObserver::CallbackOnError(int channel, int err_code) {
76 // Add printf for other error codes here
77 if (err_code == VE_TYPING_NOISE_WARNING) {
78 printf(" TYPING NOISE DETECTED \n");
79 } else if (err_code == VE_TYPING_NOISE_OFF_WARNING) {
80 printf(" TYPING NOISE OFF DETECTED \n");
81 } else if (err_code == VE_RECEIVE_PACKET_TIMEOUT) {
82 printf(" RECEIVE PACKET TIMEOUT \n");
83 } else if (err_code == VE_PACKET_RECEIPT_RESTARTED) {
84 printf(" PACKET RECEIPT RESTARTED \n");
85 } else if (err_code == VE_RUNTIME_PLAY_WARNING) {
86 printf(" RUNTIME PLAY WARNING \n");
87 } else if (err_code == VE_RUNTIME_REC_WARNING) {
88 printf(" RUNTIME RECORD WARNING \n");
89 } else if (err_code == VE_SATURATION_WARNING) {
90 printf(" SATURATION WARNING \n");
91 } else if (err_code == VE_RUNTIME_PLAY_ERROR) {
92 printf(" RUNTIME PLAY ERROR \n");
93 } else if (err_code == VE_RUNTIME_REC_ERROR) {
94 printf(" RUNTIME RECORD ERROR \n");
95 } else if (err_code == VE_REC_DEVICE_REMOVED) {
96 printf(" RECORD DEVICE REMOVED \n");
100 void SetStereoIfOpus(bool use_stereo, CodecInst* codec_params) {
101 if (strncmp(codec_params->plname, "opus", 4) == 0) {
103 codec_params->channels = 2;
105 codec_params->channels = 1;
109 void PrintCodecs(bool opus_stereo) {
110 CodecInst codec_params;
111 for (int i = 0; i < codec->NumOfCodecs(); ++i) {
112 int res = codec->GetCodec(i, codec_params);
114 SetStereoIfOpus(opus_stereo, &codec_params);
115 printf("%2d. %3d %s/%d/%d \n", i, codec_params.pltype, codec_params.plname,
116 codec_params.plfreq, codec_params.channels);
120 int main(int argc, char** argv) {
121 google::ParseCommandLineFlags(&argc, &argv, true);
125 printf("Test started \n");
127 m_voe = VoiceEngine::Create();
128 base1 = VoEBase::GetInterface(m_voe);
129 codec = VoECodec::GetInterface(m_voe);
130 apm = VoEAudioProcessing::GetInterface(m_voe);
131 volume = VoEVolumeControl::GetInterface(m_voe);
132 dtmf = VoEDtmf::GetInterface(m_voe);
133 rtp_rtcp = VoERTP_RTCP::GetInterface(m_voe);
134 netw = VoENetwork::GetInterface(m_voe);
135 file = VoEFile::GetInterface(m_voe);
136 vsync = VoEVideoSync::GetInterface(m_voe);
137 hardware = VoEHardware::GetInterface(m_voe);
138 xmedia = VoEExternalMedia::GetInterface(m_voe);
139 neteqst = VoENetEqStats::GetInterface(m_voe);
141 MyObserver my_observer;
143 scoped_ptr<test::TraceToStderr> trace_to_stderr;
144 if (!FLAGS_use_log_file) {
145 trace_to_stderr.reset(new test::TraceToStderr);
147 const std::string trace_filename = test::OutputPath() + "webrtc_trace.txt";
148 VoiceEngine::SetTraceFilter(kTraceAll);
149 res = VoiceEngine::SetTraceFile(trace_filename.c_str());
151 res = VoiceEngine::SetTraceCallback(NULL);
153 printf("Outputting logs to file: %s\n", trace_filename.c_str());
159 printf("\nError calling Init: %d\n", base1->LastError());
164 res = base1->RegisterVoiceEngineObserver(my_observer);
169 res = base1->GetVersion(tmp);
173 RunTest(test::OutputPath());
175 printf("Terminate \n");
177 base1->DeRegisterVoiceEngineObserver();
179 res = base1->Terminate();
218 VoiceEngine::Delete(m_voe);
223 void RunTest(std::string out_path) {
226 bool enable_aec = false;
227 bool enable_agc = false;
228 bool enable_rx_agc = false;
229 bool enable_cng = false;
230 bool enable_ns = false;
231 bool enable_rx_ns = false;
232 bool typing_detection = false;
234 bool opus_stereo = false;
235 bool experimental_ns_enabled = false;
237 #if defined(WEBRTC_ANDROID)
238 std::string resource_path = "/sdcard/";
240 std::string resource_path = webrtc::test::ProjectRootPath();
241 if (resource_path == webrtc::test::kCannotFindProjectRootDir) {
242 printf("*** Unable to get project root directory. "
243 "File playing may fail. ***\n");
244 // Fall back to the current directory.
245 resource_path = "./";
247 resource_path += "data/voice_engine/";
250 const std::string audio_filename = resource_path + "audio_long16.pcm";
252 const std::string play_filename = out_path + "recorded_playout.pcm";
253 const std::string mic_filename = out_path + "recorded_mic.pcm";
255 chan = base1->CreateChannel();
257 printf("************ Error code = %i\n", base1->LastError());
261 scoped_ptr<VoiceChannelTransport> voice_channel_transport(
262 new VoiceChannelTransport(netw, chan));
265 printf("1. 127.0.0.1 \n");
266 printf("2. Specify IP \n");
268 ASSERT_EQ(1, scanf("%i", &ip_selection));
270 if (ip_selection == 1) {
271 strcpy(ip, "127.0.0.1");
273 printf("Specify remote IP: ");
274 ASSERT_EQ(1, scanf("%s", ip));
278 printf("Specify remote port (1=1234): ");
279 ASSERT_EQ(1, scanf("%i", &rPort));
282 printf("Set Send port \n");
284 printf("Set Send IP \n");
285 res = voice_channel_transport->SetSendDestination(ip, rPort);
289 printf("Specify local port (1=1234): ");
290 ASSERT_EQ(1, scanf("%i", &lPort));
293 printf("Set Rec Port \n");
295 res = voice_channel_transport->SetLocalReceiver(lPort);
299 PrintCodecs(opus_stereo);
300 printf("Select send codec: ");
302 ASSERT_EQ(1, scanf("%i", &codec_selection));
303 codec->GetCodec(codec_selection, cinst);
305 printf("Set primary codec\n");
306 SetStereoIfOpus(opus_stereo, &cinst);
307 res = codec->SetSendCodec(chan, cinst);
310 const int kMaxNumChannels = 8;
311 int channel_index = 0;
312 std::vector<int> channels(kMaxNumChannels);
313 std::vector<VoiceChannelTransport*> voice_channel_transports(kMaxNumChannels);
315 for (int i = 0; i < kMaxNumChannels; ++i) {
316 channels[i] = base1->CreateChannel();
317 int port = rPort + (i + 1) * 2;
319 voice_channel_transports[i] = new VoiceChannelTransport(netw, channels[i]);
321 res = voice_channel_transports[i]->SetSendDestination(ip, port);
323 res = voice_channel_transports[i]->SetLocalReceiver(port);
325 res = codec->SetSendCodec(channels[i], cinst);
333 res = hardware->GetNumOfRecordingDevices(rd);
335 res = hardware->GetNumOfPlayoutDevices(pd);
338 char dn[128] = { 0 };
339 char guid[128] = { 0 };
340 printf("\nPlayout devices (%d): \n", pd);
341 for (int j = 0; j < pd; ++j) {
342 res = hardware->GetPlayoutDeviceName(j, dn, guid);
344 printf(" %d: %s \n", j, dn);
347 printf("Recording devices (%d): \n", rd);
348 for (int j = 0; j < rd; ++j) {
349 res = hardware->GetRecordingDeviceName(j, dn, guid);
351 printf(" %d: %s \n", j, dn);
354 printf("Select playout device: ");
355 ASSERT_EQ(1, scanf("%d", &pd));
356 res = hardware->SetPlayoutDevice(pd);
358 printf("Select recording device: ");
359 ASSERT_EQ(1, scanf("%d", &rd));
360 printf("Setting sound devices \n");
361 res = hardware->SetRecordingDevice(rd);
364 res = codec->SetVADStatus(0, enable_cng);
367 res = apm->SetAgcStatus(enable_agc);
370 res = apm->SetEcStatus(enable_aec);
373 res = apm->SetNsStatus(enable_ns);
376 printf("\n1. Send, listen and playout \n");
377 printf("2. Send only \n");
378 printf("3. Listen and playout only \n");
379 printf("Select transfer mode: ");
381 ASSERT_EQ(1, scanf("%i", &call_selection));
382 const bool send = !(call_selection == 3);
383 const bool receive = !(call_selection == 2);
386 #ifndef EXTERNAL_TRANSPORT
387 printf("Start Listen \n");
388 res = base1->StartReceive(chan);
392 printf("Start Playout \n");
393 res = base1->StartPlayout(chan);
398 printf("Start Send \n");
399 res = base1->StartSend(chan);
403 printf("Getting mic volume \n");
404 unsigned int vol = 999;
405 res = volume->GetMicVolume(vol);
407 if ((vol > 255) || (vol < 1)) {
408 printf("\n****ERROR in GetMicVolume");
413 printf("\nSelect codec\n");
414 PrintCodecs(opus_stereo);
415 printf("\nOther actions\n");
416 const int num_codecs = codec->NumOfCodecs();
417 int option_index = num_codecs;
418 printf("%i. Toggle CNG\n", option_index++);
419 printf("%i. Toggle AGC\n", option_index++);
420 printf("%i. Toggle NS\n", option_index++);
421 printf("%i. Toggle experimental NS\n", option_index++);
422 printf("%i. Toggle EC\n", option_index++);
423 printf("%i. Select AEC\n", option_index++);
424 printf("%i. Select AECM\n", option_index++);
425 printf("%i. Get speaker volume\n", option_index++);
426 printf("%i. Set speaker volume\n", option_index++);
427 printf("%i. Get microphone volume\n", option_index++);
428 printf("%i. Set microphone volume\n", option_index++);
429 printf("%i. Play local file (audio_long16.pcm) \n", option_index++);
430 printf("%i. Change playout device \n", option_index++);
431 printf("%i. Change recording device \n", option_index++);
432 printf("%i. Toggle receive-side AGC \n", option_index++);
433 printf("%i. Toggle receive-side NS \n", option_index++);
434 printf("%i. AGC status \n", option_index++);
435 printf("%i. Toggle microphone mute \n", option_index++);
436 printf("%i. Get last error code \n", option_index++);
437 printf("%i. Toggle typing detection \n",
439 printf("%i. Record a PCM file \n", option_index++);
440 printf("%i. Play a previously recorded PCM file locally \n",
442 printf("%i. Play a previously recorded PCM file as microphone \n",
444 printf("%i. Add an additional file-playing channel \n", option_index++);
445 printf("%i. Remove a file-playing channel \n", option_index++);
446 printf("%i. Toggle Opus stereo (Opus must be selected again to apply "
447 "the setting) \n", option_index++);
448 printf("%i. Set Opus maximum playback rate \n", option_index++);
449 printf("%i. Set bit rate (only take effect on codecs that allow the "
450 "change) \n", option_index++);
452 printf("Select action or %i to stop the call: ", option_index);
453 int option_selection;
454 ASSERT_EQ(1, scanf("%i", &option_selection));
456 option_index = num_codecs;
457 if (option_selection < option_index) {
458 res = codec->GetCodec(option_selection, cinst);
460 SetStereoIfOpus(opus_stereo, &cinst);
461 printf("Set primary codec\n");
462 res = codec->SetSendCodec(chan, cinst);
464 } else if (option_selection == option_index++) {
465 enable_cng = !enable_cng;
466 res = codec->SetVADStatus(0, enable_cng);
469 printf("\n CNG is now on! \n");
471 printf("\n CNG is now off! \n");
472 } else if (option_selection == option_index++) {
473 enable_agc = !enable_agc;
474 res = apm->SetAgcStatus(enable_agc);
477 printf("\n AGC is now on! \n");
479 printf("\n AGC is now off! \n");
480 } else if (option_selection == option_index++) {
481 enable_ns = !enable_ns;
482 res = apm->SetNsStatus(enable_ns);
485 printf("\n NS is now on! \n");
487 printf("\n NS is now off! \n");
488 } else if (option_selection == option_index++) {
489 experimental_ns_enabled = !experimental_ns_enabled;
491 config.Set<ExperimentalNs>(new ExperimentalNs(experimental_ns_enabled));
492 base1->audio_processing()->SetExtraOptions(config);
493 if (experimental_ns_enabled) {
494 printf("\n Experimental NS is now on!\n");
496 printf("\n Experimental NS is now off!\n");
498 } else if (option_selection == option_index++) {
499 enable_aec = !enable_aec;
500 res = apm->SetEcStatus(enable_aec, kEcUnchanged);
503 printf("\n Echo control is now on! \n");
505 printf("\n Echo control is now off! \n");
506 } else if (option_selection == option_index++) {
507 res = apm->SetEcStatus(enable_aec, kEcAec);
509 printf("\n AEC selected! \n");
511 printf(" (Echo control is on)\n");
513 printf(" (Echo control is off)\n");
514 } else if (option_selection == option_index++) {
515 res = apm->SetEcStatus(enable_aec, kEcAecm);
517 printf("\n AECM selected! \n");
519 printf(" (Echo control is on)\n");
521 printf(" (Echo control is off)\n");
522 } else if (option_selection == option_index++) {
524 res = volume->GetSpeakerVolume(vol);
526 printf("\n Speaker Volume is %d \n", vol);
527 } else if (option_selection == option_index++) {
530 ASSERT_EQ(1, scanf("%i", &level));
531 res = volume->SetSpeakerVolume(level);
533 } else if (option_selection == option_index++) {
535 res = volume->GetMicVolume(vol);
537 printf("\n Microphone Volume is %d \n", vol);
538 } else if (option_selection == option_index++) {
541 ASSERT_EQ(1, scanf("%i", &level));
542 res = volume->SetMicVolume(level);
544 } else if (option_selection == option_index++) {
545 res = file->StartPlayingFileLocally(0, audio_filename.c_str());
547 } else if (option_selection == option_index++) {
548 // change the playout device with current call
550 res = hardware->GetNumOfPlayoutDevices(num_pd);
553 char dn[128] = { 0 };
554 char guid[128] = { 0 };
556 printf("\nPlayout devices (%d): \n", num_pd);
557 for (int i = 0; i < num_pd; ++i) {
558 res = hardware->GetPlayoutDeviceName(i, dn, guid);
560 printf(" %d: %s \n", i, dn);
562 printf("Select playout device: ");
563 ASSERT_EQ(1, scanf("%d", &num_pd));
564 // Will use plughw for hardware devices
565 res = hardware->SetPlayoutDevice(num_pd);
567 } else if (option_selection == option_index++) {
568 // change the recording device with current call
571 res = hardware->GetNumOfRecordingDevices(num_rd);
574 char dn[128] = { 0 };
575 char guid[128] = { 0 };
577 printf("Recording devices (%d): \n", num_rd);
578 for (int i = 0; i < num_rd; ++i) {
579 res = hardware->GetRecordingDeviceName(i, dn, guid);
581 printf(" %d: %s \n", i, dn);
584 printf("Select recording device: ");
585 ASSERT_EQ(1, scanf("%d", &num_rd));
586 printf("Setting sound devices \n");
587 // Will use plughw for hardware devices
588 res = hardware->SetRecordingDevice(num_rd);
590 } else if (option_selection == option_index++) {
592 enable_rx_agc = !enable_rx_agc;
593 res = apm->SetRxAgcStatus(chan, enable_rx_agc);
596 printf("\n Receive-side AGC is now on! \n");
598 printf("\n Receive-side AGC is now off! \n");
599 } else if (option_selection == option_index++) {
601 enable_rx_ns = !enable_rx_ns;
602 res = apm->SetRxNsStatus(chan, enable_rx_ns);
605 printf("\n Receive-side NS is now on! \n");
607 printf("\n Receive-side NS is now off! \n");
608 } else if (option_selection == option_index++) {
611 res = apm->GetAgcStatus(enable, agcmode);
613 printf("\n AGC enable is %d, mode is %d \n", enable, agcmode);
614 } else if (option_selection == option_index++) {
615 // Toggle Mute on Microphone
616 res = volume->GetInputMute(chan, muted);
619 res = volume->SetInputMute(chan, muted);
622 printf("\n Microphone is now on mute! \n");
624 printf("\n Microphone is no longer on mute! \n");
625 } else if (option_selection == option_index++) {
626 // Get the last error code and print to screen
628 err_code = base1->LastError();
630 printf("\n The last error code was %i.\n", err_code);
631 } else if (option_selection == option_index++) {
632 typing_detection= !typing_detection;
633 res = apm->SetTypingDetectionStatus(typing_detection);
635 if (typing_detection)
636 printf("\n Typing detection is now on!\n");
638 printf("\n Typing detection is now off!\n");
639 } else if (option_selection == option_index++) {
642 printf("\n Select source of recorded file. ");
643 printf("\n 1. Record from microphone to file ");
644 printf("\n 2. Record from playout to file ");
645 printf("\n Enter your selection: \n");
646 ASSERT_EQ(1, scanf("%i", &file_source));
647 if (file_source == 1) {
648 printf("\n Start recording microphone as %s \n",
649 mic_filename.c_str());
650 res = file->StartRecordingMicrophone(mic_filename.c_str());
653 printf("\n Start recording playout as %s \n", play_filename.c_str());
654 res = file->StartRecordingPlayout(chan, play_filename.c_str());
657 while (stop_record != 0) {
658 printf("\n Type 0 to stop recording file \n");
659 ASSERT_EQ(1, scanf("%i", &stop_record));
661 if (file_source == 1) {
662 res = file->StopRecordingMicrophone();
665 res = file->StopRecordingPlayout(chan);
668 printf("\n File finished recording \n");
669 } else if (option_selection == option_index++) {
672 printf("\n Select a file to play locally in a loop.");
673 printf("\n 1. Play %s", mic_filename.c_str());
674 printf("\n 2. Play %s", play_filename.c_str());
675 printf("\n Enter your selection\n");
676 ASSERT_EQ(1, scanf("%i", &file_type));
677 if (file_type == 1) {
678 printf("\n Start playing %s locally in a loop\n",
679 mic_filename.c_str());
680 res = file->StartPlayingFileLocally(chan, mic_filename.c_str(), true);
683 printf("\n Start playing %s locally in a loop\n",
684 play_filename.c_str());
685 res = file->StartPlayingFileLocally(chan, play_filename.c_str(),
689 while (stop_play != 0) {
690 printf("\n Type 0 to stop playing file\n");
691 ASSERT_EQ(1, scanf("%i", &stop_play));
693 res = file->StopPlayingFileLocally(chan);
695 } else if (option_selection == option_index++) {
698 printf("\n Select a file to play as microphone in a loop.");
699 printf("\n 1. Play %s", mic_filename.c_str());
700 printf("\n 2. Play %s", play_filename.c_str());
701 printf("\n Enter your selection\n");
702 ASSERT_EQ(1, scanf("%i", &file_type));
703 if (file_type == 1) {
704 printf("\n Start playing %s as mic in a loop\n",
705 mic_filename.c_str());
706 res = file->StartPlayingFileAsMicrophone(chan, mic_filename.c_str(),
710 printf("\n Start playing %s as mic in a loop\n",
711 play_filename.c_str());
712 res = file->StartPlayingFileAsMicrophone(chan, play_filename.c_str(),
716 while (stop_play != 0) {
717 printf("\n Type 0 to stop playing file\n");
718 ASSERT_EQ(1, scanf("%i", &stop_play));
720 res = file->StopPlayingFileAsMicrophone(chan);
722 } else if (option_selection == option_index++) {
723 if (channel_index < kMaxNumChannels) {
724 res = base1->StartReceive(channels[channel_index]);
726 res = base1->StartPlayout(channels[channel_index]);
728 res = base1->StartSend(channels[channel_index]);
730 res = file->StartPlayingFileAsMicrophone(channels[channel_index],
731 audio_filename.c_str(),
736 printf("Using %d additional channels\n", channel_index);
738 printf("Max number of channels reached\n");
740 } else if (option_selection == option_index++) {
741 if (channel_index > 0) {
743 res = file->StopPlayingFileAsMicrophone(channels[channel_index]);
745 res = base1->StopSend(channels[channel_index]);
747 res = base1->StopPlayout(channels[channel_index]);
749 res = base1->StopReceive(channels[channel_index]);
751 printf("Using %d additional channels\n", channel_index);
753 printf("All additional channels stopped\n");
755 } else if (option_selection == option_index++) {
756 opus_stereo = !opus_stereo;
758 printf("\n Opus stereo enabled (select Opus again to apply the "
761 printf("\n Opus mono enabled (select Opus again to apply the "
763 } else if (option_selection == option_index++) {
764 printf("\n Input maxium playback rate in Hz: ");
765 int max_playback_rate;
766 ASSERT_EQ(1, scanf("%i", &max_playback_rate));
767 res = codec->SetOpusMaxPlaybackRate(chan, max_playback_rate);
769 } else if (option_selection == option_index++) {
770 res = codec->GetSendCodec(chan, cinst);
772 printf("Current bit rate is %i bps, set to: ", cinst.rate);
773 ASSERT_EQ(1, scanf("%i", &cinst.rate));
774 res = codec->SetSendCodec(chan, cinst);
782 printf("Stop Send \n");
783 res = base1->StopSend(chan);
788 printf("Stop Playout \n");
789 res = base1->StopPlayout(chan);
792 #ifndef EXTERNAL_TRANSPORT
793 printf("Stop Listen \n");
794 res = base1->StopReceive(chan);
799 while (channel_index > 0) {
801 res = file->StopPlayingFileAsMicrophone(channels[channel_index]);
803 res = base1->StopSend(channels[channel_index]);
805 res = base1->StopPlayout(channels[channel_index]);
807 res = base1->StopReceive(channels[channel_index]);
811 printf("\n1. New call \n");
812 printf("2. Quit \n");
813 printf("Select action: ");
815 ASSERT_EQ(1, scanf("%i", &end_option));
816 newcall = (end_option == 1);
819 for (int i = 0; i < kMaxNumChannels; ++i) {
820 delete voice_channel_transports[i];
821 voice_channel_transports[i] = NULL;
824 printf("Delete channels \n");
825 res = base1->DeleteChannel(chan);
828 for (int i = 0; i < kMaxNumChannels; ++i) {
829 channels[i] = base1->DeleteChannel(channels[i]);