1 /* 2 * Copyright (c) 2019 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 #ifndef TEST_PC_E2E_ANALYZER_VIDEO_VIDEO_QUALITY_ANALYZER_INJECTION_HELPER_H_ 12 #define TEST_PC_E2E_ANALYZER_VIDEO_VIDEO_QUALITY_ANALYZER_INJECTION_HELPER_H_ 13 14 #include <stdio.h> 15 16 #include <map> 17 #include <memory> 18 #include <string> 19 #include <vector> 20 21 #include "absl/strings/string_view.h" 22 #include "api/array_view.h" 23 #include "api/test/pclf/media_configuration.h" 24 #include "api/test/stats_observer_interface.h" 25 #include "api/test/video_quality_analyzer_interface.h" 26 #include "api/video/video_frame.h" 27 #include "api/video/video_sink_interface.h" 28 #include "api/video_codecs/video_decoder_factory.h" 29 #include "api/video_codecs/video_encoder_factory.h" 30 #include "rtc_base/synchronization/mutex.h" 31 #include "system_wrappers/include/clock.h" 32 #include "test/pc/e2e/analyzer/video/analyzing_video_sink.h" 33 #include "test/pc/e2e/analyzer/video/analyzing_video_sinks_helper.h" 34 #include "test/pc/e2e/analyzer/video/encoded_image_data_injector.h" 35 #include "test/pc/e2e/analyzer/video/quality_analyzing_video_encoder.h" 36 #include "test/test_video_capturer.h" 37 #include "test/testsupport/video_frame_writer.h" 38 39 namespace webrtc { 40 namespace webrtc_pc_e2e { 41 42 // Provides factory methods for components, that will be used to inject 43 // VideoQualityAnalyzerInterface into PeerConnection pipeline. 44 class VideoQualityAnalyzerInjectionHelper : public StatsObserverInterface { 45 public: 46 VideoQualityAnalyzerInjectionHelper( 47 Clock* clock, 48 std::unique_ptr<VideoQualityAnalyzerInterface> analyzer, 49 EncodedImageDataInjector* injector, 50 EncodedImageDataExtractor* extractor); 51 ~VideoQualityAnalyzerInjectionHelper() override; 52 53 // Wraps video encoder factory to give video quality analyzer access to frames 54 // before encoding and encoded images after. 55 std::unique_ptr<VideoEncoderFactory> WrapVideoEncoderFactory( 56 absl::string_view peer_name, 57 std::unique_ptr<VideoEncoderFactory> delegate, 58 double bitrate_multiplier, 59 QualityAnalyzingVideoEncoder::EmulatedSFUConfigMap stream_to_sfu_config) 60 const; 61 // Wraps video decoder factory to give video quality analyzer access to 62 // received encoded images and frames, that were decoded from them. 63 std::unique_ptr<VideoDecoderFactory> WrapVideoDecoderFactory( 64 absl::string_view peer_name, 65 std::unique_ptr<VideoDecoderFactory> delegate) const; 66 67 // Creates VideoFrame preprocessor, that will allow video quality analyzer to 68 // get access to the captured frames. If provided config also specifies 69 // `input_dump_file_name`, video will be written into that file. 70 std::unique_ptr<test::TestVideoCapturer::FramePreprocessor> 71 CreateFramePreprocessor(absl::string_view peer_name, 72 const webrtc::webrtc_pc_e2e::VideoConfig& config); 73 // Creates sink, that will allow video quality analyzer to get access to 74 // the rendered frames. If corresponding video track has 75 // `output_dump_file_name` in its VideoConfig, which was used for 76 // CreateFramePreprocessor(...), then video also will be written 77 // into that file. 78 // TODO(titovartem): Remove method with `peer_name` only parameter. 79 std::unique_ptr<rtc::VideoSinkInterface<VideoFrame>> CreateVideoSink( 80 absl::string_view peer_name); 81 // TODO(titovartem): Remove default value for `report_infra_metrics`. 82 std::unique_ptr<AnalyzingVideoSink> CreateVideoSink( 83 absl::string_view peer_name, 84 const VideoSubscription& subscription, 85 bool report_infra_metrics = false); 86 87 void Start(std::string test_case_name, 88 rtc::ArrayView<const std::string> peer_names, 89 int max_threads_count = 1); 90 91 // Registers new call participant to the underlying video quality analyzer. 92 // The method should be called before the participant is actually added. 93 void RegisterParticipantInCall(absl::string_view peer_name); 94 95 // Will be called after test removed existing participant in the middle of the 96 // call. 97 void UnregisterParticipantInCall(absl::string_view peer_name); 98 99 // Forwards `stats_reports` for Peer Connection `pc_label` to 100 // `analyzer_`. 101 void OnStatsReports( 102 absl::string_view pc_label, 103 const rtc::scoped_refptr<const RTCStatsReport>& report) override; 104 105 // Stops VideoQualityAnalyzerInterface to populate final data and metrics. 106 // Should be invoked after analyzed video tracks are disposed. 107 void Stop(); 108 109 private: 110 // Deprecated, to be removed when old API isn't used anymore. 111 class AnalyzingVideoSink2 final : public rtc::VideoSinkInterface<VideoFrame> { 112 public: AnalyzingVideoSink2(absl::string_view peer_name,VideoQualityAnalyzerInjectionHelper * helper)113 explicit AnalyzingVideoSink2(absl::string_view peer_name, 114 VideoQualityAnalyzerInjectionHelper* helper) 115 : peer_name_(peer_name), helper_(helper) {} 116 ~AnalyzingVideoSink2() override = default; 117 OnFrame(const VideoFrame & frame)118 void OnFrame(const VideoFrame& frame) override { 119 helper_->OnFrame(peer_name_, frame); 120 } 121 122 private: 123 const std::string peer_name_; 124 VideoQualityAnalyzerInjectionHelper* const helper_; 125 }; 126 127 struct ReceiverStream { ReceiverStreamReceiverStream128 ReceiverStream(absl::string_view peer_name, absl::string_view stream_label) 129 : peer_name(peer_name), stream_label(stream_label) {} 130 131 std::string peer_name; 132 std::string stream_label; 133 134 // Define operators required to use ReceiverStream as std::map key. 135 bool operator==(const ReceiverStream& o) const { 136 return peer_name == o.peer_name && stream_label == o.stream_label; 137 } 138 bool operator<(const ReceiverStream& o) const { 139 return (peer_name == o.peer_name) ? stream_label < o.stream_label 140 : peer_name < o.peer_name; 141 } 142 }; 143 144 // Creates a deep copy of the frame and passes it to the video analyzer, while 145 // passing real frame to the sinks 146 void OnFrame(absl::string_view peer_name, const VideoFrame& frame); 147 std::vector<std::unique_ptr<rtc::VideoSinkInterface<VideoFrame>>>* 148 PopulateSinks(const ReceiverStream& receiver_stream); 149 150 Clock* const clock_; 151 std::unique_ptr<VideoQualityAnalyzerInterface> analyzer_; 152 EncodedImageDataInjector* injector_; 153 EncodedImageDataExtractor* extractor_; 154 155 std::vector<std::unique_ptr<test::VideoFrameWriter>> video_writers_; 156 157 AnalyzingVideoSinksHelper sinks_helper_; 158 Mutex mutex_; 159 int peers_count_ RTC_GUARDED_BY(mutex_); 160 // Map from stream label to the video config. 161 std::map<std::string, webrtc::webrtc_pc_e2e::VideoConfig> known_video_configs_ 162 RTC_GUARDED_BY(mutex_); 163 std::map<ReceiverStream, 164 std::vector<std::unique_ptr<rtc::VideoSinkInterface<VideoFrame>>>> 165 sinks_ RTC_GUARDED_BY(mutex_); 166 }; 167 168 } // namespace webrtc_pc_e2e 169 } // namespace webrtc 170 171 #endif // TEST_PC_E2E_ANALYZER_VIDEO_VIDEO_QUALITY_ANALYZER_INJECTION_HELPER_H_ 172