PageRenderTime 46ms CodeModel.GetById 3ms app.highlight 38ms RepoModel.GetById 2ms app.codeStats 0ms

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

https://bitbucket.org/bohlooli/webrtc
C++ | 691 lines | 544 code | 79 blank | 68 comment | 121 complexity | 8485972d800135b8492e8b90751b3818 MD5 | raw file
  1/*
  2 *  Copyright (c) 2011 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//
 12// vie_autotest_loopback.cc
 13//
 14// This code is also used as sample code for ViE 3.0
 15//
 16
 17// ===================================================================
 18//
 19// BEGIN: VideoEngine 3.0 Sample Code
 20//
 21
 22#include <iostream>
 23
 24#include "common_types.h"
 25#include "tb_external_transport.h"
 26#include "voe_base.h"
 27#include "vie_autotest_defines.h"
 28#include "vie_autotest.h"
 29#include "vie_base.h"
 30#include "vie_capture.h"
 31#include "vie_codec.h"
 32#include "vie_network.h"
 33#include "vie_render.h"
 34#include "vie_rtp_rtcp.h"
 35
 36#define VCM_RED_PAYLOAD_TYPE        96
 37#define VCM_ULPFEC_PAYLOAD_TYPE     97
 38
 39int VideoEngineSampleCode(void* window1, void* window2)
 40{
 41    //********************************************************
 42    //  Begin create/initialize Video Engine for testing
 43    //********************************************************
 44
 45    int error = 0;
 46
 47    //
 48    // Create a VideoEngine instance
 49    //
 50    webrtc::VideoEngine* ptrViE = NULL;
 51    ptrViE = webrtc::VideoEngine::Create();
 52    if (ptrViE == NULL)
 53    {
 54        printf("ERROR in VideoEngine::Create\n");
 55        return -1;
 56    }
 57
 58    error = ptrViE->SetTraceFilter(webrtc::kTraceAll);
 59    if (error == -1)
 60    {
 61        printf("ERROR in VideoEngine::SetTraceLevel\n");
 62        return -1;
 63    }
 64
 65    std::string trace_file =
 66        ViETest::GetResultOutputPath() + "ViELoopbackCall_trace.txt";
 67    error = ptrViE->SetTraceFile(trace_file.c_str());
 68    if (error == -1)
 69    {
 70        printf("ERROR in VideoEngine::SetTraceFile\n");
 71        return -1;
 72    }
 73
 74    //
 75    // Init VideoEngine and create a channel
 76    //
 77    webrtc::ViEBase* ptrViEBase = webrtc::ViEBase::GetInterface(ptrViE);
 78    if (ptrViEBase == NULL)
 79    {
 80        printf("ERROR in ViEBase::GetInterface\n");
 81        return -1;
 82    }
 83
 84    error = ptrViEBase->Init();
 85    if (error == -1)
 86    {
 87        printf("ERROR in ViEBase::Init\n");
 88        return -1;
 89    }
 90
 91    webrtc::ViERTP_RTCP* ptrViERtpRtcp =
 92        webrtc::ViERTP_RTCP::GetInterface(ptrViE);
 93    if (ptrViERtpRtcp == NULL)
 94    {
 95        printf("ERROR in ViERTP_RTCP::GetInterface\n");
 96        return -1;
 97    }
 98
 99    printf("Bandwidth estimation modes:\n");
100    printf("1. Multi-stream bandwidth estimation\n");
101    printf("2. Single-stream bandwidth estimation\n");
102    printf("Choose bandwidth estimation mode (default is 1): ");
103    std::string str;
104    std::getline(std::cin, str);
105    int bwe_mode_choice = atoi(str.c_str());
106    webrtc::BandwidthEstimationMode bwe_mode;
107    switch (bwe_mode_choice) {
108      case 1:
109        bwe_mode = webrtc::kViEMultiStreamEstimation;
110        break;
111      case 2:
112        bwe_mode = webrtc::kViESingleStreamEstimation;
113        break;
114      default:
115        bwe_mode = webrtc::kViEMultiStreamEstimation;
116        break;
117    }
118
119    error = ptrViERtpRtcp->SetBandwidthEstimationMode(bwe_mode);
120    if (error == -1)
121    {
122        printf("ERROR in ViERTP_RTCP::SetBandwidthEstimationMode\n");
123        return -1;
124    }
125
126    int videoChannel = -1;
127    error = ptrViEBase->CreateChannel(videoChannel);
128    if (error == -1)
129    {
130        printf("ERROR in ViEBase::CreateChannel\n");
131        return -1;
132    }
133
134    //
135    // List available capture devices, allocate and connect.
136    //
137    webrtc::ViECapture* ptrViECapture =
138        webrtc::ViECapture::GetInterface(ptrViE);
139    if (ptrViEBase == NULL)
140    {
141        printf("ERROR in ViECapture::GetInterface\n");
142        return -1;
143    }
144
145    const unsigned int KMaxDeviceNameLength = 128;
146    const unsigned int KMaxUniqueIdLength = 256;
147    char deviceName[KMaxDeviceNameLength];
148    memset(deviceName, 0, KMaxDeviceNameLength);
149    char uniqueId[KMaxUniqueIdLength];
150    memset(uniqueId, 0, KMaxUniqueIdLength);
151
152    printf("Available capture devices:\n");
153    int captureIdx = 0;
154    for (captureIdx = 0;
155         captureIdx < ptrViECapture->NumberOfCaptureDevices();
156         captureIdx++)
157    {
158        memset(deviceName, 0, KMaxDeviceNameLength);
159        memset(uniqueId, 0, KMaxUniqueIdLength);
160
161        error = ptrViECapture->GetCaptureDevice(captureIdx, deviceName,
162                                                KMaxDeviceNameLength, uniqueId,
163                                                KMaxUniqueIdLength);
164        if (error == -1)
165        {
166            printf("ERROR in ViECapture::GetCaptureDevice\n");
167            return -1;
168        }
169        printf("\t %d. %s\n", captureIdx + 1, deviceName);
170    }
171    printf("\nChoose capture device: ");
172#ifdef WEBRTC_ANDROID
173    captureIdx = 0;
174    printf("0\n");
175#else
176    if (scanf("%d", &captureIdx) != 1)
177    {
178        printf("Error in scanf()\n");
179        return -1;
180    }
181    getchar();
182    captureIdx = captureIdx - 1; // Compensate for idx start at 1.
183#endif
184    error = ptrViECapture->GetCaptureDevice(captureIdx, deviceName,
185                                            KMaxDeviceNameLength, uniqueId,
186                                            KMaxUniqueIdLength);
187    if (error == -1)
188    {
189        printf("ERROR in ViECapture::GetCaptureDevice\n");
190        return -1;
191    }
192
193    int captureId = 0;
194    error = ptrViECapture->AllocateCaptureDevice(uniqueId, KMaxUniqueIdLength,
195                                                 captureId);
196    if (error == -1)
197    {
198        printf("ERROR in ViECapture::AllocateCaptureDevice\n");
199        return -1;
200    }
201
202    error = ptrViECapture->ConnectCaptureDevice(captureId, videoChannel);
203    if (error == -1)
204    {
205        printf("ERROR in ViECapture::ConnectCaptureDevice\n");
206        return -1;
207    }
208
209    error = ptrViECapture->StartCapture(captureId);
210    if (error == -1)
211    {
212        printf("ERROR in ViECapture::StartCapture\n");
213        return -1;
214    }
215
216    //
217    // RTP/RTCP settings
218    //
219
220    error = ptrViERtpRtcp->SetRTCPStatus(videoChannel,
221                                         webrtc::kRtcpCompound_RFC4585);
222    if (error == -1)
223    {
224        printf("ERROR in ViERTP_RTCP::SetRTCPStatus\n");
225        return -1;
226    }
227
228    error = ptrViERtpRtcp->SetKeyFrameRequestMethod(
229        videoChannel, webrtc::kViEKeyFrameRequestPliRtcp);
230    if (error == -1)
231    {
232        printf("ERROR in ViERTP_RTCP::SetKeyFrameRequestMethod\n");
233        return -1;
234    }
235
236    error = ptrViERtpRtcp->SetRembStatus(videoChannel, true, true);
237    if (error == -1)
238    {
239        printf("ERROR in ViERTP_RTCP::SetTMMBRStatus\n");
240        return -1;
241    }
242
243    //
244    // Set up rendering
245    //
246    webrtc::ViERender* ptrViERender = webrtc::ViERender::GetInterface(ptrViE);
247    if (ptrViERender == NULL)
248    {
249        printf("ERROR in ViERender::GetInterface\n");
250        return -1;
251    }
252
253    error
254        = ptrViERender->AddRenderer(captureId, window1, 0, 0.0, 0.0, 1.0, 1.0);
255    if (error == -1)
256    {
257        printf("ERROR in ViERender::AddRenderer\n");
258        return -1;
259    }
260
261    error = ptrViERender->StartRender(captureId);
262    if (error == -1)
263    {
264        printf("ERROR in ViERender::StartRender\n");
265        return -1;
266    }
267
268    error = ptrViERender->AddRenderer(videoChannel, window2, 1, 0.0, 0.0, 1.0,
269                                      1.0);
270    if (error == -1)
271    {
272        printf("ERROR in ViERender::AddRenderer\n");
273        return -1;
274    }
275
276    error = ptrViERender->StartRender(videoChannel);
277    if (error == -1)
278    {
279        printf("ERROR in ViERender::StartRender\n");
280        return -1;
281    }
282
283    //
284    // Setup codecs
285    //
286    webrtc::ViECodec* ptrViECodec = webrtc::ViECodec::GetInterface(ptrViE);
287    if (ptrViECodec == NULL)
288    {
289        printf("ERROR in ViECodec::GetInterface\n");
290        return -1;
291    }
292
293    // Check available codecs and prepare receive codecs
294    printf("\nAvailable codecs:\n");
295    webrtc::VideoCodec videoCodec;
296    memset(&videoCodec, 0, sizeof(webrtc::VideoCodec));
297    int codecIdx = 0;
298    for (codecIdx = 0; codecIdx < ptrViECodec->NumberOfCodecs(); codecIdx++)
299    {
300        error = ptrViECodec->GetCodec(codecIdx, videoCodec);
301        if (error == -1)
302        {
303            printf("ERROR in ViECodec::GetCodec\n");
304            return -1;
305        }
306
307        // try to keep the test frame size small when I420
308        if (videoCodec.codecType == webrtc::kVideoCodecI420)
309        {
310            videoCodec.width = 176;
311            videoCodec.height = 144;
312        }
313
314        error = ptrViECodec->SetReceiveCodec(videoChannel, videoCodec);
315        if (error == -1)
316        {
317            printf("ERROR in ViECodec::SetReceiveCodec\n");
318            return -1;
319        }
320        if (videoCodec.codecType != webrtc::kVideoCodecRED
321            && videoCodec.codecType != webrtc::kVideoCodecULPFEC)
322        {
323            printf("\t %d. %s\n", codecIdx + 1, videoCodec.plName);
324        }
325    }
326    printf("Choose codec: ");
327#ifdef WEBRTC_ANDROID
328    codecIdx = 0;
329    printf("0\n");
330#else
331    if (scanf("%d", &codecIdx) != 1)
332    {
333        printf("Error in scanf()\n");
334        return -1;
335    }
336    getchar();
337    codecIdx = codecIdx - 1; // Compensate for idx start at 1.
338#endif
339
340    error = ptrViECodec->GetCodec(codecIdx, videoCodec);
341    if (error == -1)
342    {
343        printf("ERROR in ViECodec::GetCodec\n");
344        return -1;
345    }
346
347    // Set spatial resolution option
348    std::cout << std::endl;
349    std::cout << "Enter frame size option (default is CIF):" << std::endl;
350    std::cout << "1. QCIF (176X144) " << std::endl;
351    std::cout << "2. CIF  (352X288) " << std::endl;
352    std::cout << "3. VGA  (640X480) " << std::endl;
353    std::cout << "4. 4CIF (704X576) " << std::endl;
354    std::cout << "5. WHD  (1280X720) " << std::endl;
355    std::getline(std::cin, str);
356    int resolnOption = atoi(str.c_str());
357    // Try to keep the test frame size small when I420
358    if (videoCodec.codecType == webrtc::kVideoCodecI420)
359    {
360       resolnOption = 1;
361    }
362    switch (resolnOption)
363    {
364        case 1:
365            videoCodec.width = 176;
366            videoCodec.height = 144;
367            break;
368        case 2:
369            videoCodec.width = 352;
370            videoCodec.height = 288;
371            break;
372        case 3:
373            videoCodec.width = 640;
374            videoCodec.height = 480;
375            break;
376        case 4:
377            videoCodec.width = 704;
378            videoCodec.height = 576;
379            break;
380        case 5:
381            videoCodec.width = 1280;
382            videoCodec.height = 720;
383            break;
384    }
385
386    // Set number of temporal layers.
387    std::cout << std::endl;
388    std::cout << "Choose number of temporal layers (1 to 4).";
389    std::cout << "Press enter for default: \n";
390    std::getline(std::cin, str);
391    int numTemporalLayers = atoi(str.c_str());
392    if(numTemporalLayers != 0)
393    {
394        videoCodec.codecSpecific.VP8.numberOfTemporalLayers = numTemporalLayers;
395    }
396
397    // Set start bit rate
398    std::cout << std::endl;
399    std::cout << "Choose start rate (in kbps). Press enter for default:  ";
400    std::getline(std::cin, str);
401    int startRate = atoi(str.c_str());
402    if(startRate != 0)
403    {
404        videoCodec.startBitrate=startRate;
405    }
406
407    error = ptrViECodec->SetSendCodec(videoChannel, videoCodec);
408    if (error == -1)
409    {
410        printf("ERROR in ViECodec::SetSendCodec\n");
411        return -1;
412    }
413
414    //
415    // Choose Protection Mode
416    //
417    std::cout << std::endl;
418    std::cout << "Enter Protection Method:" << std::endl;
419    std::cout << "0. None" << std::endl;
420    std::cout << "1. FEC" << std::endl;
421    std::cout << "2. NACK" << std::endl;
422    std::cout << "3. NACK+FEC" << std::endl;
423    std::getline(std::cin, str);
424    int protectionMethod = atoi(str.c_str());
425    error = 0;
426    bool temporalToggling = true;
427    switch (protectionMethod)
428    {
429        case 0: // None: default is no protection
430            break;
431
432        case 1: // FEC only
433            error = ptrViERtpRtcp->SetFECStatus(videoChannel,
434                                                true,
435                                                VCM_RED_PAYLOAD_TYPE,
436                                                VCM_ULPFEC_PAYLOAD_TYPE);
437            temporalToggling = false;
438            break;
439
440        case 2: // Nack only
441            error = ptrViERtpRtcp->SetNACKStatus(videoChannel, true);
442
443            break;
444
445        case 3: // Hybrid NAck and FEC
446            error = ptrViERtpRtcp->SetHybridNACKFECStatus(
447                videoChannel,
448                true,
449                VCM_RED_PAYLOAD_TYPE,
450                VCM_ULPFEC_PAYLOAD_TYPE);
451            temporalToggling = false;
452            break;
453     }
454
455    if (error < 0)
456    {
457        printf("ERROR in ViERTP_RTCP::SetProtectionStatus\n");
458    }
459
460
461    //
462    // Address settings
463    //
464    webrtc::ViENetwork* ptrViENetwork =
465        webrtc::ViENetwork::GetInterface(ptrViE);
466    if (ptrViENetwork == NULL)
467    {
468        printf("ERROR in ViENetwork::GetInterface\n");
469        return -1;
470    }
471
472    // Setting External transport
473    TbExternalTransport extTransport(*(ptrViENetwork), videoChannel, NULL);
474
475    int testMode = 0;
476    std::cout << std::endl;
477    std::cout << "Enter 1 for testing packet loss and delay with "
478        "external transport: ";
479    std::string test_str;
480    std::getline(std::cin, test_str);
481    testMode = atoi(test_str.c_str());
482    if (testMode == 1)
483    {
484        // Avoid changing SSRC due to collision.
485        error = ptrViERtpRtcp->SetLocalSSRC(videoChannel, 1);
486
487        error = ptrViENetwork->RegisterSendTransport(videoChannel,
488                                                     extTransport);
489        if (error == -1)
490        {
491            printf("ERROR in ViECodec::RegisterSendTransport \n");
492            return -1;
493        }
494
495        // Setting uniform loss. Actual values will be set by user.
496        NetworkParameters network;
497        network.loss_model = kUniformLoss;
498        // Set up packet loss value
499        std::cout << "Enter Packet Loss Percentage" << std::endl;
500        std::string rate_str;
501        std::getline(std::cin, rate_str);
502        network.packet_loss_rate = atoi(rate_str.c_str());
503        if (network.packet_loss_rate > 0) {
504          temporalToggling = false;
505        }
506
507        // Set network delay value
508        std::cout << "Enter network delay value [mS]" << std::endl;
509        std::string delay_str;
510        std::getline(std::cin, delay_str);
511        network.mean_one_way_delay = atoi(delay_str.c_str());
512        extTransport.SetNetworkParameters(network);
513        if (numTemporalLayers > 1 && temporalToggling) {
514          extTransport.SetTemporalToggle(numTemporalLayers);
515        } else {
516          // Disabled
517          extTransport.SetTemporalToggle(0);
518        }
519    }
520    else
521    {
522        const char* ipAddress = "127.0.0.1";
523        const unsigned short rtpPort = 6000;
524        std::cout << std::endl;
525        std::cout << "Using rtp port: " << rtpPort << std::endl;
526        std::cout << std::endl;
527        error = ptrViENetwork->SetLocalReceiver(videoChannel, rtpPort);
528        if (error == -1)
529        {
530            printf("ERROR in ViENetwork::SetLocalReceiver\n");
531            return -1;
532        }
533        error = ptrViENetwork->SetSendDestination(videoChannel,
534                                                  ipAddress, rtpPort);
535        if (error == -1)
536        {
537            printf("ERROR in ViENetwork::SetSendDestination\n");
538            return -1;
539        }
540    }
541
542    error = ptrViEBase->StartReceive(videoChannel);
543    if (error == -1)
544    {
545        printf("ERROR in ViENetwork::StartReceive\n");
546        return -1;
547    }
548
549    error = ptrViEBase->StartSend(videoChannel);
550    if (error == -1)
551    {
552        printf("ERROR in ViENetwork::StartSend\n");
553        return -1;
554    }
555
556    //********************************************************
557    //  Engine started
558    //********************************************************
559
560
561    // Call started
562    printf("\nLoopback call started\n\n");
563    printf("Press enter to stop...");
564    while ((getchar()) != '\n')
565        ;
566
567    //********************************************************
568    //  Testing finished. Tear down Video Engine
569    //********************************************************
570
571    error = ptrViEBase->StopReceive(videoChannel);
572    if (error == -1)
573    {
574        printf("ERROR in ViEBase::StopReceive\n");
575        return -1;
576    }
577
578    error = ptrViEBase->StopSend(videoChannel);
579    if (error == -1)
580    {
581        printf("ERROR in ViEBase::StopSend\n");
582        return -1;
583    }
584
585    error = ptrViERender->StopRender(captureId);
586    if (error == -1)
587    {
588        printf("ERROR in ViERender::StopRender\n");
589        return -1;
590    }
591
592    error = ptrViERender->RemoveRenderer(captureId);
593    if (error == -1)
594    {
595        printf("ERROR in ViERender::RemoveRenderer\n");
596        return -1;
597    }
598
599    error = ptrViERender->StopRender(videoChannel);
600    if (error == -1)
601    {
602        printf("ERROR in ViERender::StopRender\n");
603        return -1;
604    }
605
606    error = ptrViERender->RemoveRenderer(videoChannel);
607    if (error == -1)
608    {
609        printf("ERROR in ViERender::RemoveRenderer\n");
610        return -1;
611    }
612
613    error = ptrViECapture->StopCapture(captureId);
614    if (error == -1)
615    {
616        printf("ERROR in ViECapture::StopCapture\n");
617        return -1;
618    }
619
620    error = ptrViECapture->DisconnectCaptureDevice(videoChannel);
621    if (error == -1)
622    {
623        printf("ERROR in ViECapture::DisconnectCaptureDevice\n");
624        return -1;
625    }
626
627    error = ptrViECapture->ReleaseCaptureDevice(captureId);
628    if (error == -1)
629    {
630        printf("ERROR in ViECapture::ReleaseCaptureDevice\n");
631        return -1;
632    }
633
634    error = ptrViEBase->DeleteChannel(videoChannel);
635    if (error == -1)
636    {
637        printf("ERROR in ViEBase::DeleteChannel\n");
638        return -1;
639    }
640
641    int remainingInterfaces = 0;
642    remainingInterfaces = ptrViECodec->Release();
643    remainingInterfaces += ptrViECapture->Release();
644    remainingInterfaces += ptrViERtpRtcp->Release();
645    remainingInterfaces += ptrViERender->Release();
646    remainingInterfaces += ptrViENetwork->Release();
647    remainingInterfaces += ptrViEBase->Release();
648    if (remainingInterfaces > 0)
649    {
650        printf("ERROR: Could not release all interfaces\n");
651        return -1;
652    }
653
654    bool deleted = webrtc::VideoEngine::Delete(ptrViE);
655    if (deleted == false)
656    {
657        printf("ERROR in VideoEngine::Delete\n");
658        return -1;
659    }
660
661    return 0;
662
663    //
664    // END:  VideoEngine 3.0 Sample Code
665    //
666    // ===================================================================
667}
668
669int ViEAutoTest::ViELoopbackCall()
670{
671    ViETest::Log(" ");
672    ViETest::Log("========================================");
673    ViETest::Log(" ViE Autotest Loopback Call\n");
674
675    if (VideoEngineSampleCode(_window1, _window2) == 0)
676    {
677        ViETest::Log(" ");
678        ViETest::Log(" ViE Autotest Loopback Call Done");
679        ViETest::Log("========================================");
680        ViETest::Log(" ");
681
682        return 0;
683    }
684
685    ViETest::Log(" ");
686    ViETest::Log(" ViE Autotest Loopback Call Failed");
687    ViETest::Log("========================================");
688    ViETest::Log(" ");
689    return 1;
690
691}