Don't scale frames by default in the IVF generator

Deliver original decoded resolution unless output resolution is explicitly configured via ChangeResolution().

Bug: none
Change-Id: I1d2a47fa564010202762062d7ac483ad3c4effde
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/375340
Reviewed-by: Erik Språng <sprang@webrtc.org>
Commit-Queue: Sergey Silkin <ssilkin@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#43902}
This commit is contained in:
Sergey Silkin 2025-01-25 14:34:53 +01:00 committed by WebRTC LUCI CQ
parent 20bd702ebe
commit fa7c5b6674
3 changed files with 33 additions and 11 deletions

View File

@ -58,8 +58,8 @@ IvfVideoFrameGenerator::IvfVideoFrameGenerator(const Environment& env,
: callback_(this),
file_reader_(IvfFileReader::Create(FileWrapper::OpenReadOnly(file_name))),
video_decoder_(CreateDecoder(env, file_reader_->GetVideoCodecType())),
width_(file_reader_->GetFrameWidth()),
height_(file_reader_->GetFrameHeight()),
original_resolution_({.width = file_reader_->GetFrameWidth(),
.height = file_reader_->GetFrameHeight()}),
fps_hint_(fps_hint) {
RTC_CHECK(video_decoder_) << "No decoder found for file's video codec type";
VideoDecoder::Settings decoder_settings;
@ -110,12 +110,18 @@ FrameGeneratorInterface::VideoFrameData IvfVideoFrameGenerator::NextFrame() {
MutexLock frame_lock(&frame_decode_lock_);
rtc::scoped_refptr<VideoFrameBuffer> buffer =
next_frame_->video_frame_buffer();
if (width_ != static_cast<size_t>(buffer->width()) ||
height_ != static_cast<size_t>(buffer->height())) {
// Set original resolution to resolution of decoded frame.
original_resolution_ = {.width = static_cast<size_t>(buffer->width()),
.height = static_cast<size_t>(buffer->width())};
if (output_resolution_.has_value() &&
(output_resolution_->width != original_resolution_.width ||
output_resolution_->height != original_resolution_.height)) {
// Video adapter has requested a down-scale. Allocate a new buffer and
// return scaled version.
rtc::scoped_refptr<I420Buffer> scaled_buffer =
I420Buffer::Create(width_, height_);
rtc::scoped_refptr<I420Buffer> scaled_buffer = I420Buffer::Create(
output_resolution_->width, output_resolution_->height);
scaled_buffer->ScaleFrom(*buffer->ToI420());
buffer = scaled_buffer;
}
@ -139,13 +145,12 @@ void IvfVideoFrameGenerator::SkipNextFrame() {
void IvfVideoFrameGenerator::ChangeResolution(size_t width, size_t height) {
MutexLock lock(&lock_);
width_ = width;
height_ = height;
output_resolution_ = {.width = width, .height = height};
}
FrameGeneratorInterface::Resolution IvfVideoFrameGenerator::GetResolution()
const {
return {.width = width_, .height = height_};
return output_resolution_.value_or(original_resolution_);
}
int32_t IvfVideoFrameGenerator::DecodedCallback::Decoded(

View File

@ -67,8 +67,13 @@ class IvfVideoFrameGenerator : public FrameGeneratorInterface {
std::unique_ptr<IvfFileReader> file_reader_;
std::unique_ptr<VideoDecoder> video_decoder_;
size_t width_;
size_t height_;
// Resolution of IVF. Initially readed from IVF header and then set to
// resolution of decoded frame.
Resolution original_resolution_;
// Resolution of output frames. When set, the decoded frames scaled to
// `output_resolution_`. Otherwise the decoded resolution, which may vary from
// frame to frame, is preserved.
std::optional<Resolution> output_resolution_;
std::optional<int> fps_hint_;
// This lock is used to ensure that all API method will be called

View File

@ -221,5 +221,17 @@ TEST_F(IvfVideoFrameGeneratorTest, H264) {
}
#endif
TEST_F(IvfVideoFrameGeneratorTest, ScalesResolution) {
CreateTestVideoFile(VideoCodecType::kVideoCodecVP8, CreateVp8Encoder(env_));
IvfVideoFrameGenerator generator(env_, file_name_, /*fps_hint=*/123);
generator.ChangeResolution(kWidth * 2, kHeight / 2);
rtc::scoped_refptr<VideoFrameBuffer> frame_buffer =
generator.NextFrame().buffer;
frame_buffer = generator.NextFrame().buffer;
ASSERT_TRUE(frame_buffer);
EXPECT_EQ(frame_buffer->width(), kWidth * 2);
EXPECT_EQ(frame_buffer->height(), kHeight / 2);
}
} // namespace test
} // namespace webrtc