| /* | 
 |  *  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 <cstdint> | 
 | #include <limits> | 
 | #include <map> | 
 | #include <memory> | 
 | #include <optional> | 
 | #include <string> | 
 | #include <vector> | 
 |  | 
 | #include "absl/strings/string_view.h" | 
 | #include "api/environment/environment.h" | 
 | #include "api/numerics/samples_stats_counter.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/units/time_delta.h" | 
 | #include "api/units/timestamp.h" | 
 | #include "api/video/encoded_image.h" | 
 | #include "api/video/resolution.h" | 
 | #include "api/video_codecs/scalability_mode.h" | 
 | #include "api/video_codecs/sdp_video_format.h" | 
 | #include "api/video_codecs/video_codec.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; | 
 |     VideoCodecMode content_type = VideoCodecMode::kRealtimeVideo; | 
 |     bool frame_drop = true; | 
 |     bool keyframe = false; | 
 |  | 
 |     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(); | 
 |       std::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; | 
 |       std::optional<int> qp; | 
 |       Timestamp encode_start = Timestamp::Zero(); | 
 |       TimeDelta encode_time = TimeDelta::Zero(); | 
 |       Timestamp decode_start = Timestamp::Zero(); | 
 |       TimeDelta decode_time = TimeDelta::Zero(); | 
 |       std::optional<DataRate> target_bitrate; | 
 |       std::optional<Frequency> target_framerate; | 
 |  | 
 |       struct Psnr { | 
 |         double y = 0.0; | 
 |         double u = 0.0; | 
 |         double v = 0.0; | 
 |       }; | 
 |       std::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; | 
 |     std::optional<std::string> decoder_input_base_path; | 
 |     std::optional<std::string> decoder_output_base_path; | 
 |   }; | 
 |  | 
 |   struct EncoderSettings { | 
 |     PacingSettings pacing_settings; | 
 |     std::optional<std::string> encoder_input_base_path; | 
 |     std::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 `std::nullopt` if the end-of-stream is | 
 |     // reached. Frames should have RTP timestamps representing desired frame | 
 |     // rate. | 
 |     virtual std::optional<EncodedImage> PullFrame() = 0; | 
 |   }; | 
 |  | 
 |   // A helper function that creates `EncodingSettings` from the given | 
 |   // parameters. `bitrate` is either total, or per-spatial layer or per-spatial | 
 |   // and per-temporal layer. If layer bitrates are not explicitly specified, | 
 |   // then the codec-specific rate allocators used to distribute the total | 
 |   // bitrate across spatial or/and temporal layers. | 
 |   static EncodingSettings CreateEncodingSettings(const Environment& env, | 
 |                                                  std::string codec_type, | 
 |                                                  std::string scalability_name, | 
 |                                                  int width, | 
 |                                                  int height, | 
 |                                                  std::vector<DataRate> bitrate, | 
 |                                                  Frequency framerate, | 
 |                                                  bool screencast = false, | 
 |                                                  bool frame_drop = true); | 
 |  | 
 |   // A helper function that creates a map of RTP timestamps to | 
 |   // `EncodingSettings` for the given number of frames. | 
 |   static std::map<uint32_t, EncodingSettings> CreateFrameSettings( | 
 |       const EncodingSettings& encoding_settings, | 
 |       int num_frames, | 
 |       uint32_t first_timestamp_rtp = 90000); | 
 |  | 
 |   // Decodes video, collects and returns decode metrics. | 
 |   static std::unique_ptr<VideoCodecStats> RunDecodeTest( | 
 |       const Environment& env, | 
 |       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 Environment& env, | 
 |       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 Environment& env, | 
 |       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_ |