From 9e5defcf747a99a757bd6e2f85fa13392819ee0e Mon Sep 17 00:00:00 2001 From: Jianhui Dai Date: Wed, 12 Jul 2023 04:58:09 +0800 Subject: [PATCH] Implement `Y4mFrameGenerator::ChangeResolution()` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This CL implements `ChangeResolution()` to let `Y4mFrameGenerator` generate I420 frame with resolution other than y4m input by scaling. The code is mostly copied from `IvfVideoFrameGenerator`. The test case is also added for this change. Bug: webrtc:15210 Change-Id: I690e427a545a72d93ed39b77fd0f602054a30508 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/311521 Commit-Queue: Jianhui J Dai Reviewed-by: Erik Språng Cr-Commit-Position: refs/heads/main@{#40426} --- test/testsupport/y4m_frame_generator.cc | 21 +++++++++++++++++- test/testsupport/y4m_frame_generator.h | 4 +--- test/testsupport/y4m_frame_generator_test.cc | 23 ++++++++++++++++++++ 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/test/testsupport/y4m_frame_generator.cc b/test/testsupport/y4m_frame_generator.cc index 39a5ad97aa..f1ecbf9b41 100644 --- a/test/testsupport/y4m_frame_generator.cc +++ b/test/testsupport/y4m_frame_generator.cc @@ -59,7 +59,26 @@ Y4mFrameGenerator::VideoFrameData Y4mFrameGenerator::NextFrame() { static_cast(height_)}; rtc::scoped_refptr next_frame_buffer = frame_reader_->PullFrame(); - return VideoFrameData(next_frame_buffer, update_rect); + + if (!next_frame_buffer || + (static_cast(next_frame_buffer->width()) == width_ && + static_cast(next_frame_buffer->height()) == height_)) { + return VideoFrameData(next_frame_buffer, update_rect); + } + + // Allocate a new buffer and return scaled version. + rtc::scoped_refptr scaled_buffer( + I420Buffer::Create(width_, height_)); + webrtc::I420Buffer::SetBlack(scaled_buffer.get()); + scaled_buffer->ScaleFrom(*next_frame_buffer->ToI420()); + return VideoFrameData(scaled_buffer, update_rect); +} + +void Y4mFrameGenerator::ChangeResolution(size_t width, size_t height) { + width_ = width; + height_ = height; + RTC_CHECK_GT(width_, 0); + RTC_CHECK_GT(height_, 0); } FrameGeneratorInterface::Resolution Y4mFrameGenerator::GetResolution() const { diff --git a/test/testsupport/y4m_frame_generator.h b/test/testsupport/y4m_frame_generator.h index bccd109318..4ff64be7dc 100644 --- a/test/testsupport/y4m_frame_generator.h +++ b/test/testsupport/y4m_frame_generator.h @@ -45,9 +45,7 @@ class Y4mFrameGenerator : public FrameGeneratorInterface { VideoFrameData NextFrame() override; - void ChangeResolution(size_t width, size_t height) override { - RTC_CHECK_NOTREACHED(); - } + void ChangeResolution(size_t width, size_t height) override; Resolution GetResolution() const override; diff --git a/test/testsupport/y4m_frame_generator_test.cc b/test/testsupport/y4m_frame_generator_test.cc index 4341c3e3eb..24d10c8992 100644 --- a/test/testsupport/y4m_frame_generator_test.cc +++ b/test/testsupport/y4m_frame_generator_test.cc @@ -82,6 +82,29 @@ TEST_F(Y4mFrameGeneratorTest, CanReadFPSFromFileWhenRoundingIsNeeded) { remove(input_filepath.c_str()); } +TEST_F(Y4mFrameGeneratorTest, CanChangeResolution) { + constexpr int kNewWidth = 4; + constexpr int kNewHeight = 6; + constexpr int kFrameCount = 10; + + Y4mFrameGenerator generator(input_filepath_, + Y4mFrameGenerator::RepeatMode::kLoop); + FrameGeneratorInterface::Resolution res = generator.GetResolution(); + EXPECT_EQ(res.width, 2u); + EXPECT_EQ(res.height, 2u); + + generator.ChangeResolution(kNewWidth, kNewHeight); + res = generator.GetResolution(); + EXPECT_EQ(static_cast(res.width), kNewWidth); + EXPECT_EQ(static_cast(res.height), kNewHeight); + + for (int i = 0; i < kFrameCount; ++i) { + FrameGeneratorInterface::VideoFrameData frame = generator.NextFrame(); + EXPECT_EQ(frame.buffer->width(), kNewWidth); + EXPECT_EQ(frame.buffer->height(), kNewHeight); + } +} + TEST_F(Y4mFrameGeneratorTest, SingleRepeatMode) { Y4mFrameGenerator generator(input_filepath_, Y4mFrameGenerator::RepeatMode::kSingle);