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