|  | /* | 
|  | * 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; | 
|  | assert(linesize <= src_stride); | 
|  |  | 
|  | 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->subsampling_x; | 
|  | const int ss_y = ybf->subsampling_y; | 
|  | 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 |