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 <iostream>  // NOLINT
     12 
     13 #include "webrtc/common_types.h"
     14 #include "webrtc/video_engine/include/vie_base.h"
     15 #include "webrtc/video_engine/include/vie_capture.h"
     16 #include "webrtc/video_engine/include/vie_codec.h"
     17 #include "webrtc/video_engine/include/vie_network.h"
     18 #include "webrtc/video_engine/include/vie_render.h"
     19 #include "webrtc/video_engine/include/vie_rtp_rtcp.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/libvietest/include/tb_external_transport.h"
     23 #include "webrtc/voice_engine/include/voe_base.h"
     24 
     25 enum RelayMode {
     26   kRelayOneStream = 1,
     27   kRelayAllStreams = 2
     28 };
     29 
     30 #define VCM_RED_PAYLOAD_TYPE        96
     31 #define VCM_ULPFEC_PAYLOAD_TYPE     97
     32 
     33 const int kNumStreams = 3;
     34 
     35 void InitialSingleStreamSettings(webrtc::VideoCodec* video_codec) {
     36   video_codec->numberOfSimulcastStreams = 0;
     37   video_codec->width = 1200;
     38   video_codec->height = 800;
     39 }
     40 
     41 void SetSimulcastSettings(webrtc::VideoCodec* video_codec) {
     42   video_codec->width = 1280;
     43   video_codec->height = 720;
     44 
     45   // Simulcast settings.
     46   video_codec->numberOfSimulcastStreams = kNumStreams;
     47   video_codec->simulcastStream[0].width = 320;
     48   video_codec->simulcastStream[0].height = 180;
     49   video_codec->simulcastStream[0].numberOfTemporalLayers = 0;
     50   video_codec->simulcastStream[0].maxBitrate = 100;
     51   video_codec->simulcastStream[0].targetBitrate = 100;
     52   video_codec->simulcastStream[0].minBitrate = 0;
     53   video_codec->simulcastStream[0].qpMax = video_codec->qpMax;
     54 
     55   video_codec->simulcastStream[1].width = 640;
     56   video_codec->simulcastStream[1].height = 360;
     57   video_codec->simulcastStream[1].numberOfTemporalLayers = 0;
     58   video_codec->simulcastStream[1].maxBitrate = 500;
     59   video_codec->simulcastStream[1].targetBitrate = 500;
     60   video_codec->simulcastStream[1].minBitrate = 200;
     61   video_codec->simulcastStream[1].qpMax = video_codec->qpMax;
     62 
     63   video_codec->simulcastStream[2].width = 1280;
     64   video_codec->simulcastStream[2].height = 720;
     65   video_codec->simulcastStream[2].numberOfTemporalLayers = 0;
     66   video_codec->simulcastStream[2].maxBitrate = 1200;
     67   video_codec->simulcastStream[2].targetBitrate = 1200;
     68   video_codec->simulcastStream[2].minBitrate = 900;
     69   video_codec->simulcastStream[2].qpMax = video_codec->qpMax;
     70 }
     71 
     72 void RuntimeSingleStreamSettings(webrtc::VideoCodec* video_codec) {
     73   SetSimulcastSettings(video_codec);
     74   video_codec->width = 1200;
     75   video_codec->height = 800;
     76   video_codec->numberOfSimulcastStreams = kNumStreams;
     77   video_codec->simulcastStream[0].maxBitrate = 0;
     78   video_codec->simulcastStream[0].targetBitrate = 0;
     79   video_codec->simulcastStream[0].minBitrate = 0;
     80   video_codec->simulcastStream[1].maxBitrate = 0;
     81   video_codec->simulcastStream[1].targetBitrate = 0;
     82   video_codec->simulcastStream[1].minBitrate = 0;
     83   video_codec->simulcastStream[2].maxBitrate = 0;
     84   video_codec->simulcastStream[2].targetBitrate = 0;
     85   video_codec->simulcastStream[2].minBitrate = 0;
     86 }
     87 
     88 int VideoEngineSimulcastTest(void* window1, void* window2) {
     89   // *******************************************************
     90   //  Begin create/initialize Video Engine for testing
     91   // *******************************************************
     92 
     93   int error = 0;
     94   int receive_channels[kNumStreams];
     95 
     96   // Create a VideoEngine instance.
     97   webrtc::VideoEngine* video_engine = NULL;
     98   video_engine = webrtc::VideoEngine::Create();
     99   if (video_engine == NULL) {
    100     printf("ERROR in VideoEngine::Create\n");
    101     return -1;
    102   }
    103 
    104   error = video_engine->SetTraceFilter(webrtc::kTraceAll);
    105   if (error == -1) {
    106     printf("ERROR in VideoEngine::SetTraceLevel\n");
    107     return -1;
    108   }
    109 
    110   std::string trace_file =
    111     ViETest::GetResultOutputPath() + "ViESimulcast_trace.txt";
    112   error = video_engine->SetTraceFile(trace_file.c_str());
    113   if (error == -1) {
    114     printf("ERROR in VideoEngine::SetTraceFile\n");
    115     return -1;
    116   }
    117 
    118   // Init VideoEngine and create a channel.
    119   webrtc::ViEBase* vie_base = webrtc::ViEBase::GetInterface(video_engine);
    120   if (vie_base == NULL) {
    121     printf("ERROR in ViEBase::GetInterface\n");
    122     return -1;
    123   }
    124 
    125   error = vie_base->Init();
    126   if (error == -1) {
    127     printf("ERROR in ViEBase::Init\n");
    128     return -1;
    129   }
    130 
    131   RelayMode relay_mode = kRelayOneStream;
    132   printf("Select relay mode:\n");
    133   printf("\t1. Relay one stream\n");
    134   printf("\t2. Relay all streams\n");
    135   if (scanf("%d", reinterpret_cast<int*>(&relay_mode)) != 1) {
    136     printf("Error in scanf()\n");
    137     return -1;
    138   }
    139   getchar();
    140 
    141   webrtc::ViERTP_RTCP* vie_rtp_rtcp =
    142       webrtc::ViERTP_RTCP::GetInterface(video_engine);
    143   if (vie_rtp_rtcp == NULL) {
    144     printf("ERROR in ViERTP_RTCP::GetInterface\n");
    145     return -1;
    146   }
    147 
    148   int video_channel = -1;
    149   error = vie_base->CreateChannel(video_channel);
    150   if (error == -1) {
    151     printf("ERROR in ViEBase::CreateChannel\n");
    152     return -1;
    153   }
    154 
    155   for (int i = 0; i < kNumStreams; ++i) {
    156     receive_channels[i] = -1;
    157     error = vie_base->CreateReceiveChannel(receive_channels[i], video_channel);
    158     if (error == -1) {
    159       printf("ERROR in ViEBase::CreateChannel\n");
    160       return -1;
    161     }
    162   }
    163 
    164   // List available capture devices, allocate and connect.
    165   webrtc::ViECapture* vie_capture =
    166       webrtc::ViECapture::GetInterface(video_engine);
    167   if (vie_base == NULL) {
    168     printf("ERROR in ViECapture::GetInterface\n");
    169     return -1;
    170   }
    171 
    172   const unsigned int KMaxDeviceNameLength = 128;
    173   const unsigned int KMaxUniqueIdLength = 256;
    174   char device_name[KMaxDeviceNameLength];
    175   memset(device_name, 0, KMaxDeviceNameLength);
    176   char unique_id[KMaxUniqueIdLength];
    177   memset(unique_id, 0, KMaxUniqueIdLength);
    178 
    179   printf("Available capture devices:\n");
    180   int capture_idx = 0;
    181   for (capture_idx = 0; capture_idx < vie_capture->NumberOfCaptureDevices();
    182        capture_idx++) {
    183     memset(device_name, 0, KMaxDeviceNameLength);
    184     memset(unique_id, 0, KMaxUniqueIdLength);
    185 
    186     error = vie_capture->GetCaptureDevice(capture_idx, device_name,
    187                                           KMaxDeviceNameLength, unique_id,
    188                                           KMaxUniqueIdLength);
    189     if (error == -1) {
    190       printf("ERROR in ViECapture::GetCaptureDevice\n");
    191       return -1;
    192     }
    193     printf("\t %d. %s\n", capture_idx + 1, device_name);
    194   }
    195   printf("\nChoose capture device: ");
    196 #ifdef WEBRTC_ANDROID
    197   capture_idx = 0;
    198   printf("0\n");
    199 #else
    200   if (scanf("%d", &capture_idx) != 1) {
    201     printf("Error in scanf()\n");
    202     return -1;
    203   }
    204   getchar();
    205   // Compensate for idx start at 1.
    206   capture_idx = capture_idx - 1;
    207 #endif
    208   error = vie_capture->GetCaptureDevice(capture_idx, device_name,
    209                                         KMaxDeviceNameLength, unique_id,
    210                                         KMaxUniqueIdLength);
    211   if (error == -1) {
    212     printf("ERROR in ViECapture::GetCaptureDevice\n");
    213     return -1;
    214   }
    215 
    216   int capture_id = 0;
    217   error = vie_capture->AllocateCaptureDevice(unique_id, KMaxUniqueIdLength,
    218                                              capture_id);
    219   if (error == -1) {
    220     printf("ERROR in ViECapture::AllocateCaptureDevice\n");
    221     return -1;
    222   }
    223 
    224   error = vie_capture->ConnectCaptureDevice(capture_id, video_channel);
    225   if (error == -1) {
    226     printf("ERROR in ViECapture::ConnectCaptureDevice\n");
    227     return -1;
    228   }
    229 
    230   error = vie_capture->StartCapture(capture_id);
    231   if (error == -1) {
    232     printf("ERROR in ViECapture::StartCapture\n");
    233     return -1;
    234   }
    235 
    236   // RTP/RTCP settings.
    237   error = vie_rtp_rtcp->SetRTCPStatus(video_channel,
    238                                       webrtc::kRtcpCompound_RFC4585);
    239   if (error == -1) {
    240     printf("ERROR in ViERTP_RTCP::SetRTCPStatus\n");
    241     return -1;
    242   }
    243 
    244   vie_rtp_rtcp->SetRembStatus(video_channel, true, false);
    245   if (error == -1) {
    246     printf("ERROR in ViERTP_RTCP::SetRTCPStatus\n");
    247     return -1;
    248   }
    249 
    250   error = vie_rtp_rtcp->SetKeyFrameRequestMethod(
    251             video_channel, webrtc::kViEKeyFrameRequestPliRtcp);
    252   if (error == -1) {
    253     printf("ERROR in ViERTP_RTCP::SetKeyFrameRequestMethod\n");
    254     return -1;
    255   }
    256 
    257   for (int i = 0; i < kNumStreams; ++i) {
    258     error = vie_rtp_rtcp->SetRTCPStatus(receive_channels[i],
    259                                         webrtc::kRtcpCompound_RFC4585);
    260     if (error == -1) {
    261       printf("ERROR in ViERTP_RTCP::SetRTCPStatus\n");
    262       return -1;
    263     }
    264 
    265     vie_rtp_rtcp->SetRembStatus(receive_channels[i], false, true);
    266     if (error == -1) {
    267       printf("ERROR in ViERTP_RTCP::SetRTCPStatus\n");
    268       return -1;
    269     }
    270 
    271     error = vie_rtp_rtcp->SetKeyFrameRequestMethod(
    272         receive_channels[i], webrtc::kViEKeyFrameRequestPliRtcp);
    273     if (error == -1) {
    274       printf("ERROR in ViERTP_RTCP::SetKeyFrameRequestMethod\n");
    275       return -1;
    276     }
    277   }
    278 
    279   // Set up rendering.
    280   webrtc::ViERender* vie_render = webrtc::ViERender::GetInterface(video_engine);
    281   if (vie_render == NULL) {
    282     printf("ERROR in ViERender::GetInterface\n");
    283     return -1;
    284   }
    285 
    286   error = vie_render->AddRenderer(capture_id, window1, 0, 0.0, 0.0, 1.0, 1.0);
    287   if (error == -1) {
    288     printf("ERROR in ViERender::AddRenderer\n");
    289     return -1;
    290   }
    291 
    292   error = vie_render->StartRender(capture_id);
    293   if (error == -1) {
    294     printf("ERROR in ViERender::StartRender\n");
    295     return -1;
    296   }
    297 
    298   // Only rendering the thumbnail.
    299   int channel_to_render = video_channel;
    300   if (relay_mode == kRelayAllStreams) {
    301     channel_to_render = receive_channels[0];
    302   }
    303   error = vie_render->AddRenderer(channel_to_render, window2, 1, 0.0, 0.0, 1.0,
    304                                   1.0);
    305   if (error == -1) {
    306     printf("ERROR in ViERender::AddRenderer\n");
    307     return -1;
    308   }
    309 
    310   error = vie_render->StartRender(channel_to_render);
    311   if (error == -1) {
    312     printf("ERROR in ViERender::StartRender\n");
    313     return -1;
    314   }
    315 
    316   // Setup codecs.
    317   webrtc::ViECodec* vie_codec = webrtc::ViECodec::GetInterface(video_engine);
    318   if (vie_codec == NULL) {
    319     printf("ERROR in ViECodec::GetInterface\n");
    320     return -1;
    321   }
    322 
    323   // Check available codecs and prepare receive codecs.
    324   printf("\nAvailable codecs:\n");
    325   webrtc::VideoCodec video_codec;
    326   memset(&video_codec, 0, sizeof(webrtc::VideoCodec));
    327   int codec_idx = 0;
    328   for (codec_idx = 0; codec_idx < vie_codec->NumberOfCodecs(); codec_idx++) {
    329     error = vie_codec->GetCodec(codec_idx, video_codec);
    330     if (error == -1) {
    331       printf("ERROR in ViECodec::GetCodec\n");
    332       return -1;
    333     }
    334     // Try to keep the test frame size small when I420.
    335     if (video_codec.codecType != webrtc::kVideoCodecVP8) {
    336       continue;
    337     }
    338     for (int i = 0; i < kNumStreams; ++i) {
    339       error = vie_codec->SetReceiveCodec(receive_channels[i], video_codec);
    340       if (error == -1) {
    341         printf("ERROR in ViECodec::SetReceiveCodec\n");
    342         return -1;
    343       }
    344     }
    345     if (video_codec.codecType != webrtc::kVideoCodecRED &&
    346         video_codec.codecType != webrtc::kVideoCodecULPFEC) {
    347       printf("\t %d. %s\n", codec_idx + 1, video_codec.plName);
    348     }
    349     break;
    350   }
    351   error = vie_codec->GetCodec(codec_idx, video_codec);
    352   if (error == -1) {
    353     printf("ERROR in ViECodec::GetCodec\n");
    354     return -1;
    355   }
    356 
    357   bool simulcast_mode = true;
    358   int num_streams = 1;
    359   // Set spatial resolution option.
    360   if (simulcast_mode) {
    361     SetSimulcastSettings(&video_codec);
    362     num_streams = video_codec.numberOfSimulcastStreams;
    363   } else {
    364     InitialSingleStreamSettings(&video_codec);
    365     num_streams = 1;
    366   }
    367 
    368   // Set start bit rate.
    369   std::string str;
    370   std::cout << std::endl;
    371   std::cout << "Choose start rate (in kbps). Press enter for default:  ";
    372   std::getline(std::cin, str);
    373   int start_rate = atoi(str.c_str());
    374   if (start_rate != 0) {
    375     video_codec.startBitrate = start_rate;
    376   }
    377 
    378   error = vie_codec->SetSendCodec(video_channel, video_codec);
    379   if (error == -1) {
    380     printf("ERROR in ViECodec::SetSendCodec\n");
    381     return -1;
    382   }
    383 
    384   // Address settings.
    385   webrtc::ViENetwork* vie_network =
    386       webrtc::ViENetwork::GetInterface(video_engine);
    387   if (vie_network == NULL) {
    388     printf("ERROR in ViENetwork::GetInterface\n");
    389     return -1;
    390   }
    391 
    392   TbExternalTransport::SsrcChannelMap ssrc_channel_map;
    393   for (int idx = 0; idx < num_streams; idx++) {
    394     error = vie_rtp_rtcp->SetLocalSSRC(video_channel, idx + 1,  // SSRC
    395                                        webrtc::kViEStreamTypeNormal, idx);
    396     ssrc_channel_map[idx + 1] = receive_channels[idx];
    397     if (error == -1) {
    398       printf("ERROR in ViERTP_RTCP::SetLocalSSRC(idx:%d)\n",
    399              idx);
    400       return -1;
    401     }
    402   }
    403 
    404   TbExternalTransport::SsrcChannelMap* channel_map = &ssrc_channel_map;
    405   if (relay_mode == kRelayOneStream) {
    406     channel_map = NULL;
    407   }
    408 
    409   // Setting External transport.
    410   TbExternalTransport ext_transport(*vie_network, video_channel, channel_map);
    411 
    412   error = vie_network->RegisterSendTransport(video_channel, ext_transport);
    413   if (error == -1) {
    414     printf("ERROR in ViECodec::RegisterSendTransport \n");
    415     return -1;
    416   }
    417 
    418   for (int i = 0; i < kNumStreams; ++i) {
    419     error = vie_network->RegisterSendTransport(receive_channels[i],
    420                                                ext_transport);
    421     if (error == -1) {
    422       printf("ERROR in ViECodec::RegisterSendTransport \n");
    423       return -1;
    424     }
    425   }
    426 
    427   // Set network one-way delay value.
    428   // 10 ms one-way delay.
    429   NetworkParameters network;
    430   network.loss_model = kUniformLoss;
    431   network.mean_one_way_delay = 10;
    432   ext_transport.SetNetworkParameters(network);
    433 
    434   if (relay_mode == kRelayOneStream) {
    435     ext_transport.SetSSRCFilter(num_streams);
    436   }
    437 
    438   error = vie_base->StartSend(video_channel);
    439   if (error == -1) {
    440     printf("ERROR in ViENetwork::StartSend\n");
    441     return -1;
    442   }
    443   error = vie_base->StartReceive(video_channel);
    444   if (error == -1) {
    445     printf("ERROR in ViENetwork::StartReceive\n");
    446     return -1;
    447   }
    448 
    449   for (int i = 0; i < kNumStreams; ++i) {
    450     error = vie_base->StartReceive(receive_channels[i]);
    451     if (error == -1) {
    452       printf("ERROR in ViENetwork::StartReceive\n");
    453       return -1;
    454     }
    455   }
    456 
    457   // Create a receive channel to verify that it doesn't mess up toggling
    458   // between single stream and simulcast.
    459   int video_channel2 = -1;
    460   error = vie_base->CreateReceiveChannel(video_channel2, video_channel);
    461   if (error == -1) {
    462     printf("ERROR in ViEBase::CreateReceiveChannel\n");
    463     return -1;
    464   }
    465 
    466   // *******************************************************
    467   //  Engine started
    468   // *******************************************************
    469 
    470   printf("\nSimulcast call started\n\n");
    471   do {
    472     printf("Enter new SSRC filter 1,2 or 3\n");
    473     printf("... or 0 to switch between simulcast and a single stream\n");
    474     printf("Press enter to stop...");
    475     str.clear();
    476     std::getline(std::cin, str);
    477     if (!str.empty()) {
    478       int ssrc = atoi(str.c_str());
    479       if (ssrc == 0) {
    480         // Toggle between simulcast and a single stream with different
    481         // resolution.
    482         if (simulcast_mode) {
    483           RuntimeSingleStreamSettings(&video_codec);
    484           num_streams = 1;
    485           printf("Disabling simulcast\n");
    486         } else {
    487           SetSimulcastSettings(&video_codec);
    488           num_streams = video_codec.numberOfSimulcastStreams;
    489           printf("Enabling simulcast\n");
    490         }
    491         simulcast_mode = !simulcast_mode;
    492         if (vie_codec->SetSendCodec(video_channel, video_codec) != 0) {
    493           printf("ERROR switching between simulcast and single stream\n");
    494           return -1;
    495         }
    496         for (int idx = 0; idx < num_streams; idx++) {
    497           error = vie_rtp_rtcp->SetLocalSSRC(video_channel, idx + 1,  // SSRC
    498                                              webrtc::kViEStreamTypeNormal, idx);
    499           if (error == -1) {
    500             printf("ERROR in ViERTP_RTCP::SetLocalSSRC(idx:%d)\n", idx);
    501             return -1;
    502           }
    503         }
    504         if (relay_mode == kRelayOneStream) {
    505           ext_transport.SetSSRCFilter(num_streams);
    506         }
    507       } else if (ssrc > 0 && ssrc < 4) {
    508         if (relay_mode == kRelayOneStream) {
    509           ext_transport.SetSSRCFilter(ssrc);
    510         }
    511       } else {
    512         printf("Invalid SSRC\n");
    513       }
    514     } else {
    515       break;
    516     }
    517   } while (true);
    518 
    519   // *******************************************************
    520   //  Testing finished. Tear down Video Engine
    521   // *******************************************************
    522   error = vie_base->DeleteChannel(video_channel2);
    523   if (error == -1) {
    524     printf("ERROR in ViEBase::DeleteChannel\n");
    525     return -1;
    526   }
    527 
    528   for (int i = 0; i < kNumStreams; ++i) {
    529     error = vie_base->StopReceive(receive_channels[i]);
    530     if (error == -1) {
    531       printf("ERROR in ViEBase::StopReceive\n");
    532       return -1;
    533     }
    534   }
    535 
    536   error = vie_base->StopReceive(video_channel);
    537   if (error == -1) {
    538     printf("ERROR in ViEBase::StopReceive\n");
    539     return -1;
    540   }
    541 
    542   error = vie_base->StopSend(video_channel);
    543   if (error == -1) {
    544     printf("ERROR in ViEBase::StopSend\n");
    545     return -1;
    546   }
    547 
    548   error = vie_render->StopRender(capture_id);
    549   if (error == -1) {
    550     printf("ERROR in ViERender::StopRender\n");
    551     return -1;
    552   }
    553 
    554   error = vie_render->RemoveRenderer(capture_id);
    555   if (error == -1) {
    556     printf("ERROR in ViERender::RemoveRenderer\n");
    557     return -1;
    558   }
    559 
    560   error = vie_render->StopRender(channel_to_render);
    561   if (error == -1) {
    562     printf("ERROR in ViERender::StopRender\n");
    563     return -1;
    564   }
    565 
    566   error = vie_render->RemoveRenderer(channel_to_render);
    567   if (error == -1) {
    568     printf("ERROR in ViERender::RemoveRenderer\n");
    569     return -1;
    570   }
    571 
    572   error = vie_capture->StopCapture(capture_id);
    573   if (error == -1) {
    574     printf("ERROR in ViECapture::StopCapture\n");
    575     return -1;
    576   }
    577 
    578   error = vie_capture->DisconnectCaptureDevice(video_channel);
    579   if (error == -1) {
    580     printf("ERROR in ViECapture::DisconnectCaptureDevice\n");
    581     return -1;
    582   }
    583 
    584   error = vie_capture->ReleaseCaptureDevice(capture_id);
    585   if (error == -1) {
    586     printf("ERROR in ViECapture::ReleaseCaptureDevice\n");
    587     return -1;
    588   }
    589 
    590   for (int i = 0; i < kNumStreams; ++i) {
    591     error = vie_base->DeleteChannel(receive_channels[i]);
    592     if (error == -1) {
    593       printf("ERROR in ViEBase::DeleteChannel\n");
    594       return -1;
    595     }
    596   }
    597 
    598   error = vie_base->DeleteChannel(video_channel);
    599   if (error == -1) {
    600     printf("ERROR in ViEBase::DeleteChannel\n");
    601     return -1;
    602   }
    603 
    604   int remaining_interfaces = 0;
    605   remaining_interfaces = vie_codec->Release();
    606   remaining_interfaces += vie_capture->Release();
    607   remaining_interfaces += vie_rtp_rtcp->Release();
    608   remaining_interfaces += vie_render->Release();
    609   remaining_interfaces += vie_network->Release();
    610   remaining_interfaces += vie_base->Release();
    611   if (remaining_interfaces > 0) {
    612     printf("ERROR: Could not release all interfaces\n");
    613     return -1;
    614   }
    615 
    616   bool deleted = webrtc::VideoEngine::Delete(video_engine);
    617   if (deleted == false) {
    618     printf("ERROR in VideoEngine::Delete\n");
    619     return -1;
    620   }
    621   return 0;
    622 }
    623 
    624 int ViEAutoTest::ViESimulcastCall() {
    625   ViETest::Log(" ");
    626   ViETest::Log("========================================");
    627   ViETest::Log(" ViE Autotest Simulcast Call\n");
    628 
    629   if (VideoEngineSimulcastTest(_window1, _window2) == 0) {
    630     ViETest::Log(" ");
    631     ViETest::Log(" ViE Autotest Simulcast Call Done");
    632     ViETest::Log("========================================");
    633     ViETest::Log(" ");
    634 
    635     return 0;
    636   }
    637   ViETest::Log(" ");
    638   ViETest::Log(" ViE Autotest Simulcast Call Failed");
    639   ViETest::Log("========================================");
    640   ViETest::Log(" ");
    641   return 1;
    642 }
    643