diff options
Diffstat (limited to 'third_party/libwebrtc/test/video_codec_tester.h')
-rw-r--r-- | third_party/libwebrtc/test/video_codec_tester.h | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/third_party/libwebrtc/test/video_codec_tester.h b/third_party/libwebrtc/test/video_codec_tester.h new file mode 100644 index 0000000000..87cc5f76f8 --- /dev/null +++ b/third_party/libwebrtc/test/video_codec_tester.h @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2022 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_VIDEO_CODEC_TESTER_H_ +#define TEST_VIDEO_CODEC_TESTER_H_ + +#include <limits> +#include <map> +#include <memory> +#include <string> +#include <vector> + +#include "absl/types/optional.h" +#include "api/numerics/samples_stats_counter.h" +#include "api/test/metrics/metric.h" +#include "api/test/metrics/metrics_logger.h" +#include "api/units/data_rate.h" +#include "api/units/data_size.h" +#include "api/units/frequency.h" +#include "api/video/encoded_image.h" +#include "api/video/resolution.h" +#include "api/video_codecs/video_decoder_factory.h" +#include "api/video_codecs/video_encoder_factory.h" + +namespace webrtc { +namespace test { + +class VideoCodecTester { + public: + struct LayerId { + int spatial_idx = 0; + int temporal_idx = 0; + + bool operator==(const LayerId& o) const { + return spatial_idx == o.spatial_idx && temporal_idx == o.temporal_idx; + } + bool operator<(const LayerId& o) const { + return spatial_idx < o.spatial_idx || + (spatial_idx == o.spatial_idx && temporal_idx < o.temporal_idx); + } + }; + + struct EncodingSettings { + SdpVideoFormat sdp_video_format = SdpVideoFormat("VP8"); + ScalabilityMode scalability_mode = ScalabilityMode::kL1T1; + + struct LayerSettings { + Resolution resolution; + Frequency framerate; + DataRate bitrate; + }; + std::map<LayerId, LayerSettings> layers_settings; + }; + + class VideoCodecStats { + public: + struct Filter { + uint32_t min_timestamp_rtp = std::numeric_limits<uint32_t>::min(); + uint32_t max_timestamp_rtp = std::numeric_limits<uint32_t>::max(); + absl::optional<LayerId> layer_id; + }; + + struct Frame { + uint32_t timestamp_rtp = 0; + LayerId layer_id; + bool encoded = false; + bool decoded = false; + int width = 0; + int height = 0; + DataSize frame_size = DataSize::Zero(); + bool keyframe = false; + absl::optional<int> qp; + Timestamp encode_start = Timestamp::Zero(); + TimeDelta encode_time = TimeDelta::Zero(); + Timestamp decode_start = Timestamp::Zero(); + TimeDelta decode_time = TimeDelta::Zero(); + absl::optional<DataRate> target_bitrate; + absl::optional<Frequency> target_framerate; + + struct Psnr { + double y = 0.0; + double u = 0.0; + double v = 0.0; + }; + absl::optional<Psnr> psnr; + }; + + struct Stream { + SamplesStatsCounter width; + SamplesStatsCounter height; + SamplesStatsCounter frame_size_bytes; + SamplesStatsCounter keyframe; + SamplesStatsCounter qp; + SamplesStatsCounter encode_time_ms; + SamplesStatsCounter decode_time_ms; + SamplesStatsCounter target_bitrate_kbps; + SamplesStatsCounter target_framerate_fps; + SamplesStatsCounter encoded_bitrate_kbps; + SamplesStatsCounter encoded_framerate_fps; + SamplesStatsCounter bitrate_mismatch_pct; + SamplesStatsCounter framerate_mismatch_pct; + SamplesStatsCounter transmission_time_ms; + + struct Psnr { + SamplesStatsCounter y; + SamplesStatsCounter u; + SamplesStatsCounter v; + } psnr; + + // Logs `Stream` metrics to provided `MetricsLogger`. + void LogMetrics(MetricsLogger* logger, + std::string test_case_name, + std::string prefix, + std::map<std::string, std::string> metadata = {}) const; + }; + + virtual ~VideoCodecStats() = default; + + // Returns frames for the slice specified by `filter`. If `merge` is true, + // also merges frames belonging to the same temporal unit into one + // superframe. + virtual std::vector<Frame> Slice(Filter filter, bool merge) const = 0; + + // Returns video statistics aggregated for the slice specified by `filter`. + virtual Stream Aggregate(Filter filter) const = 0; + + // Write metrics to a CSV file. + virtual void LogMetrics( + absl::string_view csv_path, + std::vector<Frame> frames, + std::map<std::string, std::string> metadata) const = 0; + }; + + // Pacing settings for codec input. + struct PacingSettings { + enum PacingMode { + // Pacing is not used. Frames are sent to codec back-to-back. + kNoPacing, + // Pace with the rate equal to the target video frame rate. Pacing time is + // derived from RTP timestamp. + kRealTime, + // Pace with the explicitly provided rate. + kConstantRate, + }; + PacingMode mode = PacingMode::kNoPacing; + // Pacing rate for `kConstantRate` mode. + Frequency constant_rate = Frequency::Zero(); + }; + + struct VideoSourceSettings { + std::string file_path; + Resolution resolution; + Frequency framerate; + }; + + struct DecoderSettings { + PacingSettings pacing_settings; + absl::optional<std::string> decoder_input_base_path; + absl::optional<std::string> decoder_output_base_path; + }; + + struct EncoderSettings { + PacingSettings pacing_settings; + absl::optional<std::string> encoder_input_base_path; + absl::optional<std::string> encoder_output_base_path; + }; + + virtual ~VideoCodecTester() = default; + + // Interface for a coded video frames source. + class CodedVideoSource { + public: + virtual ~CodedVideoSource() = default; + + // Returns next frame. Returns `absl::nullopt` if the end-of-stream is + // reached. Frames should have RTP timestamps representing desired frame + // rate. + virtual absl::optional<EncodedImage> PullFrame() = 0; + }; + + // A helper function that creates `EncodingSettings` for `num_frames` frames, + // wraps the settings into RTP timestamp -> settings map and returns the map. + static std::map<uint32_t, EncodingSettings> CreateEncodingSettings( + std::string codec_type, + std::string scalability_name, + int width, + int height, + std::vector<int> bitrates_kbps, + double framerate_fps, + int num_frames, + uint32_t first_timestamp_rtp = 90000); + + // Decodes video, collects and returns decode metrics. + static std::unique_ptr<VideoCodecStats> RunDecodeTest( + CodedVideoSource* video_source, + VideoDecoderFactory* decoder_factory, + const DecoderSettings& decoder_settings, + const SdpVideoFormat& sdp_video_format); + + // Encodes video, collects and returns encode metrics. + static std::unique_ptr<VideoCodecStats> RunEncodeTest( + const VideoSourceSettings& source_settings, + VideoEncoderFactory* encoder_factory, + const EncoderSettings& encoder_settings, + const std::map<uint32_t, EncodingSettings>& encoding_settings); + + // Encodes and decodes video, collects and returns encode and decode metrics. + static std::unique_ptr<VideoCodecStats> RunEncodeDecodeTest( + const VideoSourceSettings& source_settings, + VideoEncoderFactory* encoder_factory, + VideoDecoderFactory* decoder_factory, + const EncoderSettings& encoder_settings, + const DecoderSettings& decoder_settings, + const std::map<uint32_t, EncodingSettings>& encoding_settings); +}; + +} // namespace test +} // namespace webrtc + +#endif // TEST_VIDEO_CODEC_TESTER_H_ |