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