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