Line data Source code
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 : #include "./aom_config.h"
14 : #include "./aom_scale_rtcd.h"
15 : #include "aom/aom_integer.h"
16 : #include "aom_mem/aom_mem.h"
17 : #include "aom_ports/mem.h"
18 : #include "aom_scale/yv12config.h"
19 :
20 0 : static void extend_plane(uint8_t *const src, int src_stride, int width,
21 : int height, int extend_top, int extend_left,
22 : int extend_bottom, int extend_right) {
23 : int i;
24 0 : const int linesize = extend_left + extend_right + width;
25 :
26 : /* copy the left and right most columns out */
27 0 : uint8_t *src_ptr1 = src;
28 0 : uint8_t *src_ptr2 = src + width - 1;
29 0 : uint8_t *dst_ptr1 = src - extend_left;
30 0 : uint8_t *dst_ptr2 = src + width;
31 :
32 0 : for (i = 0; i < height; ++i) {
33 0 : memset(dst_ptr1, src_ptr1[0], extend_left);
34 0 : memset(dst_ptr2, src_ptr2[0], extend_right);
35 0 : src_ptr1 += src_stride;
36 0 : src_ptr2 += src_stride;
37 0 : dst_ptr1 += src_stride;
38 0 : dst_ptr2 += src_stride;
39 : }
40 :
41 : /* Now copy the top and bottom lines into each line of the respective
42 : * borders
43 : */
44 0 : src_ptr1 = src - extend_left;
45 0 : src_ptr2 = src + src_stride * (height - 1) - extend_left;
46 0 : dst_ptr1 = src + src_stride * -extend_top - extend_left;
47 0 : dst_ptr2 = src + src_stride * height - extend_left;
48 :
49 0 : for (i = 0; i < extend_top; ++i) {
50 0 : memcpy(dst_ptr1, src_ptr1, linesize);
51 0 : dst_ptr1 += src_stride;
52 : }
53 :
54 0 : for (i = 0; i < extend_bottom; ++i) {
55 0 : memcpy(dst_ptr2, src_ptr2, linesize);
56 0 : dst_ptr2 += src_stride;
57 : }
58 0 : }
59 :
60 : #if CONFIG_HIGHBITDEPTH
61 0 : static void extend_plane_high(uint8_t *const src8, int src_stride, int width,
62 : int height, int extend_top, int extend_left,
63 : int extend_bottom, int extend_right) {
64 : int i;
65 0 : const int linesize = extend_left + extend_right + width;
66 0 : uint16_t *src = CONVERT_TO_SHORTPTR(src8);
67 :
68 : /* copy the left and right most columns out */
69 0 : uint16_t *src_ptr1 = src;
70 0 : uint16_t *src_ptr2 = src + width - 1;
71 0 : uint16_t *dst_ptr1 = src - extend_left;
72 0 : uint16_t *dst_ptr2 = src + width;
73 :
74 0 : for (i = 0; i < height; ++i) {
75 0 : aom_memset16(dst_ptr1, src_ptr1[0], extend_left);
76 0 : aom_memset16(dst_ptr2, src_ptr2[0], extend_right);
77 0 : src_ptr1 += src_stride;
78 0 : src_ptr2 += src_stride;
79 0 : dst_ptr1 += src_stride;
80 0 : dst_ptr2 += src_stride;
81 : }
82 :
83 : /* Now copy the top and bottom lines into each line of the respective
84 : * borders
85 : */
86 0 : src_ptr1 = src - extend_left;
87 0 : src_ptr2 = src + src_stride * (height - 1) - extend_left;
88 0 : dst_ptr1 = src + src_stride * -extend_top - extend_left;
89 0 : dst_ptr2 = src + src_stride * height - extend_left;
90 :
91 0 : for (i = 0; i < extend_top; ++i) {
92 0 : memcpy(dst_ptr1, src_ptr1, linesize * sizeof(uint16_t));
93 0 : dst_ptr1 += src_stride;
94 : }
95 :
96 0 : for (i = 0; i < extend_bottom; ++i) {
97 0 : memcpy(dst_ptr2, src_ptr2, linesize * sizeof(uint16_t));
98 0 : dst_ptr2 += src_stride;
99 : }
100 0 : }
101 : #endif
102 :
103 0 : void aom_yv12_extend_frame_borders_c(YV12_BUFFER_CONFIG *ybf) {
104 0 : const int uv_border = ybf->border / 2;
105 :
106 0 : assert(ybf->border % 2 == 0);
107 0 : assert(ybf->y_height - ybf->y_crop_height < 16);
108 0 : assert(ybf->y_width - ybf->y_crop_width < 16);
109 0 : assert(ybf->y_height - ybf->y_crop_height >= 0);
110 0 : assert(ybf->y_width - ybf->y_crop_width >= 0);
111 :
112 : #if CONFIG_HIGHBITDEPTH
113 0 : if (ybf->flags & YV12_FLAG_HIGHBITDEPTH) {
114 0 : extend_plane_high(ybf->y_buffer, ybf->y_stride, ybf->y_crop_width,
115 : ybf->y_crop_height, ybf->border, ybf->border,
116 0 : ybf->border + ybf->y_height - ybf->y_crop_height,
117 0 : ybf->border + ybf->y_width - ybf->y_crop_width);
118 :
119 0 : extend_plane_high(ybf->u_buffer, ybf->uv_stride, ybf->uv_crop_width,
120 : ybf->uv_crop_height, uv_border, uv_border,
121 0 : uv_border + ybf->uv_height - ybf->uv_crop_height,
122 0 : uv_border + ybf->uv_width - ybf->uv_crop_width);
123 :
124 0 : extend_plane_high(ybf->v_buffer, ybf->uv_stride, ybf->uv_crop_width,
125 : ybf->uv_crop_height, uv_border, uv_border,
126 0 : uv_border + ybf->uv_height - ybf->uv_crop_height,
127 0 : uv_border + ybf->uv_width - ybf->uv_crop_width);
128 0 : return;
129 : }
130 : #endif
131 0 : extend_plane(ybf->y_buffer, ybf->y_stride, ybf->y_crop_width,
132 : ybf->y_crop_height, ybf->border, ybf->border,
133 0 : ybf->border + ybf->y_height - ybf->y_crop_height,
134 0 : ybf->border + ybf->y_width - ybf->y_crop_width);
135 :
136 0 : extend_plane(ybf->u_buffer, ybf->uv_stride, ybf->uv_crop_width,
137 : ybf->uv_crop_height, uv_border, uv_border,
138 0 : uv_border + ybf->uv_height - ybf->uv_crop_height,
139 0 : uv_border + ybf->uv_width - ybf->uv_crop_width);
140 :
141 0 : extend_plane(ybf->v_buffer, ybf->uv_stride, ybf->uv_crop_width,
142 : ybf->uv_crop_height, uv_border, uv_border,
143 0 : uv_border + ybf->uv_height - ybf->uv_crop_height,
144 0 : uv_border + ybf->uv_width - ybf->uv_crop_width);
145 : }
146 :
147 : #if CONFIG_AV1
148 0 : static void extend_frame(YV12_BUFFER_CONFIG *const ybf, int ext_size) {
149 0 : const int c_w = ybf->uv_crop_width;
150 0 : const int c_h = ybf->uv_crop_height;
151 0 : const int ss_x = ybf->uv_width < ybf->y_width;
152 0 : const int ss_y = ybf->uv_height < ybf->y_height;
153 0 : const int c_et = ext_size >> ss_y;
154 0 : const int c_el = ext_size >> ss_x;
155 0 : const int c_eb = c_et + ybf->uv_height - ybf->uv_crop_height;
156 0 : const int c_er = c_el + ybf->uv_width - ybf->uv_crop_width;
157 :
158 0 : assert(ybf->y_height - ybf->y_crop_height < 16);
159 0 : assert(ybf->y_width - ybf->y_crop_width < 16);
160 0 : assert(ybf->y_height - ybf->y_crop_height >= 0);
161 0 : assert(ybf->y_width - ybf->y_crop_width >= 0);
162 :
163 : #if CONFIG_HIGHBITDEPTH
164 0 : if (ybf->flags & YV12_FLAG_HIGHBITDEPTH) {
165 0 : extend_plane_high(ybf->y_buffer, ybf->y_stride, ybf->y_crop_width,
166 : ybf->y_crop_height, ext_size, ext_size,
167 0 : ext_size + ybf->y_height - ybf->y_crop_height,
168 0 : ext_size + ybf->y_width - ybf->y_crop_width);
169 0 : extend_plane_high(ybf->u_buffer, ybf->uv_stride, c_w, c_h, c_et, c_el, c_eb,
170 : c_er);
171 0 : extend_plane_high(ybf->v_buffer, ybf->uv_stride, c_w, c_h, c_et, c_el, c_eb,
172 : c_er);
173 0 : return;
174 : }
175 : #endif
176 0 : extend_plane(ybf->y_buffer, ybf->y_stride, ybf->y_crop_width,
177 : ybf->y_crop_height, ext_size, ext_size,
178 0 : ext_size + ybf->y_height - ybf->y_crop_height,
179 0 : ext_size + ybf->y_width - ybf->y_crop_width);
180 :
181 0 : extend_plane(ybf->u_buffer, ybf->uv_stride, c_w, c_h, c_et, c_el, c_eb, c_er);
182 :
183 0 : extend_plane(ybf->v_buffer, ybf->uv_stride, c_w, c_h, c_et, c_el, c_eb, c_er);
184 : }
185 :
186 0 : void aom_extend_frame_borders_c(YV12_BUFFER_CONFIG *ybf) {
187 0 : extend_frame(ybf, ybf->border);
188 0 : }
189 :
190 0 : void aom_extend_frame_inner_borders_c(YV12_BUFFER_CONFIG *ybf) {
191 0 : const int inner_bw = (ybf->border > AOMINNERBORDERINPIXELS)
192 : ? AOMINNERBORDERINPIXELS
193 0 : : ybf->border;
194 0 : extend_frame(ybf, inner_bw);
195 0 : }
196 :
197 0 : void aom_extend_frame_borders_y_c(YV12_BUFFER_CONFIG *ybf) {
198 0 : int ext_size = ybf->border;
199 0 : assert(ybf->y_height - ybf->y_crop_height < 16);
200 0 : assert(ybf->y_width - ybf->y_crop_width < 16);
201 0 : assert(ybf->y_height - ybf->y_crop_height >= 0);
202 0 : assert(ybf->y_width - ybf->y_crop_width >= 0);
203 :
204 : #if CONFIG_HIGHBITDEPTH
205 0 : if (ybf->flags & YV12_FLAG_HIGHBITDEPTH) {
206 0 : extend_plane_high(ybf->y_buffer, ybf->y_stride, ybf->y_crop_width,
207 : ybf->y_crop_height, ext_size, ext_size,
208 0 : ext_size + ybf->y_height - ybf->y_crop_height,
209 0 : ext_size + ybf->y_width - ybf->y_crop_width);
210 0 : return;
211 : }
212 : #endif
213 0 : extend_plane(ybf->y_buffer, ybf->y_stride, ybf->y_crop_width,
214 : ybf->y_crop_height, ext_size, ext_size,
215 0 : ext_size + ybf->y_height - ybf->y_crop_height,
216 0 : ext_size + ybf->y_width - ybf->y_crop_width);
217 : }
218 : #endif // CONFIG_AV1
219 :
220 : #if CONFIG_HIGHBITDEPTH
221 0 : static void memcpy_short_addr(uint8_t *dst8, const uint8_t *src8, int num) {
222 0 : uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
223 0 : uint16_t *src = CONVERT_TO_SHORTPTR(src8);
224 0 : memcpy(dst, src, num * sizeof(uint16_t));
225 0 : }
226 : #endif // CONFIG_HIGHBITDEPTH
227 :
228 : // Copies the source image into the destination image and updates the
229 : // destination's UMV borders.
230 : // Note: The frames are assumed to be identical in size.
231 0 : void aom_yv12_copy_frame_c(const YV12_BUFFER_CONFIG *src_bc,
232 : YV12_BUFFER_CONFIG *dst_bc) {
233 : int row;
234 0 : const uint8_t *src = src_bc->y_buffer;
235 0 : uint8_t *dst = dst_bc->y_buffer;
236 :
237 : #if 0
238 : /* These assertions are valid in the codec, but the libaom-tester uses
239 : * this code slightly differently.
240 : */
241 : assert(src_bc->y_width == dst_bc->y_width);
242 : assert(src_bc->y_height == dst_bc->y_height);
243 : #endif
244 :
245 : #if CONFIG_HIGHBITDEPTH
246 0 : if (src_bc->flags & YV12_FLAG_HIGHBITDEPTH) {
247 0 : assert(dst_bc->flags & YV12_FLAG_HIGHBITDEPTH);
248 0 : for (row = 0; row < src_bc->y_height; ++row) {
249 0 : memcpy_short_addr(dst, src, src_bc->y_width);
250 0 : src += src_bc->y_stride;
251 0 : dst += dst_bc->y_stride;
252 : }
253 :
254 0 : src = src_bc->u_buffer;
255 0 : dst = dst_bc->u_buffer;
256 :
257 0 : for (row = 0; row < src_bc->uv_height; ++row) {
258 0 : memcpy_short_addr(dst, src, src_bc->uv_width);
259 0 : src += src_bc->uv_stride;
260 0 : dst += dst_bc->uv_stride;
261 : }
262 :
263 0 : src = src_bc->v_buffer;
264 0 : dst = dst_bc->v_buffer;
265 :
266 0 : for (row = 0; row < src_bc->uv_height; ++row) {
267 0 : memcpy_short_addr(dst, src, src_bc->uv_width);
268 0 : src += src_bc->uv_stride;
269 0 : dst += dst_bc->uv_stride;
270 : }
271 :
272 0 : aom_yv12_extend_frame_borders_c(dst_bc);
273 0 : return;
274 : } else {
275 0 : assert(!(dst_bc->flags & YV12_FLAG_HIGHBITDEPTH));
276 : }
277 : #endif
278 :
279 0 : for (row = 0; row < src_bc->y_height; ++row) {
280 0 : memcpy(dst, src, src_bc->y_width);
281 0 : src += src_bc->y_stride;
282 0 : dst += dst_bc->y_stride;
283 : }
284 :
285 0 : src = src_bc->u_buffer;
286 0 : dst = dst_bc->u_buffer;
287 :
288 0 : for (row = 0; row < src_bc->uv_height; ++row) {
289 0 : memcpy(dst, src, src_bc->uv_width);
290 0 : src += src_bc->uv_stride;
291 0 : dst += dst_bc->uv_stride;
292 : }
293 :
294 0 : src = src_bc->v_buffer;
295 0 : dst = dst_bc->v_buffer;
296 :
297 0 : for (row = 0; row < src_bc->uv_height; ++row) {
298 0 : memcpy(dst, src, src_bc->uv_width);
299 0 : src += src_bc->uv_stride;
300 0 : dst += dst_bc->uv_stride;
301 : }
302 :
303 0 : aom_yv12_extend_frame_borders_c(dst_bc);
304 : }
305 :
306 0 : void aom_yv12_copy_y_c(const YV12_BUFFER_CONFIG *src_ybc,
307 : YV12_BUFFER_CONFIG *dst_ybc) {
308 : int row;
309 0 : const uint8_t *src = src_ybc->y_buffer;
310 0 : uint8_t *dst = dst_ybc->y_buffer;
311 :
312 : #if CONFIG_HIGHBITDEPTH
313 0 : if (src_ybc->flags & YV12_FLAG_HIGHBITDEPTH) {
314 0 : const uint16_t *src16 = CONVERT_TO_SHORTPTR(src);
315 0 : uint16_t *dst16 = CONVERT_TO_SHORTPTR(dst);
316 0 : for (row = 0; row < src_ybc->y_height; ++row) {
317 0 : memcpy(dst16, src16, src_ybc->y_width * sizeof(uint16_t));
318 0 : src16 += src_ybc->y_stride;
319 0 : dst16 += dst_ybc->y_stride;
320 : }
321 0 : return;
322 : }
323 : #endif // CONFIG_HIGHBITDEPTH
324 :
325 0 : for (row = 0; row < src_ybc->y_height; ++row) {
326 0 : memcpy(dst, src, src_ybc->y_width);
327 0 : src += src_ybc->y_stride;
328 0 : dst += dst_ybc->y_stride;
329 : }
330 : }
331 :
332 0 : void aom_yv12_copy_u_c(const YV12_BUFFER_CONFIG *src_bc,
333 : YV12_BUFFER_CONFIG *dst_bc) {
334 : int row;
335 0 : const uint8_t *src = src_bc->u_buffer;
336 0 : uint8_t *dst = dst_bc->u_buffer;
337 :
338 : #if CONFIG_HIGHBITDEPTH
339 0 : if (src_bc->flags & YV12_FLAG_HIGHBITDEPTH) {
340 0 : const uint16_t *src16 = CONVERT_TO_SHORTPTR(src);
341 0 : uint16_t *dst16 = CONVERT_TO_SHORTPTR(dst);
342 0 : for (row = 0; row < src_bc->uv_height; ++row) {
343 0 : memcpy(dst16, src16, src_bc->uv_width * sizeof(uint16_t));
344 0 : src16 += src_bc->uv_stride;
345 0 : dst16 += dst_bc->uv_stride;
346 : }
347 0 : return;
348 : }
349 : #endif // CONFIG_HIGHBITDEPTH
350 :
351 0 : for (row = 0; row < src_bc->uv_height; ++row) {
352 0 : memcpy(dst, src, src_bc->uv_width);
353 0 : src += src_bc->uv_stride;
354 0 : dst += dst_bc->uv_stride;
355 : }
356 : }
357 :
358 0 : void aom_yv12_copy_v_c(const YV12_BUFFER_CONFIG *src_bc,
359 : YV12_BUFFER_CONFIG *dst_bc) {
360 : int row;
361 0 : const uint8_t *src = src_bc->v_buffer;
362 0 : uint8_t *dst = dst_bc->v_buffer;
363 :
364 : #if CONFIG_HIGHBITDEPTH
365 0 : if (src_bc->flags & YV12_FLAG_HIGHBITDEPTH) {
366 0 : const uint16_t *src16 = CONVERT_TO_SHORTPTR(src);
367 0 : uint16_t *dst16 = CONVERT_TO_SHORTPTR(dst);
368 0 : for (row = 0; row < src_bc->uv_height; ++row) {
369 0 : memcpy(dst16, src16, src_bc->uv_width * sizeof(uint16_t));
370 0 : src16 += src_bc->uv_stride;
371 0 : dst16 += dst_bc->uv_stride;
372 : }
373 0 : return;
374 : }
375 : #endif // CONFIG_HIGHBITDEPTH
376 :
377 0 : for (row = 0; row < src_bc->uv_height; ++row) {
378 0 : memcpy(dst, src, src_bc->uv_width);
379 0 : src += src_bc->uv_stride;
380 0 : dst += dst_bc->uv_stride;
381 : }
382 : }
|