1 /*
2  * Copyright (c) 2016, Alliance for Open Media. All rights reserved
3  *
4  * This source code is subject to the terms of the BSD 2 Clause License and
5  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6  * was not distributed with this source code in the LICENSE file, you can
7  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8  * Media Patent License 1.0 was not distributed with this source code in the
9  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10  */
11 
12 #include <assert.h>
13 
14 #include "config/aom_config.h"
15 
16 #include "aom_scale/yv12config.h"
17 #include "aom_mem/aom_mem.h"
18 #include "aom_scale/aom_scale.h"
19 
20 #if HAVE_DSPR2
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)21 static void extend_plane(uint8_t *const src, int src_stride, int width,
22                          int height, int extend_top, int extend_left,
23                          int extend_bottom, int extend_right) {
24   int i, j;
25   uint8_t *left_src, *right_src;
26   uint8_t *left_dst_start, *right_dst_start;
27   uint8_t *left_dst, *right_dst;
28   uint8_t *top_src, *bot_src;
29   uint8_t *top_dst, *bot_dst;
30   uint32_t left_pix;
31   uint32_t right_pix;
32   uint32_t linesize;
33 
34   /* copy the left and right most columns out */
35   left_src = src;
36   right_src = src + width - 1;
37   left_dst_start = src - extend_left;
38   right_dst_start = src + width;
39 
40   for (i = height; i--;) {
41     left_dst = left_dst_start;
42     right_dst = right_dst_start;
43 
44     __asm__ __volatile__(
45         "lb        %[left_pix],     0(%[left_src])      \n\t"
46         "lb        %[right_pix],    0(%[right_src])     \n\t"
47         "replv.qb  %[left_pix],     %[left_pix]         \n\t"
48         "replv.qb  %[right_pix],    %[right_pix]        \n\t"
49 
50         : [left_pix] "=&r"(left_pix), [right_pix] "=&r"(right_pix)
51         : [left_src] "r"(left_src), [right_src] "r"(right_src));
52 
53     for (j = extend_left / 4; j--;) {
54       __asm__ __volatile__(
55           "sw     %[left_pix],    0(%[left_dst])     \n\t"
56           "sw     %[right_pix],   0(%[right_dst])    \n\t"
57 
58           :
59           : [left_dst] "r"(left_dst), [left_pix] "r"(left_pix),
60             [right_dst] "r"(right_dst), [right_pix] "r"(right_pix));
61 
62       left_dst += 4;
63       right_dst += 4;
64     }
65 
66     for (j = extend_left % 4; j--;) {
67       __asm__ __volatile__(
68           "sb     %[left_pix],    0(%[left_dst])     \n\t"
69           "sb     %[right_pix],   0(%[right_dst])     \n\t"
70 
71           :
72           : [left_dst] "r"(left_dst), [left_pix] "r"(left_pix),
73             [right_dst] "r"(right_dst), [right_pix] "r"(right_pix));
74 
75       left_dst += 1;
76       right_dst += 1;
77     }
78 
79     left_src += src_stride;
80     right_src += src_stride;
81     left_dst_start += src_stride;
82     right_dst_start += src_stride;
83   }
84 
85   /* Now copy the top and bottom lines into each line of the respective
86    * borders
87    */
88   top_src = src - extend_left;
89   bot_src = src + src_stride * (height - 1) - extend_left;
90   top_dst = src + src_stride * (-extend_top) - extend_left;
91   bot_dst = src + src_stride * (height)-extend_left;
92   linesize = extend_left + extend_right + width;
93 
94   for (i = 0; i < extend_top; i++) {
95     memcpy(top_dst, top_src, linesize);
96     top_dst += src_stride;
97   }
98 
99   for (i = 0; i < extend_bottom; i++) {
100     memcpy(bot_dst, bot_src, linesize);
101     bot_dst += src_stride;
102   }
103 }
104 
extend_frame(YV12_BUFFER_CONFIG * const ybf,int ext_size)105 static void extend_frame(YV12_BUFFER_CONFIG *const ybf, int ext_size) {
106   const int c_w = ybf->uv_crop_width;
107   const int c_h = ybf->uv_crop_height;
108   const int ss_x = ybf->uv_width < ybf->y_width;
109   const int ss_y = ybf->uv_height < ybf->y_height;
110   const int c_et = ext_size >> ss_y;
111   const int c_el = ext_size >> ss_x;
112   const int c_eb = c_et + ybf->uv_height - ybf->uv_crop_height;
113   const int c_er = c_el + ybf->uv_width - ybf->uv_crop_width;
114 
115   assert(ybf->y_height - ybf->y_crop_height < 16);
116   assert(ybf->y_width - ybf->y_crop_width < 16);
117   assert(ybf->y_height - ybf->y_crop_height >= 0);
118   assert(ybf->y_width - ybf->y_crop_width >= 0);
119 
120   extend_plane(ybf->y_buffer, ybf->y_stride, ybf->y_crop_width,
121                ybf->y_crop_height, ext_size, ext_size,
122                ext_size + ybf->y_height - ybf->y_crop_height,
123                ext_size + ybf->y_width - ybf->y_crop_width);
124 
125   extend_plane(ybf->u_buffer, ybf->uv_stride, c_w, c_h, c_et, c_el, c_eb, c_er);
126 
127   extend_plane(ybf->v_buffer, ybf->uv_stride, c_w, c_h, c_et, c_el, c_eb, c_er);
128 }
129 
aom_extend_frame_borders_dspr2(YV12_BUFFER_CONFIG * ybf,const int num_planes)130 void aom_extend_frame_borders_dspr2(YV12_BUFFER_CONFIG *ybf,
131                                     const int num_planes) {
132   extend_frame(ybf, ybf->border, num_planes);
133 }
134 
aom_extend_frame_inner_borders_dspr2(YV12_BUFFER_CONFIG * ybf,const int num_planes)135 void aom_extend_frame_inner_borders_dspr2(YV12_BUFFER_CONFIG *ybf,
136                                           const int num_planes) {
137   const int inner_bw = (ybf->border > AOMINNERBORDERINPIXELS)
138                            ? AOMINNERBORDERINPIXELS
139                            : ybf->border;
140   extend_frame(ybf, inner_bw, num_planes);
141 }
142 #endif
143