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