mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-13 05:40:42 +01:00

This enables testing different settings without updating code and rebuilding the test binary. Example of command: video_codec_perf_tests --gtest_also_run_disabled_tests --gtest_filter=*EncodeDecode --encoder=libaom-av1 --decoder=dav1d --scalability_mode=L1T3 --bitrate_kbps=100,200,300 --framerate_fps=30 --write_csv Also added writing per-frame stats to a CSV. It is more convenient to work with CSV than to parse metrics proto. Bug: webrtc:14852 Change-Id: I1b3970f7ffa88c016133197aff585de5bc4e35c6 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/327600 Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org> Commit-Queue: Sergey Silkin <ssilkin@webrtc.org> Reviewed-by: Rasmus Brandt <brandtr@webrtc.org> Cr-Commit-Position: refs/heads/main@{#41179}
227 lines
7.3 KiB
C++
227 lines
7.3 KiB
C++
/*
|
|
* 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_
|