diff options
Diffstat (limited to 'av1/common/arm/resize_neon.c')
-rw-r--r-- | av1/common/arm/resize_neon.c | 111 |
1 files changed, 68 insertions, 43 deletions
diff --git a/av1/common/arm/resize_neon.c b/av1/common/arm/resize_neon.c index 190a3b289..df4f7d645 100644 --- a/av1/common/arm/resize_neon.c +++ b/av1/common/arm/resize_neon.c @@ -694,13 +694,42 @@ static void scale_plane_4_to_3_general(const uint8_t *src, const int src_stride, } while (x); } +// There's SIMD optimizations for 1/4, 1/2 and 3/4 downscaling in NEON. +static INLINE bool has_normative_scaler_neon(const int src_width, + const int src_height, + const int dst_width, + const int dst_height) { + const bool has_normative_scaler = + (2 * dst_width == src_width && 2 * dst_height == src_height) || + (4 * dst_width == src_width && 4 * dst_height == src_height) || + (4 * dst_width == 3 * src_width && 4 * dst_height == 3 * src_height); + + return has_normative_scaler; +} + void av1_resize_and_extend_frame_neon(const YV12_BUFFER_CONFIG *src, YV12_BUFFER_CONFIG *dst, const InterpFilter filter, const int phase, const int num_planes) { + bool has_normative_scaler = + has_normative_scaler_neon(src->y_crop_width, src->y_crop_height, + dst->y_crop_width, dst->y_crop_height); + + if (num_planes > 1) { + has_normative_scaler = + has_normative_scaler && + has_normative_scaler_neon(src->uv_crop_width, src->uv_crop_height, + dst->uv_crop_width, dst->uv_crop_height); + } + + if (!has_normative_scaler) { + av1_resize_and_extend_frame_c(src, dst, filter, phase, num_planes); + return; + } + // We use AOMMIN(num_planes, MAX_MB_PLANE) instead of num_planes to quiet // the static analysis warnings. - int scaled = 0; + int malloc_failed = 0; for (int i = 0; i < AOMMIN(num_planes, MAX_MB_PLANE); ++i) { const int is_uv = i > 0; const int src_w = src->crop_widths[is_uv]; @@ -711,7 +740,6 @@ void av1_resize_and_extend_frame_neon(const YV12_BUFFER_CONFIG *src, const int dst_y_h = (dst->crop_heights[0] + 1) & ~1; if (2 * dst_w == src_w && 2 * dst_h == src_h) { - scaled = 1; if (phase == 0) { scale_plane_2_to_1_phase_0(src->buffers[i], src->strides[is_uv], dst->buffers[i], dst->strides[is_uv], dst_w, @@ -727,21 +755,19 @@ void av1_resize_and_extend_frame_neon(const YV12_BUFFER_CONFIG *src, const int buffer_height = (2 * dst_y_h + SUBPEL_TAPS - 2 + 7) & ~7; uint8_t *const temp_buffer = (uint8_t *)malloc(buffer_stride * buffer_height); - if (temp_buffer) { - const InterpKernel *interp_kernel = - (const InterpKernel *)av1_interp_filter_params_list[filter] - .filter_ptr; - scale_plane_2_to_1_general(src->buffers[i], src->strides[is_uv], - dst->buffers[i], dst->strides[is_uv], - dst_w, dst_h, interp_kernel[phase], - temp_buffer); - free(temp_buffer); - } else { - scaled = 0; + if (!temp_buffer) { + malloc_failed = 1; + break; } + const InterpKernel *interp_kernel = + (const InterpKernel *)av1_interp_filter_params_list[filter] + .filter_ptr; + scale_plane_2_to_1_general(src->buffers[i], src->strides[is_uv], + dst->buffers[i], dst->strides[is_uv], dst_w, + dst_h, interp_kernel[phase], temp_buffer); + free(temp_buffer); } } else if (4 * dst_w == src_w && 4 * dst_h == src_h) { - scaled = 1; if (phase == 0) { scale_plane_4_to_1_phase_0(src->buffers[i], src->strides[is_uv], dst->buffers[i], dst->strides[is_uv], dst_w, @@ -758,46 +784,45 @@ void av1_resize_and_extend_frame_neon(const YV12_BUFFER_CONFIG *src, uint8_t *const temp_buffer = (uint8_t *)malloc(buffer_stride * buffer_height); if (temp_buffer) { - const InterpKernel *interp_kernel = - (const InterpKernel *)av1_interp_filter_params_list[filter] - .filter_ptr; - scale_plane_4_to_1_general(src->buffers[i], src->strides[is_uv], - dst->buffers[i], dst->strides[is_uv], - dst_w, dst_h, interp_kernel[phase], - temp_buffer); - free(temp_buffer); - } else { - scaled = 0; + malloc_failed = 1; + break; } + const InterpKernel *interp_kernel = + (const InterpKernel *)av1_interp_filter_params_list[filter] + .filter_ptr; + scale_plane_4_to_1_general(src->buffers[i], src->strides[is_uv], + dst->buffers[i], dst->strides[is_uv], dst_w, + dst_h, interp_kernel[phase], temp_buffer); + free(temp_buffer); } - } else if (4 * dst_w == 3 * src_w && 4 * dst_h == 3 * src_h) { + } else { + assert(4 * dst_w == 3 * src_w && 4 * dst_h == 3 * src_h); // 4 to 3 const int buffer_stride = (dst_y_w + 5) - ((dst_y_w + 5) % 6) + 2; const int buffer_height = (4 * dst_y_h / 3 + SUBPEL_TAPS - 1 + 7) & ~7; uint8_t *const temp_buffer = (uint8_t *)malloc(buffer_stride * buffer_height); - if (temp_buffer) { - scaled = 1; - if (filter == BILINEAR) { - scale_plane_4_to_3_bilinear(src->buffers[i], src->strides[is_uv], - dst->buffers[i], dst->strides[is_uv], - dst_w, dst_h, phase, temp_buffer); - } else { - const InterpKernel *interp_kernel = - (const InterpKernel *)av1_interp_filter_params_list[filter] - .filter_ptr; - scale_plane_4_to_3_general(src->buffers[i], src->strides[is_uv], - dst->buffers[i], dst->strides[is_uv], - dst_w, dst_h, interp_kernel, phase, - temp_buffer); - } - free(temp_buffer); + if (!temp_buffer) { + malloc_failed = 1; + break; + } + if (filter == BILINEAR) { + scale_plane_4_to_3_bilinear(src->buffers[i], src->strides[is_uv], + dst->buffers[i], dst->strides[is_uv], dst_w, + dst_h, phase, temp_buffer); } else { - scaled = 0; + const InterpKernel *interp_kernel = + (const InterpKernel *)av1_interp_filter_params_list[filter] + .filter_ptr; + scale_plane_4_to_3_general(src->buffers[i], src->strides[is_uv], + dst->buffers[i], dst->strides[is_uv], dst_w, + dst_h, interp_kernel, phase, temp_buffer); } + free(temp_buffer); } } - if (!scaled) { + + if (malloc_failed) { av1_resize_and_extend_frame_c(src, dst, filter, phase, num_planes); } else { aom_extend_frame_borders(dst, num_planes); |