From c230da0f1bdae5350aec29f2aa2d4a2e10a911a8 Mon Sep 17 00:00:00 2001 From: Danil Chapovalov Date: Fri, 22 Mar 2024 14:54:48 +0100 Subject: [PATCH] In IvfVideoFrameGenerator test helper allow to pass webrtc::Environment at construction To reuse same environment in video encoder and thus avoid creating duplicated environment. Bug: webrtc:15860, b/326933307 Change-Id: I1c56966301a9b453d615c45626407fede2a6d8b5 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/344143 Reviewed-by: Mirko Bonadei Commit-Queue: Danil Chapovalov Cr-Commit-Position: refs/heads/main@{#41956} --- api/BUILD.gn | 8 +++- api/test/create_frame_generator.cc | 11 ++++- api/test/create_frame_generator.h | 11 ++++- rtc_tools/video_encoder/video_encoder.cc | 3 +- test/BUILD.gn | 7 ++- test/testsupport/ivf_video_frame_generator.cc | 48 +++++++++---------- test/testsupport/ivf_video_frame_generator.h | 6 +-- .../ivf_video_frame_generator_unittest.cc | 23 +++++---- 8 files changed, 71 insertions(+), 46 deletions(-) diff --git a/api/BUILD.gn b/api/BUILD.gn index 16a55f36b4..224503fb56 100644 --- a/api/BUILD.gn +++ b/api/BUILD.gn @@ -727,8 +727,14 @@ rtc_library("create_frame_generator") { "../rtc_base:checks", "../system_wrappers", "../test:frame_generator_impl", + "environment", + "environment:environment_factory", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/base:nullability", + "//third_party/abseil-cpp/absl/strings:string_view", + "//third_party/abseil-cpp/absl/types:optional", ] - absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] } rtc_library("create_peer_connection_quality_test_frame_generator") { diff --git a/api/test/create_frame_generator.cc b/api/test/create_frame_generator.cc index 5e6fb3228b..10eb1a8bc0 100644 --- a/api/test/create_frame_generator.cc +++ b/api/test/create_frame_generator.cc @@ -13,6 +13,9 @@ #include #include +#include "absl/base/nullability.h" +#include "absl/strings/string_view.h" +#include "api/environment/environment_factory.h" #include "rtc_base/checks.h" #include "test/frame_generator.h" #include "test/testsupport/ivf_video_frame_generator.h" @@ -66,7 +69,13 @@ std::unique_ptr CreateFromNV12FileFrameGenerator( std::unique_ptr CreateFromIvfFileFrameGenerator( std::string filename) { - return std::make_unique(std::move(filename)); + return CreateFromIvfFileFrameGenerator(CreateEnvironment(), filename); +} + +absl::Nonnull> +CreateFromIvfFileFrameGenerator(const Environment& env, + absl::string_view filename) { + return std::make_unique(env, filename); } std::unique_ptr diff --git a/api/test/create_frame_generator.h b/api/test/create_frame_generator.h index 70be0c4e8e..7ed0828cc5 100644 --- a/api/test/create_frame_generator.h +++ b/api/test/create_frame_generator.h @@ -15,7 +15,10 @@ #include #include +#include "absl/base/nullability.h" +#include "absl/strings/string_view.h" #include "absl/types/optional.h" +#include "api/environment/environment.h" #include "api/test/frame_generator_interface.h" #include "system_wrappers/include/clock.h" @@ -51,8 +54,12 @@ std::unique_ptr CreateFromNV12FileFrameGenerator( int frame_repeat_count = 1); // Creates a frame generator that repeatedly plays an ivf file. -std::unique_ptr CreateFromIvfFileFrameGenerator( - std::string filename); +[[deprecated]] std::unique_ptr +CreateFromIvfFileFrameGenerator(std::string filename); + +absl::Nonnull> +CreateFromIvfFileFrameGenerator(const Environment& env, + absl::string_view filename); // Creates a frame generator which takes a set of yuv files (wrapping a // frame generator created by CreateFromYuvFile() above), but outputs frames diff --git a/rtc_tools/video_encoder/video_encoder.cc b/rtc_tools/video_encoder/video_encoder.cc index 5148752959..53641b7eda 100644 --- a/rtc_tools/video_encoder/video_encoder.cc +++ b/rtc_tools/video_encoder/video_encoder.cc @@ -466,8 +466,7 @@ int main(int argc, char* argv[]) { } else if (!ivf_input_file.empty()) { // Use `IvfFileFrameGenerator` if specify `--ivf_input_file`. frame_buffer_generator = - webrtc::test::CreateFromIvfFileFrameGenerator(ivf_input_file); - RTC_CHECK(frame_buffer_generator); + webrtc::test::CreateFromIvfFileFrameGenerator(env, ivf_input_file); // Set width and height. webrtc::test::FrameGeneratorInterface::Resolution resolution = diff --git a/test/BUILD.gn b/test/BUILD.gn index d98ff0a33d..e786592e4b 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -53,7 +53,7 @@ rtc_library("frame_generator_impl") { "../api:frame_generator_api", "../api:scoped_refptr", "../api:sequence_checker", - "../api/environment:environment_factory", + "../api/environment", "../api/video:encoded_image", "../api/video:video_frame", "../api/video:video_frame_i010", @@ -76,7 +76,10 @@ rtc_library("frame_generator_impl") { "../rtc_base/system:file_wrapper", "../system_wrappers", ] - absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] + absl_deps = [ + "//third_party/abseil-cpp/absl/strings:string_view", + "//third_party/abseil-cpp/absl/types:optional", + ] } rtc_library("y4m_frame_generator") { diff --git a/test/testsupport/ivf_video_frame_generator.cc b/test/testsupport/ivf_video_frame_generator.cc index d2ce215e8b..d951a208f7 100644 --- a/test/testsupport/ivf_video_frame_generator.cc +++ b/test/testsupport/ivf_video_frame_generator.cc @@ -12,7 +12,7 @@ #include -#include "api/environment/environment_factory.h" +#include "api/environment/environment.h" #include "api/video/encoded_image.h" #include "api/video/i420_buffer.h" #include "api/video_codecs/video_codec.h" @@ -31,12 +31,32 @@ namespace { constexpr TimeDelta kMaxNextFrameWaitTimeout = TimeDelta::Seconds(1); +std::unique_ptr CreateDecoder(const Environment& env, + VideoCodecType codec_type) { + switch (codec_type) { + case VideoCodecType::kVideoCodecVP8: + return CreateVp8Decoder(env); + case VideoCodecType::kVideoCodecVP9: + return VP9Decoder::Create(); + case VideoCodecType::kVideoCodecH264: + return H264Decoder::Create(); + case VideoCodecType::kVideoCodecAV1: + return CreateDav1dDecoder(); + case VideoCodecType::kVideoCodecH265: + // TODO: bugs.webrtc.org/13485 - implement H265 decoder + return nullptr; + default: + return nullptr; + } +} + } // namespace -IvfVideoFrameGenerator::IvfVideoFrameGenerator(const std::string& file_name) +IvfVideoFrameGenerator::IvfVideoFrameGenerator(const Environment& env, + absl::string_view file_name) : callback_(this), file_reader_(IvfFileReader::Create(FileWrapper::OpenReadOnly(file_name))), - video_decoder_(CreateVideoDecoder(file_reader_->GetVideoCodecType())), + video_decoder_(CreateDecoder(env, file_reader_->GetVideoCodecType())), width_(file_reader_->GetFrameWidth()), height_(file_reader_->GetFrameHeight()) { RTC_CHECK(video_decoder_) << "No decoder found for file's video codec type"; @@ -135,27 +155,5 @@ void IvfVideoFrameGenerator::OnFrameDecoded(const VideoFrame& decoded_frame) { next_frame_decoded_.Set(); } -std::unique_ptr IvfVideoFrameGenerator::CreateVideoDecoder( - VideoCodecType codec_type) { - if (codec_type == VideoCodecType::kVideoCodecVP8) { - // Use a default environment for the VP8 decoder while there is no use case - // for a propagated environment in this test utility IvfVideoFrameGenerator. - return CreateVp8Decoder(CreateEnvironment()); - } - if (codec_type == VideoCodecType::kVideoCodecVP9) { - return VP9Decoder::Create(); - } - if (codec_type == VideoCodecType::kVideoCodecH264) { - return H264Decoder::Create(); - } - if (codec_type == VideoCodecType::kVideoCodecAV1) { - return CreateDav1dDecoder(); - } - if (codec_type == VideoCodecType::kVideoCodecH265) { - // TODO(bugs.webrtc.org/13485): implement H265 decoder - } - return nullptr; -} - } // namespace test } // namespace webrtc diff --git a/test/testsupport/ivf_video_frame_generator.h b/test/testsupport/ivf_video_frame_generator.h index 6c6fa4951d..7f2d13d048 100644 --- a/test/testsupport/ivf_video_frame_generator.h +++ b/test/testsupport/ivf_video_frame_generator.h @@ -14,7 +14,9 @@ #include #include +#include "absl/strings/string_view.h" #include "absl/types/optional.h" +#include "api/environment/environment.h" #include "api/sequence_checker.h" #include "api/test/frame_generator_interface.h" #include "api/video/video_codec_type.h" @@ -30,7 +32,7 @@ namespace test { // All methods except constructor must be used from the same thread. class IvfVideoFrameGenerator : public FrameGeneratorInterface { public: - explicit IvfVideoFrameGenerator(const std::string& file_name); + IvfVideoFrameGenerator(const Environment& env, absl::string_view file_name); ~IvfVideoFrameGenerator() override; VideoFrameData NextFrame() override; @@ -56,8 +58,6 @@ class IvfVideoFrameGenerator : public FrameGeneratorInterface { }; void OnFrameDecoded(const VideoFrame& decoded_frame); - static std::unique_ptr CreateVideoDecoder( - VideoCodecType codec_type); DecodedCallback callback_; std::unique_ptr file_reader_; diff --git a/test/testsupport/ivf_video_frame_generator_unittest.cc b/test/testsupport/ivf_video_frame_generator_unittest.cc index cac69b4ddf..f55089093b 100644 --- a/test/testsupport/ivf_video_frame_generator_unittest.cc +++ b/test/testsupport/ivf_video_frame_generator_unittest.cc @@ -14,6 +14,8 @@ #include #include "absl/types/optional.h" +#include "api/environment/environment.h" +#include "api/environment/environment_factory.h" #include "api/test/create_frame_generator.h" #include "api/units/time_delta.h" #include "api/video/encoded_image.h" @@ -158,6 +160,7 @@ class IvfVideoFrameGeneratorTest : public ::testing::Test { kMaxFrameEncodeWaitTimeout)); } + Environment env_ = CreateEnvironment(); std::string file_name_; std::vector video_frames_; }; @@ -165,14 +168,14 @@ class IvfVideoFrameGeneratorTest : public ::testing::Test { } // namespace TEST_F(IvfVideoFrameGeneratorTest, DoesNotKnowFps) { - CreateTestVideoFile(VideoCodecType::kVideoCodecVP8, VP8Encoder::Create()); - IvfVideoFrameGenerator generator(file_name_); + CreateTestVideoFile(VideoCodecType::kVideoCodecVP8, CreateVp8Encoder(env_)); + IvfVideoFrameGenerator generator(env_, file_name_); EXPECT_EQ(generator.fps(), absl::nullopt); } TEST_F(IvfVideoFrameGeneratorTest, Vp8) { - CreateTestVideoFile(VideoCodecType::kVideoCodecVP8, VP8Encoder::Create()); - IvfVideoFrameGenerator generator(file_name_); + CreateTestVideoFile(VideoCodecType::kVideoCodecVP8, CreateVp8Encoder(env_)); + IvfVideoFrameGenerator generator(env_, file_name_); for (size_t i = 0; i < video_frames_.size(); ++i) { auto& expected_frame = video_frames_[i]; VideoFrame actual_frame = BuildFrame(generator.NextFrame()); @@ -181,8 +184,8 @@ TEST_F(IvfVideoFrameGeneratorTest, Vp8) { } TEST_F(IvfVideoFrameGeneratorTest, Vp8DoubleRead) { - CreateTestVideoFile(VideoCodecType::kVideoCodecVP8, VP8Encoder::Create()); - IvfVideoFrameGenerator generator(file_name_); + CreateTestVideoFile(VideoCodecType::kVideoCodecVP8, CreateVp8Encoder(env_)); + IvfVideoFrameGenerator generator(env_, file_name_); for (size_t i = 0; i < video_frames_.size() * 2; ++i) { auto& expected_frame = video_frames_[i % video_frames_.size()]; VideoFrame actual_frame = BuildFrame(generator.NextFrame()); @@ -191,8 +194,8 @@ TEST_F(IvfVideoFrameGeneratorTest, Vp8DoubleRead) { } TEST_F(IvfVideoFrameGeneratorTest, Vp9) { - CreateTestVideoFile(VideoCodecType::kVideoCodecVP9, VP9Encoder::Create()); - IvfVideoFrameGenerator generator(file_name_); + CreateTestVideoFile(VideoCodecType::kVideoCodecVP9, CreateVp9Encoder(env_)); + IvfVideoFrameGenerator generator(env_, file_name_); for (size_t i = 0; i < video_frames_.size(); ++i) { auto& expected_frame = video_frames_[i]; VideoFrame actual_frame = BuildFrame(generator.NextFrame()); @@ -202,8 +205,8 @@ TEST_F(IvfVideoFrameGeneratorTest, Vp9) { #if defined(WEBRTC_USE_H264) TEST_F(IvfVideoFrameGeneratorTest, H264) { - CreateTestVideoFile(VideoCodecType::kVideoCodecH264, H264Encoder::Create()); - IvfVideoFrameGenerator generator(file_name_); + CreateTestVideoFile(VideoCodecType::kVideoCodecH264, CreateH264Encoder(env_)); + IvfVideoFrameGenerator generator(env_, file_name_); for (size_t i = 0; i < video_frames_.size(); ++i) { auto& expected_frame = video_frames_[i]; VideoFrame actual_frame = BuildFrame(generator.NextFrame());