Home | History | Annotate | Download | only in source
      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:
     66   ViEAutotestEncoderObserver() {}
     67   ~ViEAutotestEncoderObserver() {}
     68 
     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 
     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:
     83   ViEAutotestDecoderObserver() {}
     84   ~ViEAutotestDecoderObserver() {}
     85 
     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 
     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 
    109   void IncomingCodecChanged(const int video_channel,
    110                             const webrtc::VideoCodec& codec) {}
    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 
    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 
    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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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.
   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 
   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.
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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