xref: /aosp_15_r20/external/libaom/av1/encoder/extend.c (revision 77c1e3ccc04c968bd2bc212e87364f250e820521)
1*77c1e3ccSAndroid Build Coastguard Worker /*
2*77c1e3ccSAndroid Build Coastguard Worker  * Copyright (c) 2016, Alliance for Open Media. All rights reserved.
3*77c1e3ccSAndroid Build Coastguard Worker  *
4*77c1e3ccSAndroid Build Coastguard Worker  * This source code is subject to the terms of the BSD 2 Clause License and
5*77c1e3ccSAndroid Build Coastguard Worker  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6*77c1e3ccSAndroid Build Coastguard Worker  * was not distributed with this source code in the LICENSE file, you can
7*77c1e3ccSAndroid Build Coastguard Worker  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8*77c1e3ccSAndroid Build Coastguard Worker  * Media Patent License 1.0 was not distributed with this source code in the
9*77c1e3ccSAndroid Build Coastguard Worker  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10*77c1e3ccSAndroid Build Coastguard Worker  */
11*77c1e3ccSAndroid Build Coastguard Worker 
12*77c1e3ccSAndroid Build Coastguard Worker #include <assert.h>
13*77c1e3ccSAndroid Build Coastguard Worker 
14*77c1e3ccSAndroid Build Coastguard Worker #include "aom_dsp/aom_dsp_common.h"
15*77c1e3ccSAndroid Build Coastguard Worker #include "aom_mem/aom_mem.h"
16*77c1e3ccSAndroid Build Coastguard Worker #include "aom_ports/mem.h"
17*77c1e3ccSAndroid Build Coastguard Worker 
18*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/common.h"
19*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/extend.h"
20*77c1e3ccSAndroid 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 chroma_step)21*77c1e3ccSAndroid Build Coastguard Worker static void copy_and_extend_plane(const uint8_t *src, int src_pitch,
22*77c1e3ccSAndroid Build Coastguard Worker                                   uint8_t *dst, int dst_pitch, int w, int h,
23*77c1e3ccSAndroid Build Coastguard Worker                                   int extend_top, int extend_left,
24*77c1e3ccSAndroid Build Coastguard Worker                                   int extend_bottom, int extend_right,
25*77c1e3ccSAndroid Build Coastguard Worker                                   int chroma_step) {
26*77c1e3ccSAndroid Build Coastguard Worker   int i, linesize;
27*77c1e3ccSAndroid Build Coastguard Worker   // copy the left and right most columns out
28*77c1e3ccSAndroid Build Coastguard Worker   const uint8_t *src_ptr1 = src;
29*77c1e3ccSAndroid Build Coastguard Worker   const uint8_t *src_ptr2 = src + (w - 1) * chroma_step;
30*77c1e3ccSAndroid Build Coastguard Worker   uint8_t *dst_ptr1 = dst - extend_left;
31*77c1e3ccSAndroid Build Coastguard Worker   uint8_t *dst_ptr2 = dst + w;
32*77c1e3ccSAndroid Build Coastguard Worker 
33*77c1e3ccSAndroid Build Coastguard Worker   for (i = 0; i < h; i++) {
34*77c1e3ccSAndroid Build Coastguard Worker     memset(dst_ptr1, src_ptr1[0], extend_left);
35*77c1e3ccSAndroid Build Coastguard Worker     if (chroma_step == 1) {
36*77c1e3ccSAndroid Build Coastguard Worker       memcpy(dst_ptr1 + extend_left, src_ptr1, w);
37*77c1e3ccSAndroid Build Coastguard Worker     } else {
38*77c1e3ccSAndroid Build Coastguard Worker       for (int j = 0; j < w; j++) {
39*77c1e3ccSAndroid Build Coastguard Worker         dst_ptr1[extend_left + j] = src_ptr1[chroma_step * j];
40*77c1e3ccSAndroid Build Coastguard Worker       }
41*77c1e3ccSAndroid Build Coastguard Worker     }
42*77c1e3ccSAndroid Build Coastguard Worker     memset(dst_ptr2, src_ptr2[0], extend_right);
43*77c1e3ccSAndroid Build Coastguard Worker     src_ptr1 += src_pitch;
44*77c1e3ccSAndroid Build Coastguard Worker     src_ptr2 += src_pitch;
45*77c1e3ccSAndroid Build Coastguard Worker     dst_ptr1 += dst_pitch;
46*77c1e3ccSAndroid Build Coastguard Worker     dst_ptr2 += dst_pitch;
47*77c1e3ccSAndroid Build Coastguard Worker   }
48*77c1e3ccSAndroid Build Coastguard Worker 
49*77c1e3ccSAndroid Build Coastguard Worker   // Now copy the top and bottom lines into each line of the respective
50*77c1e3ccSAndroid Build Coastguard Worker   // borders
51*77c1e3ccSAndroid Build Coastguard Worker   src_ptr1 = dst - extend_left;
52*77c1e3ccSAndroid Build Coastguard Worker   src_ptr2 = dst + dst_pitch * (h - 1) - extend_left;
53*77c1e3ccSAndroid Build Coastguard Worker   dst_ptr1 = dst + dst_pitch * (-extend_top) - extend_left;
54*77c1e3ccSAndroid Build Coastguard Worker   dst_ptr2 = dst + dst_pitch * (h)-extend_left;
55*77c1e3ccSAndroid Build Coastguard Worker   linesize = extend_left + extend_right + w;
56*77c1e3ccSAndroid Build Coastguard Worker   assert(linesize <= dst_pitch);
57*77c1e3ccSAndroid Build Coastguard Worker 
58*77c1e3ccSAndroid Build Coastguard Worker   for (i = 0; i < extend_top; i++) {
59*77c1e3ccSAndroid Build Coastguard Worker     memcpy(dst_ptr1, src_ptr1, linesize);
60*77c1e3ccSAndroid Build Coastguard Worker     dst_ptr1 += dst_pitch;
61*77c1e3ccSAndroid Build Coastguard Worker   }
62*77c1e3ccSAndroid Build Coastguard Worker 
63*77c1e3ccSAndroid Build Coastguard Worker   for (i = 0; i < extend_bottom; i++) {
64*77c1e3ccSAndroid Build Coastguard Worker     memcpy(dst_ptr2, src_ptr2, linesize);
65*77c1e3ccSAndroid Build Coastguard Worker     dst_ptr2 += dst_pitch;
66*77c1e3ccSAndroid Build Coastguard Worker   }
67*77c1e3ccSAndroid Build Coastguard Worker }
68*77c1e3ccSAndroid Build Coastguard Worker 
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)69*77c1e3ccSAndroid Build Coastguard Worker static void highbd_copy_and_extend_plane(const uint8_t *src8, int src_pitch,
70*77c1e3ccSAndroid Build Coastguard Worker                                          uint8_t *dst8, int dst_pitch, int w,
71*77c1e3ccSAndroid Build Coastguard Worker                                          int h, int extend_top, int extend_left,
72*77c1e3ccSAndroid Build Coastguard Worker                                          int extend_bottom, int extend_right) {
73*77c1e3ccSAndroid Build Coastguard Worker   int i, linesize;
74*77c1e3ccSAndroid Build Coastguard Worker   uint16_t *src = CONVERT_TO_SHORTPTR(src8);
75*77c1e3ccSAndroid Build Coastguard Worker   uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
76*77c1e3ccSAndroid Build Coastguard Worker 
77*77c1e3ccSAndroid Build Coastguard Worker   // copy the left and right most columns out
78*77c1e3ccSAndroid Build Coastguard Worker   const uint16_t *src_ptr1 = src;
79*77c1e3ccSAndroid Build Coastguard Worker   const uint16_t *src_ptr2 = src + w - 1;
80*77c1e3ccSAndroid Build Coastguard Worker   uint16_t *dst_ptr1 = dst - extend_left;
81*77c1e3ccSAndroid Build Coastguard Worker   uint16_t *dst_ptr2 = dst + w;
82*77c1e3ccSAndroid Build Coastguard Worker 
83*77c1e3ccSAndroid Build Coastguard Worker   for (i = 0; i < h; i++) {
84*77c1e3ccSAndroid Build Coastguard Worker     aom_memset16(dst_ptr1, src_ptr1[0], extend_left);
85*77c1e3ccSAndroid Build Coastguard Worker     memcpy(dst_ptr1 + extend_left, src_ptr1, w * sizeof(src_ptr1[0]));
86*77c1e3ccSAndroid Build Coastguard Worker     aom_memset16(dst_ptr2, src_ptr2[0], extend_right);
87*77c1e3ccSAndroid Build Coastguard Worker     src_ptr1 += src_pitch;
88*77c1e3ccSAndroid Build Coastguard Worker     src_ptr2 += src_pitch;
89*77c1e3ccSAndroid Build Coastguard Worker     dst_ptr1 += dst_pitch;
90*77c1e3ccSAndroid Build Coastguard Worker     dst_ptr2 += dst_pitch;
91*77c1e3ccSAndroid Build Coastguard Worker   }
92*77c1e3ccSAndroid Build Coastguard Worker 
93*77c1e3ccSAndroid Build Coastguard Worker   // Now copy the top and bottom lines into each line of the respective
94*77c1e3ccSAndroid Build Coastguard Worker   // borders
95*77c1e3ccSAndroid Build Coastguard Worker   src_ptr1 = dst - extend_left;
96*77c1e3ccSAndroid Build Coastguard Worker   src_ptr2 = dst + dst_pitch * (h - 1) - extend_left;
97*77c1e3ccSAndroid Build Coastguard Worker   dst_ptr1 = dst + dst_pitch * (-extend_top) - extend_left;
98*77c1e3ccSAndroid Build Coastguard Worker   dst_ptr2 = dst + dst_pitch * (h)-extend_left;
99*77c1e3ccSAndroid Build Coastguard Worker   linesize = extend_left + extend_right + w;
100*77c1e3ccSAndroid Build Coastguard Worker   assert(linesize <= dst_pitch);
101*77c1e3ccSAndroid Build Coastguard Worker 
102*77c1e3ccSAndroid Build Coastguard Worker   for (i = 0; i < extend_top; i++) {
103*77c1e3ccSAndroid Build Coastguard Worker     memcpy(dst_ptr1, src_ptr1, linesize * sizeof(src_ptr1[0]));
104*77c1e3ccSAndroid Build Coastguard Worker     dst_ptr1 += dst_pitch;
105*77c1e3ccSAndroid Build Coastguard Worker   }
106*77c1e3ccSAndroid Build Coastguard Worker 
107*77c1e3ccSAndroid Build Coastguard Worker   for (i = 0; i < extend_bottom; i++) {
108*77c1e3ccSAndroid Build Coastguard Worker     memcpy(dst_ptr2, src_ptr2, linesize * sizeof(src_ptr2[0]));
109*77c1e3ccSAndroid Build Coastguard Worker     dst_ptr2 += dst_pitch;
110*77c1e3ccSAndroid Build Coastguard Worker   }
111*77c1e3ccSAndroid Build Coastguard Worker }
112*77c1e3ccSAndroid Build Coastguard Worker 
av1_copy_and_extend_frame(const YV12_BUFFER_CONFIG * src,YV12_BUFFER_CONFIG * dst)113*77c1e3ccSAndroid Build Coastguard Worker void av1_copy_and_extend_frame(const YV12_BUFFER_CONFIG *src,
114*77c1e3ccSAndroid Build Coastguard Worker                                YV12_BUFFER_CONFIG *dst) {
115*77c1e3ccSAndroid Build Coastguard Worker   // Extend src frame in buffer
116*77c1e3ccSAndroid Build Coastguard Worker   const int et_y = dst->border;
117*77c1e3ccSAndroid Build Coastguard Worker   const int el_y = dst->border;
118*77c1e3ccSAndroid Build Coastguard Worker   const int er_y =
119*77c1e3ccSAndroid Build Coastguard Worker       AOMMAX(src->y_width + dst->border, ALIGN_POWER_OF_TWO(src->y_width, 6)) -
120*77c1e3ccSAndroid Build Coastguard Worker       src->y_crop_width;
121*77c1e3ccSAndroid Build Coastguard Worker   const int eb_y = AOMMAX(src->y_height + dst->border,
122*77c1e3ccSAndroid Build Coastguard Worker                           ALIGN_POWER_OF_TWO(src->y_height, 6)) -
123*77c1e3ccSAndroid Build Coastguard Worker                    src->y_crop_height;
124*77c1e3ccSAndroid Build Coastguard Worker   const int uv_width_subsampling = src->subsampling_x;
125*77c1e3ccSAndroid Build Coastguard Worker   const int uv_height_subsampling = src->subsampling_y;
126*77c1e3ccSAndroid Build Coastguard Worker   const int et_uv = et_y >> uv_height_subsampling;
127*77c1e3ccSAndroid Build Coastguard Worker   const int el_uv = el_y >> uv_width_subsampling;
128*77c1e3ccSAndroid Build Coastguard Worker   const int eb_uv = eb_y >> uv_height_subsampling;
129*77c1e3ccSAndroid Build Coastguard Worker   const int er_uv = er_y >> uv_width_subsampling;
130*77c1e3ccSAndroid Build Coastguard Worker 
131*77c1e3ccSAndroid Build Coastguard Worker   if (src->flags & YV12_FLAG_HIGHBITDEPTH) {
132*77c1e3ccSAndroid Build Coastguard Worker     highbd_copy_and_extend_plane(src->y_buffer, src->y_stride, dst->y_buffer,
133*77c1e3ccSAndroid Build Coastguard Worker                                  dst->y_stride, src->y_crop_width,
134*77c1e3ccSAndroid Build Coastguard Worker                                  src->y_crop_height, et_y, el_y, eb_y, er_y);
135*77c1e3ccSAndroid Build Coastguard Worker     if (!src->monochrome) {
136*77c1e3ccSAndroid Build Coastguard Worker       highbd_copy_and_extend_plane(
137*77c1e3ccSAndroid Build Coastguard Worker           src->u_buffer, src->uv_stride, dst->u_buffer, dst->uv_stride,
138*77c1e3ccSAndroid Build Coastguard Worker           src->uv_crop_width, src->uv_crop_height, et_uv, el_uv, eb_uv, er_uv);
139*77c1e3ccSAndroid Build Coastguard Worker       highbd_copy_and_extend_plane(
140*77c1e3ccSAndroid Build Coastguard Worker           src->v_buffer, src->uv_stride, dst->v_buffer, dst->uv_stride,
141*77c1e3ccSAndroid Build Coastguard Worker           src->uv_crop_width, src->uv_crop_height, et_uv, el_uv, eb_uv, er_uv);
142*77c1e3ccSAndroid Build Coastguard Worker     }
143*77c1e3ccSAndroid Build Coastguard Worker     return;
144*77c1e3ccSAndroid Build Coastguard Worker   }
145*77c1e3ccSAndroid Build Coastguard Worker 
146*77c1e3ccSAndroid Build Coastguard Worker   copy_and_extend_plane(src->y_buffer, src->y_stride, dst->y_buffer,
147*77c1e3ccSAndroid Build Coastguard Worker                         dst->y_stride, src->y_crop_width, src->y_crop_height,
148*77c1e3ccSAndroid Build Coastguard Worker                         et_y, el_y, eb_y, er_y, 1);
149*77c1e3ccSAndroid Build Coastguard Worker   if (!src->monochrome) {
150*77c1e3ccSAndroid Build Coastguard Worker     // detect nv12 format
151*77c1e3ccSAndroid Build Coastguard Worker     const int chroma_step = src->v_buffer ? 1 : 2;
152*77c1e3ccSAndroid Build Coastguard Worker     const uint8_t *src_v_buffer =
153*77c1e3ccSAndroid Build Coastguard Worker         src->v_buffer ? src->v_buffer : src->u_buffer + 1;
154*77c1e3ccSAndroid Build Coastguard Worker     copy_and_extend_plane(src->u_buffer, src->uv_stride, dst->u_buffer,
155*77c1e3ccSAndroid Build Coastguard Worker                           dst->uv_stride, src->uv_crop_width,
156*77c1e3ccSAndroid Build Coastguard Worker                           src->uv_crop_height, et_uv, el_uv, eb_uv, er_uv,
157*77c1e3ccSAndroid Build Coastguard Worker                           chroma_step);
158*77c1e3ccSAndroid Build Coastguard Worker     copy_and_extend_plane(src_v_buffer, src->uv_stride, dst->v_buffer,
159*77c1e3ccSAndroid Build Coastguard Worker                           dst->uv_stride, src->uv_crop_width,
160*77c1e3ccSAndroid Build Coastguard Worker                           src->uv_crop_height, et_uv, el_uv, eb_uv, er_uv,
161*77c1e3ccSAndroid Build Coastguard Worker                           chroma_step);
162*77c1e3ccSAndroid Build Coastguard Worker   }
163*77c1e3ccSAndroid Build Coastguard Worker }
164