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