• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "config/aom_scale_rtcd.h"
16 
17 #include "aom/aom_integer.h"
18 #include "aom_mem/aom_mem.h"
19 #include "aom_ports/mem.h"
20 #include "aom_scale/yv12config.h"
21 
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)22 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   const int linesize = extend_left + extend_right + width;
27 
28   /* copy the left and right most columns out */
29   uint8_t *src_ptr1 = src;
30   uint8_t *src_ptr2 = src + width - 1;
31   uint8_t *dst_ptr1 = src - extend_left;
32   uint8_t *dst_ptr2 = src + width;
33 
34   for (i = 0; i < height; ++i) {
35     memset(dst_ptr1, src_ptr1[0], extend_left);
36     memset(dst_ptr2, src_ptr2[0], extend_right);
37     src_ptr1 += src_stride;
38     src_ptr2 += src_stride;
39     dst_ptr1 += src_stride;
40     dst_ptr2 += src_stride;
41   }
42 
43   /* Now copy the top and bottom lines into each line of the respective
44    * borders
45    */
46   src_ptr1 = src - extend_left;
47   src_ptr2 = src + src_stride * (height - 1) - extend_left;
48   dst_ptr1 = src + src_stride * -extend_top - extend_left;
49   dst_ptr2 = src + src_stride * height - extend_left;
50 
51   for (i = 0; i < extend_top; ++i) {
52     memcpy(dst_ptr1, src_ptr1, linesize);
53     dst_ptr1 += src_stride;
54   }
55 
56   for (i = 0; i < extend_bottom; ++i) {
57     memcpy(dst_ptr2, src_ptr2, linesize);
58     dst_ptr2 += src_stride;
59   }
60 }
61 
extend_plane_high(uint8_t * const src8,int src_stride,int width,int height,int extend_top,int extend_left,int extend_bottom,int extend_right)62 static void extend_plane_high(uint8_t *const src8, int src_stride, int width,
63                               int height, int extend_top, int extend_left,
64                               int extend_bottom, int extend_right) {
65   int i;
66   const int linesize = extend_left + extend_right + width;
67   uint16_t *src = CONVERT_TO_SHORTPTR(src8);
68 
69   /* copy the left and right most columns out */
70   uint16_t *src_ptr1 = src;
71   uint16_t *src_ptr2 = src + width - 1;
72   uint16_t *dst_ptr1 = src - extend_left;
73   uint16_t *dst_ptr2 = src + width;
74 
75   for (i = 0; i < height; ++i) {
76     aom_memset16(dst_ptr1, src_ptr1[0], extend_left);
77     aom_memset16(dst_ptr2, src_ptr2[0], extend_right);
78     src_ptr1 += src_stride;
79     src_ptr2 += src_stride;
80     dst_ptr1 += src_stride;
81     dst_ptr2 += src_stride;
82   }
83 
84   /* Now copy the top and bottom lines into each line of the respective
85    * borders
86    */
87   src_ptr1 = src - extend_left;
88   src_ptr2 = src + src_stride * (height - 1) - extend_left;
89   dst_ptr1 = src + src_stride * -extend_top - extend_left;
90   dst_ptr2 = src + src_stride * height - extend_left;
91 
92   for (i = 0; i < extend_top; ++i) {
93     memcpy(dst_ptr1, src_ptr1, linesize * sizeof(uint16_t));
94     dst_ptr1 += src_stride;
95   }
96 
97   for (i = 0; i < extend_bottom; ++i) {
98     memcpy(dst_ptr2, src_ptr2, linesize * sizeof(uint16_t));
99     dst_ptr2 += src_stride;
100   }
101 }
102 
aom_yv12_extend_frame_borders_c(YV12_BUFFER_CONFIG * ybf,const int num_planes)103 void aom_yv12_extend_frame_borders_c(YV12_BUFFER_CONFIG *ybf,
104                                      const int num_planes) {
105   assert(ybf->border % 2 == 0);
106   assert(ybf->y_height - ybf->y_crop_height < 16);
107   assert(ybf->y_width - ybf->y_crop_width < 16);
108   assert(ybf->y_height - ybf->y_crop_height >= 0);
109   assert(ybf->y_width - ybf->y_crop_width >= 0);
110 
111   if (ybf->flags & YV12_FLAG_HIGHBITDEPTH) {
112     for (int plane = 0; plane < num_planes; ++plane) {
113       const int is_uv = plane > 0;
114       const int plane_border = ybf->border >> is_uv;
115       extend_plane_high(
116           ybf->buffers[plane], ybf->strides[is_uv], ybf->crop_widths[is_uv],
117           ybf->crop_heights[is_uv], plane_border, plane_border,
118           plane_border + ybf->heights[is_uv] - ybf->crop_heights[is_uv],
119           plane_border + ybf->widths[is_uv] - ybf->crop_widths[is_uv]);
120     }
121     return;
122   }
123   for (int plane = 0; plane < num_planes; ++plane) {
124     const int is_uv = plane > 0;
125     const int plane_border = ybf->border >> is_uv;
126     extend_plane(ybf->buffers[plane], ybf->strides[is_uv],
127                  ybf->crop_widths[is_uv], ybf->crop_heights[is_uv],
128                  plane_border, plane_border,
129                  plane_border + ybf->heights[is_uv] - ybf->crop_heights[is_uv],
130                  plane_border + ybf->widths[is_uv] - ybf->crop_widths[is_uv]);
131   }
132 }
133 
extend_frame(YV12_BUFFER_CONFIG * const ybf,int ext_size,const int num_planes)134 static void extend_frame(YV12_BUFFER_CONFIG *const ybf, int ext_size,
135                          const int num_planes) {
136   const int ss_x = ybf->uv_width < ybf->y_width;
137   const int ss_y = ybf->uv_height < ybf->y_height;
138 
139   assert(ybf->y_height - ybf->y_crop_height < 16);
140   assert(ybf->y_width - ybf->y_crop_width < 16);
141   assert(ybf->y_height - ybf->y_crop_height >= 0);
142   assert(ybf->y_width - ybf->y_crop_width >= 0);
143 
144   if (ybf->flags & YV12_FLAG_HIGHBITDEPTH) {
145     for (int plane = 0; plane < num_planes; ++plane) {
146       const int is_uv = plane > 0;
147       const int top = ext_size >> (is_uv ? ss_y : 0);
148       const int left = ext_size >> (is_uv ? ss_x : 0);
149       const int bottom = top + ybf->heights[is_uv] - ybf->crop_heights[is_uv];
150       const int right = left + ybf->widths[is_uv] - ybf->crop_widths[is_uv];
151       extend_plane_high(ybf->buffers[plane], ybf->strides[is_uv],
152                         ybf->crop_widths[is_uv], ybf->crop_heights[is_uv], top,
153                         left, bottom, right);
154     }
155     return;
156   }
157   for (int plane = 0; plane < num_planes; ++plane) {
158     const int is_uv = plane > 0;
159     const int top = ext_size >> (is_uv ? ss_y : 0);
160     const int left = ext_size >> (is_uv ? ss_x : 0);
161     const int bottom = top + ybf->heights[is_uv] - ybf->crop_heights[is_uv];
162     const int right = left + ybf->widths[is_uv] - ybf->crop_widths[is_uv];
163     extend_plane(ybf->buffers[plane], ybf->strides[is_uv],
164                  ybf->crop_widths[is_uv], ybf->crop_heights[is_uv], top, left,
165                  bottom, right);
166   }
167 }
168 
aom_extend_frame_borders_c(YV12_BUFFER_CONFIG * ybf,const int num_planes)169 void aom_extend_frame_borders_c(YV12_BUFFER_CONFIG *ybf, const int num_planes) {
170   extend_frame(ybf, ybf->border, num_planes);
171 }
172 
aom_extend_frame_inner_borders_c(YV12_BUFFER_CONFIG * ybf,const int num_planes)173 void aom_extend_frame_inner_borders_c(YV12_BUFFER_CONFIG *ybf,
174                                       const int num_planes) {
175   const int inner_bw = (ybf->border > AOMINNERBORDERINPIXELS)
176                            ? AOMINNERBORDERINPIXELS
177                            : ybf->border;
178   extend_frame(ybf, inner_bw, num_planes);
179 }
180 
aom_extend_frame_borders_y_c(YV12_BUFFER_CONFIG * ybf)181 void aom_extend_frame_borders_y_c(YV12_BUFFER_CONFIG *ybf) {
182   int ext_size = ybf->border;
183   assert(ybf->y_height - ybf->y_crop_height < 16);
184   assert(ybf->y_width - ybf->y_crop_width < 16);
185   assert(ybf->y_height - ybf->y_crop_height >= 0);
186   assert(ybf->y_width - ybf->y_crop_width >= 0);
187 
188   if (ybf->flags & YV12_FLAG_HIGHBITDEPTH) {
189     extend_plane_high(ybf->y_buffer, ybf->y_stride, ybf->y_crop_width,
190                       ybf->y_crop_height, ext_size, ext_size,
191                       ext_size + ybf->y_height - ybf->y_crop_height,
192                       ext_size + ybf->y_width - ybf->y_crop_width);
193     return;
194   }
195   extend_plane(ybf->y_buffer, ybf->y_stride, ybf->y_crop_width,
196                ybf->y_crop_height, ext_size, ext_size,
197                ext_size + ybf->y_height - ybf->y_crop_height,
198                ext_size + ybf->y_width - ybf->y_crop_width);
199 }
200 
memcpy_short_addr(uint8_t * dst8,const uint8_t * src8,int num)201 static void memcpy_short_addr(uint8_t *dst8, const uint8_t *src8, int num) {
202   uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
203   uint16_t *src = CONVERT_TO_SHORTPTR(src8);
204   memcpy(dst, src, num * sizeof(uint16_t));
205 }
206 
207 // Copies the source image into the destination image and updates the
208 // destination's UMV borders.
209 // Note: The frames are assumed to be identical in size.
aom_yv12_copy_frame_c(const YV12_BUFFER_CONFIG * src_bc,YV12_BUFFER_CONFIG * dst_bc,const int num_planes)210 void aom_yv12_copy_frame_c(const YV12_BUFFER_CONFIG *src_bc,
211                            YV12_BUFFER_CONFIG *dst_bc, const int num_planes) {
212 #if 0
213   /* These assertions are valid in the codec, but the libaom-tester uses
214    * this code slightly differently.
215    */
216   assert(src_bc->y_width == dst_bc->y_width);
217   assert(src_bc->y_height == dst_bc->y_height);
218 #endif
219 
220   assert((src_bc->flags & YV12_FLAG_HIGHBITDEPTH) ==
221          (dst_bc->flags & YV12_FLAG_HIGHBITDEPTH));
222 
223   if (src_bc->flags & YV12_FLAG_HIGHBITDEPTH) {
224     for (int plane = 0; plane < num_planes; ++plane) {
225       const uint8_t *plane_src = src_bc->buffers[plane];
226       uint8_t *plane_dst = dst_bc->buffers[plane];
227       const int is_uv = plane > 0;
228 
229       for (int row = 0; row < src_bc->heights[is_uv]; ++row) {
230         memcpy_short_addr(plane_dst, plane_src, src_bc->widths[is_uv]);
231         plane_src += src_bc->strides[is_uv];
232         plane_dst += dst_bc->strides[is_uv];
233       }
234     }
235     aom_yv12_extend_frame_borders_c(dst_bc, num_planes);
236     return;
237   }
238   for (int plane = 0; plane < num_planes; ++plane) {
239     const uint8_t *plane_src = src_bc->buffers[plane];
240     uint8_t *plane_dst = dst_bc->buffers[plane];
241     const int is_uv = plane > 0;
242 
243     for (int row = 0; row < src_bc->heights[is_uv]; ++row) {
244       memcpy(plane_dst, plane_src, src_bc->widths[is_uv]);
245       plane_src += src_bc->strides[is_uv];
246       plane_dst += dst_bc->strides[is_uv];
247     }
248   }
249   aom_yv12_extend_frame_borders_c(dst_bc, num_planes);
250 }
251 
aom_yv12_copy_y_c(const YV12_BUFFER_CONFIG * src_ybc,YV12_BUFFER_CONFIG * dst_ybc)252 void aom_yv12_copy_y_c(const YV12_BUFFER_CONFIG *src_ybc,
253                        YV12_BUFFER_CONFIG *dst_ybc) {
254   int row;
255   const uint8_t *src = src_ybc->y_buffer;
256   uint8_t *dst = dst_ybc->y_buffer;
257 
258   if (src_ybc->flags & YV12_FLAG_HIGHBITDEPTH) {
259     const uint16_t *src16 = CONVERT_TO_SHORTPTR(src);
260     uint16_t *dst16 = CONVERT_TO_SHORTPTR(dst);
261     for (row = 0; row < src_ybc->y_height; ++row) {
262       memcpy(dst16, src16, src_ybc->y_width * sizeof(uint16_t));
263       src16 += src_ybc->y_stride;
264       dst16 += dst_ybc->y_stride;
265     }
266     return;
267   }
268 
269   for (row = 0; row < src_ybc->y_height; ++row) {
270     memcpy(dst, src, src_ybc->y_width);
271     src += src_ybc->y_stride;
272     dst += dst_ybc->y_stride;
273   }
274 }
275 
aom_yv12_copy_u_c(const YV12_BUFFER_CONFIG * src_bc,YV12_BUFFER_CONFIG * dst_bc)276 void aom_yv12_copy_u_c(const YV12_BUFFER_CONFIG *src_bc,
277                        YV12_BUFFER_CONFIG *dst_bc) {
278   int row;
279   const uint8_t *src = src_bc->u_buffer;
280   uint8_t *dst = dst_bc->u_buffer;
281 
282   if (src_bc->flags & YV12_FLAG_HIGHBITDEPTH) {
283     const uint16_t *src16 = CONVERT_TO_SHORTPTR(src);
284     uint16_t *dst16 = CONVERT_TO_SHORTPTR(dst);
285     for (row = 0; row < src_bc->uv_height; ++row) {
286       memcpy(dst16, src16, src_bc->uv_width * sizeof(uint16_t));
287       src16 += src_bc->uv_stride;
288       dst16 += dst_bc->uv_stride;
289     }
290     return;
291   }
292 
293   for (row = 0; row < src_bc->uv_height; ++row) {
294     memcpy(dst, src, src_bc->uv_width);
295     src += src_bc->uv_stride;
296     dst += dst_bc->uv_stride;
297   }
298 }
299 
aom_yv12_copy_v_c(const YV12_BUFFER_CONFIG * src_bc,YV12_BUFFER_CONFIG * dst_bc)300 void aom_yv12_copy_v_c(const YV12_BUFFER_CONFIG *src_bc,
301                        YV12_BUFFER_CONFIG *dst_bc) {
302   int row;
303   const uint8_t *src = src_bc->v_buffer;
304   uint8_t *dst = dst_bc->v_buffer;
305 
306   if (src_bc->flags & YV12_FLAG_HIGHBITDEPTH) {
307     const uint16_t *src16 = CONVERT_TO_SHORTPTR(src);
308     uint16_t *dst16 = CONVERT_TO_SHORTPTR(dst);
309     for (row = 0; row < src_bc->uv_height; ++row) {
310       memcpy(dst16, src16, src_bc->uv_width * sizeof(uint16_t));
311       src16 += src_bc->uv_stride;
312       dst16 += dst_bc->uv_stride;
313     }
314     return;
315   }
316 
317   for (row = 0; row < src_bc->uv_height; ++row) {
318     memcpy(dst, src, src_bc->uv_width);
319     src += src_bc->uv_stride;
320     dst += dst_bc->uv_stride;
321   }
322 }
323 
aom_yv12_partial_copy_y_c(const YV12_BUFFER_CONFIG * src_ybc,int hstart1,int hend1,int vstart1,int vend1,YV12_BUFFER_CONFIG * dst_ybc,int hstart2,int vstart2)324 void aom_yv12_partial_copy_y_c(const YV12_BUFFER_CONFIG *src_ybc, int hstart1,
325                                int hend1, int vstart1, int vend1,
326                                YV12_BUFFER_CONFIG *dst_ybc, int hstart2,
327                                int vstart2) {
328   int row;
329   const uint8_t *src = src_ybc->y_buffer;
330   uint8_t *dst = dst_ybc->y_buffer;
331 
332   if (src_ybc->flags & YV12_FLAG_HIGHBITDEPTH) {
333     const uint16_t *src16 =
334         CONVERT_TO_SHORTPTR(src + vstart1 * src_ybc->y_stride + hstart1);
335     uint16_t *dst16 =
336         CONVERT_TO_SHORTPTR(dst + vstart2 * dst_ybc->y_stride + hstart2);
337 
338     for (row = vstart1; row < vend1; ++row) {
339       memcpy(dst16, src16, (hend1 - hstart1) * sizeof(uint16_t));
340       src16 += src_ybc->y_stride;
341       dst16 += dst_ybc->y_stride;
342     }
343     return;
344   }
345   src = (src + vstart1 * src_ybc->y_stride + hstart1);
346   dst = (dst + vstart2 * dst_ybc->y_stride + hstart2);
347 
348   for (row = vstart1; row < vend1; ++row) {
349     memcpy(dst, src, (hend1 - hstart1));
350     src += src_ybc->y_stride;
351     dst += dst_ybc->y_stride;
352   }
353 }
354 
aom_yv12_partial_coloc_copy_y_c(const YV12_BUFFER_CONFIG * src_ybc,YV12_BUFFER_CONFIG * dst_ybc,int hstart,int hend,int vstart,int vend)355 void aom_yv12_partial_coloc_copy_y_c(const YV12_BUFFER_CONFIG *src_ybc,
356                                      YV12_BUFFER_CONFIG *dst_ybc, int hstart,
357                                      int hend, int vstart, int vend) {
358   aom_yv12_partial_copy_y_c(src_ybc, hstart, hend, vstart, vend, dst_ybc,
359                             hstart, vstart);
360 }
361 
aom_yv12_partial_copy_u_c(const YV12_BUFFER_CONFIG * src_bc,int hstart1,int hend1,int vstart1,int vend1,YV12_BUFFER_CONFIG * dst_bc,int hstart2,int vstart2)362 void aom_yv12_partial_copy_u_c(const YV12_BUFFER_CONFIG *src_bc, int hstart1,
363                                int hend1, int vstart1, int vend1,
364                                YV12_BUFFER_CONFIG *dst_bc, int hstart2,
365                                int vstart2) {
366   int row;
367   const uint8_t *src = src_bc->u_buffer;
368   uint8_t *dst = dst_bc->u_buffer;
369 
370   if (src_bc->flags & YV12_FLAG_HIGHBITDEPTH) {
371     const uint16_t *src16 =
372         CONVERT_TO_SHORTPTR(src + vstart1 * src_bc->uv_stride + hstart1);
373     uint16_t *dst16 =
374         CONVERT_TO_SHORTPTR(dst + vstart2 * dst_bc->uv_stride + hstart2);
375     for (row = vstart1; row < vend1; ++row) {
376       memcpy(dst16, src16, (hend1 - hstart1) * sizeof(uint16_t));
377       src16 += src_bc->uv_stride;
378       dst16 += dst_bc->uv_stride;
379     }
380     return;
381   }
382 
383   src = (src + vstart1 * src_bc->uv_stride + hstart1);
384   dst = (dst + vstart2 * dst_bc->uv_stride + hstart2);
385 
386   for (row = vstart1; row < vend1; ++row) {
387     memcpy(dst, src, (hend1 - hstart1));
388     src += src_bc->uv_stride;
389     dst += dst_bc->uv_stride;
390   }
391 }
392 
aom_yv12_partial_coloc_copy_u_c(const YV12_BUFFER_CONFIG * src_bc,YV12_BUFFER_CONFIG * dst_bc,int hstart,int hend,int vstart,int vend)393 void aom_yv12_partial_coloc_copy_u_c(const YV12_BUFFER_CONFIG *src_bc,
394                                      YV12_BUFFER_CONFIG *dst_bc, int hstart,
395                                      int hend, int vstart, int vend) {
396   aom_yv12_partial_copy_u_c(src_bc, hstart, hend, vstart, vend, dst_bc, hstart,
397                             vstart);
398 }
399 
aom_yv12_partial_copy_v_c(const YV12_BUFFER_CONFIG * src_bc,int hstart1,int hend1,int vstart1,int vend1,YV12_BUFFER_CONFIG * dst_bc,int hstart2,int vstart2)400 void aom_yv12_partial_copy_v_c(const YV12_BUFFER_CONFIG *src_bc, int hstart1,
401                                int hend1, int vstart1, int vend1,
402                                YV12_BUFFER_CONFIG *dst_bc, int hstart2,
403                                int vstart2) {
404   int row;
405   const uint8_t *src = src_bc->v_buffer;
406   uint8_t *dst = dst_bc->v_buffer;
407 
408   if (src_bc->flags & YV12_FLAG_HIGHBITDEPTH) {
409     const uint16_t *src16 =
410         CONVERT_TO_SHORTPTR(src + vstart1 * src_bc->uv_stride + hstart1);
411     uint16_t *dst16 =
412         CONVERT_TO_SHORTPTR(dst + vstart2 * dst_bc->uv_stride + hstart2);
413     for (row = vstart1; row < vend1; ++row) {
414       memcpy(dst16, src16, (hend1 - hstart1) * sizeof(uint16_t));
415       src16 += src_bc->uv_stride;
416       dst16 += dst_bc->uv_stride;
417     }
418     return;
419   }
420 
421   src = (src + vstart1 * src_bc->uv_stride + hstart1);
422   dst = (dst + vstart2 * dst_bc->uv_stride + hstart2);
423 
424   for (row = vstart1; row < vend1; ++row) {
425     memcpy(dst, src, (hend1 - hstart1));
426     src += src_bc->uv_stride;
427     dst += dst_bc->uv_stride;
428   }
429 }
430 
aom_yv12_partial_coloc_copy_v_c(const YV12_BUFFER_CONFIG * src_bc,YV12_BUFFER_CONFIG * dst_bc,int hstart,int hend,int vstart,int vend)431 void aom_yv12_partial_coloc_copy_v_c(const YV12_BUFFER_CONFIG *src_bc,
432                                      YV12_BUFFER_CONFIG *dst_bc, int hstart,
433                                      int hend, int vstart, int vend) {
434   aom_yv12_partial_copy_v_c(src_bc, hstart, hend, vstart, vend, dst_bc, hstart,
435                             vstart);
436 }
437 
aom_yv12_realloc_with_new_border_c(YV12_BUFFER_CONFIG * ybf,int new_border,int byte_alignment,int num_planes)438 int aom_yv12_realloc_with_new_border_c(YV12_BUFFER_CONFIG *ybf, int new_border,
439                                        int byte_alignment, int num_planes) {
440   if (ybf) {
441     if (new_border == ybf->border) return 0;
442     YV12_BUFFER_CONFIG new_buf;
443     memset(&new_buf, 0, sizeof(new_buf));
444     const int error = aom_alloc_frame_buffer(
445         &new_buf, ybf->y_crop_width, ybf->y_crop_height, ybf->subsampling_x,
446         ybf->subsampling_y, ybf->flags & YV12_FLAG_HIGHBITDEPTH, new_border,
447         byte_alignment);
448     if (error) return error;
449     // Copy image buffer
450     aom_yv12_copy_frame(ybf, &new_buf, num_planes);
451 
452     // Extend up to new border
453     aom_extend_frame_borders(&new_buf, num_planes);
454 
455     // Now free the old buffer and replace with the new
456     aom_free_frame_buffer(ybf);
457     memcpy(ybf, &new_buf, sizeof(new_buf));
458     return 0;
459   }
460   return -2;
461 }
462