1 /*
2  *  Copyright (c) 2015 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 "video/video_loopback.h"
11 
12 #include <stdio.h>
13 
14 #include <memory>
15 #include <string>
16 #include <vector>
17 
18 #include "absl/flags/flag.h"
19 #include "absl/flags/parse.h"
20 #include "absl/types/optional.h"
21 #include "api/test/simulated_network.h"
22 #include "api/test/video_quality_test_fixture.h"
23 #include "api/transport/bitrate_settings.h"
24 #include "api/video_codecs/video_codec.h"
25 #include "rtc_base/checks.h"
26 #include "rtc_base/logging.h"
27 #include "system_wrappers/include/field_trial.h"
28 #include "test/field_trial.h"
29 #include "test/gtest.h"
30 #include "test/run_test.h"
31 #include "video/video_quality_test.h"
32 
33 // Flags common with screenshare loopback, with different default values.
34 ABSL_FLAG(int, width, 640, "Video width.");
35 
36 ABSL_FLAG(int, height, 480, "Video height.");
37 
38 ABSL_FLAG(int, fps, 30, "Frames per second.");
39 
40 ABSL_FLAG(int, capture_device_index, 0, "Capture device to select");
41 
42 ABSL_FLAG(int, min_bitrate, 50, "Call and stream min bitrate in kbps.");
43 
44 ABSL_FLAG(int, start_bitrate, 300, "Call start bitrate in kbps.");
45 
46 ABSL_FLAG(int, target_bitrate, 800, "Stream target bitrate in kbps.");
47 
48 ABSL_FLAG(int, max_bitrate, 800, "Call and stream max bitrate in kbps.");
49 
50 ABSL_FLAG(bool,
51           suspend_below_min_bitrate,
52           false,
53           "Suspends video below the configured min bitrate.");
54 
55 ABSL_FLAG(int,
56           num_temporal_layers,
57           1,
58           "Number of temporal layers. Set to 1-4 to override.");
59 
60 ABSL_FLAG(int,
61           inter_layer_pred,
62           2,
63           "Inter-layer prediction mode. "
64           "0 - enabled, 1 - disabled, 2 - enabled only for key pictures.");
65 
66 // Flags common with screenshare loopback, with equal default values.
67 ABSL_FLAG(std::string, codec, "VP8", "Video codec to use.");
68 
69 ABSL_FLAG(int,
70           selected_tl,
71           -1,
72           "Temporal layer to show or analyze. -1 to disable filtering.");
73 
74 ABSL_FLAG(
75     int,
76     duration,
77     0,
78     "Duration of the test in seconds. If 0, rendered will be shown instead.");
79 
80 ABSL_FLAG(std::string, output_filename, "", "Target graph data filename.");
81 
82 ABSL_FLAG(std::string,
83           graph_title,
84           "",
85           "If empty, title will be generated automatically.");
86 
87 ABSL_FLAG(int, loss_percent, 0, "Percentage of packets randomly lost.");
88 
89 ABSL_FLAG(int,
90           avg_burst_loss_length,
91           -1,
92           "Average burst length of lost packets.");
93 
94 ABSL_FLAG(int,
95           link_capacity,
96           0,
97           "Capacity (kbps) of the fake link. 0 means infinite.");
98 
99 ABSL_FLAG(int, queue_size, 0, "Size of the bottleneck link queue in packets.");
100 
101 ABSL_FLAG(int,
102           avg_propagation_delay_ms,
103           0,
104           "Average link propagation delay in ms.");
105 
106 ABSL_FLAG(std::string,
107           rtc_event_log_name,
108           "",
109           "Filename for rtc event log. Two files "
110           "with \"_send\" and \"_recv\" suffixes will be created.");
111 
112 ABSL_FLAG(std::string,
113           rtp_dump_name,
114           "",
115           "Filename for dumped received RTP stream.");
116 
117 ABSL_FLAG(int,
118           std_propagation_delay_ms,
119           0,
120           "Link propagation delay standard deviation in ms.");
121 
122 ABSL_FLAG(int, num_streams, 0, "Number of streams to show or analyze.");
123 
124 ABSL_FLAG(int,
125           selected_stream,
126           0,
127           "ID of the stream to show or analyze. "
128           "Set to the number of streams to show them all.");
129 
130 ABSL_FLAG(int, num_spatial_layers, 1, "Number of spatial layers to use.");
131 
132 ABSL_FLAG(int,
133           selected_sl,
134           -1,
135           "Spatial layer to show or analyze. -1 to disable filtering.");
136 
137 ABSL_FLAG(std::string,
138           stream0,
139           "",
140           "Comma separated values describing VideoStream for stream #0.");
141 
142 ABSL_FLAG(std::string,
143           stream1,
144           "",
145           "Comma separated values describing VideoStream for stream #1.");
146 
147 ABSL_FLAG(std::string,
148           sl0,
149           "",
150           "Comma separated values describing SpatialLayer for layer #0.");
151 
152 ABSL_FLAG(std::string,
153           sl1,
154           "",
155           "Comma separated values describing SpatialLayer for layer #1.");
156 
157 ABSL_FLAG(std::string,
158           sl2,
159           "",
160           "Comma separated values describing SpatialLayer for layer #2.");
161 
162 ABSL_FLAG(std::string,
163           encoded_frame_path,
164           "",
165           "The base path for encoded frame logs. Created files will have "
166           "the form <encoded_frame_path>.<n>.(recv|send.<m>).ivf");
167 
168 ABSL_FLAG(bool, logs, false, "print logs to stderr");
169 
170 ABSL_FLAG(bool, send_side_bwe, true, "Use send-side bandwidth estimation");
171 
172 ABSL_FLAG(bool, generic_descriptor, false, "Use the generic frame descriptor.");
173 
174 ABSL_FLAG(bool, allow_reordering, false, "Allow packet reordering to occur");
175 
176 ABSL_FLAG(bool, use_ulpfec, false, "Use RED+ULPFEC forward error correction.");
177 
178 ABSL_FLAG(bool, use_flexfec, false, "Use FlexFEC forward error correction.");
179 
180 ABSL_FLAG(bool, audio, false, "Add audio stream");
181 
182 ABSL_FLAG(bool,
183           use_real_adm,
184           false,
185           "Use real ADM instead of fake (no effect if audio is false)");
186 
187 ABSL_FLAG(bool,
188           audio_video_sync,
189           false,
190           "Sync audio and video stream (no effect if"
191           " audio is false)");
192 
193 ABSL_FLAG(bool,
194           audio_dtx,
195           false,
196           "Enable audio DTX (no effect if audio is false)");
197 
198 ABSL_FLAG(bool, video, true, "Add video stream");
199 
200 ABSL_FLAG(
201     std::string,
202     force_fieldtrials,
203     "",
204     "Field trials control experimental feature code which can be forced. "
205     "E.g. running with --force_fieldtrials=WebRTC-FooFeature/Enabled/"
206     " will assign the group Enable to field trial WebRTC-FooFeature. Multiple "
207     "trials are separated by \"/\"");
208 
209 // Video-specific flags.
210 ABSL_FLAG(std::string,
211           clip,
212           "",
213           "Name of the clip to show. If empty, using chroma generator.");
214 
215 namespace webrtc {
216 namespace {
217 
Width()218 size_t Width() {
219   return static_cast<size_t>(absl::GetFlag(FLAGS_width));
220 }
221 
Height()222 size_t Height() {
223   return static_cast<size_t>(absl::GetFlag(FLAGS_height));
224 }
225 
Fps()226 int Fps() {
227   return absl::GetFlag(FLAGS_fps);
228 }
229 
GetCaptureDevice()230 size_t GetCaptureDevice() {
231   return static_cast<size_t>(absl::GetFlag(FLAGS_capture_device_index));
232 }
233 
MinBitrateKbps()234 int MinBitrateKbps() {
235   return absl::GetFlag(FLAGS_min_bitrate);
236 }
237 
StartBitrateKbps()238 int StartBitrateKbps() {
239   return absl::GetFlag(FLAGS_start_bitrate);
240 }
241 
TargetBitrateKbps()242 int TargetBitrateKbps() {
243   return absl::GetFlag(FLAGS_target_bitrate);
244 }
245 
MaxBitrateKbps()246 int MaxBitrateKbps() {
247   return absl::GetFlag(FLAGS_max_bitrate);
248 }
249 
NumTemporalLayers()250 int NumTemporalLayers() {
251   return absl::GetFlag(FLAGS_num_temporal_layers);
252 }
253 
InterLayerPred()254 InterLayerPredMode InterLayerPred() {
255   if (absl::GetFlag(FLAGS_inter_layer_pred) == 0) {
256     return InterLayerPredMode::kOn;
257   } else if (absl::GetFlag(FLAGS_inter_layer_pred) == 1) {
258     return InterLayerPredMode::kOff;
259   } else {
260     RTC_DCHECK_EQ(absl::GetFlag(FLAGS_inter_layer_pred), 2);
261     return InterLayerPredMode::kOnKeyPic;
262   }
263 }
264 
Codec()265 std::string Codec() {
266   return absl::GetFlag(FLAGS_codec);
267 }
268 
SelectedTL()269 int SelectedTL() {
270   return absl::GetFlag(FLAGS_selected_tl);
271 }
272 
DurationSecs()273 int DurationSecs() {
274   return absl::GetFlag(FLAGS_duration);
275 }
276 
OutputFilename()277 std::string OutputFilename() {
278   return absl::GetFlag(FLAGS_output_filename);
279 }
280 
GraphTitle()281 std::string GraphTitle() {
282   return absl::GetFlag(FLAGS_graph_title);
283 }
284 
LossPercent()285 int LossPercent() {
286   return static_cast<int>(absl::GetFlag(FLAGS_loss_percent));
287 }
288 
AvgBurstLossLength()289 int AvgBurstLossLength() {
290   return static_cast<int>(absl::GetFlag(FLAGS_avg_burst_loss_length));
291 }
292 
LinkCapacityKbps()293 int LinkCapacityKbps() {
294   return static_cast<int>(absl::GetFlag(FLAGS_link_capacity));
295 }
296 
QueueSize()297 int QueueSize() {
298   return static_cast<int>(absl::GetFlag(FLAGS_queue_size));
299 }
300 
AvgPropagationDelayMs()301 int AvgPropagationDelayMs() {
302   return static_cast<int>(absl::GetFlag(FLAGS_avg_propagation_delay_ms));
303 }
304 
RtcEventLogName()305 std::string RtcEventLogName() {
306   return absl::GetFlag(FLAGS_rtc_event_log_name);
307 }
308 
RtpDumpName()309 std::string RtpDumpName() {
310   return absl::GetFlag(FLAGS_rtp_dump_name);
311 }
312 
StdPropagationDelayMs()313 int StdPropagationDelayMs() {
314   return absl::GetFlag(FLAGS_std_propagation_delay_ms);
315 }
316 
NumStreams()317 int NumStreams() {
318   return absl::GetFlag(FLAGS_num_streams);
319 }
320 
SelectedStream()321 int SelectedStream() {
322   return absl::GetFlag(FLAGS_selected_stream);
323 }
324 
NumSpatialLayers()325 int NumSpatialLayers() {
326   return absl::GetFlag(FLAGS_num_spatial_layers);
327 }
328 
SelectedSL()329 int SelectedSL() {
330   return absl::GetFlag(FLAGS_selected_sl);
331 }
332 
Stream0()333 std::string Stream0() {
334   return absl::GetFlag(FLAGS_stream0);
335 }
336 
Stream1()337 std::string Stream1() {
338   return absl::GetFlag(FLAGS_stream1);
339 }
340 
SL0()341 std::string SL0() {
342   return absl::GetFlag(FLAGS_sl0);
343 }
344 
SL1()345 std::string SL1() {
346   return absl::GetFlag(FLAGS_sl1);
347 }
348 
SL2()349 std::string SL2() {
350   return absl::GetFlag(FLAGS_sl2);
351 }
352 
EncodedFramePath()353 std::string EncodedFramePath() {
354   return absl::GetFlag(FLAGS_encoded_frame_path);
355 }
356 
Clip()357 std::string Clip() {
358   return absl::GetFlag(FLAGS_clip);
359 }
360 
361 }  // namespace
362 
Loopback()363 void Loopback() {
364   BuiltInNetworkBehaviorConfig pipe_config;
365   pipe_config.loss_percent = LossPercent();
366   pipe_config.avg_burst_loss_length = AvgBurstLossLength();
367   pipe_config.link_capacity_kbps = LinkCapacityKbps();
368   pipe_config.queue_length_packets = QueueSize();
369   pipe_config.queue_delay_ms = AvgPropagationDelayMs();
370   pipe_config.delay_standard_deviation_ms = StdPropagationDelayMs();
371   pipe_config.allow_reordering = absl::GetFlag(FLAGS_allow_reordering);
372 
373   BitrateConstraints call_bitrate_config;
374   call_bitrate_config.min_bitrate_bps = MinBitrateKbps() * 1000;
375   call_bitrate_config.start_bitrate_bps = StartBitrateKbps() * 1000;
376   call_bitrate_config.max_bitrate_bps = -1;  // Don't cap bandwidth estimate.
377 
378   VideoQualityTest::Params params;
379   params.call.send_side_bwe = absl::GetFlag(FLAGS_send_side_bwe);
380   params.call.generic_descriptor = absl::GetFlag(FLAGS_generic_descriptor);
381   params.call.call_bitrate_config = call_bitrate_config;
382 
383   params.video[0].enabled = absl::GetFlag(FLAGS_video);
384   params.video[0].width = Width();
385   params.video[0].height = Height();
386   params.video[0].fps = Fps();
387   params.video[0].min_bitrate_bps = MinBitrateKbps() * 1000;
388   params.video[0].target_bitrate_bps = TargetBitrateKbps() * 1000;
389   params.video[0].max_bitrate_bps = MaxBitrateKbps() * 1000;
390   params.video[0].suspend_below_min_bitrate =
391       absl::GetFlag(FLAGS_suspend_below_min_bitrate);
392   params.video[0].codec = Codec();
393   params.video[0].num_temporal_layers = NumTemporalLayers();
394   params.video[0].selected_tl = SelectedTL();
395   params.video[0].min_transmit_bps = 0;
396   params.video[0].ulpfec = absl::GetFlag(FLAGS_use_ulpfec);
397   params.video[0].flexfec = absl::GetFlag(FLAGS_use_flexfec);
398   params.video[0].automatic_scaling = NumStreams() < 2;
399   params.video[0].clip_path = Clip();
400   params.video[0].capture_device_index = GetCaptureDevice();
401   params.audio.enabled = absl::GetFlag(FLAGS_audio);
402   params.audio.sync_video = absl::GetFlag(FLAGS_audio_video_sync);
403   params.audio.dtx = absl::GetFlag(FLAGS_audio_dtx);
404   params.audio.use_real_adm = absl::GetFlag(FLAGS_use_real_adm);
405   params.logging.rtc_event_log_name = RtcEventLogName();
406   params.logging.rtp_dump_name = RtpDumpName();
407   params.logging.encoded_frame_base_path = EncodedFramePath();
408   params.screenshare[0].enabled = false;
409   params.analyzer.test_label = "video";
410   params.analyzer.test_durations_secs = DurationSecs();
411   params.analyzer.graph_data_output_filename = OutputFilename();
412   params.analyzer.graph_title = GraphTitle();
413   params.config = pipe_config;
414 
415   if (NumStreams() > 1 && Stream0().empty() && Stream1().empty()) {
416     params.ss[0].infer_streams = true;
417   }
418 
419   std::vector<std::string> stream_descriptors;
420   stream_descriptors.push_back(Stream0());
421   stream_descriptors.push_back(Stream1());
422   std::vector<std::string> SL_descriptors;
423   SL_descriptors.push_back(SL0());
424   SL_descriptors.push_back(SL1());
425   SL_descriptors.push_back(SL2());
426   VideoQualityTest::FillScalabilitySettings(
427       &params, 0, stream_descriptors, NumStreams(), SelectedStream(),
428       NumSpatialLayers(), SelectedSL(), InterLayerPred(), SL_descriptors);
429 
430   auto fixture = std::make_unique<VideoQualityTest>(nullptr);
431   if (DurationSecs()) {
432     fixture->RunWithAnalyzer(params);
433   } else {
434     fixture->RunWithRenderers(params);
435   }
436 }
437 
RunLoopbackTest(int argc,char * argv[])438 int RunLoopbackTest(int argc, char* argv[]) {
439   ::testing::InitGoogleTest(&argc, argv);
440   absl::ParseCommandLine(argc, argv);
441 
442   rtc::LogMessage::SetLogToStderr(absl::GetFlag(FLAGS_logs));
443 
444   // InitFieldTrialsFromString stores the char*, so the char array must outlive
445   // the application.
446   const std::string field_trials = absl::GetFlag(FLAGS_force_fieldtrials);
447   webrtc::field_trial::InitFieldTrialsFromString(field_trials.c_str());
448 
449   webrtc::test::RunTest(webrtc::Loopback);
450   return 0;
451 }
452 }  // namespace webrtc
453