[PCLF] Introduce export_frame_ids option for video dump
Bug: b/240540206 Change-Id: I2d09be585804aa38b0bbc9e7b34dcd8f91f58846 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/270425 Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org> Commit-Queue: Artem Titov <titovartem@webrtc.org> Cr-Commit-Position: refs/heads/main@{#37675}
This commit is contained in:
parent
4c269322d6
commit
d2209256ab
@ -125,10 +125,19 @@ std::string PeerConnectionE2EQualityTestFixture::VideoSubscription::ToString()
|
||||
|
||||
PeerConnectionE2EQualityTestFixture::VideoDumpOptions::VideoDumpOptions(
|
||||
absl::string_view output_directory,
|
||||
int sampling_modulo)
|
||||
: output_directory_(output_directory), sampling_modulo_(sampling_modulo) {
|
||||
int sampling_modulo,
|
||||
bool export_frame_ids)
|
||||
: output_directory_(output_directory),
|
||||
sampling_modulo_(sampling_modulo),
|
||||
export_frame_ids_(export_frame_ids) {
|
||||
RTC_CHECK_GT(sampling_modulo, 0);
|
||||
}
|
||||
PeerConnectionE2EQualityTestFixture::VideoDumpOptions::VideoDumpOptions(
|
||||
absl::string_view output_directory,
|
||||
bool export_frame_ids)
|
||||
: VideoDumpOptions(output_directory,
|
||||
kDefaultSamplingModulo,
|
||||
export_frame_ids) {}
|
||||
|
||||
std::string
|
||||
PeerConnectionE2EQualityTestFixture::VideoDumpOptions::GetInputDumpFileName(
|
||||
@ -138,6 +147,15 @@ PeerConnectionE2EQualityTestFixture::VideoDumpOptions::GetInputDumpFileName(
|
||||
return test::JoinFilename(output_directory_, file_name.Release());
|
||||
}
|
||||
|
||||
absl::optional<std::string> PeerConnectionE2EQualityTestFixture::
|
||||
VideoDumpOptions::GetInputFrameIdsDumpFileName(
|
||||
absl::string_view stream_label) const {
|
||||
if (!export_frame_ids_) {
|
||||
return absl::nullopt;
|
||||
}
|
||||
return GetInputDumpFileName(stream_label) + ".frame_ids.txt";
|
||||
}
|
||||
|
||||
std::string
|
||||
PeerConnectionE2EQualityTestFixture::VideoDumpOptions::GetOutputDumpFileName(
|
||||
absl::string_view stream_label,
|
||||
@ -147,6 +165,16 @@ PeerConnectionE2EQualityTestFixture::VideoDumpOptions::GetOutputDumpFileName(
|
||||
return test::JoinFilename(output_directory_, file_name.Release());
|
||||
}
|
||||
|
||||
absl::optional<std::string> PeerConnectionE2EQualityTestFixture::
|
||||
VideoDumpOptions::GetOutputFrameIdsDumpFileName(
|
||||
absl::string_view stream_label,
|
||||
absl::string_view receiver) const {
|
||||
if (!export_frame_ids_) {
|
||||
return absl::nullopt;
|
||||
}
|
||||
return GetOutputDumpFileName(stream_label, receiver) + ".frame_ids.txt";
|
||||
}
|
||||
|
||||
PeerConnectionE2EQualityTestFixture::VideoConfig::VideoConfig(
|
||||
const VideoResolution& resolution)
|
||||
: width(resolution.width()),
|
||||
|
||||
@ -219,6 +219,8 @@ class PeerConnectionE2EQualityTestFixture {
|
||||
|
||||
class VideoDumpOptions {
|
||||
public:
|
||||
static constexpr int kDefaultSamplingModulo = 1;
|
||||
|
||||
// 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
|
||||
@ -227,8 +229,16 @@ class PeerConnectionE2EQualityTestFixture {
|
||||
// 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)
|
||||
// export_frame_ids - specifies if frame ids should be exported together
|
||||
// with content of the stream. If true, an output file with the same name as
|
||||
// video dump and suffix ".frame_ids.txt" will be created. It will contain
|
||||
// the frame ids in the same order as original frames in the output
|
||||
// file with stream content. File will contain one frame id per line.
|
||||
// (Default: false)
|
||||
explicit VideoDumpOptions(absl::string_view output_directory,
|
||||
int sampling_modulo = 1);
|
||||
int sampling_modulo = kDefaultSamplingModulo,
|
||||
bool export_frame_ids = false);
|
||||
VideoDumpOptions(absl::string_view output_directory, bool export_frame_ids);
|
||||
|
||||
VideoDumpOptions(const VideoDumpOptions&) = default;
|
||||
VideoDumpOptions& operator=(const VideoDumpOptions&) = default;
|
||||
@ -237,14 +247,25 @@ class PeerConnectionE2EQualityTestFixture {
|
||||
|
||||
std::string output_directory() const { return output_directory_; }
|
||||
int sampling_modulo() const { return sampling_modulo_; }
|
||||
bool export_frame_ids() const { return export_frame_ids_; }
|
||||
|
||||
std::string GetInputDumpFileName(absl::string_view stream_label) const;
|
||||
// Returns file name for input frame ids dump if `export_frame_ids()` is
|
||||
// true, absl::nullopt otherwise.
|
||||
absl::optional<std::string> GetInputFrameIdsDumpFileName(
|
||||
absl::string_view stream_label) const;
|
||||
std::string GetOutputDumpFileName(absl::string_view stream_label,
|
||||
absl::string_view receiver) const;
|
||||
// Returns file name for output frame ids dump if `export_frame_ids()` is
|
||||
// true, absl::nullopt otherwise.
|
||||
absl::optional<std::string> GetOutputFrameIdsDumpFileName(
|
||||
absl::string_view stream_label,
|
||||
absl::string_view receiver) const;
|
||||
|
||||
private:
|
||||
std::string output_directory_;
|
||||
int sampling_modulo_ = 1;
|
||||
bool export_frame_ids_ = false;
|
||||
};
|
||||
|
||||
// Contains properties of single video stream.
|
||||
|
||||
@ -10,6 +10,8 @@
|
||||
|
||||
#include "test/pc/e2e/analyzer/video/video_quality_analyzer_injection_helper.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@ -87,6 +89,46 @@ class AnalyzingFramePreprocessor
|
||||
|
||||
} // namespace
|
||||
|
||||
VideoQualityAnalyzerInjectionHelper::VideoFrameIdsWriter::VideoFrameIdsWriter(
|
||||
absl::string_view file_name)
|
||||
: file_name_(file_name) {
|
||||
output_file_ = fopen(file_name_.c_str(), "wb");
|
||||
RTC_CHECK(output_file_ != nullptr)
|
||||
<< "Failed to open file to dump frame ids for writing: " << file_name_;
|
||||
}
|
||||
|
||||
VideoQualityAnalyzerInjectionHelper::VideoFrameIdsWriter::
|
||||
~VideoFrameIdsWriter() {
|
||||
fclose(output_file_);
|
||||
}
|
||||
|
||||
void VideoQualityAnalyzerInjectionHelper::VideoFrameIdsWriter::WriteFrameId(
|
||||
uint16_t frame_id) {
|
||||
int chars_written = fprintf(output_file_, "%d\n", frame_id);
|
||||
RTC_CHECK_GE(chars_written, 2)
|
||||
<< "Failed to write frame id to the output file: " << file_name_;
|
||||
}
|
||||
|
||||
VideoQualityAnalyzerInjectionHelper::VideoWriter2::VideoWriter2(
|
||||
test::VideoFrameWriter* video_writer,
|
||||
VideoFrameIdsWriter* frame_ids_writer,
|
||||
int sampling_modulo)
|
||||
: video_writer_(video_writer),
|
||||
frame_ids_writer_(frame_ids_writer),
|
||||
sampling_modulo_(sampling_modulo) {}
|
||||
|
||||
void VideoQualityAnalyzerInjectionHelper::VideoWriter2::OnFrame(
|
||||
const VideoFrame& frame) {
|
||||
if (frames_counter_++ % sampling_modulo_ != 0) {
|
||||
return;
|
||||
}
|
||||
bool result = video_writer_->WriteFrame(frame);
|
||||
RTC_CHECK(result) << "Failed to write frame";
|
||||
if (frame_ids_writer_) {
|
||||
frame_ids_writer_->WriteFrameId(frame.id());
|
||||
}
|
||||
}
|
||||
|
||||
VideoQualityAnalyzerInjectionHelper::VideoQualityAnalyzerInjectionHelper(
|
||||
Clock* clock,
|
||||
std::unique_ptr<VideoQualityAnalyzerInterface> analyzer,
|
||||
@ -132,10 +174,19 @@ VideoQualityAnalyzerInjectionHelper::CreateFramePreprocessor(
|
||||
if (config.input_dump_options.has_value()) {
|
||||
// Using new API for video dumping.
|
||||
writer = MaybeCreateVideoWriter(
|
||||
config.input_dump_options->GetInputDumpFileName(peer_name), config);
|
||||
config.input_dump_options->GetInputDumpFileName(*config.stream_label),
|
||||
config);
|
||||
RTC_CHECK(writer);
|
||||
sinks.push_back(std::make_unique<VideoWriter>(
|
||||
writer, config.input_dump_options->sampling_modulo()));
|
||||
VideoFrameIdsWriter* frame_ids_writer = nullptr;
|
||||
if (config.input_dump_options->export_frame_ids()) {
|
||||
frame_ids_writers_.push_back(std::make_unique<VideoFrameIdsWriter>(
|
||||
*config.input_dump_options->GetInputFrameIdsDumpFileName(
|
||||
*config.stream_label)));
|
||||
frame_ids_writer = frame_ids_writers_.back().get();
|
||||
}
|
||||
sinks.push_back(std::make_unique<VideoWriter2>(
|
||||
writer, frame_ids_writer,
|
||||
config.input_dump_options->sampling_modulo()));
|
||||
} else {
|
||||
// Using old API. To be removed.
|
||||
writer = MaybeCreateVideoWriter(config.input_dump_file_name, config);
|
||||
@ -202,6 +253,7 @@ void VideoQualityAnalyzerInjectionHelper::Stop() {
|
||||
video_writer->Close();
|
||||
}
|
||||
video_writers_.clear();
|
||||
frame_ids_writers_.clear();
|
||||
}
|
||||
|
||||
test::VideoFrameWriter*
|
||||
@ -275,8 +327,16 @@ VideoQualityAnalyzerInjectionHelper::PopulateSinks(
|
||||
receiver_stream.stream_label, receiver_stream.peer_name),
|
||||
config);
|
||||
RTC_CHECK(writer);
|
||||
sinks.push_back(std::make_unique<VideoWriter>(
|
||||
writer, config.output_dump_options->sampling_modulo()));
|
||||
VideoFrameIdsWriter* frame_ids_writer = nullptr;
|
||||
if (config.output_dump_options->export_frame_ids()) {
|
||||
frame_ids_writers_.push_back(std::make_unique<VideoFrameIdsWriter>(
|
||||
*config.output_dump_options->GetOutputFrameIdsDumpFileName(
|
||||
receiver_stream.stream_label, receiver_stream.peer_name)));
|
||||
frame_ids_writer = frame_ids_writers_.back().get();
|
||||
}
|
||||
sinks.push_back(std::make_unique<VideoWriter2>(
|
||||
writer, frame_ids_writer,
|
||||
config.output_dump_options->sampling_modulo()));
|
||||
} else {
|
||||
// Using old API. To be removed.
|
||||
absl::optional<std::string> output_dump_file_name =
|
||||
|
||||
@ -11,6 +11,8 @@
|
||||
#ifndef TEST_PC_E2E_ANALYZER_VIDEO_VIDEO_QUALITY_ANALYZER_INJECTION_HELPER_H_
|
||||
#define TEST_PC_E2E_ANALYZER_VIDEO_VIDEO_QUALITY_ANALYZER_INJECTION_HELPER_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@ -131,6 +133,35 @@ class VideoQualityAnalyzerInjectionHelper : public StatsObserverInterface {
|
||||
}
|
||||
};
|
||||
|
||||
class VideoFrameIdsWriter {
|
||||
public:
|
||||
explicit VideoFrameIdsWriter(absl::string_view file_name);
|
||||
~VideoFrameIdsWriter();
|
||||
|
||||
void WriteFrameId(uint16_t frame_id);
|
||||
|
||||
private:
|
||||
const std::string file_name_;
|
||||
FILE* output_file_;
|
||||
};
|
||||
|
||||
class VideoWriter2 final : public rtc::VideoSinkInterface<VideoFrame> {
|
||||
public:
|
||||
VideoWriter2(test::VideoFrameWriter* video_writer,
|
||||
VideoFrameIdsWriter* frame_ids_writer,
|
||||
int sampling_modulo);
|
||||
~VideoWriter2() override = default;
|
||||
|
||||
void OnFrame(const VideoFrame& frame) override;
|
||||
|
||||
private:
|
||||
test::VideoFrameWriter* const video_writer_;
|
||||
VideoFrameIdsWriter* const frame_ids_writer_;
|
||||
const int sampling_modulo_;
|
||||
|
||||
int64_t frames_counter_ = 0;
|
||||
};
|
||||
|
||||
test::VideoFrameWriter* MaybeCreateVideoWriter(
|
||||
absl::optional<std::string> file_name,
|
||||
const PeerConnectionE2EQualityTestFixture::VideoConfig& config);
|
||||
@ -146,6 +177,7 @@ class VideoQualityAnalyzerInjectionHelper : public StatsObserverInterface {
|
||||
EncodedImageDataExtractor* extractor_;
|
||||
|
||||
std::vector<std::unique_ptr<test::VideoFrameWriter>> video_writers_;
|
||||
std::vector<std::unique_ptr<VideoFrameIdsWriter>> frame_ids_writers_;
|
||||
|
||||
Mutex mutex_;
|
||||
int peers_count_ RTC_GUARDED_BY(mutex_);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user