xref: /aosp_15_r20/external/libvpx/vp9/encoder/vp9_extend.c (revision fb1b10ab9aebc7c7068eedab379b749d7e3900be)
1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker  *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3*fb1b10abSAndroid Build Coastguard Worker  *
4*fb1b10abSAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*fb1b10abSAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*fb1b10abSAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*fb1b10abSAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*fb1b10abSAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*fb1b10abSAndroid Build Coastguard Worker  */
10*fb1b10abSAndroid Build Coastguard Worker 
11*fb1b10abSAndroid Build Coastguard Worker #include "vpx_dsp/vpx_dsp_common.h"
12*fb1b10abSAndroid Build Coastguard Worker #include "vpx_mem/vpx_mem.h"
13*fb1b10abSAndroid Build Coastguard Worker #include "vpx_ports/mem.h"
14*fb1b10abSAndroid Build Coastguard Worker 
15*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_common.h"
16*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_extend.h"
17*fb1b10abSAndroid Build Coastguard Worker 
copy_and_extend_plane(const uint8_t * src,int src_pitch,uint8_t * dst,int dst_pitch,int w,int h,int extend_top,int extend_left,int extend_bottom,int extend_right,int interleave_step)18*fb1b10abSAndroid Build Coastguard Worker static void copy_and_extend_plane(const uint8_t *src, int src_pitch,
19*fb1b10abSAndroid Build Coastguard Worker                                   uint8_t *dst, int dst_pitch, int w, int h,
20*fb1b10abSAndroid Build Coastguard Worker                                   int extend_top, int extend_left,
21*fb1b10abSAndroid Build Coastguard Worker                                   int extend_bottom, int extend_right,
22*fb1b10abSAndroid Build Coastguard Worker                                   int interleave_step) {
23*fb1b10abSAndroid Build Coastguard Worker   int i, j, linesize;
24*fb1b10abSAndroid Build Coastguard Worker   const int step = interleave_step < 1 ? 1 : interleave_step;
25*fb1b10abSAndroid Build Coastguard Worker 
26*fb1b10abSAndroid Build Coastguard Worker   // copy the left and right most columns out
27*fb1b10abSAndroid Build Coastguard Worker   const uint8_t *src_ptr1 = src;
28*fb1b10abSAndroid Build Coastguard Worker   const uint8_t *src_ptr2 = src + (w - 1) * step;
29*fb1b10abSAndroid Build Coastguard Worker   uint8_t *dst_ptr1 = dst - extend_left;
30*fb1b10abSAndroid Build Coastguard Worker   uint8_t *dst_ptr2 = dst + w;
31*fb1b10abSAndroid Build Coastguard Worker 
32*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < h; i++) {
33*fb1b10abSAndroid Build Coastguard Worker     memset(dst_ptr1, src_ptr1[0], extend_left);
34*fb1b10abSAndroid Build Coastguard Worker     if (step == 1) {
35*fb1b10abSAndroid Build Coastguard Worker       memcpy(dst_ptr1 + extend_left, src_ptr1, w);
36*fb1b10abSAndroid Build Coastguard Worker     } else {
37*fb1b10abSAndroid Build Coastguard Worker       for (j = 0; j < w; j++) {
38*fb1b10abSAndroid Build Coastguard Worker         dst_ptr1[extend_left + j] = src_ptr1[step * j];
39*fb1b10abSAndroid Build Coastguard Worker       }
40*fb1b10abSAndroid Build Coastguard Worker     }
41*fb1b10abSAndroid Build Coastguard Worker     memset(dst_ptr2, src_ptr2[0], extend_right);
42*fb1b10abSAndroid Build Coastguard Worker     src_ptr1 += src_pitch;
43*fb1b10abSAndroid Build Coastguard Worker     src_ptr2 += src_pitch;
44*fb1b10abSAndroid Build Coastguard Worker     dst_ptr1 += dst_pitch;
45*fb1b10abSAndroid Build Coastguard Worker     dst_ptr2 += dst_pitch;
46*fb1b10abSAndroid Build Coastguard Worker   }
47*fb1b10abSAndroid Build Coastguard Worker 
48*fb1b10abSAndroid Build Coastguard Worker   // Now copy the top and bottom lines into each line of the respective
49*fb1b10abSAndroid Build Coastguard Worker   // borders
50*fb1b10abSAndroid Build Coastguard Worker   src_ptr1 = dst - extend_left;
51*fb1b10abSAndroid Build Coastguard Worker   src_ptr2 = dst + dst_pitch * (h - 1) - extend_left;
52*fb1b10abSAndroid Build Coastguard Worker   dst_ptr1 = dst + dst_pitch * (-extend_top) - extend_left;
53*fb1b10abSAndroid Build Coastguard Worker   dst_ptr2 = dst + dst_pitch * (h)-extend_left;
54*fb1b10abSAndroid Build Coastguard Worker   linesize = extend_left + extend_right + w;
55*fb1b10abSAndroid Build Coastguard Worker 
56*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < extend_top; i++) {
57*fb1b10abSAndroid Build Coastguard Worker     memcpy(dst_ptr1, src_ptr1, linesize);
58*fb1b10abSAndroid Build Coastguard Worker     dst_ptr1 += dst_pitch;
59*fb1b10abSAndroid Build Coastguard Worker   }
60*fb1b10abSAndroid Build Coastguard Worker 
61*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < extend_bottom; i++) {
62*fb1b10abSAndroid Build Coastguard Worker     memcpy(dst_ptr2, src_ptr2, linesize);
63*fb1b10abSAndroid Build Coastguard Worker     dst_ptr2 += dst_pitch;
64*fb1b10abSAndroid Build Coastguard Worker   }
65*fb1b10abSAndroid Build Coastguard Worker }
66*fb1b10abSAndroid Build Coastguard Worker 
67*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
highbd_copy_and_extend_plane(const uint8_t * src8,int src_pitch,uint8_t * dst8,int dst_pitch,int w,int h,int extend_top,int extend_left,int extend_bottom,int extend_right)68*fb1b10abSAndroid Build Coastguard Worker static void highbd_copy_and_extend_plane(const uint8_t *src8, int src_pitch,
69*fb1b10abSAndroid Build Coastguard Worker                                          uint8_t *dst8, int dst_pitch, int w,
70*fb1b10abSAndroid Build Coastguard Worker                                          int h, int extend_top, int extend_left,
71*fb1b10abSAndroid Build Coastguard Worker                                          int extend_bottom, int extend_right) {
72*fb1b10abSAndroid Build Coastguard Worker   int i, linesize;
73*fb1b10abSAndroid Build Coastguard Worker   uint16_t *src = CONVERT_TO_SHORTPTR(src8);
74*fb1b10abSAndroid Build Coastguard Worker   uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
75*fb1b10abSAndroid Build Coastguard Worker 
76*fb1b10abSAndroid Build Coastguard Worker   // copy the left and right most columns out
77*fb1b10abSAndroid Build Coastguard Worker   const uint16_t *src_ptr1 = src;
78*fb1b10abSAndroid Build Coastguard Worker   const uint16_t *src_ptr2 = src + w - 1;
79*fb1b10abSAndroid Build Coastguard Worker   uint16_t *dst_ptr1 = dst - extend_left;
80*fb1b10abSAndroid Build Coastguard Worker   uint16_t *dst_ptr2 = dst + w;
81*fb1b10abSAndroid Build Coastguard Worker 
82*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < h; i++) {
83*fb1b10abSAndroid Build Coastguard Worker     vpx_memset16(dst_ptr1, src_ptr1[0], extend_left);
84*fb1b10abSAndroid Build Coastguard Worker     memcpy(dst_ptr1 + extend_left, src_ptr1, w * sizeof(src_ptr1[0]));
85*fb1b10abSAndroid Build Coastguard Worker     vpx_memset16(dst_ptr2, src_ptr2[0], extend_right);
86*fb1b10abSAndroid Build Coastguard Worker     src_ptr1 += src_pitch;
87*fb1b10abSAndroid Build Coastguard Worker     src_ptr2 += src_pitch;
88*fb1b10abSAndroid Build Coastguard Worker     dst_ptr1 += dst_pitch;
89*fb1b10abSAndroid Build Coastguard Worker     dst_ptr2 += dst_pitch;
90*fb1b10abSAndroid Build Coastguard Worker   }
91*fb1b10abSAndroid Build Coastguard Worker 
92*fb1b10abSAndroid Build Coastguard Worker   // Now copy the top and bottom lines into each line of the respective
93*fb1b10abSAndroid Build Coastguard Worker   // borders
94*fb1b10abSAndroid Build Coastguard Worker   src_ptr1 = dst - extend_left;
95*fb1b10abSAndroid Build Coastguard Worker   src_ptr2 = dst + dst_pitch * (h - 1) - extend_left;
96*fb1b10abSAndroid Build Coastguard Worker   dst_ptr1 = dst + dst_pitch * (-extend_top) - extend_left;
97*fb1b10abSAndroid Build Coastguard Worker   dst_ptr2 = dst + dst_pitch * (h)-extend_left;
98*fb1b10abSAndroid Build Coastguard Worker   linesize = extend_left + extend_right + w;
99*fb1b10abSAndroid Build Coastguard Worker 
100*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < extend_top; i++) {
101*fb1b10abSAndroid Build Coastguard Worker     memcpy(dst_ptr1, src_ptr1, linesize * sizeof(src_ptr1[0]));
102*fb1b10abSAndroid Build Coastguard Worker     dst_ptr1 += dst_pitch;
103*fb1b10abSAndroid Build Coastguard Worker   }
104*fb1b10abSAndroid Build Coastguard Worker 
105*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < extend_bottom; i++) {
106*fb1b10abSAndroid Build Coastguard Worker     memcpy(dst_ptr2, src_ptr2, linesize * sizeof(src_ptr2[0]));
107*fb1b10abSAndroid Build Coastguard Worker     dst_ptr2 += dst_pitch;
108*fb1b10abSAndroid Build Coastguard Worker   }
109*fb1b10abSAndroid Build Coastguard Worker }
110*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
111*fb1b10abSAndroid Build Coastguard Worker 
vp9_copy_and_extend_frame(const YV12_BUFFER_CONFIG * src,YV12_BUFFER_CONFIG * dst)112*fb1b10abSAndroid Build Coastguard Worker void vp9_copy_and_extend_frame(const YV12_BUFFER_CONFIG *src,
113*fb1b10abSAndroid Build Coastguard Worker                                YV12_BUFFER_CONFIG *dst) {
114*fb1b10abSAndroid Build Coastguard Worker   // Extend src frame in buffer
115*fb1b10abSAndroid Build Coastguard Worker   // Altref filtering assumes 16 pixel extension
116*fb1b10abSAndroid Build Coastguard Worker   const int et_y = 16;
117*fb1b10abSAndroid Build Coastguard Worker   const int el_y = 16;
118*fb1b10abSAndroid Build Coastguard Worker   // Motion estimation may use src block variance with the block size up
119*fb1b10abSAndroid Build Coastguard Worker   // to 64x64, so the right and bottom need to be extended to 64 multiple
120*fb1b10abSAndroid Build Coastguard Worker   // or up to 16, whichever is greater.
121*fb1b10abSAndroid Build Coastguard Worker   const int er_y =
122*fb1b10abSAndroid Build Coastguard Worker       VPXMAX(src->y_width + 16, ALIGN_POWER_OF_TWO(src->y_width, 6)) -
123*fb1b10abSAndroid Build Coastguard Worker       src->y_crop_width;
124*fb1b10abSAndroid Build Coastguard Worker   const int eb_y =
125*fb1b10abSAndroid Build Coastguard Worker       VPXMAX(src->y_height + 16, ALIGN_POWER_OF_TWO(src->y_height, 6)) -
126*fb1b10abSAndroid Build Coastguard Worker       src->y_crop_height;
127*fb1b10abSAndroid Build Coastguard Worker   const int uv_width_subsampling = (src->uv_width != src->y_width);
128*fb1b10abSAndroid Build Coastguard Worker   const int uv_height_subsampling = (src->uv_height != src->y_height);
129*fb1b10abSAndroid Build Coastguard Worker   const int et_uv = et_y >> uv_height_subsampling;
130*fb1b10abSAndroid Build Coastguard Worker   const int el_uv = el_y >> uv_width_subsampling;
131*fb1b10abSAndroid Build Coastguard Worker   const int eb_uv = eb_y >> uv_height_subsampling;
132*fb1b10abSAndroid Build Coastguard Worker   const int er_uv = er_y >> uv_width_subsampling;
133*fb1b10abSAndroid Build Coastguard Worker   // detect nv12 colorspace
134*fb1b10abSAndroid Build Coastguard Worker   const int chroma_step = src->v_buffer - src->u_buffer == 1 ? 2 : 1;
135*fb1b10abSAndroid Build Coastguard Worker 
136*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
137*fb1b10abSAndroid Build Coastguard Worker   if (src->flags & YV12_FLAG_HIGHBITDEPTH) {
138*fb1b10abSAndroid Build Coastguard Worker     highbd_copy_and_extend_plane(src->y_buffer, src->y_stride, dst->y_buffer,
139*fb1b10abSAndroid Build Coastguard Worker                                  dst->y_stride, src->y_crop_width,
140*fb1b10abSAndroid Build Coastguard Worker                                  src->y_crop_height, et_y, el_y, eb_y, er_y);
141*fb1b10abSAndroid Build Coastguard Worker 
142*fb1b10abSAndroid Build Coastguard Worker     highbd_copy_and_extend_plane(
143*fb1b10abSAndroid Build Coastguard Worker         src->u_buffer, src->uv_stride, dst->u_buffer, dst->uv_stride,
144*fb1b10abSAndroid Build Coastguard Worker         src->uv_crop_width, src->uv_crop_height, et_uv, el_uv, eb_uv, er_uv);
145*fb1b10abSAndroid Build Coastguard Worker 
146*fb1b10abSAndroid Build Coastguard Worker     highbd_copy_and_extend_plane(
147*fb1b10abSAndroid Build Coastguard Worker         src->v_buffer, src->uv_stride, dst->v_buffer, dst->uv_stride,
148*fb1b10abSAndroid Build Coastguard Worker         src->uv_crop_width, src->uv_crop_height, et_uv, el_uv, eb_uv, er_uv);
149*fb1b10abSAndroid Build Coastguard Worker     return;
150*fb1b10abSAndroid Build Coastguard Worker   }
151*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
152*fb1b10abSAndroid Build Coastguard Worker 
153*fb1b10abSAndroid Build Coastguard Worker   copy_and_extend_plane(src->y_buffer, src->y_stride, dst->y_buffer,
154*fb1b10abSAndroid Build Coastguard Worker                         dst->y_stride, src->y_crop_width, src->y_crop_height,
155*fb1b10abSAndroid Build Coastguard Worker                         et_y, el_y, eb_y, er_y, 1);
156*fb1b10abSAndroid Build Coastguard Worker 
157*fb1b10abSAndroid Build Coastguard Worker   copy_and_extend_plane(src->u_buffer, src->uv_stride, dst->u_buffer,
158*fb1b10abSAndroid Build Coastguard Worker                         dst->uv_stride, src->uv_crop_width, src->uv_crop_height,
159*fb1b10abSAndroid Build Coastguard Worker                         et_uv, el_uv, eb_uv, er_uv, chroma_step);
160*fb1b10abSAndroid Build Coastguard Worker 
161*fb1b10abSAndroid Build Coastguard Worker   copy_and_extend_plane(src->v_buffer, src->uv_stride, dst->v_buffer,
162*fb1b10abSAndroid Build Coastguard Worker                         dst->uv_stride, src->uv_crop_width, src->uv_crop_height,
163*fb1b10abSAndroid Build Coastguard Worker                         et_uv, el_uv, eb_uv, er_uv, chroma_step);
164*fb1b10abSAndroid Build Coastguard Worker }
165