PageRenderTime 61ms CodeModel.GetById 11ms app.highlight 44ms RepoModel.GetById 1ms app.codeStats 0ms

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

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