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