Line data Source code
1 : /*
2 : * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3 : *
4 : * Use of this source code is governed by a BSD-style license
5 : * that can be found in the LICENSE file in the root of the source
6 : * tree. An additional intellectual property rights grant can be found
7 : * in the file PATENTS. All contributing project authors may
8 : * be found in the AUTHORS file in the root of the source tree.
9 : */
10 :
11 : #include <assert.h>
12 : #include "./vpx_config.h"
13 : #include "./vpx_scale_rtcd.h"
14 : #include "vpx/vpx_integer.h"
15 : #include "vpx_mem/vpx_mem.h"
16 : #include "vpx_ports/mem.h"
17 : #include "vpx_scale/yv12config.h"
18 : #if CONFIG_VP9_HIGHBITDEPTH
19 : #include "vp9/common/vp9_common.h"
20 : #endif
21 :
22 0 : static void extend_plane(uint8_t *const src, int src_stride, int width,
23 : int height, int extend_top, int extend_left,
24 : int extend_bottom, int extend_right) {
25 : int i;
26 0 : const int linesize = extend_left + extend_right + width;
27 :
28 : /* copy the left and right most columns out */
29 0 : uint8_t *src_ptr1 = src;
30 0 : uint8_t *src_ptr2 = src + width - 1;
31 0 : uint8_t *dst_ptr1 = src - extend_left;
32 0 : uint8_t *dst_ptr2 = src + width;
33 :
34 0 : for (i = 0; i < height; ++i) {
35 0 : memset(dst_ptr1, src_ptr1[0], extend_left);
36 0 : memset(dst_ptr2, src_ptr2[0], extend_right);
37 0 : src_ptr1 += src_stride;
38 0 : src_ptr2 += src_stride;
39 0 : dst_ptr1 += src_stride;
40 0 : dst_ptr2 += src_stride;
41 : }
42 :
43 : /* Now copy the top and bottom lines into each line of the respective
44 : * borders
45 : */
46 0 : src_ptr1 = src - extend_left;
47 0 : src_ptr2 = src + src_stride * (height - 1) - extend_left;
48 0 : dst_ptr1 = src + src_stride * -extend_top - extend_left;
49 0 : dst_ptr2 = src + src_stride * height - extend_left;
50 :
51 0 : for (i = 0; i < extend_top; ++i) {
52 0 : memcpy(dst_ptr1, src_ptr1, linesize);
53 0 : dst_ptr1 += src_stride;
54 : }
55 :
56 0 : for (i = 0; i < extend_bottom; ++i) {
57 0 : memcpy(dst_ptr2, src_ptr2, linesize);
58 0 : dst_ptr2 += src_stride;
59 : }
60 0 : }
61 :
62 : #if CONFIG_VP9_HIGHBITDEPTH
63 : static void extend_plane_high(uint8_t *const src8, int src_stride, int width,
64 : int height, int extend_top, int extend_left,
65 : int extend_bottom, int extend_right) {
66 : int i;
67 : const int linesize = extend_left + extend_right + width;
68 : uint16_t *src = CONVERT_TO_SHORTPTR(src8);
69 :
70 : /* copy the left and right most columns out */
71 : uint16_t *src_ptr1 = src;
72 : uint16_t *src_ptr2 = src + width - 1;
73 : uint16_t *dst_ptr1 = src - extend_left;
74 : uint16_t *dst_ptr2 = src + width;
75 :
76 : for (i = 0; i < height; ++i) {
77 : vpx_memset16(dst_ptr1, src_ptr1[0], extend_left);
78 : vpx_memset16(dst_ptr2, src_ptr2[0], extend_right);
79 : src_ptr1 += src_stride;
80 : src_ptr2 += src_stride;
81 : dst_ptr1 += src_stride;
82 : dst_ptr2 += src_stride;
83 : }
84 :
85 : /* Now copy the top and bottom lines into each line of the respective
86 : * borders
87 : */
88 : src_ptr1 = src - extend_left;
89 : src_ptr2 = src + src_stride * (height - 1) - extend_left;
90 : dst_ptr1 = src + src_stride * -extend_top - extend_left;
91 : dst_ptr2 = src + src_stride * height - extend_left;
92 :
93 : for (i = 0; i < extend_top; ++i) {
94 : memcpy(dst_ptr1, src_ptr1, linesize * sizeof(uint16_t));
95 : dst_ptr1 += src_stride;
96 : }
97 :
98 : for (i = 0; i < extend_bottom; ++i) {
99 : memcpy(dst_ptr2, src_ptr2, linesize * sizeof(uint16_t));
100 : dst_ptr2 += src_stride;
101 : }
102 : }
103 : #endif
104 :
105 0 : void vp8_yv12_extend_frame_borders_c(YV12_BUFFER_CONFIG *ybf) {
106 0 : const int uv_border = ybf->border / 2;
107 :
108 0 : assert(ybf->border % 2 == 0);
109 0 : assert(ybf->y_height - ybf->y_crop_height < 16);
110 0 : assert(ybf->y_width - ybf->y_crop_width < 16);
111 0 : assert(ybf->y_height - ybf->y_crop_height >= 0);
112 0 : assert(ybf->y_width - ybf->y_crop_width >= 0);
113 :
114 : #if CONFIG_VP9_HIGHBITDEPTH
115 : if (ybf->flags & YV12_FLAG_HIGHBITDEPTH) {
116 : extend_plane_high(ybf->y_buffer, ybf->y_stride, ybf->y_crop_width,
117 : ybf->y_crop_height, ybf->border, ybf->border,
118 : ybf->border + ybf->y_height - ybf->y_crop_height,
119 : ybf->border + ybf->y_width - ybf->y_crop_width);
120 :
121 : extend_plane_high(ybf->u_buffer, ybf->uv_stride, ybf->uv_crop_width,
122 : ybf->uv_crop_height, uv_border, uv_border,
123 : uv_border + ybf->uv_height - ybf->uv_crop_height,
124 : uv_border + ybf->uv_width - ybf->uv_crop_width);
125 :
126 : extend_plane_high(ybf->v_buffer, ybf->uv_stride, ybf->uv_crop_width,
127 : ybf->uv_crop_height, uv_border, uv_border,
128 : uv_border + ybf->uv_height - ybf->uv_crop_height,
129 : uv_border + ybf->uv_width - ybf->uv_crop_width);
130 : return;
131 : }
132 : #endif
133 0 : extend_plane(ybf->y_buffer, ybf->y_stride, ybf->y_crop_width,
134 : ybf->y_crop_height, ybf->border, ybf->border,
135 0 : ybf->border + ybf->y_height - ybf->y_crop_height,
136 0 : ybf->border + ybf->y_width - ybf->y_crop_width);
137 :
138 0 : extend_plane(ybf->u_buffer, ybf->uv_stride, ybf->uv_crop_width,
139 : ybf->uv_crop_height, uv_border, uv_border,
140 0 : uv_border + ybf->uv_height - ybf->uv_crop_height,
141 0 : uv_border + ybf->uv_width - ybf->uv_crop_width);
142 :
143 0 : extend_plane(ybf->v_buffer, ybf->uv_stride, ybf->uv_crop_width,
144 : ybf->uv_crop_height, uv_border, uv_border,
145 0 : uv_border + ybf->uv_height - ybf->uv_crop_height,
146 0 : uv_border + ybf->uv_width - ybf->uv_crop_width);
147 0 : }
148 :
149 : #if CONFIG_VP9
150 0 : static void extend_frame(YV12_BUFFER_CONFIG *const ybf, int ext_size) {
151 0 : const int c_w = ybf->uv_crop_width;
152 0 : const int c_h = ybf->uv_crop_height;
153 0 : const int ss_x = ybf->uv_width < ybf->y_width;
154 0 : const int ss_y = ybf->uv_height < ybf->y_height;
155 0 : const int c_et = ext_size >> ss_y;
156 0 : const int c_el = ext_size >> ss_x;
157 0 : const int c_eb = c_et + ybf->uv_height - ybf->uv_crop_height;
158 0 : const int c_er = c_el + ybf->uv_width - ybf->uv_crop_width;
159 :
160 0 : assert(ybf->y_height - ybf->y_crop_height < 16);
161 0 : assert(ybf->y_width - ybf->y_crop_width < 16);
162 0 : assert(ybf->y_height - ybf->y_crop_height >= 0);
163 0 : assert(ybf->y_width - ybf->y_crop_width >= 0);
164 :
165 : #if CONFIG_VP9_HIGHBITDEPTH
166 : if (ybf->flags & YV12_FLAG_HIGHBITDEPTH) {
167 : extend_plane_high(ybf->y_buffer, ybf->y_stride, ybf->y_crop_width,
168 : ybf->y_crop_height, ext_size, ext_size,
169 : ext_size + ybf->y_height - ybf->y_crop_height,
170 : ext_size + ybf->y_width - ybf->y_crop_width);
171 : extend_plane_high(ybf->u_buffer, ybf->uv_stride, c_w, c_h, c_et, c_el, c_eb,
172 : c_er);
173 : extend_plane_high(ybf->v_buffer, ybf->uv_stride, c_w, c_h, c_et, c_el, c_eb,
174 : c_er);
175 : return;
176 : }
177 : #endif
178 0 : extend_plane(ybf->y_buffer, ybf->y_stride, ybf->y_crop_width,
179 : ybf->y_crop_height, ext_size, ext_size,
180 0 : ext_size + ybf->y_height - ybf->y_crop_height,
181 0 : ext_size + ybf->y_width - ybf->y_crop_width);
182 :
183 0 : extend_plane(ybf->u_buffer, ybf->uv_stride, c_w, c_h, c_et, c_el, c_eb, c_er);
184 :
185 0 : extend_plane(ybf->v_buffer, ybf->uv_stride, c_w, c_h, c_et, c_el, c_eb, c_er);
186 0 : }
187 :
188 0 : void vpx_extend_frame_borders_c(YV12_BUFFER_CONFIG *ybf) {
189 0 : extend_frame(ybf, ybf->border);
190 0 : }
191 :
192 0 : void vpx_extend_frame_inner_borders_c(YV12_BUFFER_CONFIG *ybf) {
193 0 : const int inner_bw = (ybf->border > VP9INNERBORDERINPIXELS)
194 : ? VP9INNERBORDERINPIXELS
195 0 : : ybf->border;
196 0 : extend_frame(ybf, inner_bw);
197 0 : }
198 :
199 : #if CONFIG_VP9_HIGHBITDEPTH
200 : static void memcpy_short_addr(uint8_t *dst8, const uint8_t *src8, int num) {
201 : uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
202 : uint16_t *src = CONVERT_TO_SHORTPTR(src8);
203 : memcpy(dst, src, num * sizeof(uint16_t));
204 : }
205 : #endif // CONFIG_VP9_HIGHBITDEPTH
206 : #endif // CONFIG_VP9
207 :
208 : // Copies the source image into the destination image and updates the
209 : // destination's UMV borders.
210 : // Note: The frames are assumed to be identical in size.
211 0 : void vp8_yv12_copy_frame_c(const YV12_BUFFER_CONFIG *src_ybc,
212 : YV12_BUFFER_CONFIG *dst_ybc) {
213 : int row;
214 0 : const uint8_t *src = src_ybc->y_buffer;
215 0 : uint8_t *dst = dst_ybc->y_buffer;
216 :
217 : #if 0
218 : /* These assertions are valid in the codec, but the libvpx-tester uses
219 : * this code slightly differently.
220 : */
221 : assert(src_ybc->y_width == dst_ybc->y_width);
222 : assert(src_ybc->y_height == dst_ybc->y_height);
223 : #endif
224 :
225 : #if CONFIG_VP9_HIGHBITDEPTH
226 : if (src_ybc->flags & YV12_FLAG_HIGHBITDEPTH) {
227 : assert(dst_ybc->flags & YV12_FLAG_HIGHBITDEPTH);
228 : for (row = 0; row < src_ybc->y_height; ++row) {
229 : memcpy_short_addr(dst, src, src_ybc->y_width);
230 : src += src_ybc->y_stride;
231 : dst += dst_ybc->y_stride;
232 : }
233 :
234 : src = src_ybc->u_buffer;
235 : dst = dst_ybc->u_buffer;
236 :
237 : for (row = 0; row < src_ybc->uv_height; ++row) {
238 : memcpy_short_addr(dst, src, src_ybc->uv_width);
239 : src += src_ybc->uv_stride;
240 : dst += dst_ybc->uv_stride;
241 : }
242 :
243 : src = src_ybc->v_buffer;
244 : dst = dst_ybc->v_buffer;
245 :
246 : for (row = 0; row < src_ybc->uv_height; ++row) {
247 : memcpy_short_addr(dst, src, src_ybc->uv_width);
248 : src += src_ybc->uv_stride;
249 : dst += dst_ybc->uv_stride;
250 : }
251 :
252 : vp8_yv12_extend_frame_borders_c(dst_ybc);
253 : return;
254 : } else {
255 : assert(!(dst_ybc->flags & YV12_FLAG_HIGHBITDEPTH));
256 : }
257 : #endif
258 :
259 0 : for (row = 0; row < src_ybc->y_height; ++row) {
260 0 : memcpy(dst, src, src_ybc->y_width);
261 0 : src += src_ybc->y_stride;
262 0 : dst += dst_ybc->y_stride;
263 : }
264 :
265 0 : src = src_ybc->u_buffer;
266 0 : dst = dst_ybc->u_buffer;
267 :
268 0 : for (row = 0; row < src_ybc->uv_height; ++row) {
269 0 : memcpy(dst, src, src_ybc->uv_width);
270 0 : src += src_ybc->uv_stride;
271 0 : dst += dst_ybc->uv_stride;
272 : }
273 :
274 0 : src = src_ybc->v_buffer;
275 0 : dst = dst_ybc->v_buffer;
276 :
277 0 : for (row = 0; row < src_ybc->uv_height; ++row) {
278 0 : memcpy(dst, src, src_ybc->uv_width);
279 0 : src += src_ybc->uv_stride;
280 0 : dst += dst_ybc->uv_stride;
281 : }
282 :
283 0 : vp8_yv12_extend_frame_borders_c(dst_ybc);
284 0 : }
285 :
286 0 : void vpx_yv12_copy_y_c(const YV12_BUFFER_CONFIG *src_ybc,
287 : YV12_BUFFER_CONFIG *dst_ybc) {
288 : int row;
289 0 : const uint8_t *src = src_ybc->y_buffer;
290 0 : uint8_t *dst = dst_ybc->y_buffer;
291 :
292 : #if CONFIG_VP9_HIGHBITDEPTH
293 : if (src_ybc->flags & YV12_FLAG_HIGHBITDEPTH) {
294 : const uint16_t *src16 = CONVERT_TO_SHORTPTR(src);
295 : uint16_t *dst16 = CONVERT_TO_SHORTPTR(dst);
296 : for (row = 0; row < src_ybc->y_height; ++row) {
297 : memcpy(dst16, src16, src_ybc->y_width * sizeof(uint16_t));
298 : src16 += src_ybc->y_stride;
299 : dst16 += dst_ybc->y_stride;
300 : }
301 : return;
302 : }
303 : #endif
304 :
305 0 : for (row = 0; row < src_ybc->y_height; ++row) {
306 0 : memcpy(dst, src, src_ybc->y_width);
307 0 : src += src_ybc->y_stride;
308 0 : dst += dst_ybc->y_stride;
309 : }
310 0 : }
|