• 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 <limits.h>
12 #include <stdarg.h>
13 #include <stdio.h>
14 
15 #include <algorithm>
16 
17 #include "gflags/gflags.h"
18 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
19 #include "webrtc/test/channel_transport/include/channel_transport.h"
20 #include "webrtc/video_engine/test/auto_test/interface/vie_autotest.h"
21 #include "webrtc/video_engine/test/auto_test/interface/vie_autotest_defines.h"
22 #include "webrtc/video_engine/test/auto_test/primitives/choice_helpers.h"
23 #include "webrtc/video_engine/test/auto_test/primitives/general_primitives.h"
24 #include "webrtc/video_engine/test/auto_test/primitives/input_helpers.h"
25 #include "webrtc/video_engine/test/libvietest/include/vie_to_file_renderer.h"
26 #include "webrtc/voice_engine/include/voe_network.h"
27 
28 #define VCM_RED_PAYLOAD_TYPE                            96
29 #define VCM_ULPFEC_PAYLOAD_TYPE                         97
30 #define DEFAULT_SEND_IP                                 "127.0.0.1"
31 #define DEFAULT_VIDEO_PORT                              "11111"
32 #define DEFAULT_VIDEO_CODEC                             "VP8"
33 #define DEFAULT_VIDEO_CODEC_WIDTH                       "640"
34 #define DEFAULT_VIDEO_CODEC_HEIGHT                      "480"
35 #define DEFAULT_VIDEO_CODEC_BITRATE                     "300"
36 #define DEFAULT_VIDEO_CODEC_MIN_BITRATE                 "100"
37 #define DEFAULT_VIDEO_CODEC_MAX_BITRATE                 "1000"
38 #define DEFAULT_AUDIO_PORT                              "11113"
39 #define DEFAULT_AUDIO_CODEC                             "ISAC"
40 #define DEFAULT_VIDEO_CODEC_MAX_FRAMERATE               "30"
41 #define DEFAULT_VIDEO_PROTECTION_METHOD                 "None"
42 #define DEFAULT_TEMPORAL_LAYER                          "0"
43 #define DEFAULT_BUFFERING_DELAY_MS                      "0"
44 
45 DEFINE_string(render_custom_call_remote_to, "", "Specify to render the remote "
46     "stream of a custom call to the provided filename instead of showing it in "
47     "window 2. The file will end up in the default output directory (out/).");
48 
49 enum StatisticsType {
50   kSendStatistic,
51   kReceivedStatistic
52 };
53 
54 enum VideoProtectionMethod {
55   kProtectionMethodNone = 1,
56   kProtectionMethodFecOnly,
57   kProtectionMethodNackOnly,
58   kProtectionMethodHybridNackAndFec,
59 };
60 
61 using webrtc::FromChoices;
62 using webrtc::TypedInput;
63 
64 class ViEAutotestEncoderObserver : public webrtc::ViEEncoderObserver {
65  public:
ViEAutotestEncoderObserver()66   ViEAutotestEncoderObserver() {}
~ViEAutotestEncoderObserver()67   ~ViEAutotestEncoderObserver() {}
68 
OutgoingRate(const int video_channel,const unsigned int framerate,const unsigned int bitrate)69   void OutgoingRate(const int video_channel,
70                     const unsigned int framerate,
71                     const unsigned int bitrate) {
72     std::cout << "Send FR: " << framerate
73               << " BR: " << bitrate << std::endl;
74   }
75 
SuspendChange(int video_channel,bool is_suspended)76   virtual void SuspendChange(int video_channel, bool is_suspended) OVERRIDE {
77     std::cout << "SuspendChange: " << is_suspended << std::endl;
78   }
79 };
80 
81 class ViEAutotestDecoderObserver : public webrtc::ViEDecoderObserver {
82  public:
ViEAutotestDecoderObserver()83   ViEAutotestDecoderObserver() {}
~ViEAutotestDecoderObserver()84   ~ViEAutotestDecoderObserver() {}
85 
IncomingRate(const int video_channel,const unsigned int framerate,const unsigned int bitrate)86   void IncomingRate(const int video_channel,
87                     const unsigned int framerate,
88                     const unsigned int bitrate) {
89     std::cout << "Received FR: " << framerate
90               << " BR: " << bitrate << std::endl;
91   }
92 
DecoderTiming(int decode_ms,int max_decode_ms,int current_delay_ms,int target_delay_ms,int jitter_buffer_ms,int min_playout_delay_ms,int render_delay_ms)93   virtual void DecoderTiming(int decode_ms,
94                              int max_decode_ms,
95                              int current_delay_ms,
96                              int target_delay_ms,
97                              int jitter_buffer_ms,
98                              int min_playout_delay_ms,
99                              int render_delay_ms) {
100     std::cout << "Decoder timing: DecodeMS: " << decode_ms
101               << ", MaxDecodeMS: " << max_decode_ms
102               << ", CurrentDelayMS: " << current_delay_ms
103               << ", TargetDelayMS: " << target_delay_ms
104               << ", JitterBufferMS: " << jitter_buffer_ms
105               << ", MinPlayoutDelayMS: " << min_playout_delay_ms
106               << ", RenderDelayMS: " << render_delay_ms;
107   }
108 
IncomingCodecChanged(const int video_channel,const webrtc::VideoCodec & codec)109   void IncomingCodecChanged(const int video_channel,
110                             const webrtc::VideoCodec& codec) {}
RequestNewKeyFrame(const int video_channel)111   void RequestNewKeyFrame(const int video_channel) {
112     std::cout << "Decoder requesting a new key frame." << std::endl;
113   }
114 };
115 
116 // The following are general helper functions.
117 bool GetVideoDevice(webrtc::ViEBase* vie_base,
118                     webrtc::ViECapture* vie_capture,
119                     char* capture_device_name, char* capture_device_unique_id);
120 std::string GetIPAddress();
121 bool ValidateIP(std::string i_str);
122 
123 // The following are Print to stdout functions.
124 void PrintCallInformation(const char* IP,
125                           const char* video_capture_device_name,
126                           const char* video_capture_unique_id,
127                           webrtc::VideoCodec video_codec,
128                           int video_tx_port,
129                           int video_rx_port,
130                           const char* audio_capture_device_name,
131                           const char* audio_playbackDeviceName,
132                           webrtc::CodecInst audio_codec,
133                           int audio_tx_port,
134                           int audio_rx_port,
135                           int protection_method);
136 void PrintRTCCPStatistics(webrtc::ViERTP_RTCP* vie_rtp_rtcp,
137                           int video_channel,
138                           StatisticsType stat_type);
139 void PrintRTPStatistics(webrtc::ViERTP_RTCP* vie_rtp_rtcp,
140                         int video_channel);
141 void PrintBandwidthUsage(webrtc::ViERTP_RTCP* vie_rtp_rtcp,
142                          int video_channel);
143 void PrintCodecStatistics(webrtc::ViECodec* vie_codec,
144                           int video_channel,
145                           StatisticsType stat_type);
146 void PrintGetDiscardedPackets(webrtc::ViECodec* vie_codec,
147                               int video_channel);
148 void PrintVideoStreamInformation(webrtc::ViECodec* vie_codec,
149                                  int video_channel);
150 void PrintVideoCodec(webrtc::VideoCodec video_codec);
151 
152 // The following are video functions.
153 void GetVideoPorts(int* tx_port, int* rx_port);
154 void SetVideoCodecType(webrtc::ViECodec* vie_codec,
155                        webrtc::VideoCodec* video_codec);
156 void SetVideoCodecResolution(webrtc::VideoCodec* video_codec);
157 void SetVideoCodecSize(webrtc::VideoCodec* video_codec);
158 void SetVideoCodecBitrate(webrtc::VideoCodec* video_codec);
159 void SetVideoCodecMinBitrate(webrtc::VideoCodec* video_codec);
160 void SetVideoCodecMaxBitrate(webrtc::VideoCodec* video_codec);
161 void SetVideoCodecMaxFramerate(webrtc::VideoCodec* video_codec);
162 void SetVideoCodecTemporalLayer(webrtc::VideoCodec* video_codec);
163 VideoProtectionMethod GetVideoProtection();
164 bool SetVideoProtection(webrtc::ViECodec* vie_codec,
165                         webrtc::ViERTP_RTCP* vie_rtp_rtcp,
166                         int video_channel,
167                         VideoProtectionMethod protection_method);
168 bool GetBitrateSignaling();
169 int GetBufferingDelay();
170 
171 // The following are audio helper functions.
172 bool GetAudioDevices(webrtc::VoEBase* voe_base,
173                      webrtc::VoEHardware* voe_hardware,
174                      char* recording_device_name, int& recording_device_index,
175                      char* playback_device_name, int& playback_device_index);
176 bool GetAudioDevices(webrtc::VoEBase* voe_base,
177                      webrtc::VoEHardware* voe_hardware,
178                      int& recording_device_index, int& playback_device_index);
179 void GetAudioPorts(int* tx_port, int* rx_port);
180 bool GetAudioCodec(webrtc::VoECodec* voe_codec,
181                    webrtc::CodecInst& audio_codec);
182 
ViECustomCall()183 int ViEAutoTest::ViECustomCall() {
184   ViETest::Log(" ");
185   ViETest::Log("========================================");
186   ViETest::Log(" Enter values to use custom settings\n");
187 
188   int error = 0;
189   int number_of_errors = 0;
190   std::string str;
191 
192   // Create the VoE and get the VoE interfaces.
193   webrtc::VoiceEngine* voe = webrtc::VoiceEngine::Create();
194   number_of_errors += ViETest::TestError(voe != NULL, "ERROR: %s at line %d",
195                                          __FUNCTION__, __LINE__);
196 
197   webrtc::VoEBase* voe_base = webrtc::VoEBase::GetInterface(voe);
198   number_of_errors += ViETest::TestError(voe_base != NULL,
199                                          "ERROR: %s at line %d", __FUNCTION__,
200                                          __LINE__);
201 
202   error = voe_base->Init();
203   number_of_errors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
204                                          __FUNCTION__, __LINE__);
205 
206   webrtc::VoECodec* voe_codec = webrtc::VoECodec::GetInterface(voe);
207   number_of_errors += ViETest::TestError(voe_codec != NULL,
208                                          "ERROR: %s at line %d", __FUNCTION__,
209                                          __LINE__);
210 
211   webrtc::VoEHardware* voe_hardware =
212       webrtc::VoEHardware::GetInterface(voe);
213   number_of_errors += ViETest::TestError(voe_hardware != NULL,
214                                          "ERROR: %s at line %d", __FUNCTION__,
215                                          __LINE__);
216 
217   webrtc::VoENetwork* voe_network=
218       webrtc::VoENetwork::GetInterface(voe);
219   number_of_errors += ViETest::TestError(voe_network != NULL,
220                                          "ERROR: %s at line %d", __FUNCTION__,
221                                          __LINE__);
222 
223   webrtc::VoEAudioProcessing* voe_apm =
224       webrtc::VoEAudioProcessing::GetInterface(voe);
225   number_of_errors += ViETest::TestError(voe_apm != NULL,
226                                          "ERROR: %s at line %d", __FUNCTION__,
227                                          __LINE__);
228 
229   // Create the ViE and get the ViE Interfaces.
230   webrtc::VideoEngine* vie = webrtc::VideoEngine::Create();
231   number_of_errors += ViETest::TestError(vie != NULL,
232                                          "ERROR: %s at line %d", __FUNCTION__,
233                                          __LINE__);
234 
235   webrtc::ViEBase* vie_base = webrtc::ViEBase::GetInterface(vie);
236   number_of_errors += ViETest::TestError(vie_base != NULL,
237                                          "ERROR: %s at line %d", __FUNCTION__,
238                                          __LINE__);
239 
240   error = vie_base->Init();
241   number_of_errors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
242                                          __FUNCTION__, __LINE__);
243 
244   webrtc::ViECapture* vie_capture =
245       webrtc::ViECapture::GetInterface(vie);
246   number_of_errors += ViETest::TestError(vie_capture != NULL,
247                                          "ERROR: %s at line %d", __FUNCTION__,
248                                          __LINE__);
249 
250   webrtc::ViERender* vie_renderer = webrtc::ViERender::GetInterface(vie);
251   number_of_errors += ViETest::TestError(vie_renderer != NULL,
252                                          "ERROR: %s at line %d", __FUNCTION__,
253                                          __LINE__);
254 
255   webrtc::ViECodec* vie_codec = webrtc::ViECodec::GetInterface(vie);
256   number_of_errors += ViETest::TestError(vie_codec != NULL,
257                                          "ERROR: %s at line %d", __FUNCTION__,
258                                          __LINE__);
259 
260   webrtc::ViENetwork* vie_network = webrtc::ViENetwork::GetInterface(vie);
261   number_of_errors += ViETest::TestError(vie_network != NULL,
262                                          "ERROR: %s at line %d", __FUNCTION__,
263                                          __LINE__);
264 
265   bool start_call = false;
266   std::string ip_address;
267   const unsigned int KMaxUniqueIdLength = 256;
268   char unique_id[KMaxUniqueIdLength] = "";
269   char device_name[KMaxUniqueIdLength] = "";
270   int video_tx_port = 0;
271   int video_rx_port = 0;
272   int video_channel = -1;
273   webrtc::VideoCodec video_send_codec;
274   char audio_capture_device_name[KMaxUniqueIdLength] = "";
275   char audio_playbackDeviceName[KMaxUniqueIdLength] = "";
276   int audio_capture_device_index = -1;
277   int audio_playback_device_index = -1;
278   int audio_tx_port = 0;
279   int audio_rx_port = 0;
280   webrtc::CodecInst audio_codec;
281   int audio_channel = -1;
282   VideoProtectionMethod protection_method = kProtectionMethodNone;
283   int buffer_delay_ms = 0;
284   bool is_image_scale_enabled = false;
285   bool remb = true;
286   webrtc::scoped_ptr<webrtc::test::VideoChannelTransport>
287       video_channel_transport;
288   webrtc::scoped_ptr<webrtc::test::VoiceChannelTransport>
289       voice_channel_transport;
290 
291   while (!start_call) {
292     // Get the IP address to use from call.
293     ip_address = GetIPAddress();
294 
295     // Get the video device to use for call.
296     memset(device_name, 0, KMaxUniqueIdLength);
297     memset(unique_id, 0, KMaxUniqueIdLength);
298     if (!GetVideoDevice(vie_base, vie_capture, device_name, unique_id))
299       return number_of_errors;
300 
301     // Get and set the video ports for the call.
302     video_tx_port = 0;
303     video_rx_port = 0;
304     GetVideoPorts(&video_tx_port, &video_rx_port);
305 
306     // Get and set the video codec parameters for the call.
307     memset(&video_send_codec, 0, sizeof(webrtc::VideoCodec));
308     SetVideoCodecType(vie_codec, &video_send_codec);
309     SetVideoCodecSize(&video_send_codec);
310     SetVideoCodecBitrate(&video_send_codec);
311     SetVideoCodecMinBitrate(&video_send_codec);
312     SetVideoCodecMaxBitrate(&video_send_codec);
313     SetVideoCodecMaxFramerate(&video_send_codec);
314     SetVideoCodecTemporalLayer(&video_send_codec);
315     remb = GetBitrateSignaling();
316 
317     // Get the video protection method for the call.
318     protection_method = GetVideoProtection();
319 
320     // Get the call mode (Real-Time/Buffered).
321     buffer_delay_ms = GetBufferingDelay();
322 
323     // Get the audio device for the call.
324     memset(audio_capture_device_name, 0, KMaxUniqueIdLength);
325     memset(audio_playbackDeviceName, 0, KMaxUniqueIdLength);
326     GetAudioDevices(voe_base, voe_hardware, audio_capture_device_name,
327                     audio_capture_device_index, audio_playbackDeviceName,
328                     audio_playback_device_index);
329 
330     // Get the audio port for the call.
331     audio_tx_port = 0;
332     audio_rx_port = 0;
333     GetAudioPorts(&audio_tx_port, &audio_rx_port);
334 
335     // Get the audio codec for the call.
336     memset(static_cast<void*>(&audio_codec), 0, sizeof(audio_codec));
337     GetAudioCodec(voe_codec, audio_codec);
338 
339     // Now ready to start the call.  Check user wants to continue.
340     PrintCallInformation(ip_address.c_str(), device_name, unique_id,
341                          video_send_codec, video_tx_port, video_rx_port,
342                          audio_capture_device_name, audio_playbackDeviceName,
343                          audio_codec, audio_tx_port, audio_rx_port,
344                          protection_method);
345 
346     printf("\n");
347     int selection =
348         FromChoices("Ready to start:",
349                     "Start the call\n"
350                     "Reconfigure call settings\n")
351                         .WithDefault("Start the call").Choose();
352     start_call = (selection == 1);
353   }
354   /// **************************************************************
355   // Begin create/initialize WebRTC Video Engine for testing.
356   /// **************************************************************
357   if (start_call == true) {
358     // Configure audio channel first.
359     audio_channel = voe_base->CreateChannel();
360 
361     voice_channel_transport.reset(
362         new webrtc::test::VoiceChannelTransport(voe_network, audio_channel));
363 
364     error = voice_channel_transport->SetSendDestination(ip_address.c_str(),
365                                                         audio_tx_port);
366     number_of_errors += ViETest::TestError(error == 0,
367                                            "ERROR: %s at line %d",
368                                            __FUNCTION__, __LINE__);
369 
370     error = voice_channel_transport->SetLocalReceiver(audio_rx_port);
371     number_of_errors += ViETest::TestError(error == 0,
372                                            "ERROR: %s at line %d",
373                                            __FUNCTION__, __LINE__);
374 
375     error = voe_hardware->SetRecordingDevice(audio_capture_device_index);
376     number_of_errors += ViETest::TestError(error == 0,
377                                            "ERROR: %s at line %d",
378                                            __FUNCTION__, __LINE__);
379 
380     error = voe_hardware->SetPlayoutDevice(audio_playback_device_index);
381     number_of_errors += ViETest::TestError(error == 0,
382                                            "ERROR: %s at line %d",
383                                            __FUNCTION__, __LINE__);
384 
385     error = voe_codec->SetSendCodec(audio_channel, audio_codec);
386     number_of_errors += ViETest::TestError(error == 0,
387                                            "ERROR: %s at line %d",
388                                            __FUNCTION__, __LINE__);
389 
390     error = voe_apm->SetAgcStatus(true, webrtc::kAgcDefault);
391     number_of_errors += ViETest::TestError(error == 0,
392                                            "ERROR: %s at line %d",
393                                            __FUNCTION__, __LINE__);
394 
395     error = voe_apm->SetNsStatus(true, webrtc::kNsHighSuppression);
396     number_of_errors += ViETest::TestError(error == 0,
397                                            "ERROR: %s at line %d",
398                                            __FUNCTION__, __LINE__);
399     // Now configure the video channel.
400     error = vie->SetTraceFilter(webrtc::kTraceAll);
401     number_of_errors += ViETest::TestError(error == 0,
402                                            "ERROR: %s at line %d",
403                                            __FUNCTION__, __LINE__);
404 
405     std::string trace_file =
406         ViETest::GetResultOutputPath() + "ViECustomCall_trace.txt";
407     error = vie->SetTraceFile(trace_file.c_str());
408     number_of_errors += ViETest::TestError(error == 0,
409                                            "ERROR: %s at line %d",
410                                            __FUNCTION__, __LINE__);
411 
412     error = vie_base->SetVoiceEngine(voe);
413     number_of_errors += ViETest::TestError(error == 0,
414                                            "ERROR: %s at line %d",
415                                            __FUNCTION__, __LINE__);
416 
417     error = vie_base->CreateChannel(video_channel);
418     number_of_errors += ViETest::TestError(error == 0,
419                                            "ERROR: %s at line %d",
420                                            __FUNCTION__, __LINE__);
421 
422     error = vie_base->ConnectAudioChannel(video_channel, audio_channel);
423     number_of_errors += ViETest::TestError(error == 0,
424                                            "ERROR: %s at line %d",
425                                            __FUNCTION__, __LINE__);
426 
427     int capture_id = 0;
428     error = vie_capture->AllocateCaptureDevice(unique_id,
429                                                KMaxUniqueIdLength,
430                                                capture_id);
431     number_of_errors += ViETest::TestError(error == 0,
432                                            "ERROR: %s at line %d",
433                                            __FUNCTION__, __LINE__);
434 
435     error = vie_capture->ConnectCaptureDevice(capture_id, video_channel);
436     number_of_errors += ViETest::TestError(error == 0,
437                                            "ERROR: %s at line %d",
438                                            __FUNCTION__, __LINE__);
439 
440     error = vie_capture->StartCapture(capture_id);
441     number_of_errors += ViETest::TestError(error == 0,
442                                            "ERROR: %s at line %d",
443                                            __FUNCTION__, __LINE__);
444 
445     webrtc::ViERTP_RTCP* vie_rtp_rtcp =
446         webrtc::ViERTP_RTCP::GetInterface(vie);
447     number_of_errors += ViETest::TestError(vie != NULL,
448                                            "ERROR: %s at line %d",
449                                            __FUNCTION__, __LINE__);
450 
451     error = vie_rtp_rtcp->SetRTCPStatus(video_channel,
452                                         webrtc::kRtcpCompound_RFC4585);
453     number_of_errors += ViETest::TestError(error == 0,
454                                            "ERROR: %s at line %d",
455                                            __FUNCTION__, __LINE__);
456 
457     error = vie_rtp_rtcp->SetKeyFrameRequestMethod(
458         video_channel, webrtc::kViEKeyFrameRequestPliRtcp);
459     number_of_errors += ViETest::TestError(error == 0,
460                                            "ERROR: %s at line %d",
461                                            __FUNCTION__, __LINE__);
462 
463     if (remb) {
464       error = vie_rtp_rtcp->SetRembStatus(video_channel, true, true);
465       number_of_errors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
466                                              __FUNCTION__, __LINE__);
467     } else  {
468       error = vie_rtp_rtcp->SetTMMBRStatus(video_channel, true);
469       number_of_errors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
470                                              __FUNCTION__, __LINE__);
471     }
472 
473     error = vie_renderer->AddRenderer(capture_id, _window1, 0, 0.0, 0.0, 1.0,
474                                       1.0);
475     number_of_errors += ViETest::TestError(error == 0,
476                                            "ERROR: %s at line %d",
477                                            __FUNCTION__, __LINE__);
478 
479 
480     ViEToFileRenderer file_renderer;
481     if (FLAGS_render_custom_call_remote_to == "") {
482       error = vie_renderer->AddRenderer(video_channel, _window2, 1, 0.0, 0.0,
483                                         1.0, 1.0);
484       number_of_errors += ViETest::TestError(error == 0,
485                                              "ERROR: %s at line %d",
486                                              __FUNCTION__, __LINE__);
487     } else {
488       std::string output_path = ViETest::GetResultOutputPath();
489       std::string filename = FLAGS_render_custom_call_remote_to;
490       ViETest::Log("Rendering remote stream to %s: you will not see any output "
491           "in the second window.", (output_path + filename).c_str());
492 
493       file_renderer.PrepareForRendering(output_path, filename);
494       RenderToFile(vie_renderer, video_channel, &file_renderer);
495     }
496 
497     video_channel_transport.reset(
498         new webrtc::test::VideoChannelTransport(vie_network, video_channel));
499 
500     error = video_channel_transport->SetSendDestination(ip_address.c_str(),
501                                                         video_tx_port);
502     number_of_errors += ViETest::TestError(error == 0,
503                                            "ERROR: %s at line %d",
504                                            __FUNCTION__, __LINE__);
505 
506     error = video_channel_transport->SetLocalReceiver(video_rx_port);
507     number_of_errors += ViETest::TestError(error == 0,
508                                            "ERROR: %s at line %d",
509                                            __FUNCTION__, __LINE__);
510 
511     error = vie_codec->SetSendCodec(video_channel, video_send_codec);
512     number_of_errors += ViETest::TestError(error == 0,
513                                            "ERROR: %s at line %d",
514                                            __FUNCTION__, __LINE__);
515 
516     error = vie_codec->SetReceiveCodec(video_channel, video_send_codec);
517     number_of_errors += ViETest::TestError(error == 0,
518                                            "ERROR: %s at line %d",
519                                            __FUNCTION__, __LINE__);
520 
521     // Set the call mode (conferencing/buffering)
522     error = vie_rtp_rtcp->SetSenderBufferingMode(video_channel,
523                                                     buffer_delay_ms);
524     number_of_errors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
525                                            __FUNCTION__, __LINE__);
526     error = vie_rtp_rtcp->SetReceiverBufferingMode(video_channel,
527                                                       buffer_delay_ms);
528     number_of_errors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
529                                            __FUNCTION__, __LINE__);
530     // Set the Video Protection before start send and receive.
531     SetVideoProtection(vie_codec, vie_rtp_rtcp,
532                        video_channel, protection_method);
533 
534     // Start Voice Playout and Receive.
535     error = voe_base->StartReceive(audio_channel);
536     number_of_errors += ViETest::TestError(error == 0,
537                                            "ERROR: %s at line %d",
538                                            __FUNCTION__, __LINE__);
539 
540     error = voe_base->StartPlayout(audio_channel);
541     number_of_errors += ViETest::TestError(error == 0,
542                                            "ERROR: %s at line %d",
543                                            __FUNCTION__, __LINE__);
544 
545     error = voe_base->StartSend(audio_channel);
546     number_of_errors += ViETest::TestError(error == 0,
547                                            "ERROR: %s at line %d",
548                                            __FUNCTION__, __LINE__);
549 
550     // Now start the Video Send & Receive.
551     error = vie_base->StartSend(video_channel);
552     number_of_errors += ViETest::TestError(error == 0,
553                                            "ERROR: %s at line %d",
554                                            __FUNCTION__, __LINE__);
555 
556     error = vie_base->StartReceive(video_channel);
557     number_of_errors += ViETest::TestError(error == 0,
558                                            "ERROR: %s at line %d",
559                                            __FUNCTION__, __LINE__);
560 
561     error = vie_renderer->StartRender(capture_id);
562     number_of_errors += ViETest::TestError(error == 0,
563                                            "ERROR: %s at line %d",
564                                            __FUNCTION__, __LINE__);
565 
566     error = vie_renderer->StartRender(video_channel);
567     number_of_errors += ViETest::TestError(error == 0,
568                                            "ERROR: %s at line %d",
569                                            __FUNCTION__, __LINE__);
570 
571     ViEAutotestEncoderObserver* codec_encoder_observer = NULL;
572     ViEAutotestDecoderObserver* codec_decoder_observer = NULL;
573 
574     //  Engine ready, wait for input.
575 
576     // Call started.
577     std::cout << std::endl;
578     std::cout << "Custom call started" << std::endl;
579 
580     // Modify call or stop call.
581     printf("\n");
582     int selection = FromChoices(
583         "And now?",
584         "Stop the call\n"
585         "Modify the call\n"
586         "Keep the call running indefinitely\n")
587             .WithDefault("Keep the call running indefinitely").Choose();
588     if (selection == 3) {
589         AutoTestSleep(std::numeric_limits<int>::max());
590     }
591 
592     while (selection == 2) {
593       // Keep on modifying the call until user stops the call.
594       int modify_selection = FromChoices(
595           "Modify the call:",
596           "Stop call\n"
597           "Change Video Send Codec\n"
598           "Change Video Send Size by Common Resolutions\n"
599           "Change Video Send Size by Width & Height\n"
600           "Change Video Capture Device\n"
601           "Change Video Protection Method\n"
602           "Toggle Encoder Observer\n"
603           "Toggle Decoder Observer\n"
604           "Print Call Information\n"
605           "Print Call Statistics\n"
606           "Toggle Image Scaling (Warning: high CPU usage when enabled)\n")
607               .WithDefault("Stop call")
608               .Choose();
609 
610       switch (modify_selection) {
611         case 1:
612           selection = 1;
613           break;
614         case 2:
615           // Change video codec.
616           SetVideoCodecType(vie_codec, &video_send_codec);
617           SetVideoCodecSize(&video_send_codec);
618           SetVideoCodecBitrate(&video_send_codec);
619           SetVideoCodecMinBitrate(&video_send_codec);
620           SetVideoCodecMaxBitrate(&video_send_codec);
621           SetVideoCodecMaxFramerate(&video_send_codec);
622           SetVideoCodecTemporalLayer(&video_send_codec);
623           PrintCallInformation(ip_address.c_str(), device_name,
624                                unique_id, video_send_codec,
625                                video_tx_port, video_rx_port,
626                                audio_capture_device_name,
627                                audio_playbackDeviceName, audio_codec,
628                                audio_tx_port, audio_rx_port, protection_method);
629           error = vie_codec->SetSendCodec(video_channel, video_send_codec);
630           number_of_errors += ViETest::TestError(error == 0,
631                                                  "ERROR: %s at line %d",
632                                                  __FUNCTION__, __LINE__);
633           error = vie_codec->SetReceiveCodec(video_channel, video_send_codec);
634           number_of_errors += ViETest::TestError(error == 0,
635                                                  "ERROR: %s at line %d",
636                                                  __FUNCTION__, __LINE__);
637           break;
638         case 3:
639           // Change Video codec size by common resolution.
640           SetVideoCodecResolution(&video_send_codec);
641           PrintCallInformation(ip_address.c_str(), device_name,
642                                unique_id, video_send_codec,
643                                video_tx_port, video_rx_port,
644                                audio_capture_device_name,
645                                audio_playbackDeviceName, audio_codec,
646                                audio_tx_port, audio_rx_port, protection_method);
647           error = vie_codec->SetSendCodec(video_channel, video_send_codec);
648           number_of_errors += ViETest::TestError(error == 0,
649                                                  "ERROR: %s at line %d",
650                                                  __FUNCTION__, __LINE__);
651           error = vie_codec->SetReceiveCodec(video_channel, video_send_codec);
652           number_of_errors += ViETest::TestError(error == 0,
653                                                  "ERROR: %s at line %d",
654                                                  __FUNCTION__, __LINE__);
655           break;
656         case 4:
657           // Change video codec by size height and width.
658           SetVideoCodecSize(&video_send_codec);
659           PrintCallInformation(ip_address.c_str(), device_name,
660                                unique_id, video_send_codec,
661                                video_tx_port, video_rx_port,
662                                audio_capture_device_name,
663                                audio_playbackDeviceName, audio_codec,
664                                audio_tx_port, audio_rx_port, protection_method);
665           error = vie_codec->SetSendCodec(video_channel, video_send_codec);
666           number_of_errors += ViETest::TestError(error == 0,
667                                                  "ERROR: %s at line %d",
668                                                  __FUNCTION__, __LINE__);
669           error = vie_codec->SetReceiveCodec(video_channel, video_send_codec);
670           number_of_errors += ViETest::TestError(error == 0,
671                                                  "ERROR: %s at line %d",
672                                                  __FUNCTION__, __LINE__);
673           break;
674         case 5:
675           error = vie_renderer->StopRender(capture_id);
676           number_of_errors += ViETest::TestError(error == 0,
677                                                  "ERROR: %s at line %d",
678                                                  __FUNCTION__, __LINE__);
679           error = vie_renderer->RemoveRenderer(capture_id);
680           number_of_errors += ViETest::TestError(error == 0,
681                                                  "ERROR: %s at line %d",
682                                                  __FUNCTION__, __LINE__);
683           error = vie_capture->StopCapture(capture_id);
684           number_of_errors += ViETest::TestError(error == 0,
685                                                  "ERROR: %s at line %d",
686                                                  __FUNCTION__, __LINE__);
687           error = vie_capture->DisconnectCaptureDevice(video_channel);
688           number_of_errors += ViETest::TestError(error == 0,
689                                                  "ERROR: %s at line %d",
690                                                  __FUNCTION__, __LINE__);
691           error = vie_capture->ReleaseCaptureDevice(capture_id);
692           number_of_errors += ViETest::TestError(error == 0,
693                                                  "ERROR: %s at line %d",
694                                                  __FUNCTION__, __LINE__);
695           memset(device_name, 0, KMaxUniqueIdLength);
696           memset(unique_id, 0, KMaxUniqueIdLength);
697           if (!GetVideoDevice(vie_base, vie_capture, device_name, unique_id))
698             return number_of_errors;
699           capture_id = 0;
700           error = vie_capture->AllocateCaptureDevice(unique_id,
701                                                      KMaxUniqueIdLength,
702                                                      capture_id);
703           number_of_errors += ViETest::TestError(error == 0,
704                                                  "ERROR: %s at line %d",
705                                                  __FUNCTION__, __LINE__);
706           error = vie_capture->ConnectCaptureDevice(capture_id,
707                                                     video_channel);
708           number_of_errors += ViETest::TestError(error == 0,
709                                                  "ERROR: %s at line %d",
710                                                  __FUNCTION__, __LINE__);
711 
712           assert(FLAGS_render_custom_call_remote_to == "" &&
713                  "Not implemented to change video capture device when "
714                  "rendering to file!");
715 
716           error = vie_capture->StartCapture(capture_id);
717           number_of_errors += ViETest::TestError(error == 0,
718                                                  "ERROR: %s at line %d",
719                                                  __FUNCTION__, __LINE__);
720           error = vie_renderer->AddRenderer(capture_id, _window1, 0, 0.0, 0.0,
721                                             1.0, 1.0);
722           number_of_errors += ViETest::TestError(error == 0,
723                                                  "ERROR: %s at line %d",
724                                                  __FUNCTION__, __LINE__);
725           error = vie_renderer->StartRender(capture_id);
726           number_of_errors += ViETest::TestError(error == 0,
727                                                  "ERROR: %s at line %d",
728                                                  __FUNCTION__, __LINE__);
729           break;
730         case 6:
731           // Change the Video Protection.
732           protection_method = GetVideoProtection();
733           SetVideoProtection(vie_codec, vie_rtp_rtcp,
734                              video_channel, protection_method);
735           break;
736         case 7:
737           // Toggle Encoder Observer.
738           if (!codec_encoder_observer) {
739             std::cout << "Registering Encoder Observer" << std::endl;
740             codec_encoder_observer = new ViEAutotestEncoderObserver();
741             error = vie_codec->RegisterEncoderObserver(video_channel,
742                                                        *codec_encoder_observer);
743             number_of_errors += ViETest::TestError(error == 0,
744                                                    "ERROR: %s at line %d",
745                                                    __FUNCTION__, __LINE__);
746           } else {
747             std::cout << "Deregistering Encoder Observer" << std::endl;
748             error = vie_codec->DeregisterEncoderObserver(video_channel);
749             delete codec_encoder_observer;
750             codec_encoder_observer = NULL;
751             number_of_errors += ViETest::TestError(error == 0,
752                                                    "ERROR: %s at line %d",
753                                                    __FUNCTION__, __LINE__);
754           }
755           break;
756         case 8:
757           // Toggle Decoder Observer.
758           if (!codec_decoder_observer) {
759             std::cout << "Registering Decoder Observer" << std::endl;
760             codec_decoder_observer = new ViEAutotestDecoderObserver();
761             error = vie_codec->RegisterDecoderObserver(video_channel,
762                                                        *codec_decoder_observer);
763             number_of_errors += ViETest::TestError(error == 0,
764                                                    "ERROR: %s at line %d",
765                                                    __FUNCTION__, __LINE__);
766           } else {
767             std::cout << "Deregistering Decoder Observer" << std::endl;
768             error = vie_codec->DeregisterDecoderObserver(video_channel);
769             delete codec_decoder_observer;
770             codec_decoder_observer = NULL;
771             number_of_errors += ViETest::TestError(error == 0,
772                                                    "ERROR: %s at line %d",
773                                                    __FUNCTION__, __LINE__);
774           }
775           break;
776         case 9:
777           // Print Call information..
778           PrintCallInformation(ip_address.c_str(), device_name,
779                                unique_id, video_send_codec,
780                                video_tx_port, video_rx_port,
781                                audio_capture_device_name,
782                                audio_playbackDeviceName,
783                                audio_codec, audio_tx_port,
784                                audio_rx_port, protection_method);
785           PrintVideoStreamInformation(vie_codec,
786                                       video_channel);
787           break;
788         case 10:
789           // Print Call statistics.
790           PrintRTCCPStatistics(vie_rtp_rtcp, video_channel,
791                                kSendStatistic);
792           PrintRTCCPStatistics(vie_rtp_rtcp, video_channel,
793                                kReceivedStatistic);
794           PrintRTPStatistics(vie_rtp_rtcp, video_channel);
795           PrintBandwidthUsage(vie_rtp_rtcp, video_channel);
796           PrintCodecStatistics(vie_codec, video_channel,
797                                kSendStatistic);
798           PrintCodecStatistics(vie_codec, video_channel,
799                                kReceivedStatistic);
800           PrintGetDiscardedPackets(vie_codec, video_channel);
801           break;
802         case 11:
803           is_image_scale_enabled = !is_image_scale_enabled;
804           vie_codec->SetImageScaleStatus(video_channel, is_image_scale_enabled);
805           if (is_image_scale_enabled) {
806             std::cout << "Image Scale is now enabled" << std::endl;
807           } else {
808             std::cout << "Image Scale is now disabled" << std::endl;
809           }
810           break;
811         default:
812           assert(false);
813           break;
814       }
815     }
816 
817     if (FLAGS_render_custom_call_remote_to != "")
818       file_renderer.StopRendering();
819 
820     // Testing finished. Tear down Voice and Video Engine.
821     // Tear down the VoE first.
822     error = voe_base->StopReceive(audio_channel);
823     number_of_errors += ViETest::TestError(error == 0,
824                                            "ERROR: %s at line %d",
825                                            __FUNCTION__, __LINE__);
826 
827     error = voe_base->StopPlayout(audio_channel);
828     number_of_errors += ViETest::TestError(error == 0,
829                                            "ERROR: %s at line %d",
830                                            __FUNCTION__, __LINE__);
831 
832     error = voe_base->DeleteChannel(audio_channel);
833     number_of_errors += ViETest::TestError(error == 0,
834                                            "ERROR: %s at line %d",
835                                            __FUNCTION__, __LINE__);
836     // Now tear down the ViE engine.
837     error = vie_base->DisconnectAudioChannel(video_channel);
838 
839     voice_channel_transport.reset(NULL);
840 
841     // If Encoder/Decoder Observer is running, delete them.
842     if (codec_encoder_observer) {
843       error = vie_codec->DeregisterEncoderObserver(video_channel);
844       delete codec_encoder_observer;
845       number_of_errors += ViETest::TestError(error == 0,
846                                              "ERROR: %s at line %d",
847                                              __FUNCTION__, __LINE__);
848     }
849     if (codec_decoder_observer) {
850       error = vie_codec->DeregisterDecoderObserver(video_channel);
851       delete codec_decoder_observer;
852       number_of_errors += ViETest::TestError(error == 0,
853                                              "ERROR: %s at line %d",
854                                              __FUNCTION__, __LINE__);
855     }
856 
857     error = vie_base->StopReceive(video_channel);
858     number_of_errors += ViETest::TestError(error == 0,
859                                            "ERROR: %s at line %d",
860                                            __FUNCTION__, __LINE__);
861 
862     error = vie_base->StopSend(video_channel);
863     number_of_errors += ViETest::TestError(error == 0,
864                                            "ERROR: %s at line %d",
865                                            __FUNCTION__, __LINE__);
866 
867     error = vie_renderer->StopRender(capture_id);
868     number_of_errors += ViETest::TestError(error == 0,
869                                            "ERROR: %s at line %d",
870                                            __FUNCTION__, __LINE__);
871 
872     error = vie_renderer->StopRender(video_channel);
873     number_of_errors += ViETest::TestError(error == 0,
874                                            "ERROR: %s at line %d",
875                                            __FUNCTION__, __LINE__);
876 
877     error = vie_renderer->RemoveRenderer(capture_id);
878     number_of_errors += ViETest::TestError(error == 0,
879                                            "ERROR: %s at line %d",
880                                            __FUNCTION__, __LINE__);
881 
882     error = vie_renderer->RemoveRenderer(video_channel);
883     number_of_errors += ViETest::TestError(error == 0,
884                                            "ERROR: %s at line %d",
885                                            __FUNCTION__, __LINE__);
886 
887     error = vie_capture->StopCapture(capture_id);
888     number_of_errors += ViETest::TestError(error == 0,
889                                            "ERROR: %s at line %d",
890                                            __FUNCTION__, __LINE__);
891 
892     error = vie_capture->DisconnectCaptureDevice(video_channel);
893     number_of_errors += ViETest::TestError(error == 0,
894                                            "ERROR: %s at line %d",
895                                            __FUNCTION__, __LINE__);
896 
897     error = vie_capture->ReleaseCaptureDevice(capture_id);
898     number_of_errors += ViETest::TestError(error == 0,
899                                            "ERROR: %s at line %d",
900                                            __FUNCTION__, __LINE__);
901 
902     video_channel_transport.reset(NULL);
903 
904     error = vie_base->DeleteChannel(video_channel);
905     number_of_errors += ViETest::TestError(error == 0,
906                                            "ERROR: %s at line %d",
907                                            __FUNCTION__, __LINE__);
908 
909     int remaining_interfaces = 0;
910     remaining_interfaces = vie_codec->Release();
911     number_of_errors += ViETest::TestError(remaining_interfaces == 0,
912                                            "ERROR: %s at line %d",
913                                            __FUNCTION__, __LINE__);
914 
915     remaining_interfaces = vie_capture->Release();
916     number_of_errors += ViETest::TestError(remaining_interfaces == 0,
917                                            "ERROR: %s at line %d",
918                                            __FUNCTION__, __LINE__);
919 
920     remaining_interfaces = vie_rtp_rtcp->Release();
921     number_of_errors += ViETest::TestError(remaining_interfaces == 0,
922                                            "ERROR: %s at line %d",
923                                            __FUNCTION__, __LINE__);
924 
925     remaining_interfaces = vie_renderer->Release();
926     number_of_errors += ViETest::TestError(remaining_interfaces == 0,
927                                            "ERROR: %s at line %d",
928                                            __FUNCTION__, __LINE__);
929 
930     remaining_interfaces = vie_network->Release();
931     number_of_errors += ViETest::TestError(remaining_interfaces == 0,
932                                            "ERROR: %s at line %d",
933                                            __FUNCTION__, __LINE__);
934 
935     remaining_interfaces = vie_base->Release();
936     number_of_errors += ViETest::TestError(remaining_interfaces == 0,
937                                            "ERROR: %s at line %d",
938                                            __FUNCTION__, __LINE__);
939 
940     bool deleted = webrtc::VideoEngine::Delete(vie);
941     number_of_errors += ViETest::TestError(deleted == true,
942                                            "ERROR: %s at line %d",
943                                            __FUNCTION__, __LINE__);
944 
945     ViETest::Log(" ");
946     ViETest::Log(" ViE Autotest Custom Call Started");
947     ViETest::Log("========================================");
948     ViETest::Log(" ");
949   }
950   return number_of_errors;
951 }
952 
GetVideoDevice(webrtc::ViEBase * vie_base,webrtc::ViECapture * vie_capture,char * capture_device_name,char * capture_device_unique_id)953 bool GetVideoDevice(webrtc::ViEBase* vie_base,
954                     webrtc::ViECapture* vie_capture,
955                     char* capture_device_name,
956                     char* capture_device_unique_id) {
957   int error = 0;
958   int number_of_errors = 0;
959 
960   const unsigned int KMaxDeviceNameLength = 128;
961   const unsigned int KMaxUniqueIdLength = 256;
962   char device_name[KMaxDeviceNameLength];
963   char unique_id[KMaxUniqueIdLength];
964 
965   if (vie_capture->NumberOfCaptureDevices() == 0) {
966     printf("You have no capture devices plugged into your system.\n");
967     return false;
968   }
969 
970   std::string capture_choices;
971   std::string first_device;
972   for (int i = 0; i < vie_capture->NumberOfCaptureDevices(); i++) {
973     memset(device_name, 0, KMaxDeviceNameLength);
974     memset(unique_id, 0, KMaxUniqueIdLength);
975 
976     error = vie_capture->GetCaptureDevice(i, device_name,
977         KMaxDeviceNameLength,
978         unique_id,
979         KMaxUniqueIdLength);
980     number_of_errors += ViETest::TestError(error == 0,
981         "ERROR: %s at line %d",
982         __FUNCTION__, __LINE__);
983     const int kCaptureLineLength =
984         KMaxDeviceNameLength + KMaxUniqueIdLength + 8;
985     char capture_line[kCaptureLineLength];
986     sprintf(capture_line, "%s (%s)", device_name, unique_id);
987     capture_choices += capture_line;
988     capture_choices += "\n";
989     if (first_device.empty())
990       first_device = capture_line;
991   }
992 
993   int choice = FromChoices("Available Video Capture Devices", capture_choices)
994       .WithDefault(first_device)
995       .Choose();
996 
997   error = vie_capture->GetCaptureDevice(
998       choice - 1, device_name, KMaxDeviceNameLength, unique_id,
999       KMaxUniqueIdLength);
1000   number_of_errors += ViETest::TestError(error == 0,
1001       "ERROR: %s at line %d",
1002       __FUNCTION__, __LINE__);
1003   strcpy(capture_device_unique_id, unique_id);
1004   strcpy(capture_device_name, device_name);
1005   return true;
1006 }
1007 
GetAudioDevices(webrtc::VoEBase * voe_base,webrtc::VoEHardware * voe_hardware,char * recording_device_name,int & recording_device_index,char * playback_device_name,int & playback_device_index)1008 bool GetAudioDevices(webrtc::VoEBase* voe_base,
1009                      webrtc::VoEHardware* voe_hardware,
1010                      char* recording_device_name,
1011                      int& recording_device_index,
1012                      char* playback_device_name,
1013                      int& playback_device_index) {
1014   int error = 0;
1015   int number_of_errors = 0;
1016 
1017   const unsigned int KMaxDeviceNameLength = 128;
1018   const unsigned int KMaxUniqueIdLength = 128;
1019   char recording_device_unique_name[KMaxDeviceNameLength];
1020   char playback_device_unique_name[KMaxUniqueIdLength];
1021 
1022   int number_of_recording_devices = -1;
1023   error = voe_hardware->GetNumOfRecordingDevices(number_of_recording_devices);
1024   number_of_errors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
1025                                          __FUNCTION__, __LINE__);
1026 
1027   recording_device_index = -1;
1028   playback_device_index = -1;
1029 
1030   std::string device_choices;
1031   std::string default_recording_line;
1032   for (int i = 0; i < number_of_recording_devices; ++i) {
1033     error = voe_hardware->GetRecordingDeviceName(
1034         i, recording_device_name, recording_device_unique_name);
1035     number_of_errors += ViETest::TestError(error == 0,
1036         "ERROR: %s at line %d",
1037         __FUNCTION__, __LINE__);
1038 
1039     device_choices += recording_device_name;
1040     device_choices += "\n";
1041     if (default_recording_line.empty())
1042       default_recording_line = recording_device_name;
1043   }
1044 
1045   int choice = FromChoices("Available audio capture devices:", device_choices)
1046       .WithDefault(default_recording_line)
1047       .Choose();
1048 
1049   recording_device_index = choice - 1;
1050   error = voe_hardware->GetRecordingDeviceName(
1051       recording_device_index, recording_device_name,
1052       recording_device_unique_name);
1053   number_of_errors += ViETest::TestError(
1054       error == 0, "ERROR: %s at line %d", __FUNCTION__, __LINE__);
1055 
1056   int number_of_playback_devices = -1;
1057   error = voe_hardware->GetNumOfPlayoutDevices(number_of_playback_devices);
1058   number_of_errors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
1059                                          __FUNCTION__, __LINE__);
1060 
1061 
1062   std::string playback_choices;
1063   std::string default_playback_line;
1064   for (int i = 0; i < number_of_playback_devices; i++) {
1065     error = voe_hardware->GetPlayoutDeviceName(i,
1066         playback_device_name,
1067         playback_device_unique_name);
1068     number_of_errors += ViETest::TestError(
1069         error == 0, "ERROR: %s at line %d", __FUNCTION__, __LINE__);
1070     playback_choices += playback_device_name;
1071     playback_choices += "\n";
1072     if (default_playback_line.empty())
1073       default_playback_line = playback_device_name;
1074   }
1075 
1076   choice = FromChoices("Available audio playout devices:", playback_choices)
1077       .WithDefault(default_playback_line)
1078       .Choose();
1079 
1080   playback_device_index = choice - 1;
1081   error = voe_hardware->GetPlayoutDeviceName(playback_device_index,
1082       playback_device_name,
1083       playback_device_unique_name);
1084   number_of_errors += ViETest::TestError(error == 0,
1085       "ERROR: %s at line %d",
1086       __FUNCTION__, __LINE__);
1087   return true;
1088 }
1089 
1090 // General helper functions.
1091 
GetIPAddress()1092 std::string GetIPAddress() {
1093   class IpValidator : public webrtc::InputValidator {
1094    public:
1095     bool InputOk(const std::string& input) const {
1096       // Just check quickly that it's on the form x.y.z.w
1097       return std::count(input.begin(), input.end(), '.') == 3;
1098     }
1099   };
1100   return TypedInput("Enter destination IP.")
1101       .WithDefault(DEFAULT_SEND_IP)
1102       .WithInputValidator(new IpValidator())
1103       .AskForInput();
1104 }
1105 
1106 // Video settings functions.
1107 
GetVideoPorts(int * tx_port,int * rx_port)1108 void GetVideoPorts(int* tx_port, int* rx_port) {
1109   std::string tx_input = TypedInput("Enter video send port.")
1110       .WithDefault(DEFAULT_VIDEO_PORT)
1111       .WithInputValidator(new webrtc::IntegerWithinRangeValidator(1, 65536))
1112       .AskForInput();
1113   *tx_port = atoi(tx_input.c_str());
1114 
1115   std::string rx_input = TypedInput("Enter video receive port.")
1116       .WithDefault(DEFAULT_VIDEO_PORT)
1117       .WithInputValidator(new webrtc::IntegerWithinRangeValidator(1, 65536))
1118       .AskForInput();
1119   *rx_port = atoi(rx_input.c_str());
1120 }
1121 
1122 // Audio settings functions.
1123 
GetAudioPorts(int * tx_port,int * rx_port)1124 void GetAudioPorts(int* tx_port, int* rx_port) {
1125   std::string tx_input = TypedInput("Enter audio send port.")
1126       .WithDefault(DEFAULT_AUDIO_PORT)
1127       .WithInputValidator(new webrtc::IntegerWithinRangeValidator(1, 65536))
1128       .AskForInput();
1129   *tx_port = atoi(tx_input.c_str());
1130 
1131   std::string rx_input = TypedInput("Enter audio receive port.")
1132       .WithDefault(DEFAULT_AUDIO_PORT)
1133       .WithInputValidator(new webrtc::IntegerWithinRangeValidator(1, 65536))
1134       .AskForInput();
1135   *rx_port = atoi(rx_input.c_str());
1136 }
1137 
GetAudioCodec(webrtc::VoECodec * voe_codec,webrtc::CodecInst & audio_codec)1138 bool GetAudioCodec(webrtc::VoECodec* voe_codec,
1139                    webrtc::CodecInst& audio_codec) {
1140   int error = 0;
1141   memset(&audio_codec, 0, sizeof(webrtc::CodecInst));
1142 
1143   std::string default_codec_line;
1144   std::string codec_choices;
1145   for (int codec_idx = 0; codec_idx < voe_codec->NumOfCodecs(); codec_idx++) {
1146     error = voe_codec->GetCodec(codec_idx, audio_codec);
1147     ViETest::TestError(error == 0,
1148         "ERROR: %s at line %d",
1149         __FUNCTION__, __LINE__);
1150 
1151     char codec_line[128];
1152     sprintf(codec_line, "%s type: %d freq: %d chan: %d",
1153         audio_codec.plname, audio_codec.pltype, audio_codec.plfreq,
1154         audio_codec.channels);
1155     codec_choices += codec_line;
1156     codec_choices += "\n";
1157 
1158     if (strcmp(audio_codec.plname, DEFAULT_AUDIO_CODEC) == 0) {
1159       default_codec_line = codec_line;
1160     }
1161   }
1162   assert(!default_codec_line.empty() && "Default codec doesn't exist.");
1163 
1164   int codec_selection = FromChoices("Available Audio Codecs:", codec_choices)
1165             .WithDefault(default_codec_line)
1166             .Choose();
1167 
1168   error = voe_codec->GetCodec(codec_selection - 1, audio_codec);
1169   ViETest::TestError(error == 0,
1170       "ERROR: %s at line %d",
1171       __FUNCTION__, __LINE__);
1172   return true;
1173 }
1174 
PrintCallInformation(const char * IP,const char * video_capture_device_name,const char * video_capture_unique_id,webrtc::VideoCodec video_codec,int video_tx_port,int video_rx_port,const char * audio_capture_device_name,const char * audio_playbackDeviceName,webrtc::CodecInst audio_codec,int audio_tx_port,int audio_rx_port,int protection_method)1175 void PrintCallInformation(const char* IP, const char* video_capture_device_name,
1176                           const char* video_capture_unique_id,
1177                           webrtc::VideoCodec video_codec,
1178                           int video_tx_port, int video_rx_port,
1179                           const char* audio_capture_device_name,
1180                           const char* audio_playbackDeviceName,
1181                           webrtc::CodecInst audio_codec,
1182                           int audio_tx_port, int audio_rx_port,
1183                           int protection_method) {
1184   std::string str;
1185 
1186   std::cout << "************************************************"
1187             << std::endl;
1188   std::cout << "The call has the following settings: " << std::endl;
1189   std::cout << "\tIP: " << IP << std::endl;
1190   std::cout << "\tVideo Capture Device: " << video_capture_device_name
1191             << std::endl;
1192   std::cout << "\t\tName: " << video_capture_device_name << std::endl;
1193   std::cout << "\t\tUniqueId: " << video_capture_unique_id << std::endl;
1194   PrintVideoCodec(video_codec);
1195   std::cout << "\t Video Tx Port: " << video_tx_port << std::endl;
1196   std::cout << "\t Video Rx Port: " << video_rx_port << std::endl;
1197   std::cout << "\t Video Protection Method (NOTE: Starts at 1 now): "
1198             << protection_method  << std::endl;
1199   std::cout << "\tAudio Capture Device: " << audio_capture_device_name
1200             << std::endl;
1201   std::cout << "\tAudio Playback Device: " << audio_playbackDeviceName
1202             << std::endl;
1203   std::cout << "\tAudio Codec: " << std::endl;
1204   std::cout << "\t\tplname: " << audio_codec.plname << std::endl;
1205   std::cout << "\t\tpltype: " << static_cast<int>(audio_codec.pltype)
1206             << std::endl;
1207   std::cout << "\t Audio Tx Port: " << audio_tx_port << std::endl;
1208   std::cout << "\t Audio Rx Port: " << audio_rx_port << std::endl;
1209   std::cout << "************************************************"
1210             << std::endl;
1211 }
1212 
SetVideoCodecType(webrtc::ViECodec * vie_codec,webrtc::VideoCodec * video_codec)1213 void SetVideoCodecType(webrtc::ViECodec* vie_codec,
1214                        webrtc::VideoCodec* video_codec) {
1215   int error = 0;
1216   int number_of_errors = 0;
1217   memset(video_codec, 0, sizeof(webrtc::VideoCodec));
1218 
1219   std::string codec_choices;
1220   std::string default_codec_line;
1221   for (int i = 0; i < vie_codec->NumberOfCodecs(); i++) {
1222     error = vie_codec->GetCodec(i, *video_codec);
1223     number_of_errors += ViETest::TestError(
1224         error == 0, "ERROR: %s at line %d", __FUNCTION__, __LINE__);
1225 
1226     codec_choices += video_codec->plName;
1227     codec_choices += "\n";
1228     if (strcmp(video_codec->plName, DEFAULT_VIDEO_CODEC) == 0)
1229       default_codec_line = video_codec->plName;
1230   }
1231   assert(!default_codec_line.empty() && "Default does not exist.");
1232 
1233   int choice = FromChoices("Available Video Codecs", codec_choices)
1234       .WithDefault(default_codec_line)
1235       .Choose();
1236   error = vie_codec->GetCodec(choice - 1, *video_codec);
1237   number_of_errors += ViETest::TestError(
1238       error == 0, "ERROR: %s at line %d", __FUNCTION__, __LINE__);
1239 
1240   if (video_codec->codecType == webrtc::kVideoCodecI420) {
1241     video_codec->width = 176;
1242     video_codec->height = 144;
1243   }
1244 }
1245 
SetVideoCodecResolution(webrtc::VideoCodec * video_codec)1246 void SetVideoCodecResolution(webrtc::VideoCodec* video_codec) {
1247   if (video_codec->codecType != webrtc::kVideoCodecVP8) {
1248     printf("Can only change codec size if it's VP8\n");
1249     return;
1250   }
1251 
1252   int choice = FromChoices(
1253       "Available Common Resolutions:",
1254       "SQCIF (128X96)\n"
1255       "QQVGA (160X120)\n"
1256       "QCIF  (176X144)\n"
1257       "CIF   (352X288)\n"
1258       "VGA   (640X480)\n"
1259       "WVGA  (800x480)\n"
1260       "4CIF  (704X576)\n"
1261       "SVGA  (800X600)\n"
1262       "HD    (1280X720)\n"
1263       "XGA   (1024x768)\n")
1264           .Choose();
1265 
1266   switch (choice) {
1267     case 1:
1268       video_codec->width = 128;
1269       video_codec->height = 96;
1270       break;
1271     case 2:
1272       video_codec->width = 160;
1273       video_codec->height = 120;
1274       break;
1275     case 3:
1276       video_codec->width = 176;
1277       video_codec->height = 144;
1278       break;
1279     case 4:
1280       video_codec->width = 352;
1281       video_codec->height = 288;
1282       break;
1283     case 5:
1284       video_codec->width = 640;
1285       video_codec->height = 480;
1286       break;
1287     case 6:
1288       video_codec->width = 800;
1289       video_codec->height = 480;
1290       break;
1291     case 7:
1292       video_codec->width = 704;
1293       video_codec->height = 576;
1294       break;
1295     case 8:
1296       video_codec->width = 800;
1297       video_codec->height = 600;
1298       break;
1299     case 9:
1300       video_codec->width = 1280;
1301       video_codec->height = 720;
1302       break;
1303     case 10:
1304       video_codec->width = 1024;
1305       video_codec->height = 768;
1306       break;
1307   }
1308 }
1309 
SetVideoCodecSize(webrtc::VideoCodec * video_codec)1310 void SetVideoCodecSize(webrtc::VideoCodec* video_codec) {
1311   if (video_codec->codecType != webrtc::kVideoCodecVP8) {
1312     printf("Can only change codec size if it's VP8\n");
1313     return;
1314   }
1315 
1316   std::string input = TypedInput("Choose video width.")
1317       .WithDefault(DEFAULT_VIDEO_CODEC_WIDTH)
1318       .WithInputValidator(new webrtc::IntegerWithinRangeValidator(1, INT_MAX))
1319       .AskForInput();
1320   video_codec->width = atoi(input.c_str());
1321 
1322   input = TypedInput("Choose video height.")
1323       .WithDefault(DEFAULT_VIDEO_CODEC_HEIGHT)
1324       .WithInputValidator(new webrtc::IntegerWithinRangeValidator(1, INT_MAX))
1325       .AskForInput();
1326   video_codec->height = atoi(input.c_str());
1327 }
1328 
SetVideoCodecBitrate(webrtc::VideoCodec * video_codec)1329 void SetVideoCodecBitrate(webrtc::VideoCodec* video_codec) {
1330   std::string input = TypedInput("Choose start rate (in kbps).")
1331       .WithDefault(DEFAULT_VIDEO_CODEC_BITRATE)
1332       .WithInputValidator(new webrtc::IntegerWithinRangeValidator(1, INT_MAX))
1333       .AskForInput();
1334 
1335   video_codec->startBitrate = atoi(input.c_str());
1336 }
1337 
SetVideoCodecMaxBitrate(webrtc::VideoCodec * video_codec)1338 void SetVideoCodecMaxBitrate(webrtc::VideoCodec* video_codec) {
1339   std::string input = TypedInput("Choose max bitrate (in kbps).")
1340       .WithDefault(DEFAULT_VIDEO_CODEC_MAX_BITRATE)
1341       .WithInputValidator(new webrtc::IntegerWithinRangeValidator(1, INT_MAX))
1342       .AskForInput();
1343 
1344   video_codec->maxBitrate = atoi(input.c_str());
1345 }
1346 
SetVideoCodecMinBitrate(webrtc::VideoCodec * video_codec)1347 void SetVideoCodecMinBitrate(webrtc::VideoCodec* video_codec) {
1348   std::string input = TypedInput("Choose min bitrate (in kbps).")
1349       .WithDefault(DEFAULT_VIDEO_CODEC_MIN_BITRATE)
1350       .WithInputValidator(new webrtc::IntegerWithinRangeValidator(1, INT_MAX))
1351       .AskForInput();
1352 
1353   video_codec->minBitrate = atoi(input.c_str());
1354 }
1355 
SetVideoCodecMaxFramerate(webrtc::VideoCodec * video_codec)1356 void SetVideoCodecMaxFramerate(webrtc::VideoCodec* video_codec) {
1357   std::string input = TypedInput("Choose max framerate (in fps).")
1358       .WithDefault(DEFAULT_VIDEO_CODEC_MAX_FRAMERATE)
1359       .WithInputValidator(new webrtc::IntegerWithinRangeValidator(1, INT_MAX))
1360       .AskForInput();
1361   video_codec->maxFramerate = atoi(input.c_str());
1362 }
1363 
SetVideoCodecTemporalLayer(webrtc::VideoCodec * video_codec)1364 void SetVideoCodecTemporalLayer(webrtc::VideoCodec* video_codec) {
1365   if (video_codec->codecType != webrtc::kVideoCodecVP8)
1366     return;
1367 
1368   std::string input = TypedInput("Choose number of temporal layers (0 to 4).")
1369       .WithDefault(DEFAULT_TEMPORAL_LAYER)
1370       .WithInputValidator(new webrtc::IntegerWithinRangeValidator(0, 4))
1371       .AskForInput();
1372   video_codec->codecSpecific.VP8.numberOfTemporalLayers = atoi(input.c_str());
1373 }
1374 
1375 // GetVideoProtection only prints the prompt to get a number
1376 // that SetVideoProtection method uses.
GetVideoProtection()1377 VideoProtectionMethod GetVideoProtection() {
1378   int choice = FromChoices(
1379       "Available Video Protection Methods:",
1380       "None\n"
1381       "FEC\n"
1382       "NACK\n"
1383       "NACK+FEC\n")
1384           .WithDefault(DEFAULT_VIDEO_PROTECTION_METHOD)
1385           .Choose();
1386 
1387   assert(choice >= kProtectionMethodNone &&
1388          choice <= kProtectionMethodHybridNackAndFec);
1389   return static_cast<VideoProtectionMethod>(choice);
1390 }
1391 
SetVideoProtection(webrtc::ViECodec * vie_codec,webrtc::ViERTP_RTCP * vie_rtp_rtcp,int video_channel,VideoProtectionMethod protection_method)1392 bool SetVideoProtection(webrtc::ViECodec* vie_codec,
1393                         webrtc::ViERTP_RTCP* vie_rtp_rtcp,
1394                         int video_channel,
1395                         VideoProtectionMethod protection_method) {
1396   int error = 0;
1397   int number_of_errors = 0;
1398   webrtc::VideoCodec video_codec;
1399 
1400   memset(&video_codec, 0, sizeof(webrtc::VideoCodec));
1401 
1402   // Set all video protection to false initially
1403   error = vie_rtp_rtcp->SetHybridNACKFECStatus(video_channel, false,
1404                                                VCM_RED_PAYLOAD_TYPE,
1405                                                VCM_ULPFEC_PAYLOAD_TYPE);
1406   number_of_errors += ViETest::TestError(error == 0,
1407                                          "ERROR: %s at line %d",
1408                                          __FUNCTION__, __LINE__);
1409   error = vie_rtp_rtcp->SetFECStatus(video_channel, false,
1410                                      VCM_RED_PAYLOAD_TYPE,
1411                                      VCM_ULPFEC_PAYLOAD_TYPE);
1412   number_of_errors += ViETest::TestError(error == 0,
1413                                          "ERROR: %s at line %d",
1414                                          __FUNCTION__, __LINE__);
1415   error = vie_rtp_rtcp->SetNACKStatus(video_channel, false);
1416   number_of_errors += ViETest::TestError(error == 0,
1417                                          "ERROR: %s at line %d",
1418                                          __FUNCTION__, __LINE__);
1419   // Set video protection for FEC, NACK or Hybrid.
1420   switch (protection_method) {
1421     case kProtectionMethodNone:
1422       // No protection selected, all protection already at false.
1423       std::cout << "Call using None protection Method" << std::endl;
1424       break;
1425     case kProtectionMethodFecOnly:
1426       std::cout << "Call using FEC protection Method" << std::endl;
1427       error = vie_rtp_rtcp->SetFECStatus(video_channel, true,
1428                                          VCM_RED_PAYLOAD_TYPE,
1429                                          VCM_ULPFEC_PAYLOAD_TYPE);
1430       number_of_errors += ViETest::TestError(error == 0,
1431                                              "ERROR: %s at line %d",
1432                                              __FUNCTION__, __LINE__);
1433       break;
1434     case kProtectionMethodNackOnly:
1435       std::cout << "Call using NACK protection Method" << std::endl;
1436       error = vie_rtp_rtcp->SetNACKStatus(video_channel, true);
1437       number_of_errors += ViETest::TestError(error == 0,
1438                                              "ERROR: %s at line %d",
1439                                              __FUNCTION__, __LINE__);
1440       break;
1441     case kProtectionMethodHybridNackAndFec:
1442       std::cout << "Call using Hybrid NACK and FEC protection Method"
1443                 << std::endl;
1444       error = vie_rtp_rtcp->SetHybridNACKFECStatus(video_channel, true,
1445                                                    VCM_RED_PAYLOAD_TYPE,
1446                                                    VCM_ULPFEC_PAYLOAD_TYPE);
1447       number_of_errors += ViETest::TestError(error == 0,
1448                                              "ERROR: %s at line %d",
1449                                              __FUNCTION__, __LINE__);
1450       break;
1451   }
1452 
1453   // Set receive codecs for FEC and hybrid NACK/FEC.
1454   if (protection_method == kProtectionMethodFecOnly ||
1455       protection_method == kProtectionMethodHybridNackAndFec) {
1456     // RED.
1457     error = vie_codec->GetCodec(vie_codec->NumberOfCodecs() - 2,
1458                                 video_codec);
1459     number_of_errors += ViETest::TestError(error == 0,
1460                                            "ERROR: %s at line %d",
1461                                            __FUNCTION__, __LINE__);
1462     video_codec.plType = VCM_RED_PAYLOAD_TYPE;
1463     error = vie_codec->SetReceiveCodec(video_channel, video_codec);
1464     number_of_errors += ViETest::TestError(error == 0,
1465                                            "ERROR: %s at line %d",
1466                                            __FUNCTION__, __LINE__);
1467     std::cout << "RED Codec Information:" << std::endl;
1468     PrintVideoCodec(video_codec);
1469     // ULPFEC.
1470     error = vie_codec->GetCodec(vie_codec->NumberOfCodecs() - 1,
1471                                 video_codec);
1472     number_of_errors += ViETest::TestError(error == 0,
1473                                            "ERROR: %s at line %d",
1474                                            __FUNCTION__, __LINE__);
1475     video_codec.plType = VCM_ULPFEC_PAYLOAD_TYPE;
1476     error = vie_codec->SetReceiveCodec(video_channel, video_codec);
1477     number_of_errors += ViETest::TestError(error == 0,
1478                                            "ERROR: %s at line %d",
1479                                            __FUNCTION__, __LINE__);
1480     std::cout << "ULPFEC Codec Information:" << std::endl;
1481     PrintVideoCodec(video_codec);
1482   }
1483 
1484   return true;
1485 }
1486 
1487 // Returns true if REMB, false if TMMBR.
GetBitrateSignaling()1488 bool GetBitrateSignaling() {
1489   int choice = FromChoices(
1490       "Available Bitrate Signaling Methods:",
1491       "REMB\n"
1492       "TMMBR\n")
1493           .WithDefault("REMB")
1494           .Choose();
1495   return choice == 1;
1496 }
1497 
GetBufferingDelay()1498 int GetBufferingDelay() {
1499   std::string input = TypedInput("Choose buffering delay (mS).")
1500       .WithDefault(DEFAULT_BUFFERING_DELAY_MS)
1501       .WithInputValidator(new webrtc::IntegerWithinRangeValidator(0, 10000))
1502       .AskForInput();
1503   std::string delay_ms = input;
1504   return atoi(delay_ms.c_str());
1505 }
1506 
PrintRTCCPStatistics(webrtc::ViERTP_RTCP * vie_rtp_rtcp,int video_channel,StatisticsType stat_type)1507 void PrintRTCCPStatistics(webrtc::ViERTP_RTCP* vie_rtp_rtcp,
1508                           int video_channel,
1509                           StatisticsType stat_type) {
1510   int error = 0;
1511   int number_of_errors = 0;
1512   webrtc::RtcpStatistics rtcp_stats;
1513   int rtt_ms = 0;
1514 
1515   switch (stat_type) {
1516     case kReceivedStatistic:
1517       std::cout << "RTCP Received statistics"
1518                 << std::endl;
1519       // Get and print the Received RTCP Statistics
1520       error = vie_rtp_rtcp->GetReceiveChannelRtcpStatistics(video_channel,
1521                                                       rtcp_stats,
1522                                                       rtt_ms);
1523       number_of_errors += ViETest::TestError(error == 0,
1524                                              "ERROR: %s at line %d",
1525                                              __FUNCTION__, __LINE__);
1526       break;
1527     case kSendStatistic:
1528       std::cout << "RTCP Sent statistics"
1529                 << std::endl;
1530       // Get and print the Sent RTCP Statistics
1531       error = vie_rtp_rtcp->GetSendChannelRtcpStatistics(video_channel,
1532                                                   rtcp_stats,
1533                                                   rtt_ms);
1534       number_of_errors += ViETest::TestError(error == 0,
1535                                              "ERROR: %s at line %d",
1536                                              __FUNCTION__, __LINE__);
1537       break;
1538   }
1539   std::cout << "\tRTCP fraction of lost packets: "
1540             << rtcp_stats.fraction_lost << std::endl;
1541   std::cout << "\tRTCP cumulative number of lost packets: "
1542             << rtcp_stats.cumulative_lost << std::endl;
1543   std::cout << "\tRTCP max received sequence number "
1544             << rtcp_stats.extended_max_sequence_number << std::endl;
1545   std::cout << "\tRTCP jitter: "
1546             << rtcp_stats.jitter << std::endl;
1547   std::cout << "\tRTCP round trip (ms): "
1548             << rtt_ms << std::endl;
1549 }
1550 
PrintRTPStatistics(webrtc::ViERTP_RTCP * vie_rtp_rtcp,int video_channel)1551 void PrintRTPStatistics(webrtc::ViERTP_RTCP* vie_rtp_rtcp,
1552                         int video_channel) {
1553   int error = 0;
1554   int number_of_errors = 0;
1555   webrtc::StreamDataCounters sent;
1556   webrtc::StreamDataCounters received;
1557 
1558   std::cout << "RTP statistics"
1559             << std::endl;
1560 
1561   // Get and print the RTP Statistics
1562   error = vie_rtp_rtcp->GetRtpStatistics(video_channel, sent, received);
1563   number_of_errors += ViETest::TestError(error == 0,
1564                                          "ERROR: %s at line %d",
1565                                          __FUNCTION__, __LINE__);
1566   std::cout << "\tRTP bytes sent: "
1567             << sent.bytes << std::endl;
1568   std::cout << "\tRTP packets sent: "
1569             << sent.packets << std::endl;
1570   std::cout << "\tRTP bytes received: "
1571             << received.bytes << std::endl;
1572   std::cout << "\tRTP packets received: "
1573             << received.packets << std::endl;
1574 }
1575 
PrintBandwidthUsage(webrtc::ViERTP_RTCP * vie_rtp_rtcp,int video_channel)1576 void PrintBandwidthUsage(webrtc::ViERTP_RTCP* vie_rtp_rtcp,
1577                          int video_channel) {
1578   int error = 0;
1579   int number_of_errors = 0;
1580   unsigned int total_bitrate_sent = 0;
1581   unsigned int video_bitrate_sent = 0;
1582   unsigned int fec_bitrate_sent = 0;
1583   unsigned int nack_bitrate_sent = 0;
1584   double percentage_fec = 0;
1585   double percentage_nack = 0;
1586 
1587   std::cout << "Bandwidth Usage" << std::endl;
1588 
1589   // Get and print Bandwidth usage
1590   error = vie_rtp_rtcp->GetBandwidthUsage(video_channel, total_bitrate_sent,
1591                                           video_bitrate_sent, fec_bitrate_sent,
1592                                           nack_bitrate_sent);
1593   number_of_errors += ViETest::TestError(error == 0,
1594                                          "ERROR: %s at line %d",
1595                                          __FUNCTION__, __LINE__);
1596   std::cout << "\tTotal bitrate sent (Kbit/s): "
1597             << total_bitrate_sent << std::endl;
1598   std::cout << "\tVideo bitrate sent (Kbit/s): "
1599             << video_bitrate_sent << std::endl;
1600   std::cout << "\tFEC bitrate sent (Kbit/s): "
1601             << fec_bitrate_sent << std::endl;
1602   percentage_fec =
1603       (static_cast<double>(fec_bitrate_sent) /
1604       static_cast<double>(total_bitrate_sent)) * 100;
1605   std::cout << "\tPercentage FEC bitrate sent from total bitrate: "
1606             << percentage_fec << std::endl;
1607   std::cout << "\tNACK bitrate sent (Kbit/s): "
1608             << nack_bitrate_sent << std::endl;
1609   percentage_nack =
1610       (static_cast<double>(nack_bitrate_sent) /
1611       static_cast<double>(total_bitrate_sent)) * 100;
1612   std::cout << "\tPercentage NACK bitrate sent from total bitrate: "
1613             << percentage_nack << std::endl;
1614 }
1615 
PrintCodecStatistics(webrtc::ViECodec * vie_codec,int video_channel,StatisticsType stat_type)1616 void PrintCodecStatistics(webrtc::ViECodec* vie_codec,
1617                           int video_channel,
1618                           StatisticsType stat_type) {
1619   int error = 0;
1620   int number_of_errors = 0;
1621   unsigned int key_frames = 0;
1622   unsigned int delta_frames = 0;
1623   switch (stat_type) {
1624     case kReceivedStatistic:
1625       std::cout << "Codec Receive statistics"
1626                 << std::endl;
1627       // Get and print the Receive Codec Statistics
1628       error = vie_codec->GetReceiveCodecStastistics(video_channel, key_frames,
1629                                                     delta_frames);
1630       number_of_errors += ViETest::TestError(error == 0,
1631                                              "ERROR: %s at line %d",
1632                                              __FUNCTION__, __LINE__);
1633       break;
1634     case kSendStatistic:
1635       std::cout << "Codec Send statistics"
1636                 << std::endl;
1637       // Get and print the Send Codec Statistics
1638       error = vie_codec->GetSendCodecStastistics(video_channel, key_frames,
1639                                                  delta_frames);
1640       number_of_errors += ViETest::TestError(error == 0,
1641                                              "ERROR: %s at line %d",
1642                                              __FUNCTION__, __LINE__);
1643       break;
1644   }
1645   std::cout << "\tNumber of encoded key frames: "
1646             << key_frames << std::endl;
1647   std::cout << "\tNumber of encoded delta frames: "
1648             << delta_frames << std::endl;
1649 }
1650 
PrintGetDiscardedPackets(webrtc::ViECodec * vie_codec,int video_channel)1651 void PrintGetDiscardedPackets(webrtc::ViECodec* vie_codec, int video_channel) {
1652   std::cout << "Discarded Packets" << std::endl;
1653   int discarded_packets = 0;
1654   discarded_packets = vie_codec->GetDiscardedPackets(video_channel);
1655   std::cout << "\tNumber of discarded packets: "
1656             << discarded_packets << std::endl;
1657 }
1658 
PrintVideoStreamInformation(webrtc::ViECodec * vie_codec,int video_channel)1659 void PrintVideoStreamInformation(webrtc::ViECodec* vie_codec,
1660                                  int video_channel) {
1661   webrtc::VideoCodec outgoing_codec;
1662   webrtc::VideoCodec incoming_codec;
1663 
1664   memset(&outgoing_codec, 0, sizeof(webrtc::VideoCodec));
1665   memset(&incoming_codec, 0, sizeof(webrtc::VideoCodec));
1666 
1667   vie_codec->GetSendCodec(video_channel, outgoing_codec);
1668   vie_codec->GetReceiveCodec(video_channel, incoming_codec);
1669 
1670   std::cout << "************************************************"
1671             << std::endl;
1672   std::cout << "ChannelId: " << video_channel << std::endl;
1673   std::cout << "Outgoing Stream information:" << std::endl;
1674   PrintVideoCodec(outgoing_codec);
1675   std::cout << "Incoming Stream information:" << std::endl;
1676   PrintVideoCodec(incoming_codec);
1677   std::cout << "************************************************"
1678             << std::endl;
1679 }
1680 
PrintVideoCodec(webrtc::VideoCodec video_codec)1681 void PrintVideoCodec(webrtc::VideoCodec video_codec) {
1682   std::cout << "\t\tplName: " << video_codec.plName << std::endl;
1683   std::cout << "\t\tplType: " << static_cast<int>(video_codec.plType)
1684             << std::endl;
1685   std::cout << "\t\twidth: " << video_codec.width << std::endl;
1686   std::cout << "\t\theight: " << video_codec.height << std::endl;
1687   std::cout << "\t\tstartBitrate: " << video_codec.startBitrate
1688             << std::endl;
1689   std::cout << "\t\tminBitrate: " << video_codec.minBitrate
1690             << std::endl;
1691   std::cout << "\t\tmaxBitrate: " << video_codec.maxBitrate
1692             << std::endl;
1693   std::cout << "\t\tmaxFramerate: "
1694             << static_cast<int>(video_codec.maxFramerate) << std::endl;
1695   if (video_codec.codecType == webrtc::kVideoCodecVP8) {
1696     int number_of_layers =
1697         static_cast<int>(video_codec.codecSpecific.VP8.numberOfTemporalLayers);
1698     std::cout << "\t\tVP8 Temporal Layer: " << number_of_layers << std::endl;
1699   }
1700 }
1701