Update border for ref buffer to allow scaled pred
Adds a function to realloc and copy a frame buffer
to accommodate a different border size. The new buffer is
also extended by replication.
BUG=aomedia:2348
Change-Id: I83cd559a201e810df273dcba361cc3e261d1a260
diff --git a/aom_scale/aom_scale_rtcd.pl b/aom_scale/aom_scale_rtcd.pl
index 27378c7e..eef6f16 100644
--- a/aom_scale/aom_scale_rtcd.pl
+++ b/aom_scale/aom_scale_rtcd.pl
@@ -26,6 +26,8 @@
add_proto qw/void aom_vertical_band_2_1_scale_i/, "unsigned char *source, int src_pitch, unsigned char *dest, int dest_pitch, unsigned int dest_width";
}
+add_proto qw/int aom_yv12_realloc_with_new_border/, "struct yv12_buffer_config *ybf, int new_border, int byte_alignment, int num_planes";
+
add_proto qw/void aom_yv12_extend_frame_borders/, "struct yv12_buffer_config *ybf, const int num_planes";
add_proto qw/void aom_yv12_copy_frame/, "const struct yv12_buffer_config *src_bc, struct yv12_buffer_config *dst_bc, const int num_planes";
diff --git a/aom_scale/generic/yv12extend.c b/aom_scale/generic/yv12extend.c
index 127ca23..6e9cfff 100644
--- a/aom_scale/generic/yv12extend.c
+++ b/aom_scale/generic/yv12extend.c
@@ -434,3 +434,28 @@
aom_yv12_partial_copy_v_c(src_bc, hstart, hend, vstart, vend, dst_bc, hstart,
vstart);
}
+
+int aom_yv12_realloc_with_new_border_c(YV12_BUFFER_CONFIG *ybf, int new_border,
+ int byte_alignment, int num_planes) {
+ if (ybf) {
+ if (new_border == ybf->border) return 0;
+ YV12_BUFFER_CONFIG new_buf;
+ memset(&new_buf, 0, sizeof(new_buf));
+ const int error = aom_alloc_frame_buffer(
+ &new_buf, ybf->y_crop_width, ybf->y_crop_height, ybf->subsampling_x,
+ ybf->subsampling_y, ybf->flags & YV12_FLAG_HIGHBITDEPTH, new_border,
+ byte_alignment);
+ if (error) return error;
+ // Copy image buffer
+ aom_yv12_copy_frame(ybf, &new_buf, num_planes);
+
+ // Extend up to new border
+ aom_extend_frame_borders(&new_buf, num_planes);
+
+ // Now free the old buffer and replace with the new
+ aom_free_frame_buffer(ybf);
+ memcpy(ybf, &new_buf, sizeof(new_buf));
+ return 0;
+ }
+ return -2;
+}
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 9174d2e..592e6df 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -3364,6 +3364,20 @@
}
if (ref->y_crop_width != cm->width || ref->y_crop_height != cm->height) {
+ // Replace the reference buffer with a copy having a thicker border,
+ // if the reference buffer is higher resolution than the current
+ // frame, and the border is thin.
+ if ((ref->y_crop_width > cm->width ||
+ ref->y_crop_height > cm->height) &&
+ ref->border < AOM_BORDER_IN_PIXELS) {
+ RefCntBuffer *ref_fb = get_ref_frame_buf(cm, ref_frame);
+ if (aom_yv12_realloc_with_new_border(
+ &ref_fb->buf, AOM_BORDER_IN_PIXELS, cm->byte_alignment,
+ num_planes) != 0) {
+ aom_internal_error(&cm->error, AOM_CODEC_MEM_ERROR,
+ "Failed to allocate frame buffer");
+ }
+ }
int force_scaling = 0;
RefCntBuffer *new_fb = cpi->scaled_ref_buf[ref_frame - 1];
if (new_fb == NULL) {