/* * Copyright (c) 2016, Alliance for Open Media. All rights reserved. * * This source code is subject to the terms of the BSD 2 Clause License and * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License * was not distributed with this source code in the LICENSE file, you can * obtain it at www.aomedia.org/license/software. If the Alliance for Open * Media Patent License 1.0 was not distributed with this source code in the * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
class ResizeTest
: public ::libaom_test::CodecTestWithParam<libaom_test::TestMode>, public ::libaom_test::EncoderTest { protected:
ResizeTest() : EncoderTest(GET_PARAM(0)) {}
TEST_P(ResizeTest, TestExternalResizeWorks) {
ResizingVideoSource video;
video.flag_codec_ = 0;
video.change_start_resln_ = false;
cfg_.g_lag_in_frames = 0; // We use max(kInitialWidth, kInitialHeight) because during the test // the width and height of the frame are swapped
cfg_.g_forced_max_frame_width = cfg_.g_forced_max_frame_height =
AOMMAX(kInitialWidth, kInitialHeight);
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
#if CONFIG_AV1_DECODER // Check we decoded the same number of frames as we attempted to encode
ASSERT_EQ(frame_info_list_.size(), video.limit());
// q picked such that initial keyframe on this clip is ~30dB PSNR
cfg_.rc_min_quantizer = cfg_.rc_max_quantizer = 48;
// If the number of frames being encoded is smaller than g_lag_in_frames // the encoded frame is unavailable using the current API. Comparing // frames to detect mismatch would then not be possible. Set // g_lag_in_frames = 0 to get around this.
cfg_.g_lag_in_frames = 0;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
info != frame_info_list_.end(); ++info) {
} for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
info != frame_info_list_.end(); ++info) { const aom_codec_pts_t pts = info->pts; if (pts >= kStepDownFrame && pts < kStepUpFrame) {
ASSERT_EQ(282U, info->w) << "Frame " << pts << " had unexpected width";
ASSERT_EQ(173U, info->h) << "Frame " << pts << " had unexpected height";
} else {
EXPECT_EQ(352U, info->w) << "Frame " << pts << " had unexpected width";
EXPECT_EQ(288U, info->h) << "Frame " << pts << " had unexpected height";
}
}
}
void DefaultConfig() {
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_buf_optimal_sz = 600;
cfg_.rc_buf_sz = 1000;
cfg_.rc_min_quantizer = 2;
cfg_.rc_max_quantizer = 56;
cfg_.rc_undershoot_pct = 50;
cfg_.rc_overshoot_pct = 50;
cfg_.rc_end_usage = AOM_CBR;
cfg_.kf_mode = AOM_KF_AUTO;
cfg_.g_lag_in_frames = 0;
cfg_.kf_min_dist = cfg_.kf_max_dist = 3000; // Enable dropped frames.
cfg_.rc_dropframe_thresh = 1; // Disable error_resilience mode.
cfg_.g_error_resilient = 0;
cfg_.g_threads = num_threads_; // Run at low bitrate.
cfg_.rc_target_bitrate = 200; // We use max(kInitialWidth, kInitialHeight) because during the test // the width and height of the frame are swapped
cfg_.g_forced_max_frame_width = cfg_.g_forced_max_frame_height =
AOMMAX(kInitialWidth, kInitialHeight); if (set_scale_mode_ || set_scale_mode2_ || set_scale_mode3_) {
cfg_.rc_dropframe_thresh = 0;
cfg_.g_forced_max_frame_width = 1280;
cfg_.g_forced_max_frame_height = 1280;
}
}
std::vector<FrameInfo> frame_info_list_; int set_cpu_used_; int num_threads_; bool change_bitrate_; unsignedint frame_change_bitrate_; double mismatch_psnr_; int mismatch_nframes_; bool set_scale_mode_; bool set_scale_mode2_; bool set_scale_mode3_; bool is_screen_;
};
// Check the AOME_SET_SCALEMODE control by downsizing to // 1/2, then 1/4, and then back up to originsal.
TEST_P(ResizeRealtimeTest, TestInternalResizeSetScaleMode1) {
::libaom_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60);
cfg_.g_w = 1280;
cfg_.g_h = 720;
set_scale_mode_ = true;
set_scale_mode2_ = false;
set_scale_mode3_ = false;
DefaultConfig();
change_bitrate_ = false;
mismatch_nframes_ = 0;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); #if CONFIG_AV1_DECODER // Check we decoded the same number of frames as we attempted to encode
ASSERT_EQ(frame_info_list_.size(), video.limit()); for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
info != frame_info_list_.end(); ++info) { constauto frame = static_cast<unsigned>(info->pts); unsignedint expected_w = 1280 >> 1; unsignedint expected_h = 720 >> 1; if (frame > 40) {
expected_w = 1280;
expected_h = 720;
} elseif (frame > 20 && frame <= 40) {
expected_w = 1280 >> 2;
expected_h = 720 >> 2;
}
EXPECT_EQ(expected_w, info->w)
<< "Frame " << frame << " had unexpected width";
EXPECT_EQ(expected_h, info->h)
<< "Frame " << frame << " had unexpected height";
EXPECT_EQ(static_cast<unsignedint>(0), GetMismatchFrames());
} #else
printf("Warning: AV1 decoder unavailable, unable to check resize count!\n"); #endif
}
// Check the AOME_SET_SCALEMODE control by downsizing to // 1/2, then 1/4, and then back up to originsal.
TEST_P(ResizeRealtimeTest, TestInternalResizeSetScaleMode1QVGA) {
::libaom_test::I420VideoSource video("desktop1.320_180.yuv", 320, 180, 30, 1,
0, 80);
cfg_.g_w = 320;
cfg_.g_h = 180;
set_scale_mode_ = true;
set_scale_mode2_ = false;
set_scale_mode3_ = false;
DefaultConfig();
change_bitrate_ = false;
mismatch_nframes_ = 0;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); #if CONFIG_AV1_DECODER // Check we decoded the same number of frames as we attempted to encode
ASSERT_EQ(frame_info_list_.size(), video.limit()); for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
info != frame_info_list_.end(); ++info) { constauto frame = static_cast<unsigned>(info->pts); unsignedint expected_w = 320 >> 1; unsignedint expected_h = 180 >> 1; if (frame > 40) {
expected_w = 320;
expected_h = 180;
} elseif (frame > 20 && frame <= 40) {
expected_w = 320 >> 2;
expected_h = 180 >> 2;
}
EXPECT_EQ(expected_w, info->w)
<< "Frame " << frame << " had unexpected width";
EXPECT_EQ(expected_h, info->h)
<< "Frame " << frame << " had unexpected height";
EXPECT_EQ(static_cast<unsignedint>(0), GetMismatchFrames());
} #else
printf("Warning: AV1 decoder unavailable, unable to check resize count!\n"); #endif
}
// Check the AOME_SET_SCALEMODE control by downsizing to // 1/4, then 1/2, and then up to 3/4.
TEST_P(ResizeRealtimeTest, TestInternalResizeSetScaleMode2) {
::libaom_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60);
cfg_.g_w = 1280;
cfg_.g_h = 720;
set_scale_mode_ = false;
set_scale_mode2_ = true;
set_scale_mode3_ = false;
DefaultConfig();
change_bitrate_ = false;
mismatch_nframes_ = 0;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); #if CONFIG_AV1_DECODER // Check we decoded the same number of frames as we attempted to encode
ASSERT_EQ(frame_info_list_.size(), video.limit()); for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
info != frame_info_list_.end(); ++info) { constauto frame = static_cast<unsigned>(info->pts); unsignedint expected_w = 1280 >> 2; unsignedint expected_h = 720 >> 2; if (frame > 40) {
expected_w = (3 * 1280) >> 2;
expected_h = (3 * 720) >> 2;
} elseif (frame > 20 && frame <= 40) {
expected_w = 1280 >> 1;
expected_h = 720 >> 1;
}
EXPECT_EQ(expected_w, info->w)
<< "Frame " << frame << " had unexpected width";
EXPECT_EQ(expected_h, info->h)
<< "Frame " << frame << " had unexpected height";
EXPECT_EQ(static_cast<unsignedint>(0), GetMismatchFrames());
} #else
printf("Warning: AV1 decoder unavailable, unable to check resize count!\n"); #endif
}
// Check the AOME_SET_SCALEMODE control by downsizing to // 1/2 horizontally only and then back up to original.
TEST_P(ResizeRealtimeTest, TestInternalResizeSetScaleMode3) {
::libaom_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60);
cfg_.g_w = 1280;
cfg_.g_h = 720;
set_scale_mode_ = false;
set_scale_mode2_ = false;
set_scale_mode3_ = true;
DefaultConfig();
change_bitrate_ = false;
mismatch_nframes_ = 0;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); #if CONFIG_AV1_DECODER // Check we decoded the same number of frames as we attempted to encode
ASSERT_EQ(frame_info_list_.size(), video.limit()); for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
info != frame_info_list_.end(); ++info) { constauto frame = static_cast<unsigned>(info->pts); unsignedint expected_w = 640; unsignedint expected_h = 720; if (frame > 30) {
expected_w = 1280;
expected_h = 720;
}
EXPECT_EQ(expected_w, info->w)
<< "Frame " << frame << " had unexpected width";
EXPECT_EQ(expected_h, info->h)
<< "Frame " << frame << " had unexpected height";
EXPECT_EQ(static_cast<unsignedint>(0), GetMismatchFrames());
} #else
printf("Warning: AV1 decoder unavailable, unable to check resize count!\n"); #endif
}
TEST_P(ResizeRealtimeTest, TestExternalResizeWorks) {
ResizingVideoSource video;
video.flag_codec_ = 1;
change_bitrate_ = false;
set_scale_mode_ = false;
set_scale_mode2_ = false;
set_scale_mode3_ = false;
mismatch_psnr_ = 0.0;
mismatch_nframes_ = 0;
DefaultConfig(); // Test external resizing with start resolution equal to // 1. kInitialWidth and kInitialHeight // 2. down-scaled kInitialWidth and kInitialHeight for (int i = 0; i < 2; i++) {
video.change_start_resln_ = static_cast<bool>(i);
ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); #if CONFIG_AV1_DECODER // Check we decoded the same number of frames as we attempted to encode
ASSERT_EQ(frame_info_list_.size(), video.limit()); for (constauto &info : frame_info_list_) { constunsignedint frame = static_cast<unsigned>(info.pts); unsignedint expected_w; unsignedint expected_h;
ScaleForFrameNumber(frame, kInitialWidth, kInitialHeight,
video.flag_codec_, video.change_start_resln_,
&expected_w, &expected_h);
EXPECT_EQ(expected_w, info.w)
<< "Frame " << frame << " had unexpected width";
EXPECT_EQ(expected_h, info.h)
<< "Frame " << frame << " had unexpected height";
EXPECT_EQ(static_cast<unsignedint>(0), GetMismatchFrames());
} #else
printf("Warning: AV1 decoder unavailable, unable to check resize count!\n"); #endif
frame_info_list_.clear();
}
}
TEST_P(ResizeRealtimeTest, TestExternalResizeWorksUsePSNR) {
ResizingVideoSource video;
video.flag_codec_ = 1;
change_bitrate_ = false;
set_scale_mode_ = false;
set_scale_mode2_ = false;
set_scale_mode3_ = false;
mismatch_psnr_ = 0.0;
mismatch_nframes_ = 0;
init_flags_ = AOM_CODEC_USE_PSNR;
cfg_.rc_dropframe_thresh = 30;
DefaultConfig(); // Test external resizing with start resolution equal to // 1. kInitialWidth and kInitialHeight // 2. down-scaled kInitialWidth and kInitialHeight for (int i = 0; i < 2; i++) {
video.change_start_resln_ = static_cast<bool>(i);
ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); #if CONFIG_AV1_DECODER // Check we decoded the same number of frames as we attempted to encode
ASSERT_EQ(frame_info_list_.size(), video.limit()); for (constauto &info : frame_info_list_) { constunsignedint frame = static_cast<unsigned>(info.pts); unsignedint expected_w; unsignedint expected_h;
ScaleForFrameNumber(frame, kInitialWidth, kInitialHeight,
video.flag_codec_, video.change_start_resln_,
&expected_w, &expected_h);
EXPECT_EQ(expected_w, info.w)
<< "Frame " << frame << " had unexpected width";
EXPECT_EQ(expected_h, info.h)
<< "Frame " << frame << " had unexpected height";
EXPECT_EQ(static_cast<unsignedint>(0), GetMismatchFrames());
} #else
printf("Warning: AV1 decoder unavailable, unable to check resize count!\n"); #endif
frame_info_list_.clear();
}
}
// Verify the dynamic resizer behavior for real time, 1 pass CBR mode. // Run at low bitrate, with resize_allowed = 1, and verify that we get // one resize down event.
TEST_P(ResizeRealtimeTest, TestInternalResizeDown) {
::libaom_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
0, 400);
cfg_.g_w = 640;
cfg_.g_h = 480;
change_bitrate_ = false;
set_scale_mode_ = false;
set_scale_mode2_ = false;
set_scale_mode3_ = false;
mismatch_psnr_ = 0.0;
mismatch_nframes_ = 0;
DefaultConfig(); // Disable dropped frames.
cfg_.rc_dropframe_thresh = 0; // Starting bitrate low.
cfg_.rc_target_bitrate = 150;
cfg_.rc_resize_mode = RESIZE_DYNAMIC;
cfg_.g_forced_max_frame_width = 1280;
cfg_.g_forced_max_frame_height = 1280;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
#if CONFIG_AV1_DECODER unsignedint last_w = cfg_.g_w; unsignedint last_h = cfg_.g_h; int resize_down_count = 0; for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
info != frame_info_list_.end(); ++info) { if (info->w != last_w || info->h != last_h) { // Verify that resize down occurs. if (info->w < last_w && info->h < last_h) {
resize_down_count++;
}
last_w = info->w;
last_h = info->h;
}
}
// Verify that we get at lease 1 resize down event in this test.
ASSERT_GE(resize_down_count, 1) << "Resizing should occur.";
EXPECT_EQ(static_cast<unsignedint>(0), GetMismatchFrames()); #else
printf("Warning: AV1 decoder unavailable, unable to check resize count!\n"); #endif
}
// Verify the dynamic resizer behavior for real time, 1 pass CBR mode. // Start at low target bitrate, raise the bitrate in the middle of the clip // (at frame# = frame_change_bitrate_), scaling-up should occur after bitrate // is increased.
TEST_P(ResizeRealtimeTest, TestInternalResizeDownUpChangeBitRate) {
::libaom_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
0, 400);
init_flags_ = AOM_CODEC_USE_PSNR;
cfg_.g_w = 640;
cfg_.g_h = 480;
change_bitrate_ = true;
frame_change_bitrate_ = 120;
set_scale_mode_ = false;
set_scale_mode2_ = false;
set_scale_mode3_ = false;
mismatch_psnr_ = 0.0;
mismatch_nframes_ = 0;
DefaultConfig(); // Disable dropped frames.
cfg_.rc_dropframe_thresh = 0; // Starting bitrate low.
cfg_.rc_target_bitrate = 150;
cfg_.rc_resize_mode = RESIZE_DYNAMIC;
cfg_.g_forced_max_frame_width = 1280;
cfg_.g_forced_max_frame_height = 1280;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
#if CONFIG_AV1_DECODER unsignedint last_w = cfg_.g_w; unsignedint last_h = cfg_.g_h; unsignedint frame_number = 0; int resize_down_count = 0; int resize_up_count = 0; for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
info != frame_info_list_.end(); ++info) { if (info->w != last_w || info->h != last_h) { if (frame_number < frame_change_bitrate_) { // Verify that resize down occurs, before bitrate is increased.
ASSERT_LT(info->w, last_w);
ASSERT_LT(info->h, last_h);
resize_down_count++;
} else { // Verify that resize up occurs, after bitrate is increased.
ASSERT_GT(info->w, last_w);
ASSERT_GT(info->h, last_h);
resize_up_count++;
}
last_w = info->w;
last_h = info->h;
}
frame_number++;
}
// Verify that we get at least 2 resize events in this test.
ASSERT_GE(resize_up_count, 1) << "Resizing up should occur at lease once.";
ASSERT_GE(resize_down_count, 1)
<< "Resizing down should occur at lease once.";
EXPECT_EQ(static_cast<unsignedint>(0), GetMismatchFrames()); #else
printf("Warning: AV1 decoder unavailable, unable to check resize count!\n"); #endif
}
// Verify the dynamic resizer behavior for real time, 1 pass CBR mode for // screen content mode. Start at low target bitrate, raise the bitrate in the // middle of the clip (at frame# = frame_change_bitrate_), scaling-up should // occur after bitrate is increased.
TEST_P(ResizeRealtimeTest, TestInternalResizeDownUpChangeBitRateScreen) {
::libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 300);
init_flags_ = AOM_CODEC_USE_PSNR;
cfg_.g_w = 352;
cfg_.g_h = 288;
change_bitrate_ = true;
frame_change_bitrate_ = 120;
set_scale_mode_ = false;
set_scale_mode2_ = false;
set_scale_mode3_ = false;
mismatch_psnr_ = 0.0;
mismatch_nframes_ = 0;
is_screen_ = true;
DefaultConfig(); // Disable dropped frames.
cfg_.rc_dropframe_thresh = 0; // Starting bitrate low.
cfg_.rc_target_bitrate = 100;
cfg_.rc_resize_mode = RESIZE_DYNAMIC;
cfg_.g_forced_max_frame_width = 1280;
cfg_.g_forced_max_frame_height = 1280;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
#if CONFIG_AV1_DECODER unsignedint last_w = cfg_.g_w; unsignedint last_h = cfg_.g_h; unsignedint frame_number = 0; int resize_down_count = 0; for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
info != frame_info_list_.end(); ++info) { if (info->w != last_w || info->h != last_h) { if (frame_number < frame_change_bitrate_) { // Verify that resize down occurs, before bitrate is increased.
ASSERT_LT(info->w, last_w);
ASSERT_LT(info->h, last_h);
resize_down_count++;
}
last_w = info->w;
last_h = info->h;
}
frame_number++;
}
// Verify that we get at least 1 resize event in this test.
ASSERT_GE(resize_down_count, 1)
<< "Resizing down should occur at lease once.";
EXPECT_EQ(static_cast<unsignedint>(0), GetMismatchFrames()); #else
printf("Warning: AV1 decoder unavailable, unable to check resize count!\n"); #endif
}
#if CONFIG_AV1_DECODER // Check we decoded the same number of frames as we attempted to encode
ASSERT_EQ(frame_info_list_.size(), video.limit());
frame_info_list_.clear(); #endif
}
}
#if !CONFIG_REALTIME_ONLY // This class is used to check if there are any fatal // failures while encoding with resize-mode > 0 class ResizeModeTestLarge
: public ::libaom_test::CodecTestWith5Params<libaom_test::TestMode, int, int, int, int>, public ::libaom_test::EncoderTest { protected:
ResizeModeTestLarge()
: EncoderTest(GET_PARAM(0)), encoding_mode_(GET_PARAM(1)),
resize_mode_(GET_PARAM(2)), resize_denominator_(GET_PARAM(3)),
resize_kf_denominator_(GET_PARAM(4)), cpu_used_(GET_PARAM(5)) {}
~ResizeModeTestLarge() override = default;
// A test that reproduces crbug.com/1410766. In realtime usage mode // for SVC with temporal layers, encode frames of sizes 600x600, // 600x600, and 100x480. ASan should report no memory errors.
TEST(ResizeSimpleTest, SmallerFrameSizeSVC) {
constexpr int kWidth = 600;
constexpr int kHeight = 600; // Dummy buffer of zero samples.
constexpr size_t kBufferSize =
kWidth * kHeight + 2 * (kWidth + 1) / 2 * (kHeight + 1) / 2;
std::vector<unsignedchar> buffer(kBufferSize);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.