From 6b750587746475b4bb8b8f95d63d47ec764efa63 Mon Sep 17 00:00:00 2001 From: Artem Titov Date: Tue, 11 Oct 2022 10:16:22 +0200 Subject: [PATCH] [PCLF] Extract video dumping from video_quality_analyzer_injection_helper for testability Bug: b/240540204 Change-Id: I7f5970fae2b1472b37ea5fd5cbb16b2ce25dd968 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/278622 Reviewed-by: Mirko Bonadei Commit-Queue: Artem Titov Cr-Commit-Position: refs/heads/main@{#38347} --- test/pc/e2e/BUILD.gn | 36 +++ test/pc/e2e/analyzer/video/video_dumping.cc | 121 ++++++++++ test/pc/e2e/analyzer/video/video_dumping.h | 58 +++++ .../e2e/analyzer/video/video_dumping_test.cc | 227 ++++++++++++++++++ ...video_quality_analyzer_injection_helper.cc | 114 +-------- .../video_quality_analyzer_injection_helper.h | 32 --- 6 files changed, 455 insertions(+), 133 deletions(-) create mode 100644 test/pc/e2e/analyzer/video/video_dumping.cc create mode 100644 test/pc/e2e/analyzer/video/video_dumping.h create mode 100644 test/pc/e2e/analyzer/video/video_dumping_test.cc diff --git a/test/pc/e2e/BUILD.gn b/test/pc/e2e/BUILD.gn index ddcf9c98db..4c07f4320f 100644 --- a/test/pc/e2e/BUILD.gn +++ b/test/pc/e2e/BUILD.gn @@ -44,6 +44,7 @@ if (!build_with_chromium) { ":peer_connection_quality_test_metric_names_test", ":single_process_encoded_image_data_injector_unittest", ":stats_poller_test", + ":video_dumping_test", ":video_frame_tracking_id_injector_unittest", ] } @@ -177,6 +178,40 @@ if (!build_with_chromium) { } if (rtc_include_tests) { + rtc_library("video_dumping") { + testonly = true + sources = [ + "analyzer/video/video_dumping.cc", + "analyzer/video/video_dumping.h", + ] + deps = [ + "../..:video_test_support", + "../../../api:peer_connection_quality_test_fixture_api", + "../../../api/video:video_frame", + "../../../system_wrappers", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] + } + + rtc_library("video_dumping_test") { + testonly = true + sources = [ "analyzer/video/video_dumping_test.cc" ] + deps = [ + ":video_dumping", + "../..:fileutils", + "../..:test_support", + "../..:video_test_support", + "../../../api:peer_connection_quality_test_fixture_api", + "../../../api:scoped_refptr", + "../../../api/video:video_frame", + "../../../rtc_base:random", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] + } + rtc_library("video_quality_analyzer_injection_helper") { visibility = [ "*" ] testonly = true @@ -189,6 +224,7 @@ if (!build_with_chromium) { ":quality_analyzing_video_decoder", ":quality_analyzing_video_encoder", ":simulcast_dummy_buffer_helper", + ":video_dumping", "../..:fixed_fps_video_frame_writer_adapter", "../..:test_renderer", "../../../api:array_view", diff --git a/test/pc/e2e/analyzer/video/video_dumping.cc b/test/pc/e2e/analyzer/video/video_dumping.cc new file mode 100644 index 0000000000..f06e84742b --- /dev/null +++ b/test/pc/e2e/analyzer/video/video_dumping.cc @@ -0,0 +1,121 @@ +/* + * 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. + */ +#include "test/pc/e2e/analyzer/video/video_dumping.h" + +#include + +#include +#include +#include +#include + +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" +#include "api/test/peerconnection_quality_test_fixture.h" +#include "api/video/video_frame.h" +#include "system_wrappers/include/clock.h" +#include "test/testsupport/video_frame_writer.h" + +namespace webrtc { +namespace webrtc_pc_e2e { +namespace { + +class VideoFrameIdsWriter final : public test::VideoFrameWriter { + public: + explicit 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_; + } + ~VideoFrameIdsWriter() override { Close(); } + + bool WriteFrame(const VideoFrame& frame) override { + RTC_CHECK(output_file_ != nullptr) << "Writer is already closed"; + int chars_written = fprintf(output_file_, "%d\n", frame.id()); + if (chars_written < 2) { + RTC_LOG(LS_ERROR) << "Failed to write frame id to the output file: " + << file_name_; + return false; + } + return true; + } + + void Close() override { + if (output_file_ != nullptr) { + fclose(output_file_); + output_file_ = nullptr; + } + } + + private: + const std::string file_name_; + FILE* output_file_; +}; + +// Broadcast received frame to multiple underlying frame writers. +class BroadcastingFrameWriter final : public test::VideoFrameWriter { + public: + explicit BroadcastingFrameWriter( + std::vector> delegates) + : delegates_(std::move(delegates)) {} + ~BroadcastingFrameWriter() override { Close(); } + + bool WriteFrame(const webrtc::VideoFrame& frame) override { + for (auto& delegate : delegates_) { + if (!delegate->WriteFrame(frame)) { + return false; + } + } + return true; + } + + void Close() override { + for (auto& delegate : delegates_) { + delegate->Close(); + } + } + + private: + std::vector> delegates_; +}; + +} // namespace + +VideoWriter::VideoWriter(test::VideoFrameWriter* video_writer, + int sampling_modulo) + : video_writer_(video_writer), sampling_modulo_(sampling_modulo) {} + +void VideoWriter::OnFrame(const VideoFrame& frame) { + if (frames_counter_++ % sampling_modulo_ != 0) { + return; + } + bool result = video_writer_->WriteFrame(frame); + RTC_CHECK(result) << "Failed to write frame"; +} + +std::unique_ptr CreateVideoFrameWriter( + absl::string_view file_name, + absl::optional frame_ids_dump_file_name, + const PeerConnectionE2EQualityTestFixture::VideoResolution& resolution) { + std::vector> requested_writers; + requested_writers.push_back(std::make_unique( + std::string(file_name), resolution.width(), resolution.height(), + resolution.fps())); + if (frame_ids_dump_file_name.has_value()) { + requested_writers.push_back( + std::make_unique(*frame_ids_dump_file_name)); + } + return std::make_unique( + std::move(requested_writers)); +} + +} // namespace webrtc_pc_e2e +} // namespace webrtc diff --git a/test/pc/e2e/analyzer/video/video_dumping.h b/test/pc/e2e/analyzer/video/video_dumping.h new file mode 100644 index 0000000000..8cd8762304 --- /dev/null +++ b/test/pc/e2e/analyzer/video/video_dumping.h @@ -0,0 +1,58 @@ +/* + * 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_PC_E2E_ANALYZER_VIDEO_VIDEO_DUMPING_H_ +#define TEST_PC_E2E_ANALYZER_VIDEO_VIDEO_DUMPING_H_ + +#include +#include + +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" +#include "api/test/peerconnection_quality_test_fixture.h" +#include "api/video/video_frame.h" +#include "api/video/video_sink_interface.h" +#include "test/testsupport/video_frame_writer.h" + +namespace webrtc { +namespace webrtc_pc_e2e { + +// `VideoSinkInterface` to dump incoming video frames into specified video +// writer. +class VideoWriter final : public rtc::VideoSinkInterface { + public: + // Creates video writer. Caller keeps ownership of `video_writer` and is + // responsible for closing it after VideoWriter will be destroyed. + VideoWriter(test::VideoFrameWriter* video_writer, int sampling_modulo); + VideoWriter(const VideoWriter&) = delete; + VideoWriter& operator=(const VideoWriter&) = delete; + ~VideoWriter() override = default; + + void OnFrame(const VideoFrame& frame) override; + + private: + test::VideoFrameWriter* const video_writer_; + const int sampling_modulo_; + + int64_t frames_counter_ = 0; +}; + +// Creates a `VideoFrameWriter` to dump video frames into the specified file +// `file_name`. If `frame_ids_dump_file_name` is specified then created writer +// will also log ids of those frames into the specified file. +std::unique_ptr CreateVideoFrameWriter( + absl::string_view file_name, + absl::optional frame_ids_dump_file_name, + const PeerConnectionE2EQualityTestFixture::VideoResolution& resolution); + +} // namespace webrtc_pc_e2e +} // namespace webrtc + +#endif // TEST_PC_E2E_ANALYZER_VIDEO_VIDEO_DUMPING_H_ diff --git a/test/pc/e2e/analyzer/video/video_dumping_test.cc b/test/pc/e2e/analyzer/video/video_dumping_test.cc new file mode 100644 index 0000000000..0047981ad3 --- /dev/null +++ b/test/pc/e2e/analyzer/video/video_dumping_test.cc @@ -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. + */ +#include "test/pc/e2e/analyzer/video/video_dumping.h" + +#include + +#include +#include +#include + +#include "absl/types/optional.h" +#include "api/scoped_refptr.h" +#include "api/test/peerconnection_quality_test_fixture.h" +#include "api/video/i420_buffer.h" +#include "api/video/video_frame.h" +#include "api/video/video_frame_buffer.h" +#include "rtc_base/random.h" +#include "test/gmock.h" +#include "test/gtest.h" +#include "test/testsupport/file_utils.h" +#include "test/testsupport/frame_reader.h" +#include "test/testsupport/video_frame_writer.h" + +namespace webrtc { +namespace webrtc_pc_e2e { +namespace { + +using ::testing::ElementsAreArray; +using ::testing::Eq; +using ::testing::Test; + +using VideoResolution = ::webrtc::webrtc_pc_e2e:: + PeerConnectionE2EQualityTestFixture::VideoResolution; + +uint8_t RandByte(Random& random) { + return random.Rand(255); +} + +VideoFrame CreateRandom2x2VideoFrame(uint16_t id, Random& random) { + rtc::scoped_refptr buffer = I420Buffer::Create(2, 2); + + uint8_t data[6] = {RandByte(random), RandByte(random), RandByte(random), + RandByte(random), RandByte(random), RandByte(random)}; + + memcpy(buffer->MutableDataY(), data, 2); + memcpy(buffer->MutableDataY() + buffer->StrideY(), data + 2, 2); + memcpy(buffer->MutableDataU(), data + 4, 1); + memcpy(buffer->MutableDataV(), data + 5, 1); + + return VideoFrame::Builder() + .set_id(id) + .set_video_frame_buffer(buffer) + .set_timestamp_us(1) + .build(); +} + +std::vector AsVector(const uint8_t* data, size_t size) { + std::vector out; + out.assign(data, data + size); + return out; +} + +void AssertFramesEqual(rtc::scoped_refptr actual, + rtc::scoped_refptr expected) { + ASSERT_THAT(actual->width(), Eq(expected->width())); + ASSERT_THAT(actual->height(), Eq(expected->height())); + rtc::scoped_refptr expected_i420 = + expected->ToI420(); + + int height = actual->height(); + + EXPECT_THAT(AsVector(actual->DataY(), actual->StrideY() * height), + ElementsAreArray(expected_i420->DataY(), + expected_i420->StrideY() * height)); + EXPECT_THAT(AsVector(actual->DataU(), actual->StrideU() * (height + 1) / 2), + ElementsAreArray(expected_i420->DataU(), + expected_i420->StrideU() * (height + 1) / 2)); + EXPECT_THAT(AsVector(actual->DataV(), actual->StrideV() * (height + 1) / 2), + ElementsAreArray(expected_i420->DataV(), + expected_i420->StrideV() * (height + 1) / 2)); +} + +void AssertFrameIdsAre(const std::string& filename, + std::vector expected_ids) { + FILE* file = fopen(filename.c_str(), "r"); + ASSERT_TRUE(file != nullptr); + std::vector actual_ids; + char buffer[8]; + while (fgets(buffer, sizeof buffer, file) != nullptr) { + std::string current_id(buffer); + ASSERT_GE(current_id.size(), 2lu); + // Trim "\n" at the end. + actual_ids.push_back(current_id.substr(0, current_id.size() - 1)); + } + EXPECT_THAT(actual_ids, ElementsAreArray(expected_ids)); +} + +class VideoDumpingTest : public Test { + protected: + ~VideoDumpingTest() override = default; + + void SetUp() override { + video_filename_ = webrtc::test::TempFilename(webrtc::test::OutputPath(), + "video_dumping_test"); + ids_filename_ = webrtc::test::TempFilename(webrtc::test::OutputPath(), + "video_dumping_test"); + } + + void TearDown() override { + remove(video_filename_.c_str()); + remove(ids_filename_.c_str()); + } + + std::string video_filename_; + std::string ids_filename_; +}; + +using CreateVideoFrameWriterTest = VideoDumpingTest; + +TEST_F(CreateVideoFrameWriterTest, VideoIsWritenCorrectly) { + Random random(/*seed=*/100); + VideoFrame frame1 = CreateRandom2x2VideoFrame(1, random); + VideoFrame frame2 = CreateRandom2x2VideoFrame(2, random); + + std::unique_ptr writer = CreateVideoFrameWriter( + video_filename_, + /*frame_ids_dump_file_name=*/absl::nullopt, + VideoResolution(/*width=*/2, /*height=*/2, /*fps=*/2)); + + ASSERT_TRUE(writer->WriteFrame(frame1)); + ASSERT_TRUE(writer->WriteFrame(frame2)); + writer->Close(); + + test::Y4mFrameReaderImpl frame_reader(video_filename_, /*width=*/2, + /*height=*/2); + ASSERT_TRUE(frame_reader.Init()); + EXPECT_THAT(frame_reader.NumberOfFrames(), Eq(2)); + AssertFramesEqual(frame_reader.ReadFrame(), frame1.video_frame_buffer()); + AssertFramesEqual(frame_reader.ReadFrame(), frame2.video_frame_buffer()); +} + +TEST_F(CreateVideoFrameWriterTest, VideoIsWritenWithFrameIds) { + Random random(/*seed=*/100); + VideoFrame frame1 = CreateRandom2x2VideoFrame(1, random); + VideoFrame frame2 = CreateRandom2x2VideoFrame(2, random); + + std::unique_ptr writer = CreateVideoFrameWriter( + video_filename_, ids_filename_, + VideoResolution(/*width=*/2, /*height=*/2, /*fps=*/2)); + + ASSERT_TRUE(writer->WriteFrame(frame1)); + ASSERT_TRUE(writer->WriteFrame(frame2)); + writer->Close(); + + test::Y4mFrameReaderImpl frame_reader(video_filename_, /*width=*/2, + /*height=*/2); + ASSERT_TRUE(frame_reader.Init()); + EXPECT_THAT(frame_reader.NumberOfFrames(), Eq(2)); + AssertFramesEqual(frame_reader.ReadFrame(), frame1.video_frame_buffer()); + AssertFramesEqual(frame_reader.ReadFrame(), frame2.video_frame_buffer()); + AssertFrameIdsAre(ids_filename_, {"1", "2"}); +} + +using VideoWriterTest = VideoDumpingTest; + +TEST_F(VideoWriterTest, AllFramesAreWrittenWithSamplingModulo1) { + Random random(/*seed=*/100); + VideoFrame frame1 = CreateRandom2x2VideoFrame(1, random); + VideoFrame frame2 = CreateRandom2x2VideoFrame(2, random); + + { + std::unique_ptr frame_writer = + CreateVideoFrameWriter( + video_filename_, /*frame_ids_dump_file_name=*/absl::nullopt, + VideoResolution(/*width=*/2, /*height=*/2, /*fps=*/2)); + VideoWriter writer(frame_writer.get(), /*sampling_modulo=*/1); + + writer.OnFrame(frame1); + writer.OnFrame(frame2); + frame_writer->Close(); + } + + test::Y4mFrameReaderImpl frame_reader(video_filename_, /*width=*/2, + /*height=*/2); + ASSERT_TRUE(frame_reader.Init()); + EXPECT_THAT(frame_reader.NumberOfFrames(), Eq(2)); + AssertFramesEqual(frame_reader.ReadFrame(), frame1.video_frame_buffer()); + AssertFramesEqual(frame_reader.ReadFrame(), frame2.video_frame_buffer()); +} + +TEST_F(VideoWriterTest, OnlyEvery2ndFramesIsWrittenWithSamplingModulo2) { + Random random(/*seed=*/100); + VideoFrame frame1 = CreateRandom2x2VideoFrame(1, random); + VideoFrame frame2 = CreateRandom2x2VideoFrame(2, random); + VideoFrame frame3 = CreateRandom2x2VideoFrame(3, random); + + { + std::unique_ptr frame_writer = + CreateVideoFrameWriter( + video_filename_, /*frame_ids_dump_file_name=*/absl::nullopt, + VideoResolution(/*width=*/2, /*height=*/2, /*fps=*/2)); + VideoWriter writer(frame_writer.get(), /*sampling_modulo=*/2); + + writer.OnFrame(frame1); + writer.OnFrame(frame2); + writer.OnFrame(frame3); + frame_writer->Close(); + } + + test::Y4mFrameReaderImpl frame_reader(video_filename_, /*width=*/2, + /*height=*/2); + ASSERT_TRUE(frame_reader.Init()); + EXPECT_THAT(frame_reader.NumberOfFrames(), Eq(2)); + AssertFramesEqual(frame_reader.ReadFrame(), frame1.video_frame_buffer()); + AssertFramesEqual(frame_reader.ReadFrame(), frame3.video_frame_buffer()); +} + +} // namespace +} // namespace webrtc_pc_e2e +} // namespace webrtc diff --git a/test/pc/e2e/analyzer/video/video_quality_analyzer_injection_helper.cc b/test/pc/e2e/analyzer/video/video_quality_analyzer_injection_helper.cc index 8232ac2076..6114dd5a44 100644 --- a/test/pc/e2e/analyzer/video/video_quality_analyzer_injection_helper.cc +++ b/test/pc/e2e/analyzer/video/video_quality_analyzer_injection_helper.cc @@ -26,6 +26,7 @@ #include "test/pc/e2e/analyzer/video/quality_analyzing_video_decoder.h" #include "test/pc/e2e/analyzer/video/quality_analyzing_video_encoder.h" #include "test/pc/e2e/analyzer/video/simulcast_dummy_buffer_helper.h" +#include "test/pc/e2e/analyzer/video/video_dumping.h" #include "test/testsupport/fixed_fps_video_frame_writer_adapter.h" #include "test/video_renderer.h" @@ -71,76 +72,8 @@ class AnalyzingFramePreprocessor sinks_; }; -// Broadcast received frame to multiple underlying frame writers. -class BroadcastingFrameWriter final : public test::VideoFrameWriter { - public: - explicit BroadcastingFrameWriter( - std::vector> delegates) - : delegates_(std::move(delegates)) {} - ~BroadcastingFrameWriter() override { Close(); } - - bool WriteFrame(const webrtc::VideoFrame& frame) override { - for (auto& delegate : delegates_) { - if (!delegate->WriteFrame(frame)) { - return false; - } - } - return true; - } - - void Close() override { - for (auto& delegate : delegates_) { - delegate->Close(); - } - } - - private: - std::vector> delegates_; -}; - } // 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_; -} - -bool VideoQualityAnalyzerInjectionHelper::VideoFrameIdsWriter::WriteFrame( - const VideoFrame& frame) { - RTC_CHECK(output_file_ != nullptr) << "Writer is already closed"; - int chars_written = fprintf(output_file_, "%d\n", frame.id()); - if (chars_written < 2) { - RTC_LOG(LS_ERROR) << "Failed to write frame id to the output file: " - << file_name_; - return false; - } - return true; -} - -void VideoQualityAnalyzerInjectionHelper::VideoFrameIdsWriter::Close() { - if (output_file_ != nullptr) { - fclose(output_file_); - output_file_ = nullptr; - } -} - -VideoQualityAnalyzerInjectionHelper::VideoWriter::VideoWriter( - test::VideoFrameWriter* video_writer, - int sampling_modulo) - : video_writer_(video_writer), sampling_modulo_(sampling_modulo) {} - -void VideoQualityAnalyzerInjectionHelper::VideoWriter::OnFrame( - const VideoFrame& frame) { - if (frames_counter_++ % sampling_modulo_ != 0) { - return; - } - bool result = video_writer_->WriteFrame(frame); - RTC_CHECK(result) << "Failed to write frame"; -} - VideoQualityAnalyzerInjectionHelper::VideoQualityAnalyzerInjectionHelper( Clock* clock, std::unique_ptr analyzer, @@ -181,15 +114,15 @@ VideoQualityAnalyzerInjectionHelper::CreateFramePreprocessor( absl::string_view peer_name, const VideoConfig& config) { std::vector>> sinks; - test::VideoFrameWriter* writer = nullptr; if (config.input_dump_options.has_value()) { - writer = CreateVideoWriter( + std::unique_ptr writer = CreateVideoFrameWriter( config.input_dump_options->GetInputDumpFileName(*config.stream_label), config.input_dump_options->GetInputFrameIdsDumpFileName( *config.stream_label), - config); + config.GetResolution()); sinks.push_back(std::make_unique( - writer, config.input_dump_options->sampling_modulo())); + writer.get(), config.input_dump_options->sampling_modulo())); + video_writers_.push_back(std::move(writer)); } if (config.show_on_screen) { sinks.push_back(absl::WrapUnique( @@ -251,31 +184,6 @@ void VideoQualityAnalyzerInjectionHelper::Stop() { video_writers_.clear(); } -test::VideoFrameWriter* VideoQualityAnalyzerInjectionHelper::CreateVideoWriter( - absl::string_view file_name, - absl::optional frame_ids_dump_file_name, - const PeerConnectionE2EQualityTestFixture::VideoConfig& config) { - // TODO(titovartem) create only one file writer for simulcast video track. - // For now this code will be invoked for each simulcast stream separately, but - // only one file will be used. - std::vector> requested_writers; - requested_writers.push_back(std::make_unique( - std::string(file_name), config.width, config.height, config.fps)); - if (frame_ids_dump_file_name.has_value()) { - requested_writers.push_back( - std::make_unique(*frame_ids_dump_file_name)); - } - std::unique_ptr video_writer = - std::make_unique(std::move(requested_writers)); - if (config.output_dump_use_fixed_framerate) { - video_writer = std::make_unique( - config.fps, clock_, std::move(video_writer)); - } - test::VideoFrameWriter* out = video_writer.get(); - video_writers_.push_back(std::move(video_writer)); - return out; -} - void VideoQualityAnalyzerInjectionHelper::OnFrame(absl::string_view peer_name, const VideoFrame& frame) { rtc::scoped_refptr i420_buffer = @@ -317,16 +225,20 @@ VideoQualityAnalyzerInjectionHelper::PopulateSinks( const VideoConfig& config = it->second; std::vector>> sinks; - test::VideoFrameWriter* writer = nullptr; if (config.output_dump_options.has_value()) { - writer = CreateVideoWriter( + std::unique_ptr writer = CreateVideoFrameWriter( config.output_dump_options->GetOutputDumpFileName( receiver_stream.stream_label, receiver_stream.peer_name), config.output_dump_options->GetOutputFrameIdsDumpFileName( receiver_stream.stream_label, receiver_stream.peer_name), - config); + config.GetResolution()); + if (config.output_dump_use_fixed_framerate) { + writer = std::make_unique( + config.fps, clock_, std::move(writer)); + } sinks.push_back(std::make_unique( - writer, config.output_dump_options->sampling_modulo())); + writer.get(), config.output_dump_options->sampling_modulo())); + video_writers_.push_back(std::move(writer)); } if (config.show_on_screen) { sinks.push_back(absl::WrapUnique( diff --git a/test/pc/e2e/analyzer/video/video_quality_analyzer_injection_helper.h b/test/pc/e2e/analyzer/video/video_quality_analyzer_injection_helper.h index e91b855ffc..3eee5a0566 100644 --- a/test/pc/e2e/analyzer/video/video_quality_analyzer_injection_helper.h +++ b/test/pc/e2e/analyzer/video/video_quality_analyzer_injection_helper.h @@ -134,38 +134,6 @@ class VideoQualityAnalyzerInjectionHelper : public StatsObserverInterface { } }; - class VideoFrameIdsWriter final : public test::VideoFrameWriter { - public: - explicit VideoFrameIdsWriter(absl::string_view file_name); - ~VideoFrameIdsWriter() { Close(); } - - bool WriteFrame(const VideoFrame& frame) override; - - void Close() override; - - private: - const std::string file_name_; - FILE* output_file_; - }; - - class VideoWriter final : public rtc::VideoSinkInterface { - public: - VideoWriter(test::VideoFrameWriter* video_writer, int sampling_modulo); - ~VideoWriter() override = default; - - void OnFrame(const VideoFrame& frame) override; - - private: - test::VideoFrameWriter* const video_writer_; - const int sampling_modulo_; - - int64_t frames_counter_ = 0; - }; - - test::VideoFrameWriter* CreateVideoWriter( - absl::string_view file_name, - absl::optional frame_ids_dump_file_name, - const PeerConnectionE2EQualityTestFixture::VideoConfig& config); // Creates a deep copy of the frame and passes it to the video analyzer, while // passing real frame to the sinks void OnFrame(absl::string_view peer_name, const VideoFrame& frame);