PageRenderTime 67ms CodeModel.GetById 33ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://bitbucket.org/bohlooli/webrtc
C++ | 1729 lines | 1476 code | 182 blank | 71 comment | 184 complexity | 6cf6978a8687dc3d1c1498530e41cd78 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, BSD-3-Clause
  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. #include <climits>
  11. #include <cstdarg>
  12. #include <cstdio>
  13. #include <algorithm>
  14. #include "video_engine/test/auto_test/interface/vie_autotest.h"
  15. #include "video_engine/test/auto_test/interface/vie_autotest_defines.h"
  16. #include "video_engine/test/auto_test/primitives/choice_helpers.h"
  17. #include "video_engine/test/auto_test/primitives/input_helpers.h"
  18. #define VCM_RED_PAYLOAD_TYPE 96
  19. #define VCM_ULPFEC_PAYLOAD_TYPE 97
  20. #define DEFAULT_SEND_IP "127.0.0.1"
  21. #define DEFAULT_VIDEO_PORT "11111"
  22. #define DEFAULT_VIDEO_CODEC "VP8"
  23. #define DEFAULT_VIDEO_CODEC_WIDTH "640"
  24. #define DEFAULT_VIDEO_CODEC_HEIGHT "480"
  25. #define DEFAULT_VIDEO_CODEC_BITRATE "300"
  26. #define DEFAULT_VIDEO_CODEC_MIN_BITRATE "100"
  27. #define DEFAULT_VIDEO_CODEC_MAX_BITRATE "1000"
  28. #define DEFAULT_AUDIO_PORT "11113"
  29. #define DEFAULT_AUDIO_CODEC "ISAC"
  30. #define DEFAULT_INCOMING_FILE_NAME "IncomingFile.avi"
  31. #define DEFAULT_OUTGOING_FILE_NAME "OutgoingFile.avi"
  32. #define DEFAULT_VIDEO_CODEC_MAX_FRAMERATE "30"
  33. #define DEFAULT_VIDEO_PROTECTION_METHOD "None"
  34. #define DEFAULT_TEMPORAL_LAYER "0"
  35. enum StatisticsType {
  36. kSendStatistic,
  37. kReceivedStatistic
  38. };
  39. enum VideoProtectionMethod {
  40. kProtectionMethodNone = 1,
  41. kProtectionMethodFecOnly,
  42. kProtectionMethodNackOnly,
  43. kProtectionMethodHybridNackAndFec,
  44. };
  45. using webrtc::FromChoices;
  46. using webrtc::TypedInput;
  47. class ViEAutotestFileObserver : public webrtc::ViEFileObserver {
  48. public:
  49. ViEAutotestFileObserver() {}
  50. ~ViEAutotestFileObserver() {}
  51. void PlayFileEnded(const WebRtc_Word32 file_id) {
  52. ViETest::Log("PlayFile ended");
  53. }
  54. };
  55. class ViEAutotestEncoderObserver : public webrtc::ViEEncoderObserver {
  56. public:
  57. ViEAutotestEncoderObserver() {}
  58. ~ViEAutotestEncoderObserver() {}
  59. void OutgoingRate(const int video_channel,
  60. const unsigned int framerate,
  61. const unsigned int bitrate) {
  62. std::cout << "Send FR: " << framerate
  63. << " BR: " << bitrate << std::endl;
  64. }
  65. };
  66. class ViEAutotestDecoderObserver : public webrtc::ViEDecoderObserver {
  67. public:
  68. ViEAutotestDecoderObserver() {}
  69. ~ViEAutotestDecoderObserver() {}
  70. void IncomingRate(const int video_channel,
  71. const unsigned int framerate,
  72. const unsigned int bitrate) {
  73. std::cout << "Received FR: " << framerate
  74. << " BR: " << bitrate << std::endl;
  75. }
  76. void IncomingCodecChanged(const int video_channel,
  77. const webrtc::VideoCodec& codec) {}
  78. void RequestNewKeyFrame(const int video_channel) {
  79. std::cout << "Decoder requesting a new key frame." << std::endl;
  80. }
  81. };
  82. // The following are general helper functions.
  83. bool GetVideoDevice(webrtc::ViEBase* vie_base,
  84. webrtc::ViECapture* vie_capture,
  85. char* capture_device_name, char* capture_device_unique_id);
  86. std::string GetIPAddress();
  87. bool ValidateIP(std::string i_str);
  88. // The following are Print to stdout functions.
  89. void PrintCallInformation(const char* IP,
  90. const char* video_capture_device_name,
  91. const char* video_capture_unique_id,
  92. webrtc::VideoCodec video_codec,
  93. int video_tx_port,
  94. int video_rx_port,
  95. const char* audio_capture_device_name,
  96. const char* audio_playbackDeviceName,
  97. webrtc::CodecInst audio_codec,
  98. int audio_tx_port,
  99. int audio_rx_port,
  100. int protection_method);
  101. void PrintRTCCPStatistics(webrtc::ViERTP_RTCP* vie_rtp_rtcp,
  102. int video_channel,
  103. StatisticsType stat_type);
  104. void PrintRTPStatistics(webrtc::ViERTP_RTCP* vie_rtp_rtcp,
  105. int video_channel);
  106. void PrintBandwidthUsage(webrtc::ViERTP_RTCP* vie_rtp_rtcp,
  107. int video_channel);
  108. void PrintCodecStatistics(webrtc::ViECodec* vie_codec,
  109. int video_channel,
  110. StatisticsType stat_type);
  111. void PrintGetDiscardedPackets(webrtc::ViECodec* vie_codec,
  112. int video_channel);
  113. void PrintVideoStreamInformation(webrtc::ViECodec* vie_codec,
  114. int video_channel);
  115. void PrintVideoCodec(webrtc::VideoCodec video_codec);
  116. // The following are video functions.
  117. void GetVideoPorts(int* tx_port, int* rx_port);
  118. void SetVideoCodecType(webrtc::ViECodec* vie_codec,
  119. webrtc::VideoCodec* video_codec);
  120. void SetVideoCodecResolution(webrtc::VideoCodec* video_codec);
  121. void SetVideoCodecSize(webrtc::VideoCodec* video_codec);
  122. void SetVideoCodecBitrate(webrtc::VideoCodec* video_codec);
  123. void SetVideoCodecMinBitrate(webrtc::VideoCodec* video_codec);
  124. void SetVideoCodecMaxBitrate(webrtc::VideoCodec* video_codec);
  125. void SetVideoCodecMaxFramerate(webrtc::VideoCodec* video_codec);
  126. void SetVideoCodecTemporalLayer(webrtc::VideoCodec* video_codec);
  127. VideoProtectionMethod GetVideoProtection();
  128. bool SetVideoProtection(webrtc::ViECodec* vie_codec,
  129. webrtc::ViERTP_RTCP* vie_rtp_rtcp,
  130. int video_channel,
  131. VideoProtectionMethod protection_method);
  132. bool GetBitrateSignaling();
  133. // The following are audio helper functions.
  134. bool GetAudioDevices(webrtc::VoEBase* voe_base,
  135. webrtc::VoEHardware* voe_hardware,
  136. char* recording_device_name, int& recording_device_index,
  137. char* playback_device_name, int& playback_device_index);
  138. bool GetAudioDevices(webrtc::VoEBase* voe_base,
  139. webrtc::VoEHardware* voe_hardware,
  140. int& recording_device_index, int& playback_device_index);
  141. void GetAudioPorts(int* tx_port, int* rx_port);
  142. bool GetAudioCodec(webrtc::VoECodec* voe_codec,
  143. webrtc::CodecInst& audio_codec);
  144. int ViEAutoTest::ViECustomCall() {
  145. ViETest::Log(" ");
  146. ViETest::Log("========================================");
  147. ViETest::Log(" Enter values to use custom settings\n");
  148. int error = 0;
  149. int number_of_errors = 0;
  150. std::string str;
  151. // Create the VoE and get the VoE interfaces.
  152. webrtc::VoiceEngine* voe = webrtc::VoiceEngine::Create();
  153. number_of_errors += ViETest::TestError(voe != NULL, "ERROR: %s at line %d",
  154. __FUNCTION__, __LINE__);
  155. webrtc::VoEBase* voe_base = webrtc::VoEBase::GetInterface(voe);
  156. number_of_errors += ViETest::TestError(voe_base != NULL,
  157. "ERROR: %s at line %d", __FUNCTION__,
  158. __LINE__);
  159. error = voe_base->Init();
  160. number_of_errors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
  161. __FUNCTION__, __LINE__);
  162. webrtc::VoECodec* voe_codec = webrtc::VoECodec::GetInterface(voe);
  163. number_of_errors += ViETest::TestError(voe_codec != NULL,
  164. "ERROR: %s at line %d", __FUNCTION__,
  165. __LINE__);
  166. webrtc::VoEHardware* voe_hardware =
  167. webrtc::VoEHardware::GetInterface(voe);
  168. number_of_errors += ViETest::TestError(voe_hardware != NULL,
  169. "ERROR: %s at line %d", __FUNCTION__,
  170. __LINE__);
  171. webrtc::VoEAudioProcessing* voe_apm =
  172. webrtc::VoEAudioProcessing::GetInterface(voe);
  173. number_of_errors += ViETest::TestError(voe_apm != NULL,
  174. "ERROR: %s at line %d", __FUNCTION__,
  175. __LINE__);
  176. // Create the ViE and get the ViE Interfaces.
  177. webrtc::VideoEngine* vie = webrtc::VideoEngine::Create();
  178. number_of_errors += ViETest::TestError(vie != NULL,
  179. "ERROR: %s at line %d", __FUNCTION__,
  180. __LINE__);
  181. webrtc::ViEBase* vie_base = webrtc::ViEBase::GetInterface(vie);
  182. number_of_errors += ViETest::TestError(vie_base != NULL,
  183. "ERROR: %s at line %d", __FUNCTION__,
  184. __LINE__);
  185. error = vie_base->Init();
  186. number_of_errors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
  187. __FUNCTION__, __LINE__);
  188. webrtc::ViECapture* vie_capture =
  189. webrtc::ViECapture::GetInterface(vie);
  190. number_of_errors += ViETest::TestError(vie_capture != NULL,
  191. "ERROR: %s at line %d", __FUNCTION__,
  192. __LINE__);
  193. webrtc::ViERender* vie_renderer = webrtc::ViERender::GetInterface(vie);
  194. number_of_errors += ViETest::TestError(vie_renderer != NULL,
  195. "ERROR: %s at line %d", __FUNCTION__,
  196. __LINE__);
  197. webrtc::ViECodec* vie_codec = webrtc::ViECodec::GetInterface(vie);
  198. number_of_errors += ViETest::TestError(vie_codec != NULL,
  199. "ERROR: %s at line %d", __FUNCTION__,
  200. __LINE__);
  201. webrtc::ViENetwork* vie_network = webrtc::ViENetwork::GetInterface(vie);
  202. number_of_errors += ViETest::TestError(vie_network != NULL,
  203. "ERROR: %s at line %d", __FUNCTION__,
  204. __LINE__);
  205. webrtc::ViEFile* vie_file = webrtc::ViEFile::GetInterface(vie);
  206. number_of_errors += ViETest::TestError(vie_file != NULL,
  207. "ERROR: %s at line %d", __FUNCTION__,
  208. __LINE__);
  209. bool start_call = false;
  210. std::string ip_address;
  211. const unsigned int KMaxUniqueIdLength = 256;
  212. char unique_id[KMaxUniqueIdLength] = "";
  213. char device_name[KMaxUniqueIdLength] = "";
  214. int video_tx_port = 0;
  215. int video_rx_port = 0;
  216. int video_channel = -1;
  217. webrtc::VideoCodec video_send_codec;
  218. char audio_capture_device_name[KMaxUniqueIdLength] = "";
  219. char audio_playbackDeviceName[KMaxUniqueIdLength] = "";
  220. int audio_capture_device_index = -1;
  221. int audio_playback_device_index = -1;
  222. int audio_tx_port = 0;
  223. int audio_rx_port = 0;
  224. webrtc::CodecInst audio_codec;
  225. int audio_channel = -1;
  226. VideoProtectionMethod protection_method = kProtectionMethodNone;
  227. bool is_image_scale_enabled = false;
  228. bool remb = true;
  229. while (!start_call) {
  230. // Get the IP address to use from call.
  231. ip_address = GetIPAddress();
  232. // Get the video device to use for call.
  233. memset(device_name, 0, KMaxUniqueIdLength);
  234. memset(unique_id, 0, KMaxUniqueIdLength);
  235. if (!GetVideoDevice(vie_base, vie_capture, device_name, unique_id))
  236. return number_of_errors;
  237. // Get and set the video ports for the call.
  238. video_tx_port = 0;
  239. video_rx_port = 0;
  240. GetVideoPorts(&video_tx_port, &video_rx_port);
  241. // Get and set the video codec parameters for the call.
  242. memset(&video_send_codec, 0, sizeof(webrtc::VideoCodec));
  243. SetVideoCodecType(vie_codec, &video_send_codec);
  244. SetVideoCodecSize(&video_send_codec);
  245. SetVideoCodecBitrate(&video_send_codec);
  246. SetVideoCodecMinBitrate(&video_send_codec);
  247. SetVideoCodecMaxBitrate(&video_send_codec);
  248. SetVideoCodecMaxFramerate(&video_send_codec);
  249. SetVideoCodecTemporalLayer(&video_send_codec);
  250. remb = GetBitrateSignaling();
  251. // Get the video protection method for the call.
  252. protection_method = GetVideoProtection();
  253. // Get the audio device for the call.
  254. memset(audio_capture_device_name, 0, KMaxUniqueIdLength);
  255. memset(audio_playbackDeviceName, 0, KMaxUniqueIdLength);
  256. GetAudioDevices(voe_base, voe_hardware, audio_capture_device_name,
  257. audio_capture_device_index, audio_playbackDeviceName,
  258. audio_playback_device_index);
  259. // Get the audio port for the call.
  260. audio_tx_port = 0;
  261. audio_rx_port = 0;
  262. GetAudioPorts(&audio_tx_port, &audio_rx_port);
  263. // Get the audio codec for the call.
  264. memset(static_cast<void*>(&audio_codec), 0, sizeof(audio_codec));
  265. GetAudioCodec(voe_codec, audio_codec);
  266. // Now ready to start the call. Check user wants to continue.
  267. PrintCallInformation(ip_address.c_str(), device_name, unique_id,
  268. video_send_codec, video_tx_port, video_rx_port,
  269. audio_capture_device_name, audio_playbackDeviceName,
  270. audio_codec, audio_tx_port, audio_rx_port,
  271. protection_method);
  272. printf("\n");
  273. int selection =
  274. FromChoices("Ready to start:",
  275. "Start the call\n"
  276. "Reconfigure call settings\n")
  277. .WithDefault("Start the call").Choose();
  278. start_call = (selection == 1);
  279. }
  280. /// **************************************************************
  281. // Begin create/initialize WebRTC Video Engine for testing.
  282. /// **************************************************************
  283. if (start_call == true) {
  284. // Configure audio channel first.
  285. audio_channel = voe_base->CreateChannel();
  286. error = voe_base->SetSendDestination(audio_channel, audio_tx_port,
  287. ip_address.c_str());
  288. number_of_errors += ViETest::TestError(error == 0,
  289. "ERROR: %s at line %d",
  290. __FUNCTION__, __LINE__);
  291. error = voe_base->SetLocalReceiver(audio_channel, audio_rx_port);
  292. number_of_errors += ViETest::TestError(error == 0,
  293. "ERROR: %s at line %d",
  294. __FUNCTION__, __LINE__);
  295. error = voe_hardware->SetRecordingDevice(audio_capture_device_index);
  296. number_of_errors += ViETest::TestError(error == 0,
  297. "ERROR: %s at line %d",
  298. __FUNCTION__, __LINE__);
  299. error = voe_hardware->SetPlayoutDevice(audio_playback_device_index);
  300. number_of_errors += ViETest::TestError(error == 0,
  301. "ERROR: %s at line %d",
  302. __FUNCTION__, __LINE__);
  303. error = voe_codec->SetSendCodec(audio_channel, audio_codec);
  304. number_of_errors += ViETest::TestError(error == 0,
  305. "ERROR: %s at line %d",
  306. __FUNCTION__, __LINE__);
  307. error = voe_apm->SetAgcStatus(true, webrtc::kAgcDefault);
  308. number_of_errors += ViETest::TestError(error == 0,
  309. "ERROR: %s at line %d",
  310. __FUNCTION__, __LINE__);
  311. error = voe_apm->SetNsStatus(true, webrtc::kNsHighSuppression);
  312. number_of_errors += ViETest::TestError(error == 0,
  313. "ERROR: %s at line %d",
  314. __FUNCTION__, __LINE__);
  315. // Now configure the video channel.
  316. error = vie->SetTraceFilter(webrtc::kTraceAll);
  317. number_of_errors += ViETest::TestError(error == 0,
  318. "ERROR: %s at line %d",
  319. __FUNCTION__, __LINE__);
  320. std::string trace_file =
  321. ViETest::GetResultOutputPath() + "ViECustomCall_trace.txt";
  322. error = vie->SetTraceFile(trace_file.c_str());
  323. number_of_errors += ViETest::TestError(error == 0,
  324. "ERROR: %s at line %d",
  325. __FUNCTION__, __LINE__);
  326. error = vie_base->SetVoiceEngine(voe);
  327. number_of_errors += ViETest::TestError(error == 0,
  328. "ERROR: %s at line %d",
  329. __FUNCTION__, __LINE__);
  330. error = vie_base->CreateChannel(video_channel);
  331. number_of_errors += ViETest::TestError(error == 0,
  332. "ERROR: %s at line %d",
  333. __FUNCTION__, __LINE__);
  334. error = vie_base->ConnectAudioChannel(video_channel, audio_channel);
  335. number_of_errors += ViETest::TestError(error == 0,
  336. "ERROR: %s at line %d",
  337. __FUNCTION__, __LINE__);
  338. int capture_id = 0;
  339. error = vie_capture->AllocateCaptureDevice(unique_id,
  340. KMaxUniqueIdLength,
  341. capture_id);
  342. number_of_errors += ViETest::TestError(error == 0,
  343. "ERROR: %s at line %d",
  344. __FUNCTION__, __LINE__);
  345. error = vie_capture->ConnectCaptureDevice(capture_id, video_channel);
  346. number_of_errors += ViETest::TestError(error == 0,
  347. "ERROR: %s at line %d",
  348. __FUNCTION__, __LINE__);
  349. error = vie_capture->StartCapture(capture_id);
  350. number_of_errors += ViETest::TestError(error == 0,
  351. "ERROR: %s at line %d",
  352. __FUNCTION__, __LINE__);
  353. webrtc::ViERTP_RTCP* vie_rtp_rtcp =
  354. webrtc::ViERTP_RTCP::GetInterface(vie);
  355. number_of_errors += ViETest::TestError(vie != NULL,
  356. "ERROR: %s at line %d",
  357. __FUNCTION__, __LINE__);
  358. error = vie_rtp_rtcp->SetRTCPStatus(video_channel,
  359. webrtc::kRtcpCompound_RFC4585);
  360. number_of_errors += ViETest::TestError(error == 0,
  361. "ERROR: %s at line %d",
  362. __FUNCTION__, __LINE__);
  363. error = vie_rtp_rtcp->SetKeyFrameRequestMethod(
  364. video_channel, webrtc::kViEKeyFrameRequestPliRtcp);
  365. number_of_errors += ViETest::TestError(error == 0,
  366. "ERROR: %s at line %d",
  367. __FUNCTION__, __LINE__);
  368. if (remb) {
  369. error = vie_rtp_rtcp->SetRembStatus(video_channel, true, true);
  370. number_of_errors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
  371. __FUNCTION__, __LINE__);
  372. } else {
  373. error = vie_rtp_rtcp->SetTMMBRStatus(video_channel, true);
  374. number_of_errors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
  375. __FUNCTION__, __LINE__);
  376. }
  377. error = vie_renderer->AddRenderer(capture_id, _window1, 0, 0.0, 0.0, 1.0,
  378. 1.0);
  379. number_of_errors += ViETest::TestError(error == 0,
  380. "ERROR: %s at line %d",
  381. __FUNCTION__, __LINE__);
  382. error = vie_renderer->AddRenderer(video_channel, _window2, 1, 0.0, 0.0, 1.0,
  383. 1.0);
  384. number_of_errors += ViETest::TestError(error == 0,
  385. "ERROR: %s at line %d",
  386. __FUNCTION__, __LINE__);
  387. error = vie_network->SetSendDestination(video_channel, ip_address.c_str(),
  388. video_tx_port);
  389. number_of_errors += ViETest::TestError(error == 0,
  390. "ERROR: %s at line %d",
  391. __FUNCTION__, __LINE__);
  392. error = vie_network->SetLocalReceiver(video_channel, video_rx_port);
  393. number_of_errors += ViETest::TestError(error == 0,
  394. "ERROR: %s at line %d",
  395. __FUNCTION__, __LINE__);
  396. error = vie_codec->SetSendCodec(video_channel, video_send_codec);
  397. number_of_errors += ViETest::TestError(error == 0,
  398. "ERROR: %s at line %d",
  399. __FUNCTION__, __LINE__);
  400. error = vie_codec->SetReceiveCodec(video_channel, video_send_codec);
  401. number_of_errors += ViETest::TestError(error == 0,
  402. "ERROR: %s at line %d",
  403. __FUNCTION__, __LINE__);
  404. // Set the Video Protection before start send and receive.
  405. SetVideoProtection(vie_codec, vie_rtp_rtcp,
  406. video_channel, protection_method);
  407. // Start Voice Playout and Receive.
  408. error = voe_base->StartReceive(audio_channel);
  409. number_of_errors += ViETest::TestError(error == 0,
  410. "ERROR: %s at line %d",
  411. __FUNCTION__, __LINE__);
  412. error = voe_base->StartPlayout(audio_channel);
  413. number_of_errors += ViETest::TestError(error == 0,
  414. "ERROR: %s at line %d",
  415. __FUNCTION__, __LINE__);
  416. error = voe_base->StartSend(audio_channel);
  417. number_of_errors += ViETest::TestError(error == 0,
  418. "ERROR: %s at line %d",
  419. __FUNCTION__, __LINE__);
  420. // Now start the Video Send & Receive.
  421. error = vie_base->StartSend(video_channel);
  422. number_of_errors += ViETest::TestError(error == 0,
  423. "ERROR: %s at line %d",
  424. __FUNCTION__, __LINE__);
  425. error = vie_base->StartReceive(video_channel);
  426. number_of_errors += ViETest::TestError(error == 0,
  427. "ERROR: %s at line %d",
  428. __FUNCTION__, __LINE__);
  429. error = vie_renderer->StartRender(capture_id);
  430. number_of_errors += ViETest::TestError(error == 0,
  431. "ERROR: %s at line %d",
  432. __FUNCTION__, __LINE__);
  433. error = vie_renderer->StartRender(video_channel);
  434. number_of_errors += ViETest::TestError(error == 0,
  435. "ERROR: %s at line %d",
  436. __FUNCTION__, __LINE__);
  437. ViEAutotestFileObserver file_observer;
  438. int file_id;
  439. ViEAutotestEncoderObserver* codec_encoder_observer = NULL;
  440. ViEAutotestDecoderObserver* codec_decoder_observer = NULL;
  441. // Engine ready, wait for input.
  442. // Call started.
  443. std::cout << std::endl;
  444. std::cout << "Custom call started" << std::endl;
  445. // Modify call or stop call.
  446. printf("\n");
  447. int selection = FromChoices(
  448. "And now?",
  449. "Stop the call\n"
  450. "Modify the call\n").Choose();
  451. int file_selection = 0;
  452. while (selection == 2) {
  453. // Keep on modifying the call until user stops the call.
  454. int modify_selection = FromChoices(
  455. "Modify the call:",
  456. "Stop call\n"
  457. "Change Video Send Codec\n"
  458. "Change Video Send Size by Common Resolutions\n"
  459. "Change Video Send Size by Width & Height\n"
  460. "Change Video Capture Device\n"
  461. "Record Incoming Call\n"
  462. "Record Outgoing Call\n"
  463. "Play File on Video Channel "
  464. "(Assumes you recorded incoming & outgoing call)\n"
  465. "Change Video Protection Method\n"
  466. "Toggle Encoder Observer\n"
  467. "Toggle Decoder Observer\n"
  468. "Print Call Information\n"
  469. "Print Call Statistics\n"
  470. "Toggle Image Scaling (Warning: high CPU usage when enabled)\n")
  471. .WithDefault("Stop call")
  472. .Choose();
  473. switch (modify_selection) {
  474. case 1:
  475. selection = 1;
  476. break;
  477. case 2:
  478. // Change video codec.
  479. SetVideoCodecType(vie_codec, &video_send_codec);
  480. SetVideoCodecSize(&video_send_codec);
  481. SetVideoCodecBitrate(&video_send_codec);
  482. SetVideoCodecMinBitrate(&video_send_codec);
  483. SetVideoCodecMaxBitrate(&video_send_codec);
  484. SetVideoCodecMaxFramerate(&video_send_codec);
  485. SetVideoCodecTemporalLayer(&video_send_codec);
  486. PrintCallInformation(ip_address.c_str(), device_name,
  487. unique_id, video_send_codec,
  488. video_tx_port, video_rx_port,
  489. audio_capture_device_name,
  490. audio_playbackDeviceName, audio_codec,
  491. audio_tx_port, audio_rx_port, protection_method);
  492. error = vie_codec->SetSendCodec(video_channel, video_send_codec);
  493. number_of_errors += ViETest::TestError(error == 0,
  494. "ERROR: %s at line %d",
  495. __FUNCTION__, __LINE__);
  496. error = vie_codec->SetReceiveCodec(video_channel, video_send_codec);
  497. number_of_errors += ViETest::TestError(error == 0,
  498. "ERROR: %s at line %d",
  499. __FUNCTION__, __LINE__);
  500. break;
  501. case 3:
  502. // Change Video codec size by common resolution.
  503. SetVideoCodecResolution(&video_send_codec);
  504. PrintCallInformation(ip_address.c_str(), device_name,
  505. unique_id, video_send_codec,
  506. video_tx_port, video_rx_port,
  507. audio_capture_device_name,
  508. audio_playbackDeviceName, audio_codec,
  509. audio_tx_port, audio_rx_port, protection_method);
  510. error = vie_codec->SetSendCodec(video_channel, video_send_codec);
  511. number_of_errors += ViETest::TestError(error == 0,
  512. "ERROR: %s at line %d",
  513. __FUNCTION__, __LINE__);
  514. error = vie_codec->SetReceiveCodec(video_channel, video_send_codec);
  515. number_of_errors += ViETest::TestError(error == 0,
  516. "ERROR: %s at line %d",
  517. __FUNCTION__, __LINE__);
  518. break;
  519. case 4:
  520. // Change video codec by size height and width.
  521. SetVideoCodecSize(&video_send_codec);
  522. PrintCallInformation(ip_address.c_str(), device_name,
  523. unique_id, video_send_codec,
  524. video_tx_port, video_rx_port,
  525. audio_capture_device_name,
  526. audio_playbackDeviceName, audio_codec,
  527. audio_tx_port, audio_rx_port, protection_method);
  528. error = vie_codec->SetSendCodec(video_channel, video_send_codec);
  529. number_of_errors += ViETest::TestError(error == 0,
  530. "ERROR: %s at line %d",
  531. __FUNCTION__, __LINE__);
  532. error = vie_codec->SetReceiveCodec(video_channel, video_send_codec);
  533. number_of_errors += ViETest::TestError(error == 0,
  534. "ERROR: %s at line %d",
  535. __FUNCTION__, __LINE__);
  536. break;
  537. case 5:
  538. error = vie_renderer->StopRender(capture_id);
  539. number_of_errors += ViETest::TestError(error == 0,
  540. "ERROR: %s at line %d",
  541. __FUNCTION__, __LINE__);
  542. error = vie_renderer->RemoveRenderer(capture_id);
  543. number_of_errors += ViETest::TestError(error == 0,
  544. "ERROR: %s at line %d",
  545. __FUNCTION__, __LINE__);
  546. error = vie_capture->StopCapture(capture_id);
  547. number_of_errors += ViETest::TestError(error == 0,
  548. "ERROR: %s at line %d",
  549. __FUNCTION__, __LINE__);
  550. error = vie_capture->DisconnectCaptureDevice(video_channel);
  551. number_of_errors += ViETest::TestError(error == 0,
  552. "ERROR: %s at line %d",
  553. __FUNCTION__, __LINE__);
  554. error = vie_capture->ReleaseCaptureDevice(capture_id);
  555. number_of_errors += ViETest::TestError(error == 0,
  556. "ERROR: %s at line %d",
  557. __FUNCTION__, __LINE__);
  558. memset(device_name, 0, KMaxUniqueIdLength);
  559. memset(unique_id, 0, KMaxUniqueIdLength);
  560. if (!GetVideoDevice(vie_base, vie_capture, device_name, unique_id))
  561. return number_of_errors;
  562. capture_id = 0;
  563. error = vie_capture->AllocateCaptureDevice(unique_id,
  564. KMaxUniqueIdLength,
  565. capture_id);
  566. number_of_errors += ViETest::TestError(error == 0,
  567. "ERROR: %s at line %d",
  568. __FUNCTION__, __LINE__);
  569. error = vie_capture->ConnectCaptureDevice(capture_id,
  570. video_channel);
  571. number_of_errors += ViETest::TestError(error == 0,
  572. "ERROR: %s at line %d",
  573. __FUNCTION__, __LINE__);
  574. error = vie_capture->StartCapture(capture_id);
  575. number_of_errors += ViETest::TestError(error == 0,
  576. "ERROR: %s at line %d",
  577. __FUNCTION__, __LINE__);
  578. error = vie_renderer->AddRenderer(capture_id, _window1, 0, 0.0, 0.0,
  579. 1.0, 1.0);
  580. number_of_errors += ViETest::TestError(error == 0,
  581. "ERROR: %s at line %d",
  582. __FUNCTION__, __LINE__);
  583. error = vie_renderer->StartRender(capture_id);
  584. number_of_errors += ViETest::TestError(error == 0,
  585. "ERROR: %s at line %d",
  586. __FUNCTION__, __LINE__);
  587. break;
  588. case 6:
  589. // Record the incoming call.
  590. std::cout << "Start Recording Incoming Video "
  591. << DEFAULT_INCOMING_FILE_NAME << std::endl;
  592. error = vie_file->StartRecordIncomingVideo(
  593. video_channel, DEFAULT_INCOMING_FILE_NAME,
  594. webrtc::NO_AUDIO, audio_codec, video_send_codec);
  595. std::cout << "Press enter to stop...";
  596. std::getline(std::cin, str);
  597. error = vie_file->StopRecordIncomingVideo(video_channel);
  598. number_of_errors += ViETest::TestError(error == 0,
  599. "ERROR:%d %s at line %d",
  600. vie_base->LastError(),
  601. __FUNCTION__, __LINE__);
  602. break;
  603. case 7:
  604. // Record the outgoing call.
  605. std::cout << "Start Recording Outgoing Video "
  606. << DEFAULT_OUTGOING_FILE_NAME << std::endl;
  607. error = vie_file->StartRecordOutgoingVideo(
  608. video_channel, DEFAULT_OUTGOING_FILE_NAME,
  609. webrtc::NO_AUDIO, audio_codec, video_send_codec);
  610. std::cout << "Press enter to stop...";
  611. std::getline(std::cin, str);
  612. error = vie_file->StopRecordOutgoingVideo(video_channel);
  613. number_of_errors += ViETest::TestError(error == 0,
  614. "ERROR:%d %s at line %d",
  615. vie_base->LastError(),
  616. __FUNCTION__, __LINE__);
  617. break;
  618. case 8:
  619. // Send the file on the video_channel.
  620. file_selection = FromChoices(
  621. "Choose a file name:",
  622. DEFAULT_INCOMING_FILE_NAME "\n"
  623. DEFAULT_OUTGOING_FILE_NAME "\n")
  624. .WithDefault(DEFAULT_INCOMING_FILE_NAME).Choose();
  625. // Disconnect the camera first.
  626. error = vie_capture->DisconnectCaptureDevice(video_channel);
  627. number_of_errors += ViETest::TestError(error == 0,
  628. "ERROR:%d %s at line %d",
  629. vie_base->LastError(),
  630. __FUNCTION__, __LINE__);
  631. if (file_selection == 2)
  632. error = vie_file->StartPlayFile(DEFAULT_OUTGOING_FILE_NAME,
  633. file_id, true);
  634. else
  635. error = vie_file->StartPlayFile(DEFAULT_INCOMING_FILE_NAME,
  636. file_id, true);
  637. number_of_errors += ViETest::TestError(error == 0,
  638. "ERROR:%d %s at line %d",
  639. vie_base->LastError(),
  640. __FUNCTION__, __LINE__);
  641. ViETest::Log("Registering file observer");
  642. error = vie_file->RegisterObserver(file_id, file_observer);
  643. number_of_errors += ViETest::TestError(error == 0,
  644. "ERROR:%d %s at line %d",
  645. vie_base->LastError(),
  646. __FUNCTION__, __LINE__);
  647. std::cout << std::endl;
  648. std::cout << "Start sending the file that is played in a loop "
  649. << std::endl;
  650. error = vie_file->SendFileOnChannel(file_id, video_channel);
  651. number_of_errors += ViETest::TestError(error == 0,
  652. "ERROR:%d %s at line %d",
  653. vie_base->LastError(),
  654. __FUNCTION__, __LINE__);
  655. std::cout << "Press enter to stop...";
  656. std::getline(std::cin, str);
  657. ViETest::Log("Stopped sending video on channel");
  658. error = vie_file->StopSendFileOnChannel(video_channel);
  659. number_of_errors += ViETest::TestError(error == 0,
  660. "ERROR:%d %s at line %d",
  661. vie_base->LastError(),
  662. __FUNCTION__, __LINE__);
  663. ViETest::Log("Stop playing the file.");
  664. error = vie_file->StopPlayFile(file_id);
  665. number_of_errors += ViETest::TestError(error == 0,
  666. "ERROR:%d %s at line %d",
  667. vie_base->LastError(),
  668. __FUNCTION__, __LINE__);
  669. error = vie_capture->ConnectCaptureDevice(capture_id,
  670. video_channel);
  671. number_of_errors += ViETest::TestError(error == 0,
  672. "ERROR:%d %s at line %d",
  673. vie_base->LastError(),
  674. __FUNCTION__, __LINE__);
  675. error = vie_file->DeregisterObserver(file_id, file_observer);
  676. number_of_errors += ViETest::TestError(error == -1,
  677. "ERROR:%d %s at line %d",
  678. vie_base->LastError(),
  679. __FUNCTION__, __LINE__);
  680. break;
  681. case 9:
  682. // Change the Video Protection.
  683. protection_method = GetVideoProtection();
  684. SetVideoProtection(vie_codec, vie_rtp_rtcp,
  685. video_channel, protection_method);
  686. break;
  687. case 10:
  688. // Toggle Encoder Observer.
  689. if (!codec_encoder_observer) {
  690. std::cout << "Registering Encoder Observer" << std::endl;
  691. codec_encoder_observer = new ViEAutotestEncoderObserver();
  692. error = vie_codec->RegisterEncoderObserver(video_channel,
  693. *codec_encoder_observer);
  694. number_of_errors += ViETest::TestError(error == 0,
  695. "ERROR: %s at line %d",
  696. __FUNCTION__, __LINE__);
  697. } else {
  698. std::cout << "Deregistering Encoder Observer" << std::endl;
  699. error = vie_codec->DeregisterEncoderObserver(video_channel);
  700. delete codec_encoder_observer;
  701. codec_encoder_observer = NULL;
  702. number_of_errors += ViETest::TestError(error == 0,
  703. "ERROR: %s at line %d",
  704. __FUNCTION__, __LINE__);
  705. }
  706. break;
  707. case 11:
  708. // Toggle Decoder Observer.
  709. if (!codec_decoder_observer) {
  710. std::cout << "Registering Decoder Observer" << std::endl;
  711. codec_decoder_observer = new ViEAutotestDecoderObserver();
  712. error = vie_codec->RegisterDecoderObserver(video_channel,
  713. *codec_decoder_observer);
  714. number_of_errors += ViETest::TestError(error == 0,
  715. "ERROR: %s at line %d",
  716. __FUNCTION__, __LINE__);
  717. } else {
  718. std::cout << "Deregistering Decoder Observer" << std::endl;
  719. error = vie_codec->DeregisterDecoderObserver(video_channel);
  720. delete codec_decoder_observer;
  721. codec_decoder_observer = NULL;
  722. number_of_errors += ViETest::TestError(error == 0,
  723. "ERROR: %s at line %d",
  724. __FUNCTION__, __LINE__);
  725. }
  726. break;
  727. case 12:
  728. // Print Call information..
  729. PrintCallInformation(ip_address.c_str(), device_name,
  730. unique_id, video_send_codec,
  731. video_tx_port, video_rx_port,
  732. audio_capture_device_name,
  733. audio_playbackDeviceName,
  734. audio_codec, audio_tx_port,
  735. audio_rx_port, protection_method);
  736. PrintVideoStreamInformation(vie_codec,
  737. video_channel);
  738. break;
  739. case 13:
  740. // Print Call statistics.
  741. PrintRTCCPStatistics(vie_rtp_rtcp, video_channel,
  742. kSendStatistic);
  743. PrintRTCCPStatistics(vie_rtp_rtcp, video_channel,
  744. kReceivedStatistic);
  745. PrintRTPStatistics(vie_rtp_rtcp, video_channel);
  746. PrintBandwidthUsage(vie_rtp_rtcp, video_channel);
  747. PrintCodecStatistics(vie_codec, video_channel,
  748. kSendStatistic);
  749. PrintCodecStatistics(vie_codec, video_channel,
  750. kReceivedStatistic);
  751. PrintGetDiscardedPackets(vie_codec, video_channel);
  752. break;
  753. case 14:
  754. is_image_scale_enabled = !is_image_scale_enabled;
  755. vie_codec->SetImageScaleStatus(video_channel, is_image_scale_enabled);
  756. if (is_image_scale_enabled) {
  757. std::cout << "Image Scale is now enabled" << std::endl;
  758. } else {
  759. std::cout << "Image Scale is now disabled" << std::endl;
  760. }
  761. break;
  762. default:
  763. assert(false);
  764. break;
  765. }
  766. }
  767. // Testing finished. Tear down Voice and Video Engine.
  768. // Tear down the VoE first.
  769. error = voe_base->StopReceive(audio_channel);
  770. number_of_errors += ViETest::TestError(error == 0,
  771. "ERROR: %s at line %d",
  772. __FUNCTION__, __LINE__);
  773. error = voe_base->StopPlayout(audio_channel);
  774. number_of_errors += ViETest::TestError(error == 0,
  775. "ERROR: %s at line %d",
  776. __FUNCTION__, __LINE__);
  777. error = voe_base->DeleteChannel(audio_channel);
  778. number_of_errors += ViETest::TestError(error == 0,
  779. "ERROR: %s at line %d",
  780. __FUNCTION__, __LINE__);
  781. // Now tear down the ViE engine.
  782. error = vie_base->DisconnectAudioChannel(video_channel);
  783. // If Encoder/Decoder Observer is running, delete them.
  784. if (codec_encoder_observer) {
  785. error = vie_codec->DeregisterEncoderObserver(video_channel);
  786. delete codec_encoder_observer;
  787. number_of_errors += ViETest::TestError(error == 0,
  788. "ERROR: %s at line %d",
  789. __FUNCTION__, __LINE__);
  790. }
  791. if (codec_decoder_observer) {
  792. error = vie_codec->DeregisterDecoderObserver(video_channel);
  793. delete codec_decoder_observer;
  794. number_of_errors += ViETest::TestError(error == 0,
  795. "ERROR: %s at line %d",
  796. __FUNCTION__, __LINE__);
  797. }
  798. error = vie_base->StopReceive(video_channel);
  799. number_of_errors += ViETest::TestError(error == 0,
  800. "ERROR: %s at line %d",
  801. __FUNCTION__, __LINE__);
  802. error = vie_base->StopSend(video_channel);
  803. number_of_errors += ViETest::TestError(error == 0,
  804. "ERROR: %s at line %d",
  805. __FUNCTION__, __LINE__);
  806. error = vie_renderer->StopRender(capture_id);
  807. number_of_errors += ViETest::TestError(error == 0,
  808. "ERROR: %s at line %d",
  809. __FUNCTION__, __LINE__);
  810. error = vie_renderer->StopRender(video_channel);
  811. number_of_errors += ViETest::TestError(error == 0,
  812. "ERROR: %s at line %d",
  813. __FUNCTION__, __LINE__);
  814. error = vie_renderer->RemoveRenderer(capture_id);
  815. number_of_errors += ViETest::TestError(error == 0,
  816. "ERROR: %s at line %d",
  817. __FUNCTION__, __LINE__);
  818. error = vie_renderer->RemoveRenderer(video_channel);
  819. number_of_errors += ViETest::TestError(error == 0,
  820. "ERROR: %s at line %d",
  821. __FUNCTION__, __LINE__);
  822. error = vie_capture->StopCapture(capture_id);
  823. number_of_errors += ViETest::TestError(error == 0,
  824. "ERROR: %s at line %d",
  825. __FUNCTION__, __LINE__);
  826. error = vie_capture->DisconnectCaptureDevice(video_channel);
  827. number_of_errors += ViETest::TestError(error == 0,
  828. "ERROR: %s at line %d",
  829. __FUNCTION__, __LINE__);
  830. error = vie_capture->ReleaseCaptureDevice(capture_id);
  831. number_of_errors += ViETest::TestError(error == 0,
  832. "ERROR: %s at line %d",
  833. __FUNCTION__, __LINE__);
  834. error = vie_base->DeleteChannel(video_channel);
  835. number_of_errors += ViETest::TestError(error == 0,
  836. "ERROR: %s at line %d",
  837. __FUNCTION__, __LINE__);
  838. int remaining_interfaces = 0;
  839. remaining_interfaces = vie_file->Release();
  840. number_of_errors += ViETest::TestError(remaining_interfaces == 0,
  841. "ERROR: %s at line %d",
  842. __FUNCTION__, __LINE__);
  843. remaining_interfaces = vie_codec->Release();
  844. number_of_errors += ViETest::TestError(remaining_interfaces == 0,
  845. "ERROR: %s at line %d",
  846. __FUNCTION__, __LINE__);
  847. remaining_interfaces = vie_capture->Release();
  848. number_of_errors += ViETest::TestError(remaining_interfaces == 0,
  849. "ERROR: %s at line %d",
  850. __FUNCTION__, __LINE__);
  851. remaining_interfaces = vie_rtp_rtcp->Release();
  852. number_of_errors += ViETest::TestError(remaining_interfaces == 0,
  853. "ERROR: %s at line %d",
  854. __FUNCTION__, __LINE__);
  855. remaining_interfaces = vie_renderer->Release();
  856. number_of_errors += ViETest::TestError(remaining_interfaces == 0,
  857. "ERROR: %s at line %d",
  858. __FUNCTION__, __LINE__);
  859. remaining_interfaces = vie_network->Release();
  860. number_of_errors += ViETest::TestError(remaining_interfaces == 0,
  861. "ERROR: %s at line %d",
  862. __FUNCTION__, __LINE__);
  863. remaining_interfaces = vie_base->Release();
  864. number_of_errors += ViETest::TestError(remaining_interfaces == 0,
  865. "ERROR: %s at line %d",
  866. __FUNCTION__, __LINE__);
  867. bool deleted = webrtc::VideoEngine::Delete(vie);
  868. number_of_errors += ViETest::TestError(deleted == true,
  869. "ERROR: %s at line %d",
  870. __FUNCTION__, __LINE__);
  871. ViETest::Log(" ");
  872. ViETest::Log(" ViE Autotest Custom Call Started");
  873. ViETest::Log("========================================");
  874. ViETest::Log(" ");
  875. }
  876. return number_of_errors;
  877. }
  878. bool GetVideoDevice(webrtc::ViEBase* vie_base,
  879. webrtc::ViECapture* vie_capture,
  880. char* capture_device_name,
  881. char* capture_device_unique_id) {
  882. int error = 0;
  883. int number_of_errors = 0;
  884. const unsigned int KMaxDeviceNameLength = 128;
  885. const unsigned int KMaxUniqueIdLength = 256;
  886. char device_name[KMaxDeviceNameLength];
  887. char unique_id[KMaxUniqueIdLength];
  888. if (vie_capture->NumberOfCaptureDevices() == 0) {
  889. printf("You have no capture devices plugged into your system.\n");
  890. return false;
  891. }
  892. std::string capture_choices;
  893. std::string first_device;
  894. for (int i = 0; i < vie_capture->NumberOfCaptureDevices(); i++) {
  895. memset(device_name, 0, KMaxDeviceNameLength);
  896. memset(unique_id, 0, KMaxUniqueIdLength);
  897. error = vie_capture->GetCaptureDevice(i, device_name,
  898. KMaxDeviceNameLength,
  899. unique_id,
  900. KMaxUniqueIdLength);
  901. number_of_errors += ViETest::TestError(error == 0,
  902. "ERROR: %s at line %d",
  903. __FUNCTION__, __LINE__);
  904. const int kCaptureLineLength =
  905. KMaxDeviceNameLength + KMaxUniqueIdLength + 8;
  906. char capture_line[kCaptureLineLength];
  907. sprintf(capture_line, "%s (%s)", device_name, unique_id);
  908. capture_choices += capture_line;
  909. capture_choices += "\n";
  910. if (first_device.empty())
  911. first_device = capture_line;
  912. }
  913. int choice = FromChoices("Available Video Capture Devices", capture_choices)
  914. .WithDefault(first_device)
  915. .Choose();
  916. error = vie_capture->GetCaptureDevice(
  917. choice - 1, device_name, KMaxDeviceNameLength, unique_id,
  918. KMaxUniqueIdLength);
  919. number_of_errors += ViETest::TestError(error == 0,
  920. "ERROR: %s at line %d",
  921. __FUNCTION__, __LINE__);
  922. strcpy(capture_device_unique_id, unique_id);
  923. strcpy(capture_device_name, device_name);
  924. return true;
  925. }
  926. bool GetAudioDevices(webrtc::VoEBase* voe_base,
  927. webrtc::VoEHardware* voe_hardware,
  928. char* recording_device_name,
  929. int& recording_device_index,
  930. char* playback_device_name,
  931. int& playback_device_index) {
  932. int error = 0;
  933. int number_of_errors = 0;
  934. const unsigned int KMaxDeviceNameLength = 128;
  935. const unsigned int KMaxUniqueIdLength = 128;
  936. char recording_device_unique_name[KMaxDeviceNameLength];
  937. char playback_device_unique_name[KMaxUniqueIdLength];
  938. int number_of_recording_devices = -1;
  939. error = voe_hardware->GetNumOfRecordingDevices(number_of_recording_devices);
  940. number_of_errors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
  941. __FUNCTION__, __LINE__);
  942. recording_device_index = -1;
  943. playback_device_index = -1;
  944. std::string device_choices;
  945. std::string default_recording_line;
  946. for (int i = 0; i < number_of_recording_devices; ++i) {
  947. error = voe_hardware->GetRecordingDeviceName(
  948. i, recording_device_name, recording_device_unique_name);
  949. number_of_errors += ViETest::TestError(error == 0,
  950. "ERROR: %s at line %d",
  951. __FUNCTION__, __LINE__);
  952. device_choices += recording_device_name;
  953. device_choices += "\n";
  954. if (default_recording_line.empty())
  955. default_recording_line = recording_device_name;
  956. }
  957. int choice = FromChoices("Available audio capture devices:", device_choices)
  958. .WithDefault(default_recording_line)
  959. .Choose();
  960. recording_device_index = choice - 1;
  961. error = voe_hardware->GetRecordingDeviceName(
  962. recording_device_index, recording_device_name,
  963. recording_device_unique_name);
  964. number_of_errors += ViETest::TestError(
  965. error == 0, "ERROR: %s at line %d", __FUNCTION__, __LINE__);
  966. int number_of_playback_devices = -1;
  967. error = voe_hardware->GetNumOfPlayoutDevices(number_of_playback_devices);
  968. number_of_errors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
  969. __FUNCTION__, __LINE__);
  970. std::string playback_choices;
  971. std::string default_playback_line;
  972. for (int i = 0; i < number_of_playback_devices; i++) {
  973. error = voe_hardware->GetPlayoutDeviceName(i,
  974. playback_device_name,
  975. playback_device_unique_name);
  976. number_of_errors += ViETest::TestError(
  977. error == 0, "ERROR: %s at line %d", __FUNCTION__, __LINE__);
  978. playback_choices += playback_device_name;
  979. playback_choices += "\n";
  980. if (default_playback_line.empty())
  981. default_playback_line = playback_device_name;
  982. }
  983. choice = FromChoices("Available audio playout devices:", playback_choices)
  984. .WithDefault(default_playback_line)
  985. .Choose();
  986. playback_device_index = choice - 1;
  987. error = voe_hardware->GetPlayoutDeviceName(playback_device_index,
  988. playback_device_name,
  989. playback_device_unique_name);
  990. number_of_errors += ViETest::TestError(error == 0,
  991. "ERROR: %s at line %d",
  992. __FUNCTION__, __LINE__);
  993. return true;
  994. }
  995. // General helper functions.
  996. std::string GetIPAddress() {
  997. class IpValidator : public webrtc::InputValidator {
  998. public:
  999. bool InputOk(const std::string& input) const {
  1000. // Just check quickly that it's on the form x.y.z.w
  1001. return std::count(input.begin(), input.end(), '.') == 3;
  1002. }
  1003. };
  1004. return TypedInput("Enter destination IP.")
  1005. .WithDefault(DEFAULT_SEND_IP)
  1006. .WithInputValidator(new IpValidator())
  1007. .AskForInput();
  1008. }
  1009. // Video settings functions.
  1010. void GetVideoPorts(int* tx_port, int* rx_port) {
  1011. std::string tx_input = TypedInput("Enter video send port.")
  1012. .WithDefault(DEFAULT_VIDEO_PORT)
  1013. .WithInputValidator(new webrtc::IntegerWithinRangeValidator(1, 65536))
  1014. .AskForInput();
  1015. *tx_port = atoi(tx_input.c_str());
  1016. std::string rx_input = TypedInput("Enter video receive port.")
  1017. .WithDefault(DEFAULT_VIDEO_PORT)
  1018. .WithInputValidator(new webrtc::IntegerWithinRangeValidator(1, 65536))
  1019. .AskForInput();
  1020. *rx_port = atoi(rx_input.c_str());
  1021. }
  1022. // Audio settings functions.
  1023. void GetAudioPorts(int* tx_port, int* rx_port) {
  1024. std::string tx_input = TypedInput("Enter audio send port.")
  1025. .WithDefault(DEFAULT_AUDIO_PORT)
  1026. .WithInputValidator(new webrtc::IntegerWithinRangeValidator(1, 65536))
  1027. .AskForInput();
  1028. *tx_port = atoi(tx_input.c_str());
  1029. std::string rx_input = TypedInput("Enter audio receive port.")
  1030. .WithDefault(DEFAULT_AUDIO_PORT)
  1031. .WithInputValidator(new webrtc::IntegerWithinRangeValidator(1, 65536))
  1032. .AskForInput();
  1033. *rx_port = atoi(rx_input.c_str());
  1034. }
  1035. bool GetAudioCodec(webrtc::VoECodec* voe_codec,
  1036. webrtc::CodecInst& audio_codec) {
  1037. int error = 0;
  1038. memset(&audio_codec, 0, sizeof(webrtc::CodecInst));
  1039. std::string default_codec_line;
  1040. std::string codec_choices;
  1041. for (int codec_idx = 0; codec_idx < voe_codec->NumOfCodecs(); codec_idx++) {
  1042. error = voe_codec->GetCodec(codec_idx, audio_codec);
  1043. ViETest::TestError(error == 0,
  1044. "ERROR: %s at line %d",
  1045. __FUNCTION__, __LINE__);
  1046. char codec_line[128];
  1047. sprintf(codec_line, "%s type: %d freq: %d chan: %d",
  1048. audio_codec.plname, audio_codec.pltype, audio_codec.plfreq,
  1049. audio_codec.channels);
  1050. codec_choices += codec_line;
  1051. codec_choices += "\n";
  1052. if (strcmp(audio_codec.plname, DEFAULT_AUDIO_CODEC) == 0) {
  1053. default_codec_line = codec_line;
  1054. }
  1055. }
  1056. assert(!default_codec_line.empty() && "Default codec doesn't exist.");
  1057. int codec_selection = FromChoices("Available Audio Codecs:", codec_choices)
  1058. .WithDefault(default_codec_line)
  1059. .Choose();
  1060. error = voe_codec->GetCodec(codec_selection - 1, audio_codec);
  1061. ViETest::TestError(error == 0,
  1062. "ERROR: %s at line %d",
  1063. __FUNCTION__, __LINE__);
  1064. return true;
  1065. }
  1066. void PrintCallInformation(const char* IP, const char* video_capture_device_name,
  1067. const char* video_capture_unique_id,
  1068. webrtc::VideoCodec video_codec,
  1069. int video_tx_port, int video_rx_port,
  1070. const char* audio_capture_device_name,
  1071. const char* audio_playbackDeviceName,
  1072. webrtc::CodecInst audio_codec,
  1073. int audio_tx_port, int audio_rx_port,
  1074. int protection_method) {
  1075. std::string str;
  1076. std::cout << "************************************************"
  1077. << std::endl;
  1078. std::cout << "The call has the following settings: " << std::endl;
  1079. std::cout << "\tIP: " << IP << std::endl;
  1080. std::cout << "\tVideo Capture Device: " << video_capture_device_name
  1081. << std::endl;
  1082. std::cout << "\t\tName: " << video_capture_device_name << std::endl;
  1083. std::cout << "\t\tUniqueId: " << video_capture_unique_id << std::endl;
  1084. PrintVideoCodec(video_codec);
  1085. std::cout << "\t Video Tx Port: " << video_tx_port << std::endl;
  1086. std::cout << "\t Video Rx Port: " << video_rx_port << std::endl;
  1087. std::cout << "\t Video Protection Method (NOTE: Starts at 1 now): "
  1088. << protection_method << std::endl;
  1089. std::cout << "\tAudio Capture Device: " << audio_capture_device_name
  1090. << std::endl;
  1091. std::cout << "\tAudio Playback Device: " << audio_playbackDeviceName
  1092. << std::endl;
  1093. std::cout << "\tAudio Codec: " << std::endl;
  1094. std::cout << "\t\tplname: " << audio_codec.plname << std::endl;
  1095. std::cout << "\t\tpltype: " << static_cast<int>(audio_codec.pltype)
  1096. << std::endl;
  1097. std::cout << "\t Audio Tx Port: " << audio_tx_port << std::endl;
  1098. std::cout << "\t Audio Rx Port: " << audio_rx_port << std::endl;
  1099. std::cout << "************************************************"
  1100. << std::endl;
  1101. }
  1102. void SetVideoCodecType(webrtc::ViECodec* vie_codec,
  1103. webrtc::VideoCodec* video_codec) {
  1104. int error = 0;
  1105. int number_of_errors = 0;
  1106. memset(video_codec, 0, sizeof(webrtc::VideoCodec));
  1107. std::string codec_choices;
  1108. std::string default_codec_line;
  1109. for (int i = 0; i < vie_codec->NumberOfCodecs(); i++) {
  1110. error = vie_codec->GetCodec(i, *video_codec);
  1111. number_of_errors += ViETest::TestError(
  1112. error == 0, "ERROR: %s at line %d", __FUNCTION__, __LINE__);
  1113. codec_choices += video_codec->plName;
  1114. codec_choices += "\n";
  1115. if (strcmp(video_codec->plName, DEFAULT_VIDEO_CODEC) == 0)
  1116. default_codec_line = video_codec->plName;
  1117. }
  1118. assert(!default_codec_line.empty() && "Default does not exist.");
  1119. int choice = FromChoices("Available Video Codecs", codec_choices)
  1120. .WithDefault(default_codec_line)
  1121. .Choose();
  1122. error = vie_codec->GetCodec(choice - 1, *video_codec);
  1123. number_of_errors += ViETest::TestError(
  1124. error == 0, "ERROR: %s at line %d", __FUNCTION__, __LINE__);
  1125. if (video_codec->codecType == webrtc::kVideoCodecI420) {
  1126. video_codec->width = 176;
  1127. video_codec->height = 144;
  1128. }
  1129. }
  1130. void SetVideoCodecResolution(webrtc::VideoCodec* video_codec) {
  1131. if (video_codec->codecType != webrtc::kVideoCodecVP8) {
  1132. printf("Can only change codec size if it's VP8\n");
  1133. return;
  1134. }
  1135. int choice = FromChoices(
  1136. "Available Common Resolutions:",
  1137. "SQCIF (128X96)\n"
  1138. "QQVGA (160X120)\n"
  1139. "QCIF (176X144)\n"
  1140. "CIF (352X288)\n"
  1141. "VGA (640X480)\n"
  1142. "WVGA (800x480)\n"
  1143. "4CIF (704X576)\n"
  1144. "SVGA (800X600)\n"
  1145. "HD (1280X720)\n"
  1146. "XGA (1024x768)\n")
  1147. .Choose();
  1148. switch (choice) {
  1149. case 1:
  1150. video_codec->width = 128;
  1151. video_codec->height = 96;
  1152. break;
  1153. case 2:
  1154. video_codec->width = 160;
  1155. video_codec->height = 120;
  1156. break;
  1157. case 3:
  1158. video_codec->width = 176;
  1159. video_codec->height = 144;
  1160. break;
  1161. case 4:
  1162. video_codec->width = 352;
  1163. video_codec->height = 288;
  1164. break;
  1165. case 5:
  1166. video_codec->width = 640;
  1167. video_codec->height = 480;
  1168. break;
  1169. case 6:
  1170. video_codec->width = 800;
  1171. video_codec->height = 480;
  1172. break;
  1173. case 7:
  1174. video_codec->width = 704;
  1175. video_codec->height = 576;
  1176. break;
  1177. case 8:
  1178. video_codec->width = 800;
  1179. video_codec->height = 600;
  1180. break;
  1181. case 9:
  1182. video_codec->width = 1280;
  1183. video_codec->height = 720;
  1184. break;
  1185. case 10:
  1186. video_codec->width = 1024;
  1187. video_codec->height = 768;
  1188. break;
  1189. }
  1190. }
  1191. void SetVideoCodecSize(webrtc::VideoCodec* video_codec) {
  1192. if (video_codec->codecType != webrtc::kVideoCodecVP8) {
  1193. printf("Can only change codec size if it's VP8\n");
  1194. return;
  1195. }
  1196. std::string input = TypedInput("Choose video width.")
  1197. .WithDefault(DEFAULT_VIDEO_CODEC_WIDTH)
  1198. .WithInputValidator(new webrtc::IntegerWithinRangeValidator(1, INT_MAX))
  1199. .AskForInput();
  1200. video_codec->width = atoi(input.c_str());
  1201. input = TypedInput("Choose video height.")
  1202. .WithDefault(DEFAULT_VIDEO_CODEC_HEIGHT)
  1203. .WithInputValidator(new webrtc::IntegerWithinRangeValidator(1, INT_MAX))
  1204. .AskForInput();
  1205. video_codec->height = atoi(input.c_str());
  1206. }
  1207. void SetVideoCodecBitrate(webrtc::VideoCodec* video_codec) {
  1208. std::string input = TypedInput("Choose start rate (in kbps).")
  1209. .WithDefault(DEFAULT_VIDEO_CODEC_BITRATE)
  1210. .WithInputValidator(new webrtc::IntegerWithinRangeValidator(1, INT_MAX))
  1211. .AskForInput();
  1212. video_codec->startBitrate = atoi(input.c_str());
  1213. }
  1214. void SetVideoCodecMaxBitrate(webrtc::VideoCodec* video_codec) {
  1215. std::string input = TypedInput("Choose max bitrate (in kbps).")
  1216. .WithDefault(DEFAULT_VIDEO_CODEC_MAX_BITRATE)
  1217. .WithInputValidator(new webrtc::IntegerWithinRangeValidator(1, INT_MAX))
  1218. .AskForInput();
  1219. video_codec->maxBitrate = atoi(input.c_str());
  1220. }
  1221. void SetVideoCodecMinBitrate(webrtc::VideoCodec* video_codec) {
  1222. std::string input = TypedInput("Choose min bitrate (in kbps).")
  1223. .WithDefault(DEFAULT_VIDEO_CODEC_MIN_BITRATE)
  1224. .WithInputValidator(new webrtc::IntegerWithinRangeValidator(1, INT_MAX))
  1225. .AskForInput();
  1226. video_codec->minBitrate = atoi(input.c_str());
  1227. }
  1228. void SetVideoCodecMaxFramerate(webrtc::VideoCodec* video_codec) {
  1229. std::string input = TypedInput("Choose max framerate (in fps).")
  1230. .WithDefault(DEFAULT_VIDEO_CODEC_MAX_FRAMERATE)
  1231. .WithInputValidator(new webrtc::IntegerWithinRangeValidator(1, INT_MAX))
  1232. .AskForInput();
  1233. video_codec->maxFramerate = atoi(input.c_str());
  1234. }
  1235. void SetVideoCodecTemporalLayer(webrtc::VideoCodec* video_codec) {
  1236. if (video_codec->codecType != webrtc::kVideoCodecVP8)
  1237. return;
  1238. std::string input = TypedInput("Choose number of temporal layers (0 to 4).")
  1239. .WithDefault(DEFAULT_TEMPORAL_LAYER)
  1240. .WithInputValidator(new webrtc::IntegerWithinRangeValidator(0, 4))
  1241. .AskForInput();
  1242. video_codec->codecSpecific.VP8.numberOfTemporalLayers = atoi(input.c_str());
  1243. }
  1244. // GetVideoProtection only prints the prompt to get a number
  1245. // that SetVideoProtection method uses.
  1246. VideoProtectionMethod GetVideoProtection() {
  1247. int choice = FromChoices(
  1248. "Available Video Protection Methods:",
  1249. "None\n"
  1250. "FEC\n"
  1251. "NACK\n"
  1252. "NACK+FEC\n")
  1253. .WithDefault(DEFAULT_VIDEO_PROTECTION_METHOD)
  1254. .Choose();
  1255. assert(choice >= kProtectionMethodNone &&
  1256. choice <= kProtectionMethodHybridNackAndFec);
  1257. return static_cast<VideoProtectionMethod>(choice);
  1258. }
  1259. bool SetVideoProtection(webrtc::ViECodec* vie_codec,
  1260. webrtc::ViERTP_RTCP* vie_rtp_rtcp,
  1261. int video_channel,
  1262. VideoProtectionMethod protection_method) {
  1263. int error = 0;
  1264. int number_of_errors = 0;
  1265. webrtc::VideoCodec video_codec;
  1266. memset(&video_codec, 0, sizeof(webrtc::VideoCodec));
  1267. // Set all video protection to false initially
  1268. error = vie_rtp_rtcp->SetHybridNACKFECStatus(video_channel, false,
  1269. VCM_RED_PAYLOAD_TYPE,
  1270. VCM_ULPFEC_PAYLOAD_TYPE);
  1271. number_of_errors += ViETest::TestError(error == 0,
  1272. "ERROR: %s at line %d",
  1273. __FUNCTION__, __LINE__);
  1274. error = vie_rtp_rtcp->SetFECStatus(video_channel, false,
  1275. VCM_RED_PAYLOAD_TYPE,
  1276. VCM_ULPFEC_PAYLOAD_TYPE);
  1277. number_of_errors += ViETest::TestError(error == 0,
  1278. "ERROR: %s at line %d",
  1279. __FUNCTION__, __LINE__);
  1280. error = vie_rtp_rtcp->SetNACKStatus(video_channel, false);
  1281. number_of_errors += ViETest::TestError(error == 0,
  1282. "ERROR: %s at line %d",
  1283. __FUNCTION__, __LINE__);
  1284. // Set video protection for FEC, NACK or Hybrid.
  1285. switch (protection_method) {
  1286. case kProtectionMethodNone:
  1287. // No protection selected, all protection already at false.
  1288. std::cout << "Call using None protection Method" << std::endl;
  1289. break;
  1290. case kProtectionMethodFecOnly:
  1291. std::cout << "Call using FEC protection Method" << std::endl;
  1292. error = vie_rtp_rtcp->SetFECStatus(video_channel, true,
  1293. VCM_RED_PAYLOAD_TYPE,
  1294. VCM_ULPFEC_PAYLOAD_TYPE);
  1295. number_of_errors += ViETest::TestError(error == 0,
  1296. "ERROR: %s at line %d",
  1297. __FUNCTION__, __LINE__);
  1298. break;
  1299. case kProtectionMethodNackOnly:
  1300. std::cout << "Call using NACK protection Method" << std::endl;
  1301. error = vie_rtp_rtcp->SetNACKStatus(video_channel, true);
  1302. number_of_errors += ViETest::TestError(error == 0,
  1303. "ERROR: %s at line %d",
  1304. __FUNCTION__, __LINE__);
  1305. break;
  1306. case kProtectionMethodHybridNackAndFec:
  1307. std::cout << "Call using Hybrid NACK and FEC protection Method"
  1308. << std::endl;
  1309. error = vie_rtp_rtcp->SetHybridNACKFECStatus(video_channel, true,
  1310. VCM_RED_PAYLOAD_TYPE,
  1311. VCM_ULPFEC_PAYLOAD_TYPE);
  1312. number_of_errors += ViETest::TestError(error == 0,
  1313. "ERROR: %s at line %d",
  1314. __FUNCTION__, __LINE__);
  1315. break;
  1316. }
  1317. // Set receive codecs for FEC and hybrid NACK/FEC.
  1318. if (protection_method == kProtectionMethodFecOnly ||
  1319. protection_method == kProtectionMethodHybridNackAndFec) {
  1320. // RED.
  1321. error = vie_codec->GetCodec(vie_codec->NumberOfCodecs() - 2,
  1322. video_codec);
  1323. number_of_errors += ViETest::TestError(error == 0,
  1324. "ERROR: %s at line %d",
  1325. __FUNCTION__, __LINE__);
  1326. video_codec.plType = VCM_RED_PAYLOAD_TYPE;
  1327. error = vie_codec->SetReceiveCodec(video_channel, video_codec);
  1328. number_of_errors += ViETest::TestError(error == 0,
  1329. "ERROR: %s at line %d",
  1330. __FUNCTION__, __LINE__);
  1331. std::cout << "RED Codec Information:" << std::endl;
  1332. PrintVideoCodec(video_codec);
  1333. // ULPFEC.
  1334. error = vie_codec->GetCodec(vie_codec->NumberOfCodecs() - 1,
  1335. video_codec);
  1336. number_of_errors += ViETest::TestError(error == 0,
  1337. "ERROR: %s at line %d",
  1338. __FUNCTION__, __LINE__);
  1339. video_codec.plType = VCM_ULPFEC_PAYLOAD_TYPE;
  1340. error = vie_codec->SetReceiveCodec(video_channel, video_codec);
  1341. number_of_errors += ViETest::TestError(error == 0,
  1342. "ERROR: %s at line %d",
  1343. __FUNCTION__, __LINE__);
  1344. std::cout << "ULPFEC Codec Information:" << std::endl;
  1345. PrintVideoCodec(video_codec);
  1346. }
  1347. return true;
  1348. }
  1349. // Returns true if REMB, false if TMMBR.
  1350. bool GetBitrateSignaling() {
  1351. int choice = FromChoices(
  1352. "Available Bitrate Signaling Methods:",
  1353. "REMB\n"
  1354. "TMMBR\n")
  1355. .WithDefault("REMB")
  1356. .Choose();
  1357. return choice == 1;
  1358. }
  1359. void PrintRTCCPStatistics(webrtc::ViERTP_RTCP* vie_rtp_rtcp,
  1360. int video_channel,
  1361. StatisticsType stat_type) {
  1362. int error = 0;
  1363. int number_of_errors = 0;
  1364. uint16_t fraction_lost = 0;
  1365. unsigned int cumulative_lost = 0;
  1366. unsigned int extended_max = 0;
  1367. unsigned int jitter = 0;
  1368. int rtt_ms = 0;
  1369. switch (stat_type) {
  1370. case kReceivedStatistic:
  1371. std::cout << "RTCP Received statistics"
  1372. << std::endl;
  1373. // Get and print the Received RTCP Statistics
  1374. error = vie_rtp_rtcp->GetReceivedRTCPStatistics(video_channel,
  1375. fraction_lost,
  1376. cumulative_lost,
  1377. extended_max,
  1378. jitter, rtt_ms);
  1379. number_of_errors += ViETest::TestError(error == 0,
  1380. "ERROR: %s at line %d",
  1381. __FUNCTION__, __LINE__);
  1382. break;
  1383. case kSendStatistic:
  1384. std::cout << "RTCP Sent statistics"
  1385. << std::endl;
  1386. // Get and print the Sent RTCP Statistics
  1387. error = vie_rtp_rtcp->GetSentRTCPStatistics(video_channel, fraction_lost,
  1388. cumulative_lost, extended_max,
  1389. jitter, rtt_ms);
  1390. number_of_errors += ViETest::TestError(error == 0,
  1391. "ERROR: %s at line %d",
  1392. __FUNCTION__, __LINE__);
  1393. break;
  1394. }
  1395. std::cout << "\tRTCP fraction of lost packets: "
  1396. << fraction_lost << std::endl;
  1397. std::cout << "\tRTCP cumulative number of lost packets: "
  1398. << cumulative_lost << std::endl;
  1399. std::cout << "\tRTCP max received sequence number "
  1400. << extended_max << std::endl;
  1401. std::cout << "\tRTCP jitter: "
  1402. << jitter << std::endl;
  1403. std::cout << "\tRTCP round trip (ms): "
  1404. << rtt_ms << std::endl;
  1405. }
  1406. void PrintRTPStatistics(webrtc::ViERTP_RTCP* vie_rtp_rtcp,
  1407. int video_channel) {
  1408. int error = 0;
  1409. int number_of_errors = 0;
  1410. unsigned int bytes_sent = 0;
  1411. unsigned int packets_sent = 0;
  1412. unsigned int bytes_received = 0;
  1413. unsigned int packets_received = 0;
  1414. std::cout << "RTP statistics"
  1415. << std::endl;
  1416. // Get and print the RTP Statistics
  1417. error = vie_rtp_rtcp->GetRTPStatistics(video_channel, bytes_sent,
  1418. packets_sent, bytes_received,
  1419. packets_received);
  1420. number_of_errors += ViETest::TestError(error == 0,
  1421. "ERROR: %s at line %d",
  1422. __FUNCTION__, __LINE__);
  1423. std::cout << "\tRTP bytes sent: "
  1424. << bytes_sent << std::endl;
  1425. std::cout << "\tRTP packets sent: "
  1426. << packets_sent << std::endl;
  1427. std::cout << "\tRTP bytes received: "
  1428. << bytes_received << std::endl;
  1429. std::cout << "\tRTP packets received: "
  1430. << packets_received << std::endl;
  1431. }
  1432. void PrintBandwidthUsage(webrtc::ViERTP_RTCP* vie_rtp_rtcp,
  1433. int video_channel) {
  1434. int error = 0;
  1435. int number_of_errors = 0;
  1436. unsigned int total_bitrate_sent = 0;
  1437. unsigned int video_bitrate_sent = 0;
  1438. unsigned int fec_bitrate_sent = 0;
  1439. unsigned int nack_bitrate_sent = 0;
  1440. double percentage_fec = 0;
  1441. double percentage_nack = 0;
  1442. std::cout << "Bandwidth Usage" << std::endl;
  1443. // Get and print Bandwidth usage
  1444. error = vie_rtp_rtcp->GetBandwidthUsage(video_channel, total_bitrate_sent,
  1445. video_bitrate_sent, fec_bitrate_sent,
  1446. nack_bitrate_sent);
  1447. number_of_errors += ViETest::TestError(error == 0,
  1448. "ERROR: %s at line %d",
  1449. __FUNCTION__, __LINE__);
  1450. std::cout << "\tTotal bitrate sent (Kbit/s): "
  1451. << total_bitrate_sent << std::endl;
  1452. std::cout << "\tVideo bitrate sent (Kbit/s): "
  1453. << video_bitrate_sent << std::endl;
  1454. std::cout << "\tFEC bitrate sent (Kbit/s): "
  1455. << fec_bitrate_sent << std::endl;
  1456. percentage_fec =
  1457. (static_cast<double>(fec_bitrate_sent) /
  1458. static_cast<double>(total_bitrate_sent)) * 100;
  1459. std::cout << "\tPercentage FEC bitrate sent from total bitrate: "
  1460. << percentage_fec << std::endl;
  1461. std::cout << "\tNACK bitrate sent (Kbit/s): "
  1462. << nack_bitrate_sent << std::endl;
  1463. percentage_nack =
  1464. (static_cast<double>(nack_bitrate_sent) /
  1465. static_cast<double>(total_bitrate_sent)) * 100;
  1466. std::cout << "\tPercentage NACK bitrate sent from total bitrate: "
  1467. << percentage_nack << std::endl;
  1468. }
  1469. void PrintCodecStatistics(webrtc::ViECodec* vie_codec,
  1470. int video_channel,
  1471. StatisticsType stat_type) {
  1472. int error = 0;
  1473. int number_of_errors = 0;
  1474. unsigned int key_frames = 0;
  1475. unsigned int delta_frames = 0;
  1476. switch (stat_type) {
  1477. case kReceivedStatistic:
  1478. std::cout << "Codec Receive statistics"
  1479. << std::endl;
  1480. // Get and print the Receive Codec Statistics
  1481. error = vie_codec->GetReceiveCodecStastistics(video_channel, key_frames,
  1482. delta_frames);
  1483. number_of_errors += ViETest::TestError(error == 0,
  1484. "ERROR: %s at line %d",
  1485. __FUNCTION__, __LINE__);
  1486. break;
  1487. case kSendStatistic:
  1488. std::cout << "Codec Send statistics"
  1489. << std::endl;
  1490. // Get and print the Send Codec Statistics
  1491. error = vie_codec->GetSendCodecStastistics(video_channel, key_frames,
  1492. delta_frames);
  1493. number_of_errors += ViETest::TestError(error == 0,
  1494. "ERROR: %s at line %d",
  1495. __FUNCTION__, __LINE__);
  1496. break;
  1497. }
  1498. std::cout << "\tNumber of encoded key frames: "
  1499. << key_frames << std::endl;
  1500. std::cout << "\tNumber of encoded delta frames: "
  1501. << delta_frames << std::endl;
  1502. }
  1503. void PrintGetDiscardedPackets(webrtc::ViECodec* vie_codec, int video_channel) {
  1504. std::cout << "Discarded Packets" << std::endl;
  1505. int discarded_packets = 0;
  1506. discarded_packets = vie_codec->GetDiscardedPackets(video_channel);
  1507. std::cout << "\tNumber of discarded packets: "
  1508. << discarded_packets << std::endl;
  1509. }
  1510. void PrintVideoStreamInformation(webrtc::ViECodec* vie_codec,
  1511. int video_channel) {
  1512. webrtc::VideoCodec outgoing_codec;
  1513. webrtc::VideoCodec incoming_codec;
  1514. memset(&outgoing_codec, 0, sizeof(webrtc::VideoCodec));
  1515. memset(&incoming_codec, 0, sizeof(webrtc::VideoCodec));
  1516. vie_codec->GetSendCodec(video_channel, outgoing_codec);
  1517. vie_codec->GetReceiveCodec(video_channel, incoming_codec);
  1518. std::cout << "************************************************"
  1519. << std::endl;
  1520. std::cout << "ChannelId: " << video_channel << std::endl;
  1521. std::cout << "Outgoing Stream information:" << std::endl;
  1522. PrintVideoCodec(outgoing_codec);
  1523. std::cout << "Incoming Stream information:" << std::endl;
  1524. PrintVideoCodec(incoming_codec);
  1525. std::cout << "************************************************"
  1526. << std::endl;
  1527. }
  1528. void PrintVideoCodec(webrtc::VideoCodec video_codec) {
  1529. std::cout << "\t\tplName: " << video_codec.plName << std::endl;
  1530. std::cout << "\t\tplType: " << static_cast<int>(video_codec.plType)
  1531. << std::endl;
  1532. std::cout << "\t\twidth: " << video_codec.width << std::endl;
  1533. std::cout << "\t\theight: " << video_codec.height << std::endl;
  1534. std::cout << "\t\tstartBitrate: " << video_codec.startBitrate
  1535. << std::endl;
  1536. std::cout << "\t\tminBitrate: " << video_codec.minBitrate
  1537. << std::endl;
  1538. std::cout << "\t\tmaxBitrate: " << video_codec.maxBitrate
  1539. << std::endl;
  1540. std::cout << "\t\tmaxFramerate: "
  1541. << static_cast<int>(video_codec.maxFramerate) << std::endl;
  1542. if (video_codec.codecType == webrtc::kVideoCodecVP8) {
  1543. int number_of_layers =
  1544. static_cast<int>(video_codec.codecSpecific.VP8.numberOfTemporalLayers);
  1545. std::cout << "\t\tVP8 Temporal Layer: " << number_of_layers << std::endl;
  1546. }
  1547. }