1 /* 2 * Copyright (c) 2021 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_DEFAULT_VIDEO_QUALITY_ANALYZER_SHARED_OBJECTS_H_ 12 #define TEST_PC_E2E_ANALYZER_VIDEO_DEFAULT_VIDEO_QUALITY_ANALYZER_SHARED_OBJECTS_H_ 13 14 #include <cstdint> 15 #include <map> 16 #include <memory> 17 #include <ostream> 18 #include <set> 19 #include <string> 20 #include <utility> 21 #include <vector> 22 23 #include "absl/types/optional.h" 24 #include "api/numerics/samples_stats_counter.h" 25 #include "api/units/timestamp.h" 26 #include "rtc_base/strings/string_builder.h" 27 28 namespace webrtc { 29 30 // WebRTC will request a key frame after 3 seconds if no frames were received. 31 // We assume max frame rate ~60 fps, so 270 frames will cover max freeze without 32 // key frame request. 33 constexpr size_t kDefaultMaxFramesInFlightPerStream = 270; 34 35 class SamplesRateCounter { 36 public: 37 void AddEvent(Timestamp event_time); 38 IsEmpty()39 bool IsEmpty() const { return event_first_time_ == event_last_time_; } 40 41 double GetEventsPerSecond() const; 42 43 private: 44 Timestamp event_first_time_ = Timestamp::MinusInfinity(); 45 Timestamp event_last_time_ = Timestamp::MinusInfinity(); 46 int64_t events_count_ = 0; 47 }; 48 49 struct FrameCounters { 50 // Count of frames, that were passed into WebRTC pipeline by video stream 51 // source. 52 int64_t captured = 0; 53 // Count of frames that reached video encoder. 54 int64_t pre_encoded = 0; 55 // Count of encoded images that were produced by encoder for all requested 56 // spatial layers and simulcast streams. 57 int64_t encoded = 0; 58 // Count of encoded images received in decoder for all requested spatial 59 // layers and simulcast streams. 60 int64_t received = 0; 61 // Count of frames that were produced by decoder. 62 int64_t decoded = 0; 63 // Count of frames that went out from WebRTC pipeline to video sink. 64 int64_t rendered = 0; 65 // Count of frames that were dropped in any point between capturing and 66 // rendering. 67 int64_t dropped = 0; 68 // Count of frames for which decoder returned error when they were sent for 69 // decoding. 70 int64_t failed_to_decode = 0; 71 }; 72 73 // Contains information about the codec that was used for encoding or decoding 74 // the stream. 75 struct StreamCodecInfo { 76 // Codec implementation name. 77 std::string codec_name; 78 // Id of the first frame for which this codec was used. 79 uint16_t first_frame_id; 80 // Id of the last frame for which this codec was used. 81 uint16_t last_frame_id; 82 // Timestamp when the first frame was handled by the encode/decoder. 83 Timestamp switched_on_at = Timestamp::PlusInfinity(); 84 // Timestamp when this codec was used last time. 85 Timestamp switched_from_at = Timestamp::PlusInfinity(); 86 87 std::string ToString() const; 88 }; 89 90 std::ostream& operator<<(std::ostream& os, const StreamCodecInfo& state); 91 rtc::StringBuilder& operator<<(rtc::StringBuilder& sb, 92 const StreamCodecInfo& state); 93 bool operator==(const StreamCodecInfo& a, const StreamCodecInfo& b); 94 95 // Represents phases where video frame can be dropped and such drop will be 96 // detected by analyzer. 97 enum class FrameDropPhase : int { 98 kBeforeEncoder, 99 kByEncoder, 100 kTransport, 101 kByDecoder, 102 kAfterDecoder, 103 // kLastValue must be the last value in this enumeration. 104 kLastValue 105 }; 106 107 std::string ToString(FrameDropPhase phase); 108 std::ostream& operator<<(std::ostream& os, FrameDropPhase phase); 109 rtc::StringBuilder& operator<<(rtc::StringBuilder& sb, FrameDropPhase phase); 110 111 struct StreamStats { 112 explicit StreamStats(Timestamp stream_started_time); 113 114 // The time when the first frame of this stream was captured. 115 Timestamp stream_started_time; 116 117 // Spatial quality metrics. 118 SamplesStatsCounter psnr; 119 SamplesStatsCounter ssim; 120 121 // Time from frame encoded (time point on exit from encoder) to the 122 // encoded image received in decoder (time point on entrance to decoder). 123 SamplesStatsCounter transport_time_ms; 124 // Time from frame was captured on device to time frame was displayed on 125 // device. 126 SamplesStatsCounter total_delay_incl_transport_ms; 127 // Time between frames out from renderer. 128 SamplesStatsCounter time_between_rendered_frames_ms; 129 SamplesRateCounter capture_frame_rate; 130 SamplesRateCounter encode_frame_rate; 131 SamplesStatsCounter encode_time_ms; 132 SamplesStatsCounter decode_time_ms; 133 // Time from last packet of frame is received until it's sent to the renderer. 134 SamplesStatsCounter receive_to_render_time_ms; 135 // Max frames skipped between two nearest. 136 SamplesStatsCounter skipped_between_rendered; 137 // In the next 2 metrics freeze is a pause that is longer, than maximum: 138 // 1. 150ms 139 // 2. 3 * average time between two sequential frames. 140 // Item 1 will cover high fps video and is a duration, that is noticeable by 141 // human eye. Item 2 will cover low fps video like screen sharing. 142 // Freeze duration. 143 SamplesStatsCounter freeze_time_ms; 144 // Mean time between one freeze end and next freeze start. 145 SamplesStatsCounter time_between_freezes_ms; 146 SamplesStatsCounter resolution_of_decoded_frame; 147 SamplesStatsCounter target_encode_bitrate; 148 SamplesStatsCounter qp; 149 150 int64_t total_encoded_images_payload = 0; 151 // Counters on which phase how many frames were dropped. 152 std::map<FrameDropPhase, int64_t> dropped_by_phase; 153 154 // Frame count metrics. 155 int64_t num_send_key_frames = 0; 156 int64_t num_recv_key_frames = 0; 157 158 // Encoded frame size (in bytes) metrics. 159 SamplesStatsCounter recv_key_frame_size_bytes; 160 SamplesStatsCounter recv_delta_frame_size_bytes; 161 162 // Vector of encoders used for this stream by sending client. 163 std::vector<StreamCodecInfo> encoders; 164 // Vectors of decoders used for this stream by receiving client. 165 std::vector<StreamCodecInfo> decoders; 166 }; 167 168 struct AnalyzerStats { 169 // Size of analyzer internal comparisons queue, measured when new element 170 // id added to the queue. 171 SamplesStatsCounter comparisons_queue_size; 172 // Number of performed comparisons of 2 video frames from captured and 173 // rendered streams. 174 int64_t comparisons_done = 0; 175 // Number of cpu overloaded comparisons. Comparison is cpu overloaded if it is 176 // queued when there are too many not processed comparisons in the queue. 177 // Overloaded comparison doesn't include metrics like SSIM and PSNR that 178 // require heavy computations. 179 int64_t cpu_overloaded_comparisons_done = 0; 180 // Number of memory overloaded comparisons. Comparison is memory overloaded if 181 // it is queued when its captured frame was already removed due to high memory 182 // usage for that video stream. 183 int64_t memory_overloaded_comparisons_done = 0; 184 // Count of frames in flight in analyzer measured when new comparison is added 185 // and after analyzer was stopped. 186 SamplesStatsCounter frames_in_flight_left_count; 187 188 // Next metrics are collected and reported iff 189 // `DefaultVideoQualityAnalyzerOptions::report_infra_metrics` is true. 190 SamplesStatsCounter on_frame_captured_processing_time_ms; 191 SamplesStatsCounter on_frame_pre_encode_processing_time_ms; 192 SamplesStatsCounter on_frame_encoded_processing_time_ms; 193 SamplesStatsCounter on_frame_pre_decode_processing_time_ms; 194 SamplesStatsCounter on_frame_decoded_processing_time_ms; 195 SamplesStatsCounter on_frame_rendered_processing_time_ms; 196 SamplesStatsCounter on_decoder_error_processing_time_ms; 197 }; 198 199 struct StatsKey { StatsKeyStatsKey200 StatsKey(std::string stream_label, std::string receiver) 201 : stream_label(std::move(stream_label)), receiver(std::move(receiver)) {} 202 203 std::string ToString() const; 204 205 // Label of video stream to which stats belongs to. 206 std::string stream_label; 207 // Name of the peer on which stream was received. 208 std::string receiver; 209 }; 210 211 // Required to use StatsKey as std::map key. 212 bool operator<(const StatsKey& a, const StatsKey& b); 213 bool operator==(const StatsKey& a, const StatsKey& b); 214 215 // Contains all metadata related to the video streams that were seen by the 216 // video analyzer. 217 class VideoStreamsInfo { 218 public: 219 std::set<StatsKey> GetStatsKeys() const; 220 221 // Returns all stream labels that are known to the video analyzer. 222 std::set<std::string> GetStreams() const; 223 224 // Returns set of the stream for specified `sender_name`. If sender didn't 225 // send any streams or `sender_name` isn't known to the video analyzer 226 // empty set will be returned. 227 std::set<std::string> GetStreams(absl::string_view sender_name) const; 228 229 // Returns sender name for specified `stream_label`. Returns `absl::nullopt` 230 // if provided `stream_label` isn't known to the video analyzer. 231 absl::optional<std::string> GetSender(absl::string_view stream_label) const; 232 233 // Returns set of the receivers for specified `stream_label`. If stream wasn't 234 // received by any peer or `stream_label` isn't known to the video analyzer 235 // empty set will be returned. 236 std::set<std::string> GetReceivers(absl::string_view stream_label) const; 237 238 protected: 239 friend class DefaultVideoQualityAnalyzer; 240 VideoStreamsInfo( 241 std::map<std::string, std::string> stream_to_sender, 242 std::map<std::string, std::set<std::string>> sender_to_streams, 243 std::map<std::string, std::set<std::string>> stream_to_receivers); 244 245 private: 246 std::map<std::string, std::string> stream_to_sender_; 247 std::map<std::string, std::set<std::string>> sender_to_streams_; 248 std::map<std::string, std::set<std::string>> stream_to_receivers_; 249 }; 250 251 struct DefaultVideoQualityAnalyzerOptions { 252 // Tells DefaultVideoQualityAnalyzer if heavy metrics have to be computed. 253 bool compute_psnr = true; 254 bool compute_ssim = true; 255 // If true, weights the luma plane more than the chroma planes in the PSNR. 256 bool use_weighted_psnr = false; 257 // Tells DefaultVideoQualityAnalyzer if detailed frame stats should be 258 // reported. 259 bool report_detailed_frame_stats = false; 260 // Tells DefaultVideoQualityAnalyzer if infra metrics related to the 261 // performance and stability of the analyzer itself should be reported. 262 bool report_infra_metrics = false; 263 // If true DefaultVideoQualityAnalyzer will try to adjust frames before 264 // computing PSNR and SSIM for them. In some cases picture may be shifted by 265 // a few pixels after the encode/decode step. Those difference is invisible 266 // for a human eye, but it affects the metrics. So the adjustment is used to 267 // get metrics that are closer to how human perceive the video. This feature 268 // significantly slows down the comparison, so turn it on only when it is 269 // needed. 270 bool adjust_cropping_before_comparing_frames = false; 271 // Amount of frames that are queued in the DefaultVideoQualityAnalyzer from 272 // the point they were captured to the point they were rendered on all 273 // receivers per stream. 274 size_t max_frames_in_flight_per_stream_count = 275 kDefaultMaxFramesInFlightPerStream; 276 // If true, the analyzer will expect peers to receive their own video streams. 277 bool enable_receive_own_stream = false; 278 }; 279 280 } // namespace webrtc 281 282 #endif // TEST_PC_E2E_ANALYZER_VIDEO_DEFAULT_VIDEO_QUALITY_ANALYZER_SHARED_OBJECTS_H_ 283