[PCLF] Introduce VideoDumpOptions API to better control video dumping
This CL propose a new API for video dumps in PCLF also removing differences between p2p and multipeer usage of API. Bug: b/240540206 Change-Id: Id4d32cc98250500949b3f9e2cf2e86c4bdce7efb Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/270400 Commit-Queue: Artem Titov <titovartem@webrtc.org> Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org> Cr-Commit-Position: refs/heads/main@{#37665}
This commit is contained in:
parent
a204ad210d
commit
72bc2e24cc
@ -530,6 +530,7 @@ rtc_source_set("peer_connection_quality_test_fixture_api") {
|
||||
"../rtc_base:rtc_base",
|
||||
"../rtc_base:stringutils",
|
||||
"../rtc_base:threading",
|
||||
"../test:fileutils",
|
||||
"audio:audio_mixer_api",
|
||||
"rtc_event_log",
|
||||
"task_queue",
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
#include "api/array_view.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/strings/string_builder.h"
|
||||
#include "test/testsupport/file_utils.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace webrtc_pc_e2e {
|
||||
@ -122,6 +123,30 @@ std::string PeerConnectionE2EQualityTestFixture::VideoSubscription::ToString()
|
||||
return out.Release();
|
||||
}
|
||||
|
||||
PeerConnectionE2EQualityTestFixture::VideoDumpOptions::VideoDumpOptions(
|
||||
absl::string_view output_directory,
|
||||
int sampling_modulo)
|
||||
: output_directory_(output_directory), sampling_modulo_(sampling_modulo) {
|
||||
RTC_CHECK_GT(sampling_modulo, 0);
|
||||
}
|
||||
|
||||
std::string
|
||||
PeerConnectionE2EQualityTestFixture::VideoDumpOptions::GetInputDumpFileName(
|
||||
absl::string_view stream_label) const {
|
||||
rtc::StringBuilder file_name;
|
||||
file_name << stream_label << ".y4m";
|
||||
return test::JoinFilename(output_directory_, file_name.Release());
|
||||
}
|
||||
|
||||
std::string
|
||||
PeerConnectionE2EQualityTestFixture::VideoDumpOptions::GetOutputDumpFileName(
|
||||
absl::string_view stream_label,
|
||||
absl::string_view receiver) const {
|
||||
rtc::StringBuilder file_name;
|
||||
file_name << stream_label << "_" << receiver << ".y4m";
|
||||
return test::JoinFilename(output_directory_, file_name.Release());
|
||||
}
|
||||
|
||||
PeerConnectionE2EQualityTestFixture::VideoConfig::VideoConfig(
|
||||
const VideoResolution& resolution)
|
||||
: width(resolution.width()),
|
||||
|
||||
@ -217,6 +217,36 @@ class PeerConnectionE2EQualityTestFixture {
|
||||
Spec spec_ = Spec::kNone;
|
||||
};
|
||||
|
||||
class VideoDumpOptions {
|
||||
public:
|
||||
// output_directory - the output directory where stream will be dumped. The
|
||||
// output files' names will be constructed as
|
||||
// <stream_name>_<receiver_name>.<extension> for output dumps and
|
||||
// <stream_name>.<extension> for input dumps. By default <extension> is
|
||||
// "y4m".
|
||||
// sampling_modulo - the module for the video frames to be dumped. Modulo
|
||||
// equals X means every Xth frame will be written to the dump file. The
|
||||
// value must be greater than 0. (Default: 1)
|
||||
explicit VideoDumpOptions(absl::string_view output_directory,
|
||||
int sampling_modulo = 1);
|
||||
|
||||
VideoDumpOptions(const VideoDumpOptions&) = default;
|
||||
VideoDumpOptions& operator=(const VideoDumpOptions&) = default;
|
||||
VideoDumpOptions(VideoDumpOptions&&) = default;
|
||||
VideoDumpOptions& operator=(VideoDumpOptions&&) = default;
|
||||
|
||||
std::string output_directory() const { return output_directory_; }
|
||||
int sampling_modulo() const { return sampling_modulo_; }
|
||||
|
||||
std::string GetInputDumpFileName(absl::string_view stream_label) const;
|
||||
std::string GetOutputDumpFileName(absl::string_view stream_label,
|
||||
absl::string_view receiver) const;
|
||||
|
||||
private:
|
||||
std::string output_directory_;
|
||||
int sampling_modulo_ = 1;
|
||||
};
|
||||
|
||||
// Contains properties of single video stream.
|
||||
struct VideoConfig {
|
||||
explicit VideoConfig(const VideoResolution& resolution);
|
||||
@ -267,17 +297,24 @@ class PeerConnectionE2EQualityTestFixture {
|
||||
// each RtpEncodingParameters of RtpParameters of corresponding
|
||||
// RtpSenderInterface for this video stream.
|
||||
absl::optional<int> temporal_layers_count;
|
||||
// If specified the input stream will be also copied to specified file.
|
||||
// It is actually one of the test's output file, which contains copy of what
|
||||
// was captured during the test for this video stream on sender side.
|
||||
// It is useful when generator is used as input.
|
||||
// DEPRECATED: use input_dump_options instead. If specified the input stream
|
||||
// will be also copied to specified file. It is actually one of the test's
|
||||
// output file, which contains copy of what was captured during the test for
|
||||
// this video stream on sender side. It is useful when generator is used as
|
||||
// input.
|
||||
absl::optional<std::string> input_dump_file_name;
|
||||
// Used only if `input_dump_file_name` is set. Specifies the module for the
|
||||
// video frames to be dumped. Modulo equals X means every Xth frame will be
|
||||
// written to the dump file. The value must be greater than 0.
|
||||
// DEPRECATED: use input_dump_options instead. Used only if
|
||||
// `input_dump_file_name` is set. Specifies the module for the video frames
|
||||
// to be dumped. Modulo equals X means every Xth frame will be written to
|
||||
// the dump file. The value must be greater than 0.
|
||||
int input_dump_sampling_modulo = 1;
|
||||
// If specified this file will be used as output on the receiver side for
|
||||
// this stream.
|
||||
// If specified defines how input should be dumped. It is actually one of
|
||||
// the test's output file, which contains copy of what was captured during
|
||||
// the test for this video stream on sender side. It is useful when
|
||||
// generator is used as input.
|
||||
absl::optional<VideoDumpOptions> input_dump_options;
|
||||
// DEPRECATED: use output_dump_options instead. If specified this file will
|
||||
// be used as output on the receiver side for this stream.
|
||||
//
|
||||
// If multiple output streams will be produced by this stream (e.g. when the
|
||||
// stream represented by this `VideoConfig` is received by more than one
|
||||
@ -303,10 +340,15 @@ class PeerConnectionE2EQualityTestFixture {
|
||||
// The produced files contains what was rendered for this video stream on
|
||||
// receiver side.
|
||||
absl::optional<std::string> output_dump_file_name;
|
||||
// Used only if `output_dump_file_name` is set. Specifies the module for the
|
||||
// video frames to be dumped. Modulo equals X means every Xth frame will be
|
||||
// written to the dump file. The value must be greater than 0.
|
||||
// DEPRECATED: use output_dump_options instead. Used only if
|
||||
// `output_dump_file_name` is set. Specifies the module for the video frames
|
||||
// to be dumped. Modulo equals X means every Xth frame will be written to
|
||||
// the dump file. The value must be greater than 0.
|
||||
int output_dump_sampling_modulo = 1;
|
||||
// If specified defines how output should be dumped on the receiver side for
|
||||
// this stream. The produced files contain what was rendered for this video
|
||||
// stream on receiver side per each receiver.
|
||||
absl::optional<VideoDumpOptions> output_dump_options;
|
||||
// If set to true uses fixed frame rate while dumping output video to the
|
||||
// file. `fps` will be used as frame rate.
|
||||
bool output_dump_use_fixed_framerate = false;
|
||||
|
||||
@ -128,11 +128,21 @@ VideoQualityAnalyzerInjectionHelper::CreateFramePreprocessor(
|
||||
absl::string_view peer_name,
|
||||
const VideoConfig& config) {
|
||||
std::vector<std::unique_ptr<rtc::VideoSinkInterface<VideoFrame>>> sinks;
|
||||
test::VideoFrameWriter* writer =
|
||||
MaybeCreateVideoWriter(config.input_dump_file_name, config);
|
||||
if (writer) {
|
||||
test::VideoFrameWriter* writer = nullptr;
|
||||
if (config.input_dump_options.has_value()) {
|
||||
// Using new API for video dumping.
|
||||
writer = MaybeCreateVideoWriter(
|
||||
config.input_dump_options->GetInputDumpFileName(peer_name), config);
|
||||
RTC_CHECK(writer);
|
||||
sinks.push_back(std::make_unique<VideoWriter>(
|
||||
writer, config.input_dump_sampling_modulo));
|
||||
writer, config.input_dump_options->sampling_modulo()));
|
||||
} else {
|
||||
// Using old API. To be removed.
|
||||
writer = MaybeCreateVideoWriter(config.input_dump_file_name, config);
|
||||
if (writer) {
|
||||
sinks.push_back(std::make_unique<VideoWriter>(
|
||||
writer, config.input_dump_sampling_modulo));
|
||||
}
|
||||
}
|
||||
if (config.show_on_screen) {
|
||||
sinks.push_back(absl::WrapUnique(
|
||||
@ -206,7 +216,7 @@ VideoQualityAnalyzerInjectionHelper::MaybeCreateVideoWriter(
|
||||
// only one file will be used.
|
||||
std::unique_ptr<test::VideoFrameWriter> video_writer =
|
||||
std::make_unique<test::Y4mVideoFrameWriterImpl>(
|
||||
file_name.value(), config.width, config.height, config.fps);
|
||||
*file_name, config.width, config.height, config.fps);
|
||||
if (config.output_dump_use_fixed_framerate) {
|
||||
video_writer = std::make_unique<test::FixedFpsVideoFrameWriterAdapter>(
|
||||
config.fps, clock_, std::move(video_writer));
|
||||
@ -257,19 +267,31 @@ VideoQualityAnalyzerInjectionHelper::PopulateSinks(
|
||||
const VideoConfig& config = it->second;
|
||||
|
||||
std::vector<std::unique_ptr<rtc::VideoSinkInterface<VideoFrame>>> sinks;
|
||||
absl::optional<std::string> output_dump_file_name =
|
||||
config.output_dump_file_name;
|
||||
if (output_dump_file_name.has_value() && peers_count_ > 2) {
|
||||
// TODO(titovartem): make this default behavior for any amount of peers.
|
||||
rtc::StringBuilder builder(*output_dump_file_name);
|
||||
builder << "." << receiver_stream.peer_name;
|
||||
output_dump_file_name = builder.str();
|
||||
}
|
||||
test::VideoFrameWriter* writer =
|
||||
MaybeCreateVideoWriter(output_dump_file_name, config);
|
||||
if (writer) {
|
||||
test::VideoFrameWriter* writer = nullptr;
|
||||
if (config.output_dump_options.has_value()) {
|
||||
// Using new API with output directory.
|
||||
writer = MaybeCreateVideoWriter(
|
||||
config.output_dump_options->GetOutputDumpFileName(
|
||||
receiver_stream.stream_label, receiver_stream.peer_name),
|
||||
config);
|
||||
RTC_CHECK(writer);
|
||||
sinks.push_back(std::make_unique<VideoWriter>(
|
||||
writer, config.output_dump_sampling_modulo));
|
||||
writer, config.output_dump_options->sampling_modulo()));
|
||||
} else {
|
||||
// Using old API. To be removed.
|
||||
absl::optional<std::string> output_dump_file_name =
|
||||
config.output_dump_file_name;
|
||||
if (output_dump_file_name.has_value() && peers_count_ > 2) {
|
||||
// TODO(titovartem): make this default behavior for any amount of peers.
|
||||
rtc::StringBuilder builder(*output_dump_file_name);
|
||||
builder << "." << receiver_stream.peer_name;
|
||||
output_dump_file_name = builder.str();
|
||||
}
|
||||
writer = MaybeCreateVideoWriter(output_dump_file_name, config);
|
||||
if (writer) {
|
||||
sinks.push_back(std::make_unique<VideoWriter>(
|
||||
writer, config.output_dump_sampling_modulo));
|
||||
}
|
||||
}
|
||||
if (config.show_on_screen) {
|
||||
sinks.push_back(absl::WrapUnique(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user