summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/test/pc/e2e/analyzer/video/default_video_quality_analyzer_shared_objects.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--third_party/libwebrtc/test/pc/e2e/analyzer/video/default_video_quality_analyzer_shared_objects.h284
1 files changed, 284 insertions, 0 deletions
diff --git a/third_party/libwebrtc/test/pc/e2e/analyzer/video/default_video_quality_analyzer_shared_objects.h b/third_party/libwebrtc/test/pc/e2e/analyzer/video/default_video_quality_analyzer_shared_objects.h
new file mode 100644
index 0000000000..175f777b68
--- /dev/null
+++ b/third_party/libwebrtc/test/pc/e2e/analyzer/video/default_video_quality_analyzer_shared_objects.h
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef TEST_PC_E2E_ANALYZER_VIDEO_DEFAULT_VIDEO_QUALITY_ANALYZER_SHARED_OBJECTS_H_
+#define TEST_PC_E2E_ANALYZER_VIDEO_DEFAULT_VIDEO_QUALITY_ANALYZER_SHARED_OBJECTS_H_
+
+#include <cstdint>
+#include <map>
+#include <memory>
+#include <ostream>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/numerics/samples_stats_counter.h"
+#include "api/units/timestamp.h"
+#include "rtc_base/strings/string_builder.h"
+
+namespace webrtc {
+
+// WebRTC will request a key frame after 3 seconds if no frames were received.
+// We assume max frame rate ~60 fps, so 270 frames will cover max freeze without
+// key frame request.
+constexpr size_t kDefaultMaxFramesInFlightPerStream = 270;
+
+class SamplesRateCounter {
+ public:
+ void AddEvent(Timestamp event_time);
+
+ bool IsEmpty() const { return event_first_time_ == event_last_time_; }
+
+ double GetEventsPerSecond() const;
+
+ private:
+ Timestamp event_first_time_ = Timestamp::MinusInfinity();
+ Timestamp event_last_time_ = Timestamp::MinusInfinity();
+ int64_t events_count_ = 0;
+};
+
+struct FrameCounters {
+ // Count of frames, that were passed into WebRTC pipeline by video stream
+ // source.
+ int64_t captured = 0;
+ // Count of frames that reached video encoder.
+ int64_t pre_encoded = 0;
+ // Count of encoded images that were produced by encoder for all requested
+ // spatial layers and simulcast streams.
+ int64_t encoded = 0;
+ // Count of encoded images received in decoder for all requested spatial
+ // layers and simulcast streams.
+ int64_t received = 0;
+ // Count of frames that were produced by decoder.
+ int64_t decoded = 0;
+ // Count of frames that went out from WebRTC pipeline to video sink.
+ int64_t rendered = 0;
+ // Count of frames that were dropped in any point between capturing and
+ // rendering.
+ int64_t dropped = 0;
+ // Count of frames for which decoder returned error when they were sent for
+ // decoding.
+ int64_t failed_to_decode = 0;
+};
+
+// Contains information about the codec that was used for encoding or decoding
+// the stream.
+struct StreamCodecInfo {
+ // Codec implementation name.
+ std::string codec_name;
+ // Id of the first frame for which this codec was used.
+ uint16_t first_frame_id;
+ // Id of the last frame for which this codec was used.
+ uint16_t last_frame_id;
+ // Timestamp when the first frame was handled by the encode/decoder.
+ Timestamp switched_on_at = Timestamp::PlusInfinity();
+ // Timestamp when this codec was used last time.
+ Timestamp switched_from_at = Timestamp::PlusInfinity();
+
+ std::string ToString() const;
+};
+
+std::ostream& operator<<(std::ostream& os, const StreamCodecInfo& state);
+rtc::StringBuilder& operator<<(rtc::StringBuilder& sb,
+ const StreamCodecInfo& state);
+bool operator==(const StreamCodecInfo& a, const StreamCodecInfo& b);
+
+// Represents phases where video frame can be dropped and such drop will be
+// detected by analyzer.
+enum class FrameDropPhase : int {
+ kBeforeEncoder,
+ kByEncoder,
+ kTransport,
+ kByDecoder,
+ kAfterDecoder,
+ // kLastValue must be the last value in this enumeration.
+ kLastValue
+};
+
+std::string ToString(FrameDropPhase phase);
+std::ostream& operator<<(std::ostream& os, FrameDropPhase phase);
+rtc::StringBuilder& operator<<(rtc::StringBuilder& sb, FrameDropPhase phase);
+
+struct StreamStats {
+ explicit StreamStats(Timestamp stream_started_time);
+
+ // The time when the first frame of this stream was captured.
+ Timestamp stream_started_time;
+
+ // Spatial quality metrics.
+ SamplesStatsCounter psnr;
+ SamplesStatsCounter ssim;
+
+ // Time from frame encoded (time point on exit from encoder) to the
+ // encoded image received in decoder (time point on entrance to decoder).
+ SamplesStatsCounter transport_time_ms;
+ // Time from frame was captured on device to time frame was displayed on
+ // device.
+ SamplesStatsCounter total_delay_incl_transport_ms;
+ // Time between frames out from renderer.
+ SamplesStatsCounter time_between_rendered_frames_ms;
+ SamplesRateCounter capture_frame_rate;
+ SamplesRateCounter encode_frame_rate;
+ SamplesStatsCounter encode_time_ms;
+ SamplesStatsCounter decode_time_ms;
+ // Time from last packet of frame is received until it's sent to the renderer.
+ SamplesStatsCounter receive_to_render_time_ms;
+ // Max frames skipped between two nearest.
+ SamplesStatsCounter skipped_between_rendered;
+ // In the next 2 metrics freeze is a pause that is longer, than maximum:
+ // 1. 150ms
+ // 2. 3 * average time between two sequential frames.
+ // Item 1 will cover high fps video and is a duration, that is noticeable by
+ // human eye. Item 2 will cover low fps video like screen sharing.
+ // Freeze duration.
+ SamplesStatsCounter freeze_time_ms;
+ // Mean time between one freeze end and next freeze start.
+ SamplesStatsCounter time_between_freezes_ms;
+ SamplesStatsCounter resolution_of_decoded_frame;
+ SamplesStatsCounter target_encode_bitrate;
+ // Sender side qp values per spatial layer. In case when spatial layer is not
+ // set for `webrtc::EncodedImage`, 0 is used as default.
+ std::map<int, SamplesStatsCounter> spatial_layers_qp;
+
+ int64_t total_encoded_images_payload = 0;
+ // Counters on which phase how many frames were dropped.
+ std::map<FrameDropPhase, int64_t> dropped_by_phase;
+
+ // Frame count metrics.
+ int64_t num_send_key_frames = 0;
+ int64_t num_recv_key_frames = 0;
+
+ // Encoded frame size (in bytes) metrics.
+ SamplesStatsCounter recv_key_frame_size_bytes;
+ SamplesStatsCounter recv_delta_frame_size_bytes;
+
+ // Vector of encoders used for this stream by sending client.
+ std::vector<StreamCodecInfo> encoders;
+ // Vectors of decoders used for this stream by receiving client.
+ std::vector<StreamCodecInfo> decoders;
+};
+
+struct AnalyzerStats {
+ // Size of analyzer internal comparisons queue, measured when new element
+ // id added to the queue.
+ SamplesStatsCounter comparisons_queue_size;
+ // Number of performed comparisons of 2 video frames from captured and
+ // rendered streams.
+ int64_t comparisons_done = 0;
+ // Number of cpu overloaded comparisons. Comparison is cpu overloaded if it is
+ // queued when there are too many not processed comparisons in the queue.
+ // Overloaded comparison doesn't include metrics like SSIM and PSNR that
+ // require heavy computations.
+ int64_t cpu_overloaded_comparisons_done = 0;
+ // Number of memory overloaded comparisons. Comparison is memory overloaded if
+ // it is queued when its captured frame was already removed due to high memory
+ // usage for that video stream.
+ int64_t memory_overloaded_comparisons_done = 0;
+ // Count of frames in flight in analyzer measured when new comparison is added
+ // and after analyzer was stopped.
+ SamplesStatsCounter frames_in_flight_left_count;
+
+ // Next metrics are collected and reported iff
+ // `DefaultVideoQualityAnalyzerOptions::report_infra_metrics` is true.
+ SamplesStatsCounter on_frame_captured_processing_time_ms;
+ SamplesStatsCounter on_frame_pre_encode_processing_time_ms;
+ SamplesStatsCounter on_frame_encoded_processing_time_ms;
+ SamplesStatsCounter on_frame_pre_decode_processing_time_ms;
+ SamplesStatsCounter on_frame_decoded_processing_time_ms;
+ SamplesStatsCounter on_frame_rendered_processing_time_ms;
+ SamplesStatsCounter on_decoder_error_processing_time_ms;
+};
+
+struct StatsKey {
+ StatsKey(std::string stream_label, std::string receiver)
+ : stream_label(std::move(stream_label)), receiver(std::move(receiver)) {}
+
+ std::string ToString() const;
+
+ // Label of video stream to which stats belongs to.
+ std::string stream_label;
+ // Name of the peer on which stream was received.
+ std::string receiver;
+};
+
+// Required to use StatsKey as std::map key.
+bool operator<(const StatsKey& a, const StatsKey& b);
+bool operator==(const StatsKey& a, const StatsKey& b);
+
+// Contains all metadata related to the video streams that were seen by the
+// video analyzer.
+class VideoStreamsInfo {
+ public:
+ std::set<StatsKey> GetStatsKeys() const;
+
+ // Returns all stream labels that are known to the video analyzer.
+ std::set<std::string> GetStreams() const;
+
+ // Returns set of the stream for specified `sender_name`. If sender didn't
+ // send any streams or `sender_name` isn't known to the video analyzer
+ // empty set will be returned.
+ std::set<std::string> GetStreams(absl::string_view sender_name) const;
+
+ // Returns sender name for specified `stream_label`. Returns `absl::nullopt`
+ // if provided `stream_label` isn't known to the video analyzer.
+ absl::optional<std::string> GetSender(absl::string_view stream_label) const;
+
+ // Returns set of the receivers for specified `stream_label`. If stream wasn't
+ // received by any peer or `stream_label` isn't known to the video analyzer
+ // empty set will be returned.
+ std::set<std::string> GetReceivers(absl::string_view stream_label) const;
+
+ protected:
+ friend class DefaultVideoQualityAnalyzer;
+ VideoStreamsInfo(
+ std::map<std::string, std::string> stream_to_sender,
+ std::map<std::string, std::set<std::string>> sender_to_streams,
+ std::map<std::string, std::set<std::string>> stream_to_receivers);
+
+ private:
+ std::map<std::string, std::string> stream_to_sender_;
+ std::map<std::string, std::set<std::string>> sender_to_streams_;
+ std::map<std::string, std::set<std::string>> stream_to_receivers_;
+};
+
+struct DefaultVideoQualityAnalyzerOptions {
+ // Tells DefaultVideoQualityAnalyzer if heavy metrics have to be computed.
+ bool compute_psnr = true;
+ bool compute_ssim = true;
+ // If true, weights the luma plane more than the chroma planes in the PSNR.
+ bool use_weighted_psnr = false;
+ // Tells DefaultVideoQualityAnalyzer if detailed frame stats should be
+ // reported.
+ bool report_detailed_frame_stats = false;
+ // Tells DefaultVideoQualityAnalyzer if infra metrics related to the
+ // performance and stability of the analyzer itself should be reported.
+ bool report_infra_metrics = false;
+ // If true DefaultVideoQualityAnalyzer will try to adjust frames before
+ // computing PSNR and SSIM for them. In some cases picture may be shifted by
+ // a few pixels after the encode/decode step. Those difference is invisible
+ // for a human eye, but it affects the metrics. So the adjustment is used to
+ // get metrics that are closer to how human perceive the video. This feature
+ // significantly slows down the comparison, so turn it on only when it is
+ // needed.
+ bool adjust_cropping_before_comparing_frames = false;
+ // Amount of frames that are queued in the DefaultVideoQualityAnalyzer from
+ // the point they were captured to the point they were rendered on all
+ // receivers per stream.
+ size_t max_frames_in_flight_per_stream_count =
+ kDefaultMaxFramesInFlightPerStream;
+ // If true, the analyzer will expect peers to receive their own video streams.
+ bool enable_receive_own_stream = false;
+};
+
+} // namespace webrtc
+
+#endif // TEST_PC_E2E_ANALYZER_VIDEO_DEFAULT_VIDEO_QUALITY_ANALYZER_SHARED_OBJECTS_H_