PageRenderTime 6ms CodeModel.GetById 3ms app.highlight 148ms RepoModel.GetById 0ms app.codeStats 1ms

/webrtc/video_engine/test/auto_test/source/vie_autotest_custom_call.cc

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