| /* | |
| * 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. | |
| */ | |
| #include <assert.h> | |
| #include "config/aom_config.h" | |
| #include "aom_scale/yv12config.h" | |
| #include "aom_mem/aom_mem.h" | |
| #include "aom_scale/aom_scale.h" | |
| #if HAVE_DSPR2 | |
| static void extend_plane(uint8_t *const src, int src_stride, int width, | |
| int height, int extend_top, int extend_left, | |
| int extend_bottom, int extend_right) { | |
| int i, j; | |
| uint8_t *left_src, *right_src; | |
| uint8_t *left_dst_start, *right_dst_start; | |
| uint8_t *left_dst, *right_dst; | |
| uint8_t *top_src, *bot_src; | |
| uint8_t *top_dst, *bot_dst; | |
| uint32_t left_pix; | |
| uint32_t right_pix; | |
| uint32_t linesize; | |
| /* copy the left and right most columns out */ | |
| left_src = src; | |
| right_src = src + width - 1; | |
| left_dst_start = src - extend_left; | |
| right_dst_start = src + width; | |
| for (i = height; i--;) { | |
| left_dst = left_dst_start; | |
| right_dst = right_dst_start; | |
| __asm__ __volatile__( | |
| "lb %[left_pix], 0(%[left_src]) \n\t" | |
| "lb %[right_pix], 0(%[right_src]) \n\t" | |
| "replv.qb %[left_pix], %[left_pix] \n\t" | |
| "replv.qb %[right_pix], %[right_pix] \n\t" | |
| : [left_pix] "=&r"(left_pix), [right_pix] "=&r"(right_pix) | |
| : [left_src] "r"(left_src), [right_src] "r"(right_src)); | |
| for (j = extend_left / 4; j--;) { | |
| __asm__ __volatile__( | |
| "sw %[left_pix], 0(%[left_dst]) \n\t" | |
| "sw %[right_pix], 0(%[right_dst]) \n\t" | |
| : | |
| : [left_dst] "r"(left_dst), [left_pix] "r"(left_pix), | |
| [right_dst] "r"(right_dst), [right_pix] "r"(right_pix)); | |
| left_dst += 4; | |
| right_dst += 4; | |
| } | |
| for (j = extend_left % 4; j--;) { | |
| __asm__ __volatile__( | |
| "sb %[left_pix], 0(%[left_dst]) \n\t" | |
| "sb %[right_pix], 0(%[right_dst]) \n\t" | |
| : | |
| : [left_dst] "r"(left_dst), [left_pix] "r"(left_pix), | |
| [right_dst] "r"(right_dst), [right_pix] "r"(right_pix)); | |
| left_dst += 1; | |
| right_dst += 1; | |
| } | |
| left_src += src_stride; | |
| right_src += src_stride; | |
| left_dst_start += src_stride; | |
| right_dst_start += src_stride; | |
| } | |
| /* Now copy the top and bottom lines into each line of the respective | |
| * borders | |
| */ | |
| top_src = src - extend_left; | |
| bot_src = src + src_stride * (height - 1) - extend_left; | |
| top_dst = src + src_stride * (-extend_top) - extend_left; | |
| bot_dst = src + src_stride * (height)-extend_left; | |
| linesize = extend_left + extend_right + width; | |
| for (i = 0; i < extend_top; i++) { | |
| memcpy(top_dst, top_src, linesize); | |
| top_dst += src_stride; | |
| } | |
| for (i = 0; i < extend_bottom; i++) { | |
| memcpy(bot_dst, bot_src, linesize); | |
| bot_dst += src_stride; | |
| } | |
| } | |
| static void extend_frame(YV12_BUFFER_CONFIG *const ybf, int ext_size) { | |
| const int c_w = ybf->uv_crop_width; | |
| const int c_h = ybf->uv_crop_height; | |
| const int ss_x = ybf->uv_width < ybf->y_width; | |
| const int ss_y = ybf->uv_height < ybf->y_height; | |
| const int c_et = ext_size >> ss_y; | |
| const int c_el = ext_size >> ss_x; | |
| const int c_eb = c_et + ybf->uv_height - ybf->uv_crop_height; | |
| const int c_er = c_el + ybf->uv_width - ybf->uv_crop_width; | |
| assert(ybf->y_height - ybf->y_crop_height < 16); | |
| assert(ybf->y_width - ybf->y_crop_width < 16); | |
| assert(ybf->y_height - ybf->y_crop_height >= 0); | |
| assert(ybf->y_width - ybf->y_crop_width >= 0); | |
| extend_plane(ybf->y_buffer, ybf->y_stride, ybf->y_crop_width, | |
| ybf->y_crop_height, ext_size, ext_size, | |
| ext_size + ybf->y_height - ybf->y_crop_height, | |
| ext_size + ybf->y_width - ybf->y_crop_width); | |
| extend_plane(ybf->u_buffer, ybf->uv_stride, c_w, c_h, c_et, c_el, c_eb, c_er); | |
| extend_plane(ybf->v_buffer, ybf->uv_stride, c_w, c_h, c_et, c_el, c_eb, c_er); | |
| } | |
| void aom_extend_frame_borders_dspr2(YV12_BUFFER_CONFIG *ybf, | |
| const int num_planes) { | |
| extend_frame(ybf, ybf->border, num_planes); | |
| } | |
| void aom_extend_frame_inner_borders_dspr2(YV12_BUFFER_CONFIG *ybf, | |
| const int num_planes) { | |
| const int inner_bw = (ybf->border > AOMINNERBORDERINPIXELS) | |
| ? AOMINNERBORDERINPIXELS | |
| : ybf->border; | |
| extend_frame(ybf, inner_bw, num_planes); | |
| } | |
| #endif |