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 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 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