blob: ca1c2882a12d036fb15d6beffb286b6ed3c29e59 [file] [log] [blame]
Artem Titovb6c62012019-01-08 14:58:23 +01001/*
2 * Copyright (c) 2018 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 */
Artem Titovd57628f2019-03-22 12:34:25 +010010#ifndef API_TEST_PEERCONNECTION_QUALITY_TEST_FIXTURE_H_
11#define API_TEST_PEERCONNECTION_QUALITY_TEST_FIXTURE_H_
Artem Titovb6c62012019-01-08 14:58:23 +010012
Artem Titovf65a89b2019-05-07 11:56:44 +020013#include <map>
Artem Titovb6c62012019-01-08 14:58:23 +010014#include <memory>
15#include <string>
Artem Titov7581ff72019-05-15 15:45:33 +020016#include <utility>
Artem Titovb6c62012019-01-08 14:58:23 +010017#include <vector>
18
Artem Titova6a273d2019-02-07 16:43:51 +010019#include "absl/memory/memory.h"
Artem Titov4a6f8182020-02-27 13:24:19 +010020#include "absl/strings/string_view.h"
21#include "absl/types/optional.h"
Artem Titov0d510522022-04-19 13:01:03 +020022#include "api/array_view.h"
Steve Anton10542f22019-01-11 09:11:00 -080023#include "api/async_resolver_factory.h"
Artem Titov7e04b492022-03-08 01:26:03 +010024#include "api/audio/audio_mixer.h"
Steve Anton10542f22019-01-11 09:11:00 -080025#include "api/call/call_factory_interface.h"
Artem Titovb6c62012019-01-08 14:58:23 +010026#include "api/fec_controller.h"
Artem Titov741daaf2019-03-21 14:37:36 +010027#include "api/function_view.h"
Andrey Logvin435fb9a2020-05-08 08:02:49 +000028#include "api/media_stream_interface.h"
Steve Anton10542f22019-01-11 09:11:00 -080029#include "api/peer_connection_interface.h"
Danil Chapovalov9305d112019-09-04 13:16:09 +020030#include "api/rtc_event_log/rtc_event_log_factory_interface.h"
Artem Titovf9ed56b2020-05-11 21:17:25 +020031#include "api/rtp_parameters.h"
Danil Chapovalov1a5fc902019-06-10 12:58:03 +020032#include "api/task_queue/task_queue_factory.h"
Artem Titovd57628f2019-03-22 12:34:25 +010033#include "api/test/audio_quality_analyzer_interface.h"
Artem Titov00202262019-12-04 22:34:41 +010034#include "api/test/frame_generator_interface.h"
Niels Möllerf47a7242021-11-22 16:07:35 +010035#include "api/test/peer_network_dependencies.h"
Artem Titovb6c62012019-01-08 14:58:23 +010036#include "api/test/simulated_network.h"
Artem Titova8549212019-08-19 14:38:06 +020037#include "api/test/stats_observer_interface.h"
Andrey Logvin20f45822020-07-01 08:32:15 +000038#include "api/test/track_id_stream_info_map.h"
Artem Titovd57628f2019-03-22 12:34:25 +010039#include "api/test/video_quality_analyzer_interface.h"
Artem Titovb6c62012019-01-08 14:58:23 +010040#include "api/transport/network_control.h"
Artem Titovebd97702019-01-09 17:55:36 +010041#include "api/units/time_delta.h"
Artem Titovb6c62012019-01-08 14:58:23 +010042#include "api/video_codecs/video_decoder_factory.h"
43#include "api/video_codecs/video_encoder.h"
44#include "api/video_codecs/video_encoder_factory.h"
Artem Titovf65a89b2019-05-07 11:56:44 +020045#include "media/base/media_constants.h"
Artem Titov7e04b492022-03-08 01:26:03 +010046#include "modules/audio_processing/include/audio_processing.h"
Artem Titovb6c62012019-01-08 14:58:23 +010047#include "rtc_base/network.h"
Steve Anton10542f22019-01-11 09:11:00 -080048#include "rtc_base/rtc_certificate_generator.h"
49#include "rtc_base/ssl_certificate.h"
Artem Titovb6c62012019-01-08 14:58:23 +010050#include "rtc_base/thread.h"
Artem Titovb6c62012019-01-08 14:58:23 +010051
52namespace webrtc {
Artem Titov0b443142019-03-20 11:11:08 +010053namespace webrtc_pc_e2e {
Artem Titovb6c62012019-01-08 14:58:23 +010054
Artem Titov7581ff72019-05-15 15:45:33 +020055constexpr size_t kDefaultSlidesWidth = 1850;
56constexpr size_t kDefaultSlidesHeight = 1110;
57
Artem Titovd57628f2019-03-22 12:34:25 +010058// API is in development. Can be changed/removed without notice.
Artem Titovb6c62012019-01-08 14:58:23 +010059class PeerConnectionE2EQualityTestFixture {
60 public:
Andrey Logvinf3319812020-05-13 08:02:26 +000061 // The index of required capturing device in OS provided list of video
62 // devices. On Linux and Windows the list will be obtained via
63 // webrtc::VideoCaptureModule::DeviceInfo, on Mac OS via
64 // [RTCCameraVideoCapturer captureDevices].
65 enum class CapturingDeviceIndex : size_t {};
66
Artem Titov7581ff72019-05-15 15:45:33 +020067 // Contains parameters for screen share scrolling.
68 //
69 // If scrolling is enabled, then it will be done by putting sliding window
70 // on source video and moving this window from top left corner to the
71 // bottom right corner of the picture.
72 //
73 // In such case source dimensions must be greater or equal to the sliding
Artem Titov0e61fdd2021-07-25 21:50:14 +020074 // window dimensions. So `source_width` and `source_height` are the dimensions
75 // of the source frame, while `VideoConfig::width` and `VideoConfig::height`
Artem Titov7581ff72019-05-15 15:45:33 +020076 // are the dimensions of the sliding window.
77 //
Artem Titov0e61fdd2021-07-25 21:50:14 +020078 // Because `source_width` and `source_height` are dimensions of the source
Artem Titov7581ff72019-05-15 15:45:33 +020079 // frame, they have to be width and height of videos from
Artem Titov0e61fdd2021-07-25 21:50:14 +020080 // `ScreenShareConfig::slides_yuv_file_names`.
Artem Titov7581ff72019-05-15 15:45:33 +020081 //
82 // Because scrolling have to be done on single slide it also requires, that
Artem Titov0e61fdd2021-07-25 21:50:14 +020083 // `duration` must be less or equal to
84 // `ScreenShareConfig::slide_change_interval`.
Artem Titov7581ff72019-05-15 15:45:33 +020085 struct ScrollingParams {
86 ScrollingParams(TimeDelta duration,
87 size_t source_width,
88 size_t source_height)
89 : duration(duration),
90 source_width(source_width),
91 source_height(source_height) {
92 RTC_CHECK_GT(duration.ms(), 0);
93 }
94
95 // Duration of scrolling.
96 TimeDelta duration;
97 // Width of source slides video.
98 size_t source_width;
99 // Height of source slides video.
100 size_t source_height;
101 };
102
Artem Titovebd97702019-01-09 17:55:36 +0100103 // Contains screen share video stream properties.
Artem Titovb6c62012019-01-08 14:58:23 +0100104 struct ScreenShareConfig {
Artem Titov7581ff72019-05-15 15:45:33 +0200105 explicit ScreenShareConfig(TimeDelta slide_change_interval)
106 : slide_change_interval(slide_change_interval) {
107 RTC_CHECK_GT(slide_change_interval.ms(), 0);
108 }
109
Artem Titovebd97702019-01-09 17:55:36 +0100110 // Shows how long one slide should be presented on the screen during
111 // slide generation.
112 TimeDelta slide_change_interval;
Artem Titov7581ff72019-05-15 15:45:33 +0200113 // If true, slides will be generated programmatically. No scrolling params
114 // will be applied in such case.
115 bool generate_slides = false;
116 // If present scrolling will be applied. Please read extra requirement on
Artem Titov0e61fdd2021-07-25 21:50:14 +0200117 // `slides_yuv_file_names` for scrolling.
Artem Titov7581ff72019-05-15 15:45:33 +0200118 absl::optional<ScrollingParams> scrolling_params;
119 // Contains list of yuv files with slides.
120 //
121 // If empty, default set of slides will be used. In such case
Artem Titov0e61fdd2021-07-25 21:50:14 +0200122 // `VideoConfig::width` must be equal to `kDefaultSlidesWidth` and
123 // `VideoConfig::height` must be equal to `kDefaultSlidesHeight` or if
124 // `scrolling_params` are specified, then `ScrollingParams::source_width`
125 // must be equal to `kDefaultSlidesWidth` and
126 // `ScrollingParams::source_height` must be equal to `kDefaultSlidesHeight`.
Artem Titovb6c62012019-01-08 14:58:23 +0100127 std::vector<std::string> slides_yuv_file_names;
128 };
129
Florent Castellia63b6b72022-04-25 17:27:15 +0200130 // Config for Vp8 simulcast or non-standard Vp9 SVC testing.
131 //
132 // To configure standard SVC setting, use `scalability_mode` in the
133 // `encoding_params` array.
134 // This configures Vp9 SVC by requesting simulcast layers, the request is
135 // internally converted to a request for SVC layers.
Artem Titovd70d80d2019-07-19 11:00:40 +0200136 //
137 // SVC support is limited:
138 // During SVC testing there is no SFU, so framework will try to emulate SFU
139 // behavior in regular p2p call. Because of it there are such limitations:
Artem Titov0e61fdd2021-07-25 21:50:14 +0200140 // * if `target_spatial_index` is not equal to the highest spatial layer
Artem Titovd70d80d2019-07-19 11:00:40 +0200141 // then no packet/frame drops are allowed.
142 //
143 // If there will be any drops, that will affect requested layer, then
144 // WebRTC SVC implementation will continue decoding only the highest
145 // available layer and won't restore lower layers, so analyzer won't
146 // receive required data which will cause wrong results or test failures.
Artem Titovef3fd9c2019-06-13 16:36:52 +0200147 struct VideoSimulcastConfig {
Artem Titovcc57b932020-05-11 16:09:26 +0200148 explicit VideoSimulcastConfig(int simulcast_streams_count)
149 : simulcast_streams_count(simulcast_streams_count) {
150 RTC_CHECK_GT(simulcast_streams_count, 1);
151 }
Artem Titovef3fd9c2019-06-13 16:36:52 +0200152 VideoSimulcastConfig(int simulcast_streams_count, int target_spatial_index)
153 : simulcast_streams_count(simulcast_streams_count),
154 target_spatial_index(target_spatial_index) {
155 RTC_CHECK_GT(simulcast_streams_count, 1);
156 RTC_CHECK_GE(target_spatial_index, 0);
157 RTC_CHECK_LT(target_spatial_index, simulcast_streams_count);
158 }
159
160 // Specified amount of simulcast streams/SVC layers, depending on which
161 // encoder is used.
162 int simulcast_streams_count;
163 // Specifies spatial index of the video stream to analyze.
164 // There are 2 cases:
165 // 1. simulcast encoder is used:
Artem Titov0e61fdd2021-07-25 21:50:14 +0200166 // in such case `target_spatial_index` will specify the index of
Artem Titovef3fd9c2019-06-13 16:36:52 +0200167 // simulcast stream, that should be analyzed. Other streams will be
168 // dropped.
169 // 2. SVC encoder is used:
Artem Titov0e61fdd2021-07-25 21:50:14 +0200170 // in such case `target_spatial_index` will specify the top interesting
Artem Titovef3fd9c2019-06-13 16:36:52 +0200171 // spatial layer and all layers below, including target one will be
172 // processed. All layers above target one will be dropped.
Artem Titovcc57b932020-05-11 16:09:26 +0200173 // If not specified than whatever stream will be received will be analyzed.
174 // It requires Selective Forwarding Unit (SFU) to be configured in the
175 // network.
176 absl::optional<int> target_spatial_index;
Artem Titovef3fd9c2019-06-13 16:36:52 +0200177 };
178
Artem Titov7017a132022-04-20 20:57:56 +0200179 class VideoResolution {
180 public:
181 // Determines special resolutions, which can't be expressed in terms of
182 // width, height and fps.
183 enum class Spec {
184 // No extra spec set. It describes a regular resolution described by
185 // width, height and fps.
186 kNone,
187 // Describes resolution which contains max value among all sender's
188 // video streams in each dimension (width, height, fps).
189 kMaxFromSender
190 };
191
192 VideoResolution(size_t width, size_t height, int32_t fps);
193 explicit VideoResolution(Spec spec = Spec::kNone);
194
195 bool operator==(const VideoResolution& other) const;
196 bool operator!=(const VideoResolution& other) const {
197 return !(*this == other);
198 }
199
200 size_t width() const { return width_; }
201 void set_width(size_t width) { width_ = width; }
202 size_t height() const { return height_; }
203 void set_height(size_t height) { height_ = height; }
204 int32_t fps() const { return fps_; }
205 void set_fps(int32_t fps) { fps_ = fps; }
206
207 // Returns if it is a regular resolution or not. The resolution is regular
208 // if it's spec is `Spec::kNone`.
209 bool IsRegular() const { return spec_ == Spec::kNone; }
210
Artem Titovbccb4522022-06-01 22:32:15 +0200211 std::string ToString() const;
212
Artem Titov7017a132022-04-20 20:57:56 +0200213 private:
214 size_t width_ = 0;
215 size_t height_ = 0;
216 int32_t fps_ = 0;
217 Spec spec_ = Spec::kNone;
218 };
219
Artem Titov72bc2e22022-08-02 14:03:03 +0200220 class VideoDumpOptions {
221 public:
Artem Titovd2209252022-08-03 13:22:48 +0200222 static constexpr int kDefaultSamplingModulo = 1;
223
Artem Titov72bc2e22022-08-02 14:03:03 +0200224 // output_directory - the output directory where stream will be dumped. The
225 // output files' names will be constructed as
226 // <stream_name>_<receiver_name>.<extension> for output dumps and
227 // <stream_name>.<extension> for input dumps. By default <extension> is
228 // "y4m".
229 // sampling_modulo - the module for the video frames to be dumped. Modulo
230 // equals X means every Xth frame will be written to the dump file. The
231 // value must be greater than 0. (Default: 1)
Artem Titovd2209252022-08-03 13:22:48 +0200232 // export_frame_ids - specifies if frame ids should be exported together
233 // with content of the stream. If true, an output file with the same name as
234 // video dump and suffix ".frame_ids.txt" will be created. It will contain
235 // the frame ids in the same order as original frames in the output
236 // file with stream content. File will contain one frame id per line.
237 // (Default: false)
Artem Titov72bc2e22022-08-02 14:03:03 +0200238 explicit VideoDumpOptions(absl::string_view output_directory,
Artem Titovd2209252022-08-03 13:22:48 +0200239 int sampling_modulo = kDefaultSamplingModulo,
240 bool export_frame_ids = false);
241 VideoDumpOptions(absl::string_view output_directory, bool export_frame_ids);
Artem Titov72bc2e22022-08-02 14:03:03 +0200242
243 VideoDumpOptions(const VideoDumpOptions&) = default;
244 VideoDumpOptions& operator=(const VideoDumpOptions&) = default;
245 VideoDumpOptions(VideoDumpOptions&&) = default;
246 VideoDumpOptions& operator=(VideoDumpOptions&&) = default;
247
248 std::string output_directory() const { return output_directory_; }
249 int sampling_modulo() const { return sampling_modulo_; }
Artem Titovd2209252022-08-03 13:22:48 +0200250 bool export_frame_ids() const { return export_frame_ids_; }
Artem Titov72bc2e22022-08-02 14:03:03 +0200251
252 std::string GetInputDumpFileName(absl::string_view stream_label) const;
Artem Titovd2209252022-08-03 13:22:48 +0200253 // Returns file name for input frame ids dump if `export_frame_ids()` is
254 // true, absl::nullopt otherwise.
255 absl::optional<std::string> GetInputFrameIdsDumpFileName(
256 absl::string_view stream_label) const;
Artem Titov72bc2e22022-08-02 14:03:03 +0200257 std::string GetOutputDumpFileName(absl::string_view stream_label,
258 absl::string_view receiver) const;
Artem Titovd2209252022-08-03 13:22:48 +0200259 // Returns file name for output frame ids dump if `export_frame_ids()` is
260 // true, absl::nullopt otherwise.
261 absl::optional<std::string> GetOutputFrameIdsDumpFileName(
262 absl::string_view stream_label,
263 absl::string_view receiver) const;
Artem Titov72bc2e22022-08-02 14:03:03 +0200264
265 private:
266 std::string output_directory_;
267 int sampling_modulo_ = 1;
Artem Titovd2209252022-08-03 13:22:48 +0200268 bool export_frame_ids_ = false;
Artem Titov72bc2e22022-08-02 14:03:03 +0200269 };
270
Artem Titovebd97702019-01-09 17:55:36 +0100271 // Contains properties of single video stream.
Artem Titovb6c62012019-01-08 14:58:23 +0100272 struct VideoConfig {
Artem Titov7017a132022-04-20 20:57:56 +0200273 explicit VideoConfig(const VideoResolution& resolution);
Artem Titovc58c01d2019-02-28 13:19:12 +0100274 VideoConfig(size_t width, size_t height, int32_t fps)
275 : width(width), height(height), fps(fps) {}
Artem Titovb3d29102021-08-04 15:33:23 +0200276 VideoConfig(std::string stream_label,
277 size_t width,
278 size_t height,
279 int32_t fps)
280 : width(width),
281 height(height),
282 fps(fps),
283 stream_label(std::move(stream_label)) {}
Artem Titovc58c01d2019-02-28 13:19:12 +0100284
Artem Titov7581ff72019-05-15 15:45:33 +0200285 // Video stream width.
Artem Titova92d0512022-04-27 09:47:43 +0200286 size_t width;
Artem Titov7581ff72019-05-15 15:45:33 +0200287 // Video stream height.
Artem Titova92d0512022-04-27 09:47:43 +0200288 size_t height;
289 int32_t fps;
Artem Titov7017a132022-04-20 20:57:56 +0200290 VideoResolution GetResolution() const {
291 return VideoResolution(width, height, fps);
292 }
293
Artem Titovb6c62012019-01-08 14:58:23 +0100294 // Have to be unique among all specified configs for all peers in the call.
Artem Titov3481db22019-02-28 13:13:15 +0100295 // Will be auto generated if omitted.
Artem Titovb6c62012019-01-08 14:58:23 +0100296 absl::optional<std::string> stream_label;
Andrey Logvin435fb9a2020-05-08 08:02:49 +0000297 // Will be set for current video track. If equals to kText or kDetailed -
298 // screencast in on.
299 absl::optional<VideoTrackInterface::ContentHint> content_hint;
Artem Titovef3fd9c2019-06-13 16:36:52 +0200300 // If presented video will be transfered in simulcast/SVC mode depending on
301 // which encoder is used.
302 //
Artem Titov46c7a162019-07-29 13:17:14 +0200303 // Simulcast is supported only from 1st added peer. For VP8 simulcast only
304 // without RTX is supported so it will be automatically disabled for all
305 // simulcast tracks. For VP9 simulcast enables VP9 SVC mode and support RTX,
306 // but only on non-lossy networks. See more in documentation to
307 // VideoSimulcastConfig.
Artem Titovef3fd9c2019-06-13 16:36:52 +0200308 absl::optional<VideoSimulcastConfig> simulcast_config;
Florent Castellia63b6b72022-04-25 17:27:15 +0200309 // Encoding parameters for both singlecast and per simulcast layer.
310 // If singlecast is used, if not empty, a single value can be provided.
311 // If simulcast is used, if not empty, `encoding_params` size have to be
312 // equal to `simulcast_config.simulcast_streams_count`. Will be used to set
313 // transceiver send encoding params for each layer.
314 // RtpEncodingParameters::rid may be changed by fixture implementation to
315 // ensure signaling correctness.
316 std::vector<RtpEncodingParameters> encoding_params;
Artem Titov1e49ab22019-07-30 13:17:25 +0200317 // Count of temporal layers for video stream. This value will be set into
318 // each RtpEncodingParameters of RtpParameters of corresponding
319 // RtpSenderInterface for this video stream.
320 absl::optional<int> temporal_layers_count;
Artem Titov72bc2e22022-08-02 14:03:03 +0200321 // DEPRECATED: use input_dump_options instead. If specified the input stream
322 // will be also copied to specified file. It is actually one of the test's
323 // output file, which contains copy of what was captured during the test for
324 // this video stream on sender side. It is useful when generator is used as
325 // input.
Artem Titovb6c62012019-01-08 14:58:23 +0100326 absl::optional<std::string> input_dump_file_name;
Artem Titov72bc2e22022-08-02 14:03:03 +0200327 // DEPRECATED: use input_dump_options instead. Used only if
328 // `input_dump_file_name` is set. Specifies the module for the video frames
329 // to be dumped. Modulo equals X means every Xth frame will be written to
330 // the dump file. The value must be greater than 0.
Artem Titov484acf22021-02-25 20:44:11 +0100331 int input_dump_sampling_modulo = 1;
Artem Titov72bc2e22022-08-02 14:03:03 +0200332 // If specified defines how input should be dumped. It is actually one of
333 // the test's output file, which contains copy of what was captured during
334 // the test for this video stream on sender side. It is useful when
335 // generator is used as input.
336 absl::optional<VideoDumpOptions> input_dump_options;
337 // DEPRECATED: use output_dump_options instead. If specified this file will
338 // be used as output on the receiver side for this stream.
Artem Titov8177f582021-08-27 23:43:09 +0200339 //
340 // If multiple output streams will be produced by this stream (e.g. when the
341 // stream represented by this `VideoConfig` is received by more than one
342 // peer), output files will be appended with receiver names. If the second
343 // and other receivers will be added in the middle of the call after the
344 // first frame for this stream has been already written to the output file,
345 // then only dumps for newly added peers will be appended with receiver
346 // name, the dump for the first receiver will have name equal to the
347 // specified one. For example:
348 // * If we have peers A and B and A has `VideoConfig` V_a with
349 // V_a.output_dump_file_name = "/foo/a_output.yuv", then the stream
350 // related to V_a will be written into "/foo/a_output.yuv".
351 // * If we have peers A, B and C and A has `VideoConfig` V_a with
352 // V_a.output_dump_file_name = "/foo/a_output.yuv", then the stream
353 // related to V_a will be written for peer B into "/foo/a_output.yuv.B"
354 // and for peer C into "/foo/a_output.yuv.C"
355 // * If we have peers A and B and A has `VideoConfig` V_a with
356 // V_a.output_dump_file_name = "/foo/a_output.yuv", then if after B
357 // received the first frame related to V_a peer C joined the call, then
358 // the stream related to V_a will be written for peer B into
359 // "/foo/a_output.yuv" and for peer C into "/foo/a_output.yuv.C"
360 //
361 // The produced files contains what was rendered for this video stream on
362 // receiver side.
Artem Titova6a273d2019-02-07 16:43:51 +0100363 absl::optional<std::string> output_dump_file_name;
Artem Titov72bc2e22022-08-02 14:03:03 +0200364 // DEPRECATED: use output_dump_options instead. Used only if
365 // `output_dump_file_name` is set. Specifies the module for the video frames
366 // to be dumped. Modulo equals X means every Xth frame will be written to
367 // the dump file. The value must be greater than 0.
Artem Titov484acf22021-02-25 20:44:11 +0100368 int output_dump_sampling_modulo = 1;
Artem Titov72bc2e22022-08-02 14:03:03 +0200369 // If specified defines how output should be dumped on the receiver side for
370 // this stream. The produced files contain what was rendered for this video
371 // stream on receiver side per each receiver.
372 absl::optional<VideoDumpOptions> output_dump_options;
Artem Titov208129f2022-07-18 14:06:00 +0200373 // If set to true uses fixed frame rate while dumping output video to the
374 // file. `fps` will be used as frame rate.
375 bool output_dump_use_fixed_framerate = false;
Artem Titovddef8d12019-09-06 14:31:50 +0200376 // If true will display input and output video on the user's screen.
377 bool show_on_screen = false;
Artem Titov4a6f8182020-02-27 13:24:19 +0100378 // If specified, determines a sync group to which this video stream belongs.
379 // According to bugs.webrtc.org/4762 WebRTC supports synchronization only
Andrey Logvin739cfb22020-06-30 07:24:30 +0000380 // for pair of single audio and single video stream.
Artem Titov4a6f8182020-02-27 13:24:19 +0100381 absl::optional<std::string> sync_group;
Artem Titovb6c62012019-01-08 14:58:23 +0100382 };
383
Artem Titovebd97702019-01-09 17:55:36 +0100384 // Contains properties for audio in the call.
Artem Titovb6c62012019-01-08 14:58:23 +0100385 struct AudioConfig {
386 enum Mode {
387 kGenerated,
388 kFile,
389 };
Artem Titovb3d29102021-08-04 15:33:23 +0200390
391 AudioConfig() = default;
392 explicit AudioConfig(std::string stream_label)
393 : stream_label(std::move(stream_label)) {}
394
Artem Titov3481db22019-02-28 13:13:15 +0100395 // Have to be unique among all specified configs for all peers in the call.
396 // Will be auto generated if omitted.
397 absl::optional<std::string> stream_label;
Artem Titov9a7e7212019-02-28 16:34:17 +0100398 Mode mode = kGenerated;
Artem Titovb6c62012019-01-08 14:58:23 +0100399 // Have to be specified only if mode = kFile
400 absl::optional<std::string> input_file_name;
401 // If specified the input stream will be also copied to specified file.
402 absl::optional<std::string> input_dump_file_name;
403 // If specified the output stream will be copied to specified file.
Artem Titova6a273d2019-02-07 16:43:51 +0100404 absl::optional<std::string> output_dump_file_name;
Artem Titovbc558ce2019-07-08 19:13:21 +0200405
Artem Titovb6c62012019-01-08 14:58:23 +0100406 // Audio options to use.
407 cricket::AudioOptions audio_options;
Artem Titovbc558ce2019-07-08 19:13:21 +0200408 // Sampling frequency of input audio data (from file or generated).
409 int sampling_frequency_in_hz = 48000;
Artem Titov4a6f8182020-02-27 13:24:19 +0100410 // If specified, determines a sync group to which this audio stream belongs.
411 // According to bugs.webrtc.org/4762 WebRTC supports synchronization only
Andrey Logvin739cfb22020-06-30 07:24:30 +0000412 // for pair of single audio and single video stream.
Artem Titov4a6f8182020-02-27 13:24:19 +0100413 absl::optional<std::string> sync_group;
Artem Titovb6c62012019-01-08 14:58:23 +0100414 };
415
Mirko Bonadeif48c3732021-07-15 14:39:43 +0200416 struct VideoCodecConfig {
417 explicit VideoCodecConfig(std::string name)
418 : name(std::move(name)), required_params() {}
419 VideoCodecConfig(std::string name,
420 std::map<std::string, std::string> required_params)
421 : name(std::move(name)), required_params(std::move(required_params)) {}
422 // Next two fields are used to specify concrete video codec, that should be
423 // used in the test. Video code will be negotiated in SDP during offer/
424 // answer exchange.
425 // Video codec name. You can find valid names in
426 // media/base/media_constants.h
427 std::string name = cricket::kVp8CodecName;
428 // Map of parameters, that have to be specified on SDP codec. Each parameter
429 // is described by key and value. Codec parameters will match the specified
Artem Titov0e61fdd2021-07-25 21:50:14 +0200430 // map if and only if for each key from `required_params` there will be
Mirko Bonadeif48c3732021-07-15 14:39:43 +0200431 // a parameter with name equal to this key and parameter value will be equal
Artem Titov0e61fdd2021-07-25 21:50:14 +0200432 // to the value from `required_params` for this key.
Mirko Bonadeif48c3732021-07-15 14:39:43 +0200433 // If empty then only name will be used to match the codec.
434 std::map<std::string, std::string> required_params;
435 };
436
Artem Titov0d510522022-04-19 13:01:03 +0200437 // Subscription to the remote video streams. It declares which remote stream
438 // peer should receive and in which resolution (width x height x fps).
439 class VideoSubscription {
440 public:
Artem Titov0d510522022-04-19 13:01:03 +0200441 // Returns the resolution constructed as maximum from all resolution
442 // dimensions: width, height and fps.
Artem Titov7017a132022-04-20 20:57:56 +0200443 static absl::optional<VideoResolution> GetMaxResolution(
Artem Titov0d510522022-04-19 13:01:03 +0200444 rtc::ArrayView<const VideoConfig> video_configs);
Artem Titov7017a132022-04-20 20:57:56 +0200445 static absl::optional<VideoResolution> GetMaxResolution(
446 rtc::ArrayView<const VideoResolution> resolutions);
Artem Titov0d510522022-04-19 13:01:03 +0200447
Artem Titovfd8ed052022-06-01 14:11:14 +0200448 bool operator==(const VideoSubscription& other) const;
449 bool operator!=(const VideoSubscription& other) const {
450 return !(*this == other);
451 }
452
Artem Titov0d510522022-04-19 13:01:03 +0200453 // Subscribes receiver to all streams sent by the specified peer with
454 // specified resolution. It will override any resolution that was used in
455 // `SubscribeToAll` independently from methods call order.
456 VideoSubscription& SubscribeToPeer(
457 absl::string_view peer_name,
Artem Titov7017a132022-04-20 20:57:56 +0200458 VideoResolution resolution =
459 VideoResolution(VideoResolution::Spec::kMaxFromSender)) {
Artem Titov0d510522022-04-19 13:01:03 +0200460 peers_resolution_[std::string(peer_name)] = resolution;
461 return *this;
462 }
463
464 // Subscribes receiver to the all sent streams with specified resolution.
465 // If any stream was subscribed to with `SubscribeTo` method that will
466 // override resolution passed to this function independently from methods
467 // call order.
468 VideoSubscription& SubscribeToAllPeers(
Artem Titov7017a132022-04-20 20:57:56 +0200469 VideoResolution resolution =
470 VideoResolution(VideoResolution::Spec::kMaxFromSender)) {
Artem Titov0d510522022-04-19 13:01:03 +0200471 default_resolution_ = resolution;
472 return *this;
473 }
474
475 // Returns resolution for specific sender. If no specific resolution was
476 // set for this sender, then will return resolution used for all streams.
477 // If subscription doesn't subscribe to all streams, `absl::nullopt` will be
478 // returned.
Artem Titov7017a132022-04-20 20:57:56 +0200479 absl::optional<VideoResolution> GetResolutionForPeer(
Artem Titov0d510522022-04-19 13:01:03 +0200480 absl::string_view peer_name) const {
481 auto it = peers_resolution_.find(std::string(peer_name));
482 if (it == peers_resolution_.end()) {
483 return default_resolution_;
484 }
485 return it->second;
486 }
487
488 // Returns a maybe empty list of senders for which peer explicitly
489 // subscribed to with specific resolution.
490 std::vector<std::string> GetSubscribedPeers() const {
491 std::vector<std::string> subscribed_streams;
Rasmus Brandte890e362022-04-28 11:03:07 +0200492 subscribed_streams.reserve(peers_resolution_.size());
Artem Titov0d510522022-04-19 13:01:03 +0200493 for (const auto& entry : peers_resolution_) {
494 subscribed_streams.push_back(entry.first);
495 }
496 return subscribed_streams;
497 }
498
Artem Titov7c321922022-06-02 10:38:24 +0200499 std::string ToString() const;
500
Artem Titov0d510522022-04-19 13:01:03 +0200501 private:
Artem Titov7017a132022-04-20 20:57:56 +0200502 absl::optional<VideoResolution> default_resolution_ = absl::nullopt;
503 std::map<std::string, VideoResolution> peers_resolution_;
Artem Titov0d510522022-04-19 13:01:03 +0200504 };
505
Artem Titovd09bc552019-03-20 11:18:58 +0100506 // This class is used to fully configure one peer inside the call.
507 class PeerConfigurer {
508 public:
509 virtual ~PeerConfigurer() = default;
510
Artem Titovbaa2c832020-05-11 19:51:42 +0200511 // Sets peer name that will be used to report metrics related to this peer.
512 // If not set, some default name will be assigned. All names have to be
513 // unique.
514 virtual PeerConfigurer* SetName(absl::string_view name) = 0;
515
Artem Titov524417f2020-01-17 12:18:20 +0100516 // The parameters of the following 9 methods will be passed to the
Artem Titovd09bc552019-03-20 11:18:58 +0100517 // PeerConnectionFactoryInterface implementation that will be created for
518 // this peer.
Danil Chapovalov1a5fc902019-06-10 12:58:03 +0200519 virtual PeerConfigurer* SetTaskQueueFactory(
520 std::unique_ptr<TaskQueueFactory> task_queue_factory) = 0;
Artem Titovd09bc552019-03-20 11:18:58 +0100521 virtual PeerConfigurer* SetCallFactory(
522 std::unique_ptr<CallFactoryInterface> call_factory) = 0;
523 virtual PeerConfigurer* SetEventLogFactory(
524 std::unique_ptr<RtcEventLogFactoryInterface> event_log_factory) = 0;
525 virtual PeerConfigurer* SetFecControllerFactory(
526 std::unique_ptr<FecControllerFactoryInterface>
527 fec_controller_factory) = 0;
528 virtual PeerConfigurer* SetNetworkControllerFactory(
529 std::unique_ptr<NetworkControllerFactoryInterface>
530 network_controller_factory) = 0;
Artem Titovd09bc552019-03-20 11:18:58 +0100531 virtual PeerConfigurer* SetVideoEncoderFactory(
532 std::unique_ptr<VideoEncoderFactory> video_encoder_factory) = 0;
533 virtual PeerConfigurer* SetVideoDecoderFactory(
534 std::unique_ptr<VideoDecoderFactory> video_decoder_factory) = 0;
Artem Titov524417f2020-01-17 12:18:20 +0100535 // Set a custom NetEqFactory to be used in the call.
536 virtual PeerConfigurer* SetNetEqFactory(
537 std::unique_ptr<NetEqFactory> neteq_factory) = 0;
Artem Titov7e04b492022-03-08 01:26:03 +0100538 virtual PeerConfigurer* SetAudioProcessing(
539 rtc::scoped_refptr<webrtc::AudioProcessing> audio_processing) = 0;
540 virtual PeerConfigurer* SetAudioMixer(
541 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer) = 0;
Artem Titovd09bc552019-03-20 11:18:58 +0100542
Jonas Orelandc7bce992020-01-16 11:27:17 +0100543 // The parameters of the following 4 methods will be passed to the
Artem Titovd09bc552019-03-20 11:18:58 +0100544 // PeerConnectionInterface implementation that will be created for this
545 // peer.
546 virtual PeerConfigurer* SetAsyncResolverFactory(
547 std::unique_ptr<webrtc::AsyncResolverFactory>
548 async_resolver_factory) = 0;
549 virtual PeerConfigurer* SetRTCCertificateGenerator(
550 std::unique_ptr<rtc::RTCCertificateGeneratorInterface>
551 cert_generator) = 0;
552 virtual PeerConfigurer* SetSSLCertificateVerifier(
553 std::unique_ptr<rtc::SSLCertificateVerifier> tls_cert_verifier) = 0;
Jonas Orelandc7bce992020-01-16 11:27:17 +0100554 virtual PeerConfigurer* SetIceTransportFactory(
555 std::unique_ptr<IceTransportFactory> factory) = 0;
Artem Titov003e6e92022-02-23 15:23:52 +0100556 // Flags to set on `cricket::PortAllocator`. These flags will be added
557 // to the default ones that are presented on the port allocator.
558 // For possible values check p2p/base/port_allocator.h.
559 virtual PeerConfigurer* SetPortAllocatorExtraFlags(
560 uint32_t extra_flags) = 0;
Artem Titovd09bc552019-03-20 11:18:58 +0100561
562 // Add new video stream to the call that will be sent from this peer.
Andrey Logvin42c59522020-05-06 12:18:26 +0000563 // Default implementation of video frames generator will be used.
Artem Titovd09bc552019-03-20 11:18:58 +0100564 virtual PeerConfigurer* AddVideoConfig(VideoConfig config) = 0;
Artem Titovb4463ee2019-11-12 17:27:44 +0100565 // Add new video stream to the call that will be sent from this peer with
Artem Titov00202262019-12-04 22:34:41 +0100566 // provided own implementation of video frames generator.
Artem Titovb4463ee2019-11-12 17:27:44 +0100567 virtual PeerConfigurer* AddVideoConfig(
568 VideoConfig config,
Artem Titov00202262019-12-04 22:34:41 +0100569 std::unique_ptr<test::FrameGeneratorInterface> generator) = 0;
Andrey Logvinf3319812020-05-13 08:02:26 +0000570 // Add new video stream to the call that will be sent from this peer.
571 // Capturing device with specified index will be used to get input video.
572 virtual PeerConfigurer* AddVideoConfig(
573 VideoConfig config,
574 CapturingDeviceIndex capturing_device_index) = 0;
Artem Titov0d510522022-04-19 13:01:03 +0200575 // Sets video subscription for the peer. By default subscription will
576 // include all streams with `VideoSubscription::kSameAsSendStream`
577 // resolution. To override this behavior use this method.
578 virtual PeerConfigurer* SetVideoSubscription(
579 VideoSubscription subscription) = 0;
Mirko Bonadei4261a732021-07-19 14:28:48 +0200580 // Set the list of video codecs used by the peer during the test. These
581 // codecs will be negotiated in SDP during offer/answer exchange. The order
Artem Titov0e61fdd2021-07-25 21:50:14 +0200582 // of these codecs during negotiation will be the same as in `video_codecs`.
Mirko Bonadei4261a732021-07-19 14:28:48 +0200583 // Codecs have to be available in codecs list provided by peer connection to
584 // be negotiated. If some of specified codecs won't be found, the test will
585 // crash.
586 virtual PeerConfigurer* SetVideoCodecs(
587 std::vector<VideoCodecConfig> video_codecs) = 0;
Artem Titovd09bc552019-03-20 11:18:58 +0100588 // Set the audio stream for the call from this peer. If this method won't
589 // be invoked, this peer will send no audio.
590 virtual PeerConfigurer* SetAudioConfig(AudioConfig config) = 0;
Artem Titovb92d3e62022-02-15 18:46:21 +0100591
592 // Set if ULP FEC should be used or not. False by default.
593 virtual PeerConfigurer* SetUseUlpFEC(bool value) = 0;
594 // Set if Flex FEC should be used or not. False by default.
595 // Client also must enable `enable_flex_fec_support` in the `RunParams` to
596 // be able to use this feature.
597 virtual PeerConfigurer* SetUseFlexFEC(bool value) = 0;
598 // Specifies how much video encoder target bitrate should be different than
599 // target bitrate, provided by WebRTC stack. Must be greater than 0. Can be
600 // used to emulate overshooting of video encoders. This multiplier will
601 // be applied for all video encoder on both sides for all layers. Bitrate
602 // estimated by WebRTC stack will be multiplied by this multiplier and then
603 // provided into VideoEncoder::SetRates(...). 1.0 by default.
604 virtual PeerConfigurer* SetVideoEncoderBitrateMultiplier(
605 double multiplier) = 0;
606
Artem Titovd09bc552019-03-20 11:18:58 +0100607 // If is set, an RTCEventLog will be saved in that location and it will be
608 // available for further analysis.
609 virtual PeerConfigurer* SetRtcEventLogPath(std::string path) = 0;
Artem Titov70f80e52019-04-12 13:13:39 +0200610 // If is set, an AEC dump will be saved in that location and it will be
611 // available for further analysis.
612 virtual PeerConfigurer* SetAecDumpPath(std::string path) = 0;
Artem Titovd09bc552019-03-20 11:18:58 +0100613 virtual PeerConfigurer* SetRTCConfiguration(
614 PeerConnectionInterface::RTCConfiguration configuration) = 0;
Artem Titarenko21f12d52022-04-13 17:33:43 +0200615 virtual PeerConfigurer* SetRTCOfferAnswerOptions(
616 PeerConnectionInterface::RTCOfferAnswerOptions options) = 0;
Artem Titov85a9d912019-05-29 14:36:50 +0200617 // Set bitrate parameters on PeerConnection. This constraints will be
618 // applied to all summed RTP streams for this peer.
Niels Möller29d59a12020-06-22 14:48:10 +0200619 virtual PeerConfigurer* SetBitrateSettings(
620 BitrateSettings bitrate_settings) = 0;
Artem Titovd09bc552019-03-20 11:18:58 +0100621 };
622
Artem Titov728a0ee2019-08-20 13:36:35 +0200623 // Contains configuration for echo emulator.
624 struct EchoEmulationConfig {
625 // Delay which represents the echo path delay, i.e. how soon rendered signal
626 // should reach capturer.
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100627 TimeDelta echo_delay = TimeDelta::Millis(50);
Artem Titov728a0ee2019-08-20 13:36:35 +0200628 };
629
Artem Titova6a273d2019-02-07 16:43:51 +0100630 // Contains parameters, that describe how long framework should run quality
631 // test.
632 struct RunParams {
Artem Titovade945d2019-04-02 18:31:48 +0200633 explicit RunParams(TimeDelta run_duration) : run_duration(run_duration) {}
634
Artem Titova6a273d2019-02-07 16:43:51 +0100635 // Specifies how long the test should be run. This time shows how long
636 // the media should flow after connection was established and before
637 // it will be shut downed.
638 TimeDelta run_duration;
Artem Titovade945d2019-04-02 18:31:48 +0200639
Artem Titovb92d3e62022-02-15 18:46:21 +0100640 // If set to true peers will be able to use Flex FEC, otherwise they won't
641 // be able to negotiate it even if it's enabled on per peer level.
642 bool enable_flex_fec_support = false;
Artem Titov39483c62019-07-19 17:03:52 +0200643 // If true will set conference mode in SDP media section for all video
644 // tracks for all peers.
645 bool use_conference_mode = false;
Artem Titov728a0ee2019-08-20 13:36:35 +0200646 // If specified echo emulation will be done, by mixing the render audio into
647 // the capture signal. In such case input signal will be reduced by half to
648 // avoid saturation or compression in the echo path simulation.
649 absl::optional<EchoEmulationConfig> echo_emulation_config;
Artem Titova6a273d2019-02-07 16:43:51 +0100650 };
651
Artem Titov18459222019-04-24 11:09:35 +0200652 // Represent an entity that will report quality metrics after test.
Artem Titova8549212019-08-19 14:38:06 +0200653 class QualityMetricsReporter : public StatsObserverInterface {
Artem Titov18459222019-04-24 11:09:35 +0200654 public:
655 virtual ~QualityMetricsReporter() = default;
656
657 // Invoked by framework after peer connection factory and peer connection
658 // itself will be created but before offer/answer exchange will be started.
Artem Titov0e61fdd2021-07-25 21:50:14 +0200659 // `test_case_name` is name of test case, that should be used to report all
Andrey Logvin9d841fb2020-06-30 12:54:23 +0000660 // metrics.
Artem Titov0e61fdd2021-07-25 21:50:14 +0200661 // `reporter_helper` is a pointer to a class that will allow track_id to
Andrey Logvin9d841fb2020-06-30 12:54:23 +0000662 // stream_id matching. The caller is responsible for ensuring the
Andrey Logvin20f45822020-07-01 08:32:15 +0000663 // TrackIdStreamInfoMap will be valid from Start() to
Andrey Logvin9d841fb2020-06-30 12:54:23 +0000664 // StopAndReportResults().
665 virtual void Start(absl::string_view test_case_name,
Andrey Logvin20f45822020-07-01 08:32:15 +0000666 const TrackIdStreamInfoMap* reporter_helper) = 0;
Artem Titov18459222019-04-24 11:09:35 +0200667
668 // Invoked by framework after call is ended and peer connection factory and
669 // peer connection are destroyed.
670 virtual void StopAndReportResults() = 0;
671 };
672
Artem Titov79f82c12021-09-03 22:05:15 +0200673 // Represents single participant in call and can be used to perform different
674 // in-call actions. Might be extended in future.
675 class PeerHandle {
676 public:
677 virtual ~PeerHandle() = default;
678 };
679
Artem Titovd09bc552019-03-20 11:18:58 +0100680 virtual ~PeerConnectionE2EQualityTestFixture() = default;
681
Artem Titovba82e002019-03-15 15:57:53 +0100682 // Add activity that will be executed on the best effort at least after
Artem Titov0e61fdd2021-07-25 21:50:14 +0200683 // `target_time_since_start` after call will be set up (after offer/answer
Artem Titovba82e002019-03-15 15:57:53 +0100684 // exchange, ICE gathering will be done and ICE candidates will passed to
Artem Titov0e61fdd2021-07-25 21:50:14 +0200685 // remote side). `func` param is amount of time spent from the call set up.
Artem Titovba82e002019-03-15 15:57:53 +0100686 virtual void ExecuteAt(TimeDelta target_time_since_start,
687 std::function<void(TimeDelta)> func) = 0;
Artem Titov0e61fdd2021-07-25 21:50:14 +0200688 // Add activity that will be executed every `interval` with first execution
689 // on the best effort at least after `initial_delay_since_start` after call
690 // will be set up (after all participants will be connected). `func` param is
Artem Titovba82e002019-03-15 15:57:53 +0100691 // amount of time spent from the call set up.
692 virtual void ExecuteEvery(TimeDelta initial_delay_since_start,
693 TimeDelta interval,
694 std::function<void(TimeDelta)> func) = 0;
695
Artem Titov18459222019-04-24 11:09:35 +0200696 // Add stats reporter entity to observe the test.
697 virtual void AddQualityMetricsReporter(
698 std::unique_ptr<QualityMetricsReporter> quality_metrics_reporter) = 0;
699
Artem Titovd09bc552019-03-20 11:18:58 +0100700 // Add a new peer to the call and return an object through which caller
701 // can configure peer's behavior.
Niels Möllerf47a7242021-11-22 16:07:35 +0100702 // `network_dependencies` are used to provide networking for peer's peer
703 // connection. Members must be non-null.
Artem Titov0e61fdd2021-07-25 21:50:14 +0200704 // `configurer` function will be used to configure peer in the call.
Artem Titov15157ab2021-09-03 23:38:40 +0200705 virtual PeerHandle* AddPeer(
Niels Möllerf47a7242021-11-22 16:07:35 +0100706 const PeerNetworkDependencies& network_dependencies,
Niels Möller707e5a02021-11-23 14:46:11 +0100707 rtc::FunctionView<void(PeerConfigurer*)> configurer) = 0;
708
Artem Titov65dd2912020-05-27 13:55:33 +0200709 // Runs the media quality test, which includes setting up the call with
Artem Titov0e61fdd2021-07-25 21:50:14 +0200710 // configured participants, running it according to provided `run_params` and
Artem Titov65dd2912020-05-27 13:55:33 +0200711 // terminating it properly at the end. During call duration media quality
712 // metrics are gathered, which are then reported to stdout and (if configured)
713 // to the json/protobuf output file through the WebRTC perf test results
714 // reporting system.
Artem Titovd09bc552019-03-20 11:18:58 +0100715 virtual void Run(RunParams run_params) = 0;
Artem Titovb93c4e62019-05-02 10:52:07 +0200716
717 // Returns real test duration - the time of test execution measured during
718 // test. Client must call this method only after test is finished (after
719 // Run(...) method returned). Test execution time is time from end of call
720 // setup (offer/answer, ICE candidates exchange done and ICE connected) to
721 // start of call tear down (PeerConnection closed).
722 virtual TimeDelta GetRealTestDuration() const = 0;
Artem Titovb6c62012019-01-08 14:58:23 +0100723};
724
Artem Titov0b443142019-03-20 11:11:08 +0100725} // namespace webrtc_pc_e2e
Artem Titovb6c62012019-01-08 14:58:23 +0100726} // namespace webrtc
727
Artem Titovd57628f2019-03-22 12:34:25 +0100728#endif // API_TEST_PEERCONNECTION_QUALITY_TEST_FIXTURE_H_