Misc. resize fixes along with the resize test
Re-enables most of the previously disabled tests.
The ones that are still disabled expect resize to be triggered
through rate control, which is no longer supported in Av1.
Change-Id: Ie5e9ba3eb0843cd44ff1ac988500081470ba0fe2
diff --git a/av1/common/alloccommon.c b/av1/common/alloccommon.c
index 357543e..fe22667 100644
--- a/av1/common/alloccommon.c
+++ b/av1/common/alloccommon.c
@@ -91,6 +91,7 @@
if (!cm->frame_parallel_decode) {
cm->last_frame_seg_map = NULL;
}
+ cm->seg_map_alloc_size = 0;
}
void av1_free_ref_frame_buffers(BufferPool *pool) {
@@ -155,6 +156,7 @@
}
aom_free(cm->above_seg_context);
cm->above_seg_context = NULL;
+ cm->above_context_alloc_cols = 0;
#if CONFIG_VAR_TX
aom_free(cm->above_txfm_context);
cm->above_txfm_context = NULL;
diff --git a/av1/encoder/aq_cyclicrefresh.c b/av1/encoder/aq_cyclicrefresh.c
index 5f595d5..8f61c7e 100644
--- a/av1/encoder/aq_cyclicrefresh.c
+++ b/av1/encoder/aq_cyclicrefresh.c
@@ -397,6 +397,7 @@
// Set the segmentation map: cycle through the superblocks, starting at
// cr->mb_index, and stopping when either block_count blocks have been found
// to be refreshed, or we have passed through whole frame.
+ if (cr->sb_index >= sbs_in_frame) cr->sb_index = 0;
assert(cr->sb_index < sbs_in_frame);
i = cr->sb_index;
cr->target_num_seg_blocks = 0;
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 9787097..9e2f96c 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -425,6 +425,7 @@
cm->mi_grid_base = NULL;
aom_free(cm->prev_mi_grid_base);
cm->prev_mi_grid_base = NULL;
+ cm->mi_alloc_size = 0;
}
static void swap_mi_and_prev_mi(AV1_COMMON *cm) {
@@ -465,11 +466,26 @@
}
}
+static void dealloc_context_buffers_ext(AV1_COMP *cpi) {
+ if (cpi->mbmi_ext_base) {
+ aom_free(cpi->mbmi_ext_base);
+ cpi->mbmi_ext_base = NULL;
+ }
+}
+
+static void alloc_context_buffers_ext(AV1_COMP *cpi) {
+ AV1_COMMON *cm = &cpi->common;
+ int mi_size = cm->mi_cols * cm->mi_rows;
+
+ dealloc_context_buffers_ext(cpi);
+ CHECK_MEM_ERROR(cm, cpi->mbmi_ext_base,
+ aom_calloc(mi_size, sizeof(*cpi->mbmi_ext_base)));
+}
+
static void dealloc_compressor_data(AV1_COMP *cpi) {
AV1_COMMON *const cm = &cpi->common;
- aom_free(cpi->mbmi_ext_base);
- cpi->mbmi_ext_base = NULL;
+ dealloc_context_buffers_ext(cpi);
#if CONFIG_PVQ
if (cpi->oxcf.pass != 1) {
@@ -821,14 +837,6 @@
"Failed to allocate scaled last source buffer");
}
-static void alloc_context_buffers_ext(AV1_COMP *cpi) {
- AV1_COMMON *cm = &cpi->common;
- int mi_size = cm->mi_cols * cm->mi_rows;
-
- CHECK_MEM_ERROR(cm, cpi->mbmi_ext_base,
- aom_calloc(mi_size, sizeof(*cpi->mbmi_ext_base)));
-}
-
static void alloc_compressor_data(AV1_COMP *cpi) {
AV1_COMMON *cm = &cpi->common;
@@ -1038,7 +1046,6 @@
NULL);
memset(cpi->mbmi_ext_base, 0,
cm->mi_rows * cm->mi_cols * sizeof(*cpi->mbmi_ext_base));
-
set_tile_info(cpi);
}
@@ -1097,6 +1104,10 @@
cpi->static_mb_pct = 0;
cpi->ref_frame_flags = 0;
+ // Reset resize pending flags
+ cpi->resize_pending_width = 0;
+ cpi->resize_pending_height = 0;
+
init_buffer_indices(cpi);
}
@@ -2421,6 +2432,7 @@
if (cpi->initial_width) {
if (cm->width > cpi->initial_width || cm->height > cpi->initial_height) {
av1_free_context_buffers(cm);
+ av1_free_pc_tree(&cpi->td);
alloc_compressor_data(cpi);
realloc_segmentation_maps(cpi);
cpi->initial_width = cpi->initial_height = 0;
@@ -3326,6 +3338,7 @@
rdc->global_motion_used[i] * GM_RECODE_LOOP_NUM4X4_FACTOR <
cpi->gmparams_cost[i]) {
set_default_warp_params(&cm->global_motion[i]);
+ assert(cm->global_motion[i].wmtype == IDENTITY);
cpi->gmparams_cost[i] = 0;
recode = 1;
recode |= (rdc->global_motion_used[i] > 0);
@@ -4124,20 +4137,16 @@
if (width <= 0 || height <= 0) return 1;
cm->width = width;
- if (cm->width > cpi->initial_width) {
- cm->width = cpi->initial_width;
- printf("Warning: Desired width too large, changed to %d\n", cm->width);
- }
-
cm->height = height;
- if (cm->height > cpi->initial_height) {
- cm->height = cpi->initial_height;
- printf("Warning: Desired height too large, changed to %d\n", cm->height);
+
+ if (cpi->initial_width && cpi->initial_height &&
+ (cm->width > cpi->initial_width || cm->height > cpi->initial_height)) {
+ av1_free_context_buffers(cm);
+ av1_free_pc_tree(&cpi->td);
+ alloc_compressor_data(cpi);
+ realloc_segmentation_maps(cpi);
+ cpi->initial_width = cpi->initial_height = 0;
}
-
- assert(cm->width <= cpi->initial_width);
- assert(cm->height <= cpi->initial_height);
-
update_frame_size(cpi);
return 0;
@@ -4303,56 +4312,98 @@
}
static int validate_size_scales(RESIZE_MODE resize_mode,
- SUPERRES_MODE superres_mode,
- size_params_type *rsz) {
- if (rsz->resize_num * rsz->superres_num * 2 >
- SCALE_DENOMINATOR * SCALE_DENOMINATOR)
+ SUPERRES_MODE superres_mode, int owidth,
+ int oheight, size_params_type *rsz) {
+ if (rsz->resize_width * rsz->superres_num >= SCALE_DENOMINATOR * owidth / 2 &&
+ rsz->resize_height * rsz->superres_num >= SCALE_DENOMINATOR * oheight / 2)
return 1;
+ int resize_num = AOMMIN(((rsz->resize_width * 16 + owidth / 2) / owidth),
+ ((rsz->resize_height * 16 + oheight / 2) / oheight));
if (resize_mode != RESIZE_RANDOM && superres_mode == SUPERRES_RANDOM) {
rsz->superres_num =
- (SCALE_DENOMINATOR * SCALE_DENOMINATOR + 2 * rsz->resize_num - 1) /
- (2 * rsz->resize_num);
+ (SCALE_DENOMINATOR * SCALE_DENOMINATOR + 2 * resize_num - 1) /
+ (2 * resize_num);
+ if (rsz->resize_width * rsz->superres_num <
+ SCALE_DENOMINATOR * owidth / 2 ||
+ rsz->resize_height * rsz->superres_num <
+ SCALE_DENOMINATOR * oheight / 2) {
+ if (rsz->superres_num < SCALE_DENOMINATOR) rsz->superres_num++;
+ }
} else if (resize_mode == RESIZE_RANDOM && superres_mode != SUPERRES_RANDOM) {
- rsz->resize_num =
+ resize_num =
(SCALE_DENOMINATOR * SCALE_DENOMINATOR + 2 * rsz->superres_num - 1) /
(2 * rsz->superres_num);
+ rsz->resize_width = owidth;
+ rsz->resize_height = oheight;
+ av1_calculate_scaled_size(&rsz->resize_width, &rsz->resize_height,
+ resize_num);
+ if (rsz->resize_width * rsz->superres_num <
+ SCALE_DENOMINATOR * owidth / 2 ||
+ rsz->resize_height * rsz->superres_num <
+ SCALE_DENOMINATOR * oheight / 2) {
+ if (resize_num < SCALE_DENOMINATOR) resize_num++;
+ }
} else if (resize_mode == RESIZE_RANDOM && superres_mode == SUPERRES_RANDOM) {
do {
- if (rsz->resize_num < rsz->superres_num)
- ++rsz->resize_num;
+ if (resize_num < rsz->superres_num)
+ ++resize_num;
else
++rsz->superres_num;
- } while (rsz->resize_num * rsz->superres_num * 2 <=
- SCALE_DENOMINATOR * SCALE_DENOMINATOR);
+ rsz->resize_width = owidth;
+ rsz->resize_height = oheight;
+ av1_calculate_scaled_size(&rsz->resize_width, &rsz->resize_height,
+ resize_num);
+ } while ((rsz->resize_width * rsz->superres_num <
+ SCALE_DENOMINATOR * owidth / 2 ||
+ rsz->resize_height * rsz->superres_num <
+ SCALE_DENOMINATOR * oheight / 2) &&
+ (resize_num < SCALE_DENOMINATOR ||
+ rsz->superres_num < SCALE_DENOMINATOR));
} else {
return 0;
}
- return 1;
+ if (rsz->resize_width * rsz->superres_num >= SCALE_DENOMINATOR * owidth / 2 &&
+ rsz->resize_height * rsz->superres_num >= SCALE_DENOMINATOR * oheight / 2)
+ return 1;
+ return 0;
}
#endif // CONFIG_FRAME_SUPERRES
+// Calculates resize and superres params for next frame
size_params_type av1_calculate_next_size_params(AV1_COMP *cpi) {
const AV1EncoderConfig *oxcf = &cpi->oxcf;
size_params_type rsz = {
- SCALE_DENOMINATOR,
+ oxcf->width,
+ oxcf->height,
#if CONFIG_FRAME_SUPERRES
SCALE_DENOMINATOR
#endif // CONFIG_FRAME_SUPERRES
};
+ int resize_num;
if (oxcf->pass == 1) return rsz;
- rsz.resize_num = calculate_next_resize_scale(cpi);
+ if (cpi->resize_pending_width && cpi->resize_pending_height) {
+ rsz.resize_width = cpi->resize_pending_width;
+ rsz.resize_height = cpi->resize_pending_height;
+ cpi->resize_pending_width = cpi->resize_pending_height = 0;
+ } else {
+ resize_num = calculate_next_resize_scale(cpi);
+ rsz.resize_width = cpi->oxcf.width;
+ rsz.resize_height = cpi->oxcf.height;
+ av1_calculate_scaled_size(&rsz.resize_width, &rsz.resize_height,
+ resize_num);
+ }
#if CONFIG_FRAME_SUPERRES
rsz.superres_num = calculate_next_superres_scale(cpi);
- if (!validate_size_scales(oxcf->resize_mode, oxcf->superres_mode, &rsz))
+ if (!validate_size_scales(oxcf->resize_mode, oxcf->superres_mode, oxcf->width,
+ oxcf->height, &rsz))
assert(0 && "Invalid scale parameters");
#endif // CONFIG_FRAME_SUPERRES
return rsz;
}
static void setup_frame_size_from_params(AV1_COMP *cpi, size_params_type *rsz) {
- int encode_width = cpi->oxcf.width;
- int encode_height = cpi->oxcf.height;
- av1_calculate_scaled_size(&encode_width, &encode_height, rsz->resize_num);
+ int encode_width = rsz->resize_width;
+ int encode_height = rsz->resize_height;
#if CONFIG_FRAME_SUPERRES
AV1_COMMON *cm = &cpi->common;
@@ -4365,8 +4416,7 @@
}
static void setup_frame_size(AV1_COMP *cpi) {
- size_params_type rsz;
- rsz = av1_calculate_next_size_params(cpi);
+ size_params_type rsz = av1_calculate_next_size_params(cpi);
setup_frame_size_from_params(cpi, &rsz);
}
@@ -4622,12 +4672,15 @@
&frame_over_shoot_limit);
}
- cpi->source =
- av1_scale_if_required(cm, cpi->unscaled_source, &cpi->scaled_source);
#if CONFIG_GLOBAL_MOTION
// if frame was scaled calculate global_motion_search again if already done
- if (cpi->source != cpi->unscaled_source) cpi->global_motion_search_done = 0;
+ if (loop_count > 0 && cpi->source && cpi->global_motion_search_done)
+ if (cpi->source->y_crop_width != cm->width ||
+ cpi->source->y_crop_height != cm->height)
+ cpi->global_motion_search_done = 0;
#endif // CONFIG_GLOBAL_MOTION
+ cpi->source =
+ av1_scale_if_required(cm, cpi->unscaled_source, &cpi->scaled_source);
if (cpi->unscaled_last_source != NULL)
cpi->last_source = av1_scale_if_required(cm, cpi->unscaled_last_source,
&cpi->scaled_last_source);
@@ -6561,7 +6614,6 @@
int av1_set_internal_size(AV1_COMP *cpi, AOM_SCALING horiz_mode,
AOM_SCALING vert_mode) {
- AV1_COMMON *cm = &cpi->common;
int hr = 0, hs = 0, vr = 0, vs = 0;
if (horiz_mode > ONETWO || vert_mode > ONETWO) return -1;
@@ -6570,12 +6622,8 @@
Scale2Ratio(vert_mode, &vr, &vs);
// always go to the next whole number
- cm->width = (hs - 1 + cpi->oxcf.width * hr) / hs;
- cm->height = (vs - 1 + cpi->oxcf.height * vr) / vs;
- assert(cm->width <= cpi->initial_width);
- assert(cm->height <= cpi->initial_height);
-
- update_frame_size(cpi);
+ cpi->resize_pending_width = (hs - 1 + cpi->oxcf.width * hr) / hs;
+ cpi->resize_pending_height = (vs - 1 + cpi->oxcf.height * vr) / vs;
return 0;
}
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index 889d48a..3930721 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -571,6 +571,13 @@
// number of MBs in the current frame when the frame is
// scaled.
+ // When resize is triggered through external control, the desired width/height
+ // are stored here until use in the next frame coded. They are effective only
+ // for
+ // one frame and are reset after use.
+ int resize_pending_width;
+ int resize_pending_height;
+
int frame_flags;
search_site_config ss_cfg;
diff --git a/av1/encoder/ratectrl.h b/av1/encoder/ratectrl.h
index b82d29f..9172ca7 100644
--- a/av1/encoder/ratectrl.h
+++ b/av1/encoder/ratectrl.h
@@ -50,7 +50,8 @@
#endif // CONFIG_EXT_REFS
typedef struct {
- uint8_t resize_num;
+ int resize_width;
+ int resize_height;
#if CONFIG_FRAME_SUPERRES
uint8_t superres_num;
#endif // CONFIG_FRAME_SUPERRES
diff --git a/test/resize_test.cc b/test/resize_test.cc
index 2c838dd..14b10e0 100644
--- a/test/resize_test.cc
+++ b/test/resize_test.cc
@@ -351,11 +351,11 @@
encoder->Config(&cfg_);
}
} else {
- if (video->frame() == kStepDownFrame) {
+ if (video->frame() >= kStepDownFrame && video->frame() < kStepUpFrame) {
struct aom_scaling_mode mode = { AOME_FOURFIVE, AOME_THREEFIVE };
encoder->Control(AOME_SET_SCALEMODE, &mode);
}
- if (video->frame() == kStepUpFrame) {
+ if (video->frame() >= kStepUpFrame) {
struct aom_scaling_mode mode = { AOME_NORMAL, AOME_NORMAL };
encoder->Control(AOME_SET_SCALEMODE, &mode);
}
@@ -388,7 +388,7 @@
#endif
};
-TEST_P(ResizeInternalTest, DISABLED_TestInternalResizeWorks) {
+TEST_P(ResizeInternalTest, TestInternalResizeWorks) {
::libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 10);
init_flags_ = AOM_CODEC_USE_PSNR;
@@ -406,6 +406,9 @@
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";
@@ -417,7 +420,7 @@
}
}
-TEST_P(ResizeInternalTest, DISABLED_TestInternalResizeChangeConfig) {
+TEST_P(ResizeInternalTest, TestInternalResizeChangeConfig) {
::libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 10);
cfg_.g_w = 352;
@@ -493,7 +496,7 @@
int mismatch_nframes_;
};
-TEST_P(ResizeRealtimeTest, DISABLED_TestExternalResizeWorks) {
+TEST_P(ResizeRealtimeTest, TestExternalResizeWorks) {
ResizingVideoSource video;
video.flag_codec_ = 1;
DefaultConfig();
@@ -693,15 +696,6 @@
}
};
-#ifdef DISABLE_TRELLISQ_SEARCH
-TEST_P(ResizeCspTest, DISABLED_TestResizeCspWorks) {
- ResizingCspVideoSource video;
- init_flags_ = AOM_CODEC_USE_PSNR;
- cfg_.rc_min_quantizer = cfg_.rc_max_quantizer = 48;
- cfg_.g_lag_in_frames = 0;
- ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
-}
-#else
TEST_P(ResizeCspTest, TestResizeCspWorks) {
ResizingCspVideoSource video;
init_flags_ = AOM_CODEC_USE_PSNR;
@@ -709,7 +703,6 @@
cfg_.g_lag_in_frames = 0;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
}
-#endif
AV1_INSTANTIATE_TEST_CASE(ResizeTest,
::testing::Values(::libaom_test::kRealTime));