1 /* 2 * Copyright (c) 2022 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 #ifndef API_TEST_PCLF_MEDIA_CONFIGURATION_H_ 11 #define API_TEST_PCLF_MEDIA_CONFIGURATION_H_ 12 13 #include <stddef.h> 14 #include <stdint.h> 15 16 #include <functional> 17 #include <map> 18 #include <memory> 19 #include <string> 20 #include <utility> 21 #include <vector> 22 23 #include "absl/memory/memory.h" 24 #include "absl/strings/string_view.h" 25 #include "absl/types/optional.h" 26 #include "api/array_view.h" 27 #include "api/async_resolver_factory.h" 28 #include "api/audio/audio_mixer.h" 29 #include "api/audio_options.h" 30 #include "api/call/call_factory_interface.h" 31 #include "api/fec_controller.h" 32 #include "api/function_view.h" 33 #include "api/media_stream_interface.h" 34 #include "api/peer_connection_interface.h" 35 #include "api/rtc_event_log/rtc_event_log_factory_interface.h" 36 #include "api/rtp_parameters.h" 37 #include "api/task_queue/task_queue_factory.h" 38 #include "api/test/audio_quality_analyzer_interface.h" 39 #include "api/test/frame_generator_interface.h" 40 #include "api/test/peer_network_dependencies.h" 41 #include "api/test/simulated_network.h" 42 #include "api/test/stats_observer_interface.h" 43 #include "api/test/track_id_stream_info_map.h" 44 #include "api/test/video/video_frame_writer.h" 45 #include "api/test/video_quality_analyzer_interface.h" 46 #include "api/transport/network_control.h" 47 #include "api/units/time_delta.h" 48 #include "api/video_codecs/video_decoder_factory.h" 49 #include "api/video_codecs/video_encoder.h" 50 #include "api/video_codecs/video_encoder_factory.h" 51 #include "modules/audio_processing/include/audio_processing.h" 52 #include "rtc_base/checks.h" 53 #include "rtc_base/network.h" 54 #include "rtc_base/rtc_certificate_generator.h" 55 #include "rtc_base/ssl_certificate.h" 56 #include "rtc_base/thread.h" 57 58 namespace webrtc { 59 namespace webrtc_pc_e2e { 60 61 constexpr size_t kDefaultSlidesWidth = 1850; 62 constexpr size_t kDefaultSlidesHeight = 1110; 63 64 // The index of required capturing device in OS provided list of video 65 // devices. On Linux and Windows the list will be obtained via 66 // webrtc::VideoCaptureModule::DeviceInfo, on Mac OS via 67 // [RTCCameraVideoCapturer captureDevices]. 68 enum class CapturingDeviceIndex : size_t {}; 69 70 // Contains parameters for screen share scrolling. 71 // 72 // If scrolling is enabled, then it will be done by putting sliding window 73 // on source video and moving this window from top left corner to the 74 // bottom right corner of the picture. 75 // 76 // In such case source dimensions must be greater or equal to the sliding 77 // window dimensions. So `source_width` and `source_height` are the dimensions 78 // of the source frame, while `VideoConfig::width` and `VideoConfig::height` 79 // are the dimensions of the sliding window. 80 // 81 // Because `source_width` and `source_height` are dimensions of the source 82 // frame, they have to be width and height of videos from 83 // `ScreenShareConfig::slides_yuv_file_names`. 84 // 85 // Because scrolling have to be done on single slide it also requires, that 86 // `duration` must be less or equal to 87 // `ScreenShareConfig::slide_change_interval`. 88 struct ScrollingParams { 89 // Duration of scrolling. 90 TimeDelta duration; 91 // Width of source slides video. 92 size_t source_width = kDefaultSlidesWidth; 93 // Height of source slides video. 94 size_t source_height = kDefaultSlidesHeight; 95 }; 96 97 // Contains screen share video stream properties. 98 struct ScreenShareConfig { 99 explicit ScreenShareConfig(TimeDelta slide_change_interval); 100 101 // Shows how long one slide should be presented on the screen during 102 // slide generation. 103 TimeDelta slide_change_interval; 104 // If true, slides will be generated programmatically. No scrolling params 105 // will be applied in such case. 106 bool generate_slides = false; 107 // If present scrolling will be applied. Please read extra requirement on 108 // `slides_yuv_file_names` for scrolling. 109 absl::optional<ScrollingParams> scrolling_params; 110 // Contains list of yuv files with slides. 111 // 112 // If empty, default set of slides will be used. In such case 113 // `VideoConfig::width` must be equal to `kDefaultSlidesWidth` and 114 // `VideoConfig::height` must be equal to `kDefaultSlidesHeight` or if 115 // `scrolling_params` are specified, then `ScrollingParams::source_width` 116 // must be equal to `kDefaultSlidesWidth` and 117 // `ScrollingParams::source_height` must be equal to `kDefaultSlidesHeight`. 118 std::vector<std::string> slides_yuv_file_names; 119 }; 120 121 // Config for Vp8 simulcast or non-standard Vp9 SVC testing. 122 // 123 // To configure standard SVC setting, use `scalability_mode` in the 124 // `encoding_params` array. 125 // This configures Vp9 SVC by requesting simulcast layers, the request is 126 // internally converted to a request for SVC layers. 127 // 128 // SVC support is limited: 129 // During SVC testing there is no SFU, so framework will try to emulate SFU 130 // behavior in regular p2p call. Because of it there are such limitations: 131 // * if `target_spatial_index` is not equal to the highest spatial layer 132 // then no packet/frame drops are allowed. 133 // 134 // If there will be any drops, that will affect requested layer, then 135 // WebRTC SVC implementation will continue decoding only the highest 136 // available layer and won't restore lower layers, so analyzer won't 137 // receive required data which will cause wrong results or test failures. 138 struct VideoSimulcastConfig { 139 explicit VideoSimulcastConfig(int simulcast_streams_count); 140 141 // Specified amount of simulcast streams/SVC layers, depending on which 142 // encoder is used. 143 int simulcast_streams_count; 144 }; 145 146 // Configuration for the emulated Selective Forward Unit (SFU) 147 // 148 // The framework can optionally filter out frames that are decoded 149 // using an emulated SFU. 150 // When using simulcast or SVC, it's not always desirable to receive 151 // all frames. In a real world call, a SFU will only forward a subset 152 // of the frames. 153 // The emulated SFU is not able to change its configuration dynamically, 154 // if adaptation happens during the call, layers may be dropped and the 155 // analyzer won't receive the required data which will cause wrong results or 156 // test failures. 157 struct EmulatedSFUConfig { 158 EmulatedSFUConfig() = default; 159 explicit EmulatedSFUConfig(int target_layer_index); 160 EmulatedSFUConfig(absl::optional<int> target_layer_index, 161 absl::optional<int> target_temporal_index); 162 163 // Specifies simulcast or spatial index of the video stream to analyze. 164 // There are 2 cases: 165 // 1. simulcast encoding is used: 166 // in such case `target_layer_index` will specify the index of 167 // simulcast stream, that should be analyzed. Other streams will be 168 // dropped. 169 // 2. SVC encoding is used: 170 // in such case `target_layer_index` will specify the top interesting 171 // spatial layer and all layers below, including target one will be 172 // processed. All layers above target one will be dropped. 173 // If not specified then all streams will be received and analyzed. 174 // When set, it instructs the framework to create an emulated Selective 175 // Forwarding Unit (SFU) that will propagate only the requested layers. 176 absl::optional<int> target_layer_index; 177 // Specifies the index of the maximum temporal unit to keep. 178 // If not specified then all temporal layers will be received and analyzed. 179 // When set, it instructs the framework to create an emulated Selective 180 // Forwarding Unit (SFU) that will propagate only up to the requested layer. 181 absl::optional<int> target_temporal_index; 182 }; 183 184 class VideoResolution { 185 public: 186 // Determines special resolutions, which can't be expressed in terms of 187 // width, height and fps. 188 enum class Spec { 189 // No extra spec set. It describes a regular resolution described by 190 // width, height and fps. 191 kNone, 192 // Describes resolution which contains max value among all sender's 193 // video streams in each dimension (width, height, fps). 194 kMaxFromSender 195 }; 196 197 VideoResolution(size_t width, size_t height, int32_t fps); 198 explicit VideoResolution(Spec spec = Spec::kNone); 199 200 bool operator==(const VideoResolution& other) const; 201 bool operator!=(const VideoResolution& other) const; 202 width()203 size_t width() const { return width_; } set_width(size_t width)204 void set_width(size_t width) { width_ = width; } height()205 size_t height() const { return height_; } set_height(size_t height)206 void set_height(size_t height) { height_ = height; } fps()207 int32_t fps() const { return fps_; } set_fps(int32_t fps)208 void set_fps(int32_t fps) { fps_ = fps; } 209 210 // Returns if it is a regular resolution or not. The resolution is regular 211 // if it's spec is `Spec::kNone`. 212 bool IsRegular() const; 213 214 std::string ToString() const; 215 216 private: 217 size_t width_ = 0; 218 size_t height_ = 0; 219 int32_t fps_ = 0; 220 Spec spec_ = Spec::kNone; 221 }; 222 223 class VideoDumpOptions { 224 public: 225 static constexpr int kDefaultSamplingModulo = 1; 226 227 // output_directory - the output directory where stream will be dumped. The 228 // output files' names will be constructed as 229 // <stream_name>_<receiver_name>_<resolution>.<extension> for output dumps 230 // and <stream_name>_<resolution>.<extension> for input dumps. 231 // By default <extension> is "y4m". Resolution is in the format 232 // <width>x<height>_<fps>. 233 // sampling_modulo - the module for the video frames to be dumped. Modulo 234 // equals X means every Xth frame will be written to the dump file. The 235 // value must be greater than 0. (Default: 1) 236 // export_frame_ids - specifies if frame ids should be exported together 237 // with content of the stream. If true, an output file with the same name as 238 // video dump and suffix ".frame_ids.txt" will be created. It will contain 239 // the frame ids in the same order as original frames in the output 240 // file with stream content. File will contain one frame id per line. 241 // (Default: false) 242 // `video_frame_writer_factory` - factory function to create a video frame 243 // writer for input and output video files. (Default: Y4M video writer 244 // factory). 245 explicit VideoDumpOptions( 246 absl::string_view output_directory, 247 int sampling_modulo = kDefaultSamplingModulo, 248 bool export_frame_ids = false, 249 std::function<std::unique_ptr<test::VideoFrameWriter>( 250 absl::string_view file_name_prefix, 251 const VideoResolution& resolution)> video_frame_writer_factory = 252 Y4mVideoFrameWriterFactory); 253 VideoDumpOptions(absl::string_view output_directory, bool export_frame_ids); 254 255 VideoDumpOptions(const VideoDumpOptions&) = default; 256 VideoDumpOptions& operator=(const VideoDumpOptions&) = default; 257 VideoDumpOptions(VideoDumpOptions&&) = default; 258 VideoDumpOptions& operator=(VideoDumpOptions&&) = default; 259 output_directory()260 std::string output_directory() const { return output_directory_; } sampling_modulo()261 int sampling_modulo() const { return sampling_modulo_; } export_frame_ids()262 bool export_frame_ids() const { return export_frame_ids_; } 263 264 std::unique_ptr<test::VideoFrameWriter> CreateInputDumpVideoFrameWriter( 265 absl::string_view stream_label, 266 const VideoResolution& resolution) const; 267 268 std::unique_ptr<test::VideoFrameWriter> CreateOutputDumpVideoFrameWriter( 269 absl::string_view stream_label, 270 absl::string_view receiver, 271 const VideoResolution& resolution) const; 272 273 std::string ToString() const; 274 275 private: 276 static std::unique_ptr<test::VideoFrameWriter> Y4mVideoFrameWriterFactory( 277 absl::string_view file_name_prefix, 278 const VideoResolution& resolution); 279 std::string GetInputDumpFileName(absl::string_view stream_label, 280 const VideoResolution& resolution) const; 281 // Returns file name for input frame ids dump if `export_frame_ids()` is 282 // true, absl::nullopt otherwise. 283 absl::optional<std::string> GetInputFrameIdsDumpFileName( 284 absl::string_view stream_label, 285 const VideoResolution& resolution) const; 286 std::string GetOutputDumpFileName(absl::string_view stream_label, 287 absl::string_view receiver, 288 const VideoResolution& resolution) const; 289 // Returns file name for output frame ids dump if `export_frame_ids()` is 290 // true, absl::nullopt otherwise. 291 absl::optional<std::string> GetOutputFrameIdsDumpFileName( 292 absl::string_view stream_label, 293 absl::string_view receiver, 294 const VideoResolution& resolution) const; 295 296 std::string output_directory_; 297 int sampling_modulo_ = 1; 298 bool export_frame_ids_ = false; 299 std::function<std::unique_ptr<test::VideoFrameWriter>( 300 absl::string_view file_name_prefix, 301 const VideoResolution& resolution)> 302 video_frame_writer_factory_; 303 }; 304 305 // Contains properties of single video stream. 306 struct VideoConfig { 307 explicit VideoConfig(const VideoResolution& resolution); 308 VideoConfig(size_t width, size_t height, int32_t fps); 309 VideoConfig(std::string stream_label, 310 size_t width, 311 size_t height, 312 int32_t fps); 313 314 // Video stream width. 315 size_t width; 316 // Video stream height. 317 size_t height; 318 int32_t fps; GetResolutionVideoConfig319 VideoResolution GetResolution() const { 320 return VideoResolution(width, height, fps); 321 } 322 323 // Have to be unique among all specified configs for all peers in the call. 324 // Will be auto generated if omitted. 325 absl::optional<std::string> stream_label; 326 // Will be set for current video track. If equals to kText or kDetailed - 327 // screencast in on. 328 absl::optional<VideoTrackInterface::ContentHint> content_hint; 329 // If presented video will be transfered in simulcast/SVC mode depending on 330 // which encoder is used. 331 // 332 // Simulcast is supported only from 1st added peer. For VP8 simulcast only 333 // without RTX is supported so it will be automatically disabled for all 334 // simulcast tracks. For VP9 simulcast enables VP9 SVC mode and support RTX, 335 // but only on non-lossy networks. See more in documentation to 336 // VideoSimulcastConfig. 337 absl::optional<VideoSimulcastConfig> simulcast_config; 338 // Configuration for the emulated Selective Forward Unit (SFU). 339 absl::optional<EmulatedSFUConfig> emulated_sfu_config; 340 // Encoding parameters for both singlecast and per simulcast layer. 341 // If singlecast is used, if not empty, a single value can be provided. 342 // If simulcast is used, if not empty, `encoding_params` size have to be 343 // equal to `simulcast_config.simulcast_streams_count`. Will be used to set 344 // transceiver send encoding params for each layer. 345 // RtpEncodingParameters::rid may be changed by fixture implementation to 346 // ensure signaling correctness. 347 std::vector<RtpEncodingParameters> encoding_params; 348 // Count of temporal layers for video stream. This value will be set into 349 // each RtpEncodingParameters of RtpParameters of corresponding 350 // RtpSenderInterface for this video stream. 351 absl::optional<int> temporal_layers_count; 352 // If specified defines how input should be dumped. It is actually one of 353 // the test's output file, which contains copy of what was captured during 354 // the test for this video stream on sender side. It is useful when 355 // generator is used as input. 356 absl::optional<VideoDumpOptions> input_dump_options; 357 // If specified defines how output should be dumped on the receiver side for 358 // this stream. The produced files contain what was rendered for this video 359 // stream on receiver side per each receiver. 360 absl::optional<VideoDumpOptions> output_dump_options; 361 // If set to true uses fixed frame rate while dumping output video to the 362 // file. Requested `VideoSubscription::fps()` will be used as frame rate. 363 bool output_dump_use_fixed_framerate = false; 364 // If true will display input and output video on the user's screen. 365 bool show_on_screen = false; 366 // If specified, determines a sync group to which this video stream belongs. 367 // According to bugs.webrtc.org/4762 WebRTC supports synchronization only 368 // for pair of single audio and single video stream. 369 absl::optional<std::string> sync_group; 370 // If specified, it will be set into RtpParameters of corresponding 371 // RtpSenderInterface for this video stream. 372 // Note that this setting takes precedence over `content_hint`. 373 absl::optional<DegradationPreference> degradation_preference; 374 }; 375 376 // Contains properties for audio in the call. 377 struct AudioConfig { 378 enum Mode { 379 kGenerated, 380 kFile, 381 }; 382 383 AudioConfig() = default; 384 explicit AudioConfig(std::string stream_label); 385 386 // Have to be unique among all specified configs for all peers in the call. 387 // Will be auto generated if omitted. 388 absl::optional<std::string> stream_label; 389 Mode mode = kGenerated; 390 // Have to be specified only if mode = kFile 391 absl::optional<std::string> input_file_name; 392 // If specified the input stream will be also copied to specified file. 393 absl::optional<std::string> input_dump_file_name; 394 // If specified the output stream will be copied to specified file. 395 absl::optional<std::string> output_dump_file_name; 396 397 // Audio options to use. 398 cricket::AudioOptions audio_options; 399 // Sampling frequency of input audio data (from file or generated). 400 int sampling_frequency_in_hz = 48000; 401 // If specified, determines a sync group to which this audio stream belongs. 402 // According to bugs.webrtc.org/4762 WebRTC supports synchronization only 403 // for pair of single audio and single video stream. 404 absl::optional<std::string> sync_group; 405 }; 406 407 struct VideoCodecConfig { 408 explicit VideoCodecConfig(std::string name); 409 VideoCodecConfig(std::string name, 410 std::map<std::string, std::string> required_params); 411 // Next two fields are used to specify concrete video codec, that should be 412 // used in the test. Video code will be negotiated in SDP during offer/ 413 // answer exchange. 414 // Video codec name. You can find valid names in 415 // media/base/media_constants.h 416 std::string name; 417 // Map of parameters, that have to be specified on SDP codec. Each parameter 418 // is described by key and value. Codec parameters will match the specified 419 // map if and only if for each key from `required_params` there will be 420 // a parameter with name equal to this key and parameter value will be equal 421 // to the value from `required_params` for this key. 422 // If empty then only name will be used to match the codec. 423 std::map<std::string, std::string> required_params; 424 }; 425 426 // Subscription to the remote video streams. It declares which remote stream 427 // peer should receive and in which resolution (width x height x fps). 428 class VideoSubscription { 429 public: 430 // Returns the resolution constructed as maximum from all resolution 431 // dimensions: width, height and fps. 432 static absl::optional<VideoResolution> GetMaxResolution( 433 rtc::ArrayView<const VideoConfig> video_configs); 434 static absl::optional<VideoResolution> GetMaxResolution( 435 rtc::ArrayView<const VideoResolution> resolutions); 436 437 bool operator==(const VideoSubscription& other) const; 438 bool operator!=(const VideoSubscription& other) const; 439 440 // Subscribes receiver to all streams sent by the specified peer with 441 // specified resolution. It will override any resolution that was used in 442 // `SubscribeToAll` independently from methods call order. 443 VideoSubscription& SubscribeToPeer( 444 absl::string_view peer_name, 445 VideoResolution resolution = 446 VideoResolution(VideoResolution::Spec::kMaxFromSender)); 447 448 // Subscribes receiver to the all sent streams with specified resolution. 449 // If any stream was subscribed to with `SubscribeTo` method that will 450 // override resolution passed to this function independently from methods 451 // call order. 452 VideoSubscription& SubscribeToAllPeers( 453 VideoResolution resolution = 454 VideoResolution(VideoResolution::Spec::kMaxFromSender)); 455 456 // Returns resolution for specific sender. If no specific resolution was 457 // set for this sender, then will return resolution used for all streams. 458 // If subscription doesn't subscribe to all streams, `absl::nullopt` will be 459 // returned. 460 absl::optional<VideoResolution> GetResolutionForPeer( 461 absl::string_view peer_name) const; 462 463 // Returns a maybe empty list of senders for which peer explicitly 464 // subscribed to with specific resolution. 465 std::vector<std::string> GetSubscribedPeers() const; 466 467 std::string ToString() const; 468 469 private: 470 absl::optional<VideoResolution> default_resolution_ = absl::nullopt; 471 std::map<std::string, VideoResolution> peers_resolution_; 472 }; 473 474 // Contains configuration for echo emulator. 475 struct EchoEmulationConfig { 476 // Delay which represents the echo path delay, i.e. how soon rendered signal 477 // should reach capturer. 478 TimeDelta echo_delay = TimeDelta::Millis(50); 479 }; 480 481 } // namespace webrtc_pc_e2e 482 } // namespace webrtc 483 484 #endif // API_TEST_PCLF_MEDIA_CONFIGURATION_H_ 485