xref: /aosp_15_r20/external/libaom/av1/common/reconintra.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 #include <math.h>
14*77c1e3ccSAndroid Build Coastguard Worker 
15*77c1e3ccSAndroid Build Coastguard Worker #include "config/aom_config.h"
16*77c1e3ccSAndroid Build Coastguard Worker #include "config/aom_dsp_rtcd.h"
17*77c1e3ccSAndroid Build Coastguard Worker #include "config/av1_rtcd.h"
18*77c1e3ccSAndroid Build Coastguard Worker 
19*77c1e3ccSAndroid Build Coastguard Worker #include "aom_dsp/aom_dsp_common.h"
20*77c1e3ccSAndroid Build Coastguard Worker #include "aom_mem/aom_mem.h"
21*77c1e3ccSAndroid Build Coastguard Worker #include "aom_ports/aom_once.h"
22*77c1e3ccSAndroid Build Coastguard Worker #include "aom_ports/mem.h"
23*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/av1_common_int.h"
24*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/cfl.h"
25*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/reconintra.h"
26*77c1e3ccSAndroid Build Coastguard Worker 
27*77c1e3ccSAndroid Build Coastguard Worker enum {
28*77c1e3ccSAndroid Build Coastguard Worker   NEED_LEFT = 1 << 1,
29*77c1e3ccSAndroid Build Coastguard Worker   NEED_ABOVE = 1 << 2,
30*77c1e3ccSAndroid Build Coastguard Worker   NEED_ABOVERIGHT = 1 << 3,
31*77c1e3ccSAndroid Build Coastguard Worker   NEED_ABOVELEFT = 1 << 4,
32*77c1e3ccSAndroid Build Coastguard Worker   NEED_BOTTOMLEFT = 1 << 5,
33*77c1e3ccSAndroid Build Coastguard Worker };
34*77c1e3ccSAndroid Build Coastguard Worker 
35*77c1e3ccSAndroid Build Coastguard Worker #define INTRA_EDGE_FILT 3
36*77c1e3ccSAndroid Build Coastguard Worker #define INTRA_EDGE_TAPS 5
37*77c1e3ccSAndroid Build Coastguard Worker #define MAX_UPSAMPLE_SZ 16
38*77c1e3ccSAndroid Build Coastguard Worker #define NUM_INTRA_NEIGHBOUR_PIXELS (MAX_TX_SIZE * 2 + 32)
39*77c1e3ccSAndroid Build Coastguard Worker 
40*77c1e3ccSAndroid Build Coastguard Worker static const uint8_t extend_modes[INTRA_MODES] = {
41*77c1e3ccSAndroid Build Coastguard Worker   NEED_ABOVE | NEED_LEFT,                   // DC
42*77c1e3ccSAndroid Build Coastguard Worker   NEED_ABOVE,                               // V
43*77c1e3ccSAndroid Build Coastguard Worker   NEED_LEFT,                                // H
44*77c1e3ccSAndroid Build Coastguard Worker   NEED_ABOVE | NEED_ABOVERIGHT,             // D45
45*77c1e3ccSAndroid Build Coastguard Worker   NEED_LEFT | NEED_ABOVE | NEED_ABOVELEFT,  // D135
46*77c1e3ccSAndroid Build Coastguard Worker   NEED_LEFT | NEED_ABOVE | NEED_ABOVELEFT,  // D113
47*77c1e3ccSAndroid Build Coastguard Worker   NEED_LEFT | NEED_ABOVE | NEED_ABOVELEFT,  // D157
48*77c1e3ccSAndroid Build Coastguard Worker   NEED_LEFT | NEED_BOTTOMLEFT,              // D203
49*77c1e3ccSAndroid Build Coastguard Worker   NEED_ABOVE | NEED_ABOVERIGHT,             // D67
50*77c1e3ccSAndroid Build Coastguard Worker   NEED_LEFT | NEED_ABOVE,                   // SMOOTH
51*77c1e3ccSAndroid Build Coastguard Worker   NEED_LEFT | NEED_ABOVE,                   // SMOOTH_V
52*77c1e3ccSAndroid Build Coastguard Worker   NEED_LEFT | NEED_ABOVE,                   // SMOOTH_H
53*77c1e3ccSAndroid Build Coastguard Worker   NEED_LEFT | NEED_ABOVE | NEED_ABOVELEFT,  // PAETH
54*77c1e3ccSAndroid Build Coastguard Worker };
55*77c1e3ccSAndroid Build Coastguard Worker 
56*77c1e3ccSAndroid Build Coastguard Worker // Tables to store if the top-right reference pixels are available. The flags
57*77c1e3ccSAndroid Build Coastguard Worker // are represented with bits, packed into 8-bit integers. E.g., for the 32x32
58*77c1e3ccSAndroid Build Coastguard Worker // blocks in a 128x128 superblock, the index of the "o" block is 10 (in raster
59*77c1e3ccSAndroid Build Coastguard Worker // order), so its flag is stored at the 3rd bit of the 2nd entry in the table,
60*77c1e3ccSAndroid Build Coastguard Worker // i.e. (table[10 / 8] >> (10 % 8)) & 1.
61*77c1e3ccSAndroid Build Coastguard Worker //       . . . .
62*77c1e3ccSAndroid Build Coastguard Worker //       . . . .
63*77c1e3ccSAndroid Build Coastguard Worker //       . . o .
64*77c1e3ccSAndroid Build Coastguard Worker //       . . . .
65*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_tr_4x4[128] = {
66*77c1e3ccSAndroid Build Coastguard Worker   255, 255, 255, 255, 85, 85, 85, 85, 119, 119, 119, 119, 85, 85, 85, 85,
67*77c1e3ccSAndroid Build Coastguard Worker   127, 127, 127, 127, 85, 85, 85, 85, 119, 119, 119, 119, 85, 85, 85, 85,
68*77c1e3ccSAndroid Build Coastguard Worker   255, 127, 255, 127, 85, 85, 85, 85, 119, 119, 119, 119, 85, 85, 85, 85,
69*77c1e3ccSAndroid Build Coastguard Worker   127, 127, 127, 127, 85, 85, 85, 85, 119, 119, 119, 119, 85, 85, 85, 85,
70*77c1e3ccSAndroid Build Coastguard Worker   255, 255, 255, 127, 85, 85, 85, 85, 119, 119, 119, 119, 85, 85, 85, 85,
71*77c1e3ccSAndroid Build Coastguard Worker   127, 127, 127, 127, 85, 85, 85, 85, 119, 119, 119, 119, 85, 85, 85, 85,
72*77c1e3ccSAndroid Build Coastguard Worker   255, 127, 255, 127, 85, 85, 85, 85, 119, 119, 119, 119, 85, 85, 85, 85,
73*77c1e3ccSAndroid Build Coastguard Worker   127, 127, 127, 127, 85, 85, 85, 85, 119, 119, 119, 119, 85, 85, 85, 85,
74*77c1e3ccSAndroid Build Coastguard Worker };
75*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_tr_4x8[64] = {
76*77c1e3ccSAndroid Build Coastguard Worker   255, 255, 255, 255, 119, 119, 119, 119, 127, 127, 127, 127, 119,
77*77c1e3ccSAndroid Build Coastguard Worker   119, 119, 119, 255, 127, 255, 127, 119, 119, 119, 119, 127, 127,
78*77c1e3ccSAndroid Build Coastguard Worker   127, 127, 119, 119, 119, 119, 255, 255, 255, 127, 119, 119, 119,
79*77c1e3ccSAndroid Build Coastguard Worker   119, 127, 127, 127, 127, 119, 119, 119, 119, 255, 127, 255, 127,
80*77c1e3ccSAndroid Build Coastguard Worker   119, 119, 119, 119, 127, 127, 127, 127, 119, 119, 119, 119,
81*77c1e3ccSAndroid Build Coastguard Worker };
82*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_tr_8x4[64] = {
83*77c1e3ccSAndroid Build Coastguard Worker   255, 255, 0, 0, 85, 85, 0, 0, 119, 119, 0, 0, 85, 85, 0, 0,
84*77c1e3ccSAndroid Build Coastguard Worker   127, 127, 0, 0, 85, 85, 0, 0, 119, 119, 0, 0, 85, 85, 0, 0,
85*77c1e3ccSAndroid Build Coastguard Worker   255, 127, 0, 0, 85, 85, 0, 0, 119, 119, 0, 0, 85, 85, 0, 0,
86*77c1e3ccSAndroid Build Coastguard Worker   127, 127, 0, 0, 85, 85, 0, 0, 119, 119, 0, 0, 85, 85, 0, 0,
87*77c1e3ccSAndroid Build Coastguard Worker };
88*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_tr_8x8[32] = {
89*77c1e3ccSAndroid Build Coastguard Worker   255, 255, 85, 85, 119, 119, 85, 85, 127, 127, 85, 85, 119, 119, 85, 85,
90*77c1e3ccSAndroid Build Coastguard Worker   255, 127, 85, 85, 119, 119, 85, 85, 127, 127, 85, 85, 119, 119, 85, 85,
91*77c1e3ccSAndroid Build Coastguard Worker };
92*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_tr_8x16[16] = {
93*77c1e3ccSAndroid Build Coastguard Worker   255, 255, 119, 119, 127, 127, 119, 119,
94*77c1e3ccSAndroid Build Coastguard Worker   255, 127, 119, 119, 127, 127, 119, 119,
95*77c1e3ccSAndroid Build Coastguard Worker };
96*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_tr_16x8[16] = {
97*77c1e3ccSAndroid Build Coastguard Worker   255, 0, 85, 0, 119, 0, 85, 0, 127, 0, 85, 0, 119, 0, 85, 0,
98*77c1e3ccSAndroid Build Coastguard Worker };
99*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_tr_16x16[8] = {
100*77c1e3ccSAndroid Build Coastguard Worker   255, 85, 119, 85, 127, 85, 119, 85,
101*77c1e3ccSAndroid Build Coastguard Worker };
102*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_tr_16x32[4] = { 255, 119, 127, 119 };
103*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_tr_32x16[4] = { 15, 5, 7, 5 };
104*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_tr_32x32[2] = { 95, 87 };
105*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_tr_32x64[1] = { 127 };
106*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_tr_64x32[1] = { 19 };
107*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_tr_64x64[1] = { 7 };
108*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_tr_64x128[1] = { 3 };
109*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_tr_128x64[1] = { 1 };
110*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_tr_128x128[1] = { 1 };
111*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_tr_4x16[32] = {
112*77c1e3ccSAndroid Build Coastguard Worker   255, 255, 255, 255, 127, 127, 127, 127, 255, 127, 255,
113*77c1e3ccSAndroid Build Coastguard Worker   127, 127, 127, 127, 127, 255, 255, 255, 127, 127, 127,
114*77c1e3ccSAndroid Build Coastguard Worker   127, 127, 255, 127, 255, 127, 127, 127, 127, 127,
115*77c1e3ccSAndroid Build Coastguard Worker };
116*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_tr_16x4[32] = {
117*77c1e3ccSAndroid Build Coastguard Worker   255, 0, 0, 0, 85, 0, 0, 0, 119, 0, 0, 0, 85, 0, 0, 0,
118*77c1e3ccSAndroid Build Coastguard Worker   127, 0, 0, 0, 85, 0, 0, 0, 119, 0, 0, 0, 85, 0, 0, 0,
119*77c1e3ccSAndroid Build Coastguard Worker };
120*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_tr_8x32[8] = {
121*77c1e3ccSAndroid Build Coastguard Worker   255, 255, 127, 127, 255, 127, 127, 127,
122*77c1e3ccSAndroid Build Coastguard Worker };
123*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_tr_32x8[8] = {
124*77c1e3ccSAndroid Build Coastguard Worker   15, 0, 5, 0, 7, 0, 5, 0,
125*77c1e3ccSAndroid Build Coastguard Worker };
126*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_tr_16x64[2] = { 255, 127 };
127*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_tr_64x16[2] = { 3, 1 };
128*77c1e3ccSAndroid Build Coastguard Worker 
129*77c1e3ccSAndroid Build Coastguard Worker static const uint8_t *const has_tr_tables[BLOCK_SIZES_ALL] = {
130*77c1e3ccSAndroid Build Coastguard Worker   // 4X4
131*77c1e3ccSAndroid Build Coastguard Worker   has_tr_4x4,
132*77c1e3ccSAndroid Build Coastguard Worker   // 4X8,       8X4,            8X8
133*77c1e3ccSAndroid Build Coastguard Worker   has_tr_4x8, has_tr_8x4, has_tr_8x8,
134*77c1e3ccSAndroid Build Coastguard Worker   // 8X16,      16X8,           16X16
135*77c1e3ccSAndroid Build Coastguard Worker   has_tr_8x16, has_tr_16x8, has_tr_16x16,
136*77c1e3ccSAndroid Build Coastguard Worker   // 16X32,     32X16,          32X32
137*77c1e3ccSAndroid Build Coastguard Worker   has_tr_16x32, has_tr_32x16, has_tr_32x32,
138*77c1e3ccSAndroid Build Coastguard Worker   // 32X64,     64X32,          64X64
139*77c1e3ccSAndroid Build Coastguard Worker   has_tr_32x64, has_tr_64x32, has_tr_64x64,
140*77c1e3ccSAndroid Build Coastguard Worker   // 64x128,    128x64,         128x128
141*77c1e3ccSAndroid Build Coastguard Worker   has_tr_64x128, has_tr_128x64, has_tr_128x128,
142*77c1e3ccSAndroid Build Coastguard Worker   // 4x16,      16x4,            8x32
143*77c1e3ccSAndroid Build Coastguard Worker   has_tr_4x16, has_tr_16x4, has_tr_8x32,
144*77c1e3ccSAndroid Build Coastguard Worker   // 32x8,      16x64,           64x16
145*77c1e3ccSAndroid Build Coastguard Worker   has_tr_32x8, has_tr_16x64, has_tr_64x16
146*77c1e3ccSAndroid Build Coastguard Worker };
147*77c1e3ccSAndroid Build Coastguard Worker 
148*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_tr_vert_8x8[32] = {
149*77c1e3ccSAndroid Build Coastguard Worker   255, 255, 0, 0, 119, 119, 0, 0, 127, 127, 0, 0, 119, 119, 0, 0,
150*77c1e3ccSAndroid Build Coastguard Worker   255, 127, 0, 0, 119, 119, 0, 0, 127, 127, 0, 0, 119, 119, 0, 0,
151*77c1e3ccSAndroid Build Coastguard Worker };
152*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_tr_vert_16x16[8] = {
153*77c1e3ccSAndroid Build Coastguard Worker   255, 0, 119, 0, 127, 0, 119, 0,
154*77c1e3ccSAndroid Build Coastguard Worker };
155*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_tr_vert_32x32[2] = { 15, 7 };
156*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_tr_vert_64x64[1] = { 3 };
157*77c1e3ccSAndroid Build Coastguard Worker 
158*77c1e3ccSAndroid Build Coastguard Worker // The _vert_* tables are like the ordinary tables above, but describe the
159*77c1e3ccSAndroid Build Coastguard Worker // order we visit square blocks when doing a PARTITION_VERT_A or
160*77c1e3ccSAndroid Build Coastguard Worker // PARTITION_VERT_B. This is the same order as normal except for on the last
161*77c1e3ccSAndroid Build Coastguard Worker // split where we go vertically (TL, BL, TR, BR). We treat the rectangular block
162*77c1e3ccSAndroid Build Coastguard Worker // as a pair of squares, which means that these tables work correctly for both
163*77c1e3ccSAndroid Build Coastguard Worker // mixed vertical partition types.
164*77c1e3ccSAndroid Build Coastguard Worker //
165*77c1e3ccSAndroid Build Coastguard Worker // There are tables for each of the square sizes. Vertical rectangles (like
166*77c1e3ccSAndroid Build Coastguard Worker // BLOCK_16X32) use their respective "non-vert" table
167*77c1e3ccSAndroid Build Coastguard Worker static const uint8_t *const has_tr_vert_tables[BLOCK_SIZES] = {
168*77c1e3ccSAndroid Build Coastguard Worker   // 4X4
169*77c1e3ccSAndroid Build Coastguard Worker   NULL,
170*77c1e3ccSAndroid Build Coastguard Worker   // 4X8,      8X4,         8X8
171*77c1e3ccSAndroid Build Coastguard Worker   has_tr_4x8, NULL, has_tr_vert_8x8,
172*77c1e3ccSAndroid Build Coastguard Worker   // 8X16,     16X8,        16X16
173*77c1e3ccSAndroid Build Coastguard Worker   has_tr_8x16, NULL, has_tr_vert_16x16,
174*77c1e3ccSAndroid Build Coastguard Worker   // 16X32,    32X16,       32X32
175*77c1e3ccSAndroid Build Coastguard Worker   has_tr_16x32, NULL, has_tr_vert_32x32,
176*77c1e3ccSAndroid Build Coastguard Worker   // 32X64,    64X32,       64X64
177*77c1e3ccSAndroid Build Coastguard Worker   has_tr_32x64, NULL, has_tr_vert_64x64,
178*77c1e3ccSAndroid Build Coastguard Worker   // 64x128,   128x64,      128x128
179*77c1e3ccSAndroid Build Coastguard Worker   has_tr_64x128, NULL, has_tr_128x128
180*77c1e3ccSAndroid Build Coastguard Worker };
181*77c1e3ccSAndroid Build Coastguard Worker 
get_has_tr_table(PARTITION_TYPE partition,BLOCK_SIZE bsize)182*77c1e3ccSAndroid Build Coastguard Worker static const uint8_t *get_has_tr_table(PARTITION_TYPE partition,
183*77c1e3ccSAndroid Build Coastguard Worker                                        BLOCK_SIZE bsize) {
184*77c1e3ccSAndroid Build Coastguard Worker   const uint8_t *ret = NULL;
185*77c1e3ccSAndroid Build Coastguard Worker   // If this is a mixed vertical partition, look up bsize in orders_vert.
186*77c1e3ccSAndroid Build Coastguard Worker   if (partition == PARTITION_VERT_A || partition == PARTITION_VERT_B) {
187*77c1e3ccSAndroid Build Coastguard Worker     assert(bsize < BLOCK_SIZES);
188*77c1e3ccSAndroid Build Coastguard Worker     ret = has_tr_vert_tables[bsize];
189*77c1e3ccSAndroid Build Coastguard Worker   } else {
190*77c1e3ccSAndroid Build Coastguard Worker     ret = has_tr_tables[bsize];
191*77c1e3ccSAndroid Build Coastguard Worker   }
192*77c1e3ccSAndroid Build Coastguard Worker   assert(ret);
193*77c1e3ccSAndroid Build Coastguard Worker   return ret;
194*77c1e3ccSAndroid Build Coastguard Worker }
195*77c1e3ccSAndroid Build Coastguard Worker 
has_top_right(BLOCK_SIZE sb_size,BLOCK_SIZE bsize,int mi_row,int mi_col,int top_available,int right_available,PARTITION_TYPE partition,TX_SIZE txsz,int row_off,int col_off,int ss_x,int ss_y)196*77c1e3ccSAndroid Build Coastguard Worker static int has_top_right(BLOCK_SIZE sb_size, BLOCK_SIZE bsize, int mi_row,
197*77c1e3ccSAndroid Build Coastguard Worker                          int mi_col, int top_available, int right_available,
198*77c1e3ccSAndroid Build Coastguard Worker                          PARTITION_TYPE partition, TX_SIZE txsz, int row_off,
199*77c1e3ccSAndroid Build Coastguard Worker                          int col_off, int ss_x, int ss_y) {
200*77c1e3ccSAndroid Build Coastguard Worker   if (!top_available || !right_available) return 0;
201*77c1e3ccSAndroid Build Coastguard Worker 
202*77c1e3ccSAndroid Build Coastguard Worker   const int bw_unit = mi_size_wide[bsize];
203*77c1e3ccSAndroid Build Coastguard Worker   const int plane_bw_unit = AOMMAX(bw_unit >> ss_x, 1);
204*77c1e3ccSAndroid Build Coastguard Worker   const int top_right_count_unit = tx_size_wide_unit[txsz];
205*77c1e3ccSAndroid Build Coastguard Worker 
206*77c1e3ccSAndroid Build Coastguard Worker   if (row_off > 0) {  // Just need to check if enough pixels on the right.
207*77c1e3ccSAndroid Build Coastguard Worker     if (block_size_wide[bsize] > block_size_wide[BLOCK_64X64]) {
208*77c1e3ccSAndroid Build Coastguard Worker       // Special case: For 128x128 blocks, the transform unit whose
209*77c1e3ccSAndroid Build Coastguard Worker       // top-right corner is at the center of the block does in fact have
210*77c1e3ccSAndroid Build Coastguard Worker       // pixels available at its top-right corner.
211*77c1e3ccSAndroid Build Coastguard Worker       if (row_off == mi_size_high[BLOCK_64X64] >> ss_y &&
212*77c1e3ccSAndroid Build Coastguard Worker           col_off + top_right_count_unit == mi_size_wide[BLOCK_64X64] >> ss_x) {
213*77c1e3ccSAndroid Build Coastguard Worker         return 1;
214*77c1e3ccSAndroid Build Coastguard Worker       }
215*77c1e3ccSAndroid Build Coastguard Worker       const int plane_bw_unit_64 = mi_size_wide[BLOCK_64X64] >> ss_x;
216*77c1e3ccSAndroid Build Coastguard Worker       const int col_off_64 = col_off % plane_bw_unit_64;
217*77c1e3ccSAndroid Build Coastguard Worker       return col_off_64 + top_right_count_unit < plane_bw_unit_64;
218*77c1e3ccSAndroid Build Coastguard Worker     }
219*77c1e3ccSAndroid Build Coastguard Worker     return col_off + top_right_count_unit < plane_bw_unit;
220*77c1e3ccSAndroid Build Coastguard Worker   } else {
221*77c1e3ccSAndroid Build Coastguard Worker     // All top-right pixels are in the block above, which is already available.
222*77c1e3ccSAndroid Build Coastguard Worker     if (col_off + top_right_count_unit < plane_bw_unit) return 1;
223*77c1e3ccSAndroid Build Coastguard Worker 
224*77c1e3ccSAndroid Build Coastguard Worker     const int bw_in_mi_log2 = mi_size_wide_log2[bsize];
225*77c1e3ccSAndroid Build Coastguard Worker     const int bh_in_mi_log2 = mi_size_high_log2[bsize];
226*77c1e3ccSAndroid Build Coastguard Worker     const int sb_mi_size = mi_size_high[sb_size];
227*77c1e3ccSAndroid Build Coastguard Worker     const int blk_row_in_sb = (mi_row & (sb_mi_size - 1)) >> bh_in_mi_log2;
228*77c1e3ccSAndroid Build Coastguard Worker     const int blk_col_in_sb = (mi_col & (sb_mi_size - 1)) >> bw_in_mi_log2;
229*77c1e3ccSAndroid Build Coastguard Worker 
230*77c1e3ccSAndroid Build Coastguard Worker     // Top row of superblock: so top-right pixels are in the top and/or
231*77c1e3ccSAndroid Build Coastguard Worker     // top-right superblocks, both of which are already available.
232*77c1e3ccSAndroid Build Coastguard Worker     if (blk_row_in_sb == 0) return 1;
233*77c1e3ccSAndroid Build Coastguard Worker 
234*77c1e3ccSAndroid Build Coastguard Worker     // Rightmost column of superblock (and not the top row): so top-right pixels
235*77c1e3ccSAndroid Build Coastguard Worker     // fall in the right superblock, which is not available yet.
236*77c1e3ccSAndroid Build Coastguard Worker     if (((blk_col_in_sb + 1) << bw_in_mi_log2) >= sb_mi_size) {
237*77c1e3ccSAndroid Build Coastguard Worker       return 0;
238*77c1e3ccSAndroid Build Coastguard Worker     }
239*77c1e3ccSAndroid Build Coastguard Worker 
240*77c1e3ccSAndroid Build Coastguard Worker     // General case (neither top row nor rightmost column): check if the
241*77c1e3ccSAndroid Build Coastguard Worker     // top-right block is coded before the current block.
242*77c1e3ccSAndroid Build Coastguard Worker     const int this_blk_index =
243*77c1e3ccSAndroid Build Coastguard Worker         ((blk_row_in_sb + 0) << (MAX_MIB_SIZE_LOG2 - bw_in_mi_log2)) +
244*77c1e3ccSAndroid Build Coastguard Worker         blk_col_in_sb + 0;
245*77c1e3ccSAndroid Build Coastguard Worker     const int idx1 = this_blk_index / 8;
246*77c1e3ccSAndroid Build Coastguard Worker     const int idx2 = this_blk_index % 8;
247*77c1e3ccSAndroid Build Coastguard Worker     const uint8_t *has_tr_table = get_has_tr_table(partition, bsize);
248*77c1e3ccSAndroid Build Coastguard Worker     return (has_tr_table[idx1] >> idx2) & 1;
249*77c1e3ccSAndroid Build Coastguard Worker   }
250*77c1e3ccSAndroid Build Coastguard Worker }
251*77c1e3ccSAndroid Build Coastguard Worker 
252*77c1e3ccSAndroid Build Coastguard Worker // Similar to the has_tr_* tables, but store if the bottom-left reference
253*77c1e3ccSAndroid Build Coastguard Worker // pixels are available.
254*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_bl_4x4[128] = {
255*77c1e3ccSAndroid Build Coastguard Worker   84, 85, 85, 85, 16, 17, 17, 17, 84, 85, 85, 85, 0,  1,  1,  1,  84, 85, 85,
256*77c1e3ccSAndroid Build Coastguard Worker   85, 16, 17, 17, 17, 84, 85, 85, 85, 0,  0,  1,  0,  84, 85, 85, 85, 16, 17,
257*77c1e3ccSAndroid Build Coastguard Worker   17, 17, 84, 85, 85, 85, 0,  1,  1,  1,  84, 85, 85, 85, 16, 17, 17, 17, 84,
258*77c1e3ccSAndroid Build Coastguard Worker   85, 85, 85, 0,  0,  0,  0,  84, 85, 85, 85, 16, 17, 17, 17, 84, 85, 85, 85,
259*77c1e3ccSAndroid Build Coastguard Worker   0,  1,  1,  1,  84, 85, 85, 85, 16, 17, 17, 17, 84, 85, 85, 85, 0,  0,  1,
260*77c1e3ccSAndroid Build Coastguard Worker   0,  84, 85, 85, 85, 16, 17, 17, 17, 84, 85, 85, 85, 0,  1,  1,  1,  84, 85,
261*77c1e3ccSAndroid Build Coastguard Worker   85, 85, 16, 17, 17, 17, 84, 85, 85, 85, 0,  0,  0,  0,
262*77c1e3ccSAndroid Build Coastguard Worker };
263*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_bl_4x8[64] = {
264*77c1e3ccSAndroid Build Coastguard Worker   16, 17, 17, 17, 0, 1, 1, 1, 16, 17, 17, 17, 0, 0, 1, 0,
265*77c1e3ccSAndroid Build Coastguard Worker   16, 17, 17, 17, 0, 1, 1, 1, 16, 17, 17, 17, 0, 0, 0, 0,
266*77c1e3ccSAndroid Build Coastguard Worker   16, 17, 17, 17, 0, 1, 1, 1, 16, 17, 17, 17, 0, 0, 1, 0,
267*77c1e3ccSAndroid Build Coastguard Worker   16, 17, 17, 17, 0, 1, 1, 1, 16, 17, 17, 17, 0, 0, 0, 0,
268*77c1e3ccSAndroid Build Coastguard Worker };
269*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_bl_8x4[64] = {
270*77c1e3ccSAndroid Build Coastguard Worker   254, 255, 84, 85, 254, 255, 16, 17, 254, 255, 84, 85, 254, 255, 0, 1,
271*77c1e3ccSAndroid Build Coastguard Worker   254, 255, 84, 85, 254, 255, 16, 17, 254, 255, 84, 85, 254, 255, 0, 0,
272*77c1e3ccSAndroid Build Coastguard Worker   254, 255, 84, 85, 254, 255, 16, 17, 254, 255, 84, 85, 254, 255, 0, 1,
273*77c1e3ccSAndroid Build Coastguard Worker   254, 255, 84, 85, 254, 255, 16, 17, 254, 255, 84, 85, 254, 255, 0, 0,
274*77c1e3ccSAndroid Build Coastguard Worker };
275*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_bl_8x8[32] = {
276*77c1e3ccSAndroid Build Coastguard Worker   84, 85, 16, 17, 84, 85, 0, 1, 84, 85, 16, 17, 84, 85, 0, 0,
277*77c1e3ccSAndroid Build Coastguard Worker   84, 85, 16, 17, 84, 85, 0, 1, 84, 85, 16, 17, 84, 85, 0, 0,
278*77c1e3ccSAndroid Build Coastguard Worker };
279*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_bl_8x16[16] = {
280*77c1e3ccSAndroid Build Coastguard Worker   16, 17, 0, 1, 16, 17, 0, 0, 16, 17, 0, 1, 16, 17, 0, 0,
281*77c1e3ccSAndroid Build Coastguard Worker };
282*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_bl_16x8[16] = {
283*77c1e3ccSAndroid Build Coastguard Worker   254, 84, 254, 16, 254, 84, 254, 0, 254, 84, 254, 16, 254, 84, 254, 0,
284*77c1e3ccSAndroid Build Coastguard Worker };
285*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_bl_16x16[8] = {
286*77c1e3ccSAndroid Build Coastguard Worker   84, 16, 84, 0, 84, 16, 84, 0,
287*77c1e3ccSAndroid Build Coastguard Worker };
288*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_bl_16x32[4] = { 16, 0, 16, 0 };
289*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_bl_32x16[4] = { 78, 14, 78, 14 };
290*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_bl_32x32[2] = { 4, 4 };
291*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_bl_32x64[1] = { 0 };
292*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_bl_64x32[1] = { 34 };
293*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_bl_64x64[1] = { 0 };
294*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_bl_64x128[1] = { 0 };
295*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_bl_128x64[1] = { 0 };
296*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_bl_128x128[1] = { 0 };
297*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_bl_4x16[32] = {
298*77c1e3ccSAndroid Build Coastguard Worker   0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0,
299*77c1e3ccSAndroid Build Coastguard Worker   0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0,
300*77c1e3ccSAndroid Build Coastguard Worker };
301*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_bl_16x4[32] = {
302*77c1e3ccSAndroid Build Coastguard Worker   254, 254, 254, 84, 254, 254, 254, 16, 254, 254, 254, 84, 254, 254, 254, 0,
303*77c1e3ccSAndroid Build Coastguard Worker   254, 254, 254, 84, 254, 254, 254, 16, 254, 254, 254, 84, 254, 254, 254, 0,
304*77c1e3ccSAndroid Build Coastguard Worker };
305*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_bl_8x32[8] = {
306*77c1e3ccSAndroid Build Coastguard Worker   0, 1, 0, 0, 0, 1, 0, 0,
307*77c1e3ccSAndroid Build Coastguard Worker };
308*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_bl_32x8[8] = {
309*77c1e3ccSAndroid Build Coastguard Worker   238, 78, 238, 14, 238, 78, 238, 14,
310*77c1e3ccSAndroid Build Coastguard Worker };
311*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_bl_16x64[2] = { 0, 0 };
312*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_bl_64x16[2] = { 42, 42 };
313*77c1e3ccSAndroid Build Coastguard Worker 
314*77c1e3ccSAndroid Build Coastguard Worker static const uint8_t *const has_bl_tables[BLOCK_SIZES_ALL] = {
315*77c1e3ccSAndroid Build Coastguard Worker   // 4X4
316*77c1e3ccSAndroid Build Coastguard Worker   has_bl_4x4,
317*77c1e3ccSAndroid Build Coastguard Worker   // 4X8,         8X4,         8X8
318*77c1e3ccSAndroid Build Coastguard Worker   has_bl_4x8, has_bl_8x4, has_bl_8x8,
319*77c1e3ccSAndroid Build Coastguard Worker   // 8X16,        16X8,        16X16
320*77c1e3ccSAndroid Build Coastguard Worker   has_bl_8x16, has_bl_16x8, has_bl_16x16,
321*77c1e3ccSAndroid Build Coastguard Worker   // 16X32,       32X16,       32X32
322*77c1e3ccSAndroid Build Coastguard Worker   has_bl_16x32, has_bl_32x16, has_bl_32x32,
323*77c1e3ccSAndroid Build Coastguard Worker   // 32X64,       64X32,       64X64
324*77c1e3ccSAndroid Build Coastguard Worker   has_bl_32x64, has_bl_64x32, has_bl_64x64,
325*77c1e3ccSAndroid Build Coastguard Worker   // 64x128,      128x64,      128x128
326*77c1e3ccSAndroid Build Coastguard Worker   has_bl_64x128, has_bl_128x64, has_bl_128x128,
327*77c1e3ccSAndroid Build Coastguard Worker   // 4x16,        16x4,        8x32
328*77c1e3ccSAndroid Build Coastguard Worker   has_bl_4x16, has_bl_16x4, has_bl_8x32,
329*77c1e3ccSAndroid Build Coastguard Worker   // 32x8,        16x64,       64x16
330*77c1e3ccSAndroid Build Coastguard Worker   has_bl_32x8, has_bl_16x64, has_bl_64x16
331*77c1e3ccSAndroid Build Coastguard Worker };
332*77c1e3ccSAndroid Build Coastguard Worker 
333*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_bl_vert_8x8[32] = {
334*77c1e3ccSAndroid Build Coastguard Worker   254, 255, 16, 17, 254, 255, 0, 1, 254, 255, 16, 17, 254, 255, 0, 0,
335*77c1e3ccSAndroid Build Coastguard Worker   254, 255, 16, 17, 254, 255, 0, 1, 254, 255, 16, 17, 254, 255, 0, 0,
336*77c1e3ccSAndroid Build Coastguard Worker };
337*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_bl_vert_16x16[8] = {
338*77c1e3ccSAndroid Build Coastguard Worker   254, 16, 254, 0, 254, 16, 254, 0,
339*77c1e3ccSAndroid Build Coastguard Worker };
340*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_bl_vert_32x32[2] = { 14, 14 };
341*77c1e3ccSAndroid Build Coastguard Worker static uint8_t has_bl_vert_64x64[1] = { 2 };
342*77c1e3ccSAndroid Build Coastguard Worker 
343*77c1e3ccSAndroid Build Coastguard Worker // The _vert_* tables are like the ordinary tables above, but describe the
344*77c1e3ccSAndroid Build Coastguard Worker // order we visit square blocks when doing a PARTITION_VERT_A or
345*77c1e3ccSAndroid Build Coastguard Worker // PARTITION_VERT_B. This is the same order as normal except for on the last
346*77c1e3ccSAndroid Build Coastguard Worker // split where we go vertically (TL, BL, TR, BR). We treat the rectangular block
347*77c1e3ccSAndroid Build Coastguard Worker // as a pair of squares, which means that these tables work correctly for both
348*77c1e3ccSAndroid Build Coastguard Worker // mixed vertical partition types.
349*77c1e3ccSAndroid Build Coastguard Worker //
350*77c1e3ccSAndroid Build Coastguard Worker // There are tables for each of the square sizes. Vertical rectangles (like
351*77c1e3ccSAndroid Build Coastguard Worker // BLOCK_16X32) use their respective "non-vert" table
352*77c1e3ccSAndroid Build Coastguard Worker static const uint8_t *const has_bl_vert_tables[BLOCK_SIZES] = {
353*77c1e3ccSAndroid Build Coastguard Worker   // 4X4
354*77c1e3ccSAndroid Build Coastguard Worker   NULL,
355*77c1e3ccSAndroid Build Coastguard Worker   // 4X8,     8X4,         8X8
356*77c1e3ccSAndroid Build Coastguard Worker   has_bl_4x8, NULL, has_bl_vert_8x8,
357*77c1e3ccSAndroid Build Coastguard Worker   // 8X16,    16X8,        16X16
358*77c1e3ccSAndroid Build Coastguard Worker   has_bl_8x16, NULL, has_bl_vert_16x16,
359*77c1e3ccSAndroid Build Coastguard Worker   // 16X32,   32X16,       32X32
360*77c1e3ccSAndroid Build Coastguard Worker   has_bl_16x32, NULL, has_bl_vert_32x32,
361*77c1e3ccSAndroid Build Coastguard Worker   // 32X64,   64X32,       64X64
362*77c1e3ccSAndroid Build Coastguard Worker   has_bl_32x64, NULL, has_bl_vert_64x64,
363*77c1e3ccSAndroid Build Coastguard Worker   // 64x128,  128x64,      128x128
364*77c1e3ccSAndroid Build Coastguard Worker   has_bl_64x128, NULL, has_bl_128x128
365*77c1e3ccSAndroid Build Coastguard Worker };
366*77c1e3ccSAndroid Build Coastguard Worker 
get_has_bl_table(PARTITION_TYPE partition,BLOCK_SIZE bsize)367*77c1e3ccSAndroid Build Coastguard Worker static const uint8_t *get_has_bl_table(PARTITION_TYPE partition,
368*77c1e3ccSAndroid Build Coastguard Worker                                        BLOCK_SIZE bsize) {
369*77c1e3ccSAndroid Build Coastguard Worker   const uint8_t *ret = NULL;
370*77c1e3ccSAndroid Build Coastguard Worker   // If this is a mixed vertical partition, look up bsize in orders_vert.
371*77c1e3ccSAndroid Build Coastguard Worker   if (partition == PARTITION_VERT_A || partition == PARTITION_VERT_B) {
372*77c1e3ccSAndroid Build Coastguard Worker     assert(bsize < BLOCK_SIZES);
373*77c1e3ccSAndroid Build Coastguard Worker     ret = has_bl_vert_tables[bsize];
374*77c1e3ccSAndroid Build Coastguard Worker   } else {
375*77c1e3ccSAndroid Build Coastguard Worker     ret = has_bl_tables[bsize];
376*77c1e3ccSAndroid Build Coastguard Worker   }
377*77c1e3ccSAndroid Build Coastguard Worker   assert(ret);
378*77c1e3ccSAndroid Build Coastguard Worker   return ret;
379*77c1e3ccSAndroid Build Coastguard Worker }
380*77c1e3ccSAndroid Build Coastguard Worker 
has_bottom_left(BLOCK_SIZE sb_size,BLOCK_SIZE bsize,int mi_row,int mi_col,int bottom_available,int left_available,PARTITION_TYPE partition,TX_SIZE txsz,int row_off,int col_off,int ss_x,int ss_y)381*77c1e3ccSAndroid Build Coastguard Worker static int has_bottom_left(BLOCK_SIZE sb_size, BLOCK_SIZE bsize, int mi_row,
382*77c1e3ccSAndroid Build Coastguard Worker                            int mi_col, int bottom_available, int left_available,
383*77c1e3ccSAndroid Build Coastguard Worker                            PARTITION_TYPE partition, TX_SIZE txsz, int row_off,
384*77c1e3ccSAndroid Build Coastguard Worker                            int col_off, int ss_x, int ss_y) {
385*77c1e3ccSAndroid Build Coastguard Worker   if (!bottom_available || !left_available) return 0;
386*77c1e3ccSAndroid Build Coastguard Worker 
387*77c1e3ccSAndroid Build Coastguard Worker   // Special case for 128x* blocks, when col_off is half the block width.
388*77c1e3ccSAndroid Build Coastguard Worker   // This is needed because 128x* superblocks are divided into 64x* blocks in
389*77c1e3ccSAndroid Build Coastguard Worker   // raster order
390*77c1e3ccSAndroid Build Coastguard Worker   if (block_size_wide[bsize] > block_size_wide[BLOCK_64X64] && col_off > 0) {
391*77c1e3ccSAndroid Build Coastguard Worker     const int plane_bw_unit_64 = mi_size_wide[BLOCK_64X64] >> ss_x;
392*77c1e3ccSAndroid Build Coastguard Worker     const int col_off_64 = col_off % plane_bw_unit_64;
393*77c1e3ccSAndroid Build Coastguard Worker     if (col_off_64 == 0) {
394*77c1e3ccSAndroid Build Coastguard Worker       // We are at the left edge of top-right or bottom-right 64x* block.
395*77c1e3ccSAndroid Build Coastguard Worker       const int plane_bh_unit_64 = mi_size_high[BLOCK_64X64] >> ss_y;
396*77c1e3ccSAndroid Build Coastguard Worker       const int row_off_64 = row_off % plane_bh_unit_64;
397*77c1e3ccSAndroid Build Coastguard Worker       const int plane_bh_unit =
398*77c1e3ccSAndroid Build Coastguard Worker           AOMMIN(mi_size_high[bsize] >> ss_y, plane_bh_unit_64);
399*77c1e3ccSAndroid Build Coastguard Worker       // Check if all bottom-left pixels are in the left 64x* block (which is
400*77c1e3ccSAndroid Build Coastguard Worker       // already coded).
401*77c1e3ccSAndroid Build Coastguard Worker       return row_off_64 + tx_size_high_unit[txsz] < plane_bh_unit;
402*77c1e3ccSAndroid Build Coastguard Worker     }
403*77c1e3ccSAndroid Build Coastguard Worker   }
404*77c1e3ccSAndroid Build Coastguard Worker 
405*77c1e3ccSAndroid Build Coastguard Worker   if (col_off > 0) {
406*77c1e3ccSAndroid Build Coastguard Worker     // Bottom-left pixels are in the bottom-left block, which is not available.
407*77c1e3ccSAndroid Build Coastguard Worker     return 0;
408*77c1e3ccSAndroid Build Coastguard Worker   } else {
409*77c1e3ccSAndroid Build Coastguard Worker     const int bh_unit = mi_size_high[bsize];
410*77c1e3ccSAndroid Build Coastguard Worker     const int plane_bh_unit = AOMMAX(bh_unit >> ss_y, 1);
411*77c1e3ccSAndroid Build Coastguard Worker     const int bottom_left_count_unit = tx_size_high_unit[txsz];
412*77c1e3ccSAndroid Build Coastguard Worker 
413*77c1e3ccSAndroid Build Coastguard Worker     // All bottom-left pixels are in the left block, which is already available.
414*77c1e3ccSAndroid Build Coastguard Worker     if (row_off + bottom_left_count_unit < plane_bh_unit) return 1;
415*77c1e3ccSAndroid Build Coastguard Worker 
416*77c1e3ccSAndroid Build Coastguard Worker     const int bw_in_mi_log2 = mi_size_wide_log2[bsize];
417*77c1e3ccSAndroid Build Coastguard Worker     const int bh_in_mi_log2 = mi_size_high_log2[bsize];
418*77c1e3ccSAndroid Build Coastguard Worker     const int sb_mi_size = mi_size_high[sb_size];
419*77c1e3ccSAndroid Build Coastguard Worker     const int blk_row_in_sb = (mi_row & (sb_mi_size - 1)) >> bh_in_mi_log2;
420*77c1e3ccSAndroid Build Coastguard Worker     const int blk_col_in_sb = (mi_col & (sb_mi_size - 1)) >> bw_in_mi_log2;
421*77c1e3ccSAndroid Build Coastguard Worker 
422*77c1e3ccSAndroid Build Coastguard Worker     // Leftmost column of superblock: so bottom-left pixels maybe in the left
423*77c1e3ccSAndroid Build Coastguard Worker     // and/or bottom-left superblocks. But only the left superblock is
424*77c1e3ccSAndroid Build Coastguard Worker     // available, so check if all required pixels fall in that superblock.
425*77c1e3ccSAndroid Build Coastguard Worker     if (blk_col_in_sb == 0) {
426*77c1e3ccSAndroid Build Coastguard Worker       const int blk_start_row_off =
427*77c1e3ccSAndroid Build Coastguard Worker           blk_row_in_sb << (bh_in_mi_log2 + MI_SIZE_LOG2 - MI_SIZE_LOG2) >>
428*77c1e3ccSAndroid Build Coastguard Worker           ss_y;
429*77c1e3ccSAndroid Build Coastguard Worker       const int row_off_in_sb = blk_start_row_off + row_off;
430*77c1e3ccSAndroid Build Coastguard Worker       const int sb_height_unit = sb_mi_size >> ss_y;
431*77c1e3ccSAndroid Build Coastguard Worker       return row_off_in_sb + bottom_left_count_unit < sb_height_unit;
432*77c1e3ccSAndroid Build Coastguard Worker     }
433*77c1e3ccSAndroid Build Coastguard Worker 
434*77c1e3ccSAndroid Build Coastguard Worker     // Bottom row of superblock (and not the leftmost column): so bottom-left
435*77c1e3ccSAndroid Build Coastguard Worker     // pixels fall in the bottom superblock, which is not available yet.
436*77c1e3ccSAndroid Build Coastguard Worker     if (((blk_row_in_sb + 1) << bh_in_mi_log2) >= sb_mi_size) return 0;
437*77c1e3ccSAndroid Build Coastguard Worker 
438*77c1e3ccSAndroid Build Coastguard Worker     // General case (neither leftmost column nor bottom row): check if the
439*77c1e3ccSAndroid Build Coastguard Worker     // bottom-left block is coded before the current block.
440*77c1e3ccSAndroid Build Coastguard Worker     const int this_blk_index =
441*77c1e3ccSAndroid Build Coastguard Worker         ((blk_row_in_sb + 0) << (MAX_MIB_SIZE_LOG2 - bw_in_mi_log2)) +
442*77c1e3ccSAndroid Build Coastguard Worker         blk_col_in_sb + 0;
443*77c1e3ccSAndroid Build Coastguard Worker     const int idx1 = this_blk_index / 8;
444*77c1e3ccSAndroid Build Coastguard Worker     const int idx2 = this_blk_index % 8;
445*77c1e3ccSAndroid Build Coastguard Worker     const uint8_t *has_bl_table = get_has_bl_table(partition, bsize);
446*77c1e3ccSAndroid Build Coastguard Worker     return (has_bl_table[idx1] >> idx2) & 1;
447*77c1e3ccSAndroid Build Coastguard Worker   }
448*77c1e3ccSAndroid Build Coastguard Worker }
449*77c1e3ccSAndroid Build Coastguard Worker 
450*77c1e3ccSAndroid Build Coastguard Worker typedef void (*intra_pred_fn)(uint8_t *dst, ptrdiff_t stride,
451*77c1e3ccSAndroid Build Coastguard Worker                               const uint8_t *above, const uint8_t *left);
452*77c1e3ccSAndroid Build Coastguard Worker 
453*77c1e3ccSAndroid Build Coastguard Worker static intra_pred_fn pred[INTRA_MODES][TX_SIZES_ALL];
454*77c1e3ccSAndroid Build Coastguard Worker static intra_pred_fn dc_pred[2][2][TX_SIZES_ALL];
455*77c1e3ccSAndroid Build Coastguard Worker 
456*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_AV1_HIGHBITDEPTH
457*77c1e3ccSAndroid Build Coastguard Worker typedef void (*intra_high_pred_fn)(uint16_t *dst, ptrdiff_t stride,
458*77c1e3ccSAndroid Build Coastguard Worker                                    const uint16_t *above, const uint16_t *left,
459*77c1e3ccSAndroid Build Coastguard Worker                                    int bd);
460*77c1e3ccSAndroid Build Coastguard Worker static intra_high_pred_fn pred_high[INTRA_MODES][TX_SIZES_ALL];
461*77c1e3ccSAndroid Build Coastguard Worker static intra_high_pred_fn dc_pred_high[2][2][TX_SIZES_ALL];
462*77c1e3ccSAndroid Build Coastguard Worker #endif
463*77c1e3ccSAndroid Build Coastguard Worker 
init_intra_predictors_internal(void)464*77c1e3ccSAndroid Build Coastguard Worker static void init_intra_predictors_internal(void) {
465*77c1e3ccSAndroid Build Coastguard Worker   assert(NELEMENTS(mode_to_angle_map) == INTRA_MODES);
466*77c1e3ccSAndroid Build Coastguard Worker 
467*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_REALTIME_ONLY && !CONFIG_AV1_DECODER
468*77c1e3ccSAndroid Build Coastguard Worker #define INIT_RECTANGULAR(p, type)             \
469*77c1e3ccSAndroid Build Coastguard Worker   p[TX_4X8] = aom_##type##_predictor_4x8;     \
470*77c1e3ccSAndroid Build Coastguard Worker   p[TX_8X4] = aom_##type##_predictor_8x4;     \
471*77c1e3ccSAndroid Build Coastguard Worker   p[TX_8X16] = aom_##type##_predictor_8x16;   \
472*77c1e3ccSAndroid Build Coastguard Worker   p[TX_16X8] = aom_##type##_predictor_16x8;   \
473*77c1e3ccSAndroid Build Coastguard Worker   p[TX_16X32] = aom_##type##_predictor_16x32; \
474*77c1e3ccSAndroid Build Coastguard Worker   p[TX_32X16] = aom_##type##_predictor_32x16; \
475*77c1e3ccSAndroid Build Coastguard Worker   p[TX_32X64] = aom_##type##_predictor_32x64; \
476*77c1e3ccSAndroid Build Coastguard Worker   p[TX_64X32] = aom_##type##_predictor_64x32;
477*77c1e3ccSAndroid Build Coastguard Worker #else
478*77c1e3ccSAndroid Build Coastguard Worker #define INIT_RECTANGULAR(p, type)             \
479*77c1e3ccSAndroid Build Coastguard Worker   p[TX_4X8] = aom_##type##_predictor_4x8;     \
480*77c1e3ccSAndroid Build Coastguard Worker   p[TX_8X4] = aom_##type##_predictor_8x4;     \
481*77c1e3ccSAndroid Build Coastguard Worker   p[TX_8X16] = aom_##type##_predictor_8x16;   \
482*77c1e3ccSAndroid Build Coastguard Worker   p[TX_16X8] = aom_##type##_predictor_16x8;   \
483*77c1e3ccSAndroid Build Coastguard Worker   p[TX_16X32] = aom_##type##_predictor_16x32; \
484*77c1e3ccSAndroid Build Coastguard Worker   p[TX_32X16] = aom_##type##_predictor_32x16; \
485*77c1e3ccSAndroid Build Coastguard Worker   p[TX_32X64] = aom_##type##_predictor_32x64; \
486*77c1e3ccSAndroid Build Coastguard Worker   p[TX_64X32] = aom_##type##_predictor_64x32; \
487*77c1e3ccSAndroid Build Coastguard Worker   p[TX_4X16] = aom_##type##_predictor_4x16;   \
488*77c1e3ccSAndroid Build Coastguard Worker   p[TX_16X4] = aom_##type##_predictor_16x4;   \
489*77c1e3ccSAndroid Build Coastguard Worker   p[TX_8X32] = aom_##type##_predictor_8x32;   \
490*77c1e3ccSAndroid Build Coastguard Worker   p[TX_32X8] = aom_##type##_predictor_32x8;   \
491*77c1e3ccSAndroid Build Coastguard Worker   p[TX_16X64] = aom_##type##_predictor_16x64; \
492*77c1e3ccSAndroid Build Coastguard Worker   p[TX_64X16] = aom_##type##_predictor_64x16;
493*77c1e3ccSAndroid Build Coastguard Worker #endif  // CONFIG_REALTIME_ONLY && !CONFIG_AV1_DECODER
494*77c1e3ccSAndroid Build Coastguard Worker 
495*77c1e3ccSAndroid Build Coastguard Worker #define INIT_NO_4X4(p, type)                  \
496*77c1e3ccSAndroid Build Coastguard Worker   p[TX_8X8] = aom_##type##_predictor_8x8;     \
497*77c1e3ccSAndroid Build Coastguard Worker   p[TX_16X16] = aom_##type##_predictor_16x16; \
498*77c1e3ccSAndroid Build Coastguard Worker   p[TX_32X32] = aom_##type##_predictor_32x32; \
499*77c1e3ccSAndroid Build Coastguard Worker   p[TX_64X64] = aom_##type##_predictor_64x64; \
500*77c1e3ccSAndroid Build Coastguard Worker   INIT_RECTANGULAR(p, type)
501*77c1e3ccSAndroid Build Coastguard Worker 
502*77c1e3ccSAndroid Build Coastguard Worker #define INIT_ALL_SIZES(p, type)           \
503*77c1e3ccSAndroid Build Coastguard Worker   p[TX_4X4] = aom_##type##_predictor_4x4; \
504*77c1e3ccSAndroid Build Coastguard Worker   INIT_NO_4X4(p, type)
505*77c1e3ccSAndroid Build Coastguard Worker 
506*77c1e3ccSAndroid Build Coastguard Worker   INIT_ALL_SIZES(pred[V_PRED], v)
507*77c1e3ccSAndroid Build Coastguard Worker   INIT_ALL_SIZES(pred[H_PRED], h)
508*77c1e3ccSAndroid Build Coastguard Worker   INIT_ALL_SIZES(pred[PAETH_PRED], paeth)
509*77c1e3ccSAndroid Build Coastguard Worker   INIT_ALL_SIZES(pred[SMOOTH_PRED], smooth)
510*77c1e3ccSAndroid Build Coastguard Worker   INIT_ALL_SIZES(pred[SMOOTH_V_PRED], smooth_v)
511*77c1e3ccSAndroid Build Coastguard Worker   INIT_ALL_SIZES(pred[SMOOTH_H_PRED], smooth_h)
512*77c1e3ccSAndroid Build Coastguard Worker   INIT_ALL_SIZES(dc_pred[0][0], dc_128)
513*77c1e3ccSAndroid Build Coastguard Worker   INIT_ALL_SIZES(dc_pred[0][1], dc_top)
514*77c1e3ccSAndroid Build Coastguard Worker   INIT_ALL_SIZES(dc_pred[1][0], dc_left)
515*77c1e3ccSAndroid Build Coastguard Worker   INIT_ALL_SIZES(dc_pred[1][1], dc)
516*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_AV1_HIGHBITDEPTH
517*77c1e3ccSAndroid Build Coastguard Worker   INIT_ALL_SIZES(pred_high[V_PRED], highbd_v)
518*77c1e3ccSAndroid Build Coastguard Worker   INIT_ALL_SIZES(pred_high[H_PRED], highbd_h)
519*77c1e3ccSAndroid Build Coastguard Worker   INIT_ALL_SIZES(pred_high[PAETH_PRED], highbd_paeth)
520*77c1e3ccSAndroid Build Coastguard Worker   INIT_ALL_SIZES(pred_high[SMOOTH_PRED], highbd_smooth)
521*77c1e3ccSAndroid Build Coastguard Worker   INIT_ALL_SIZES(pred_high[SMOOTH_V_PRED], highbd_smooth_v)
522*77c1e3ccSAndroid Build Coastguard Worker   INIT_ALL_SIZES(pred_high[SMOOTH_H_PRED], highbd_smooth_h)
523*77c1e3ccSAndroid Build Coastguard Worker   INIT_ALL_SIZES(dc_pred_high[0][0], highbd_dc_128)
524*77c1e3ccSAndroid Build Coastguard Worker   INIT_ALL_SIZES(dc_pred_high[0][1], highbd_dc_top)
525*77c1e3ccSAndroid Build Coastguard Worker   INIT_ALL_SIZES(dc_pred_high[1][0], highbd_dc_left)
526*77c1e3ccSAndroid Build Coastguard Worker   INIT_ALL_SIZES(dc_pred_high[1][1], highbd_dc)
527*77c1e3ccSAndroid Build Coastguard Worker #endif
528*77c1e3ccSAndroid Build Coastguard Worker #undef intra_pred_allsizes
529*77c1e3ccSAndroid Build Coastguard Worker }
530*77c1e3ccSAndroid Build Coastguard Worker 
531*77c1e3ccSAndroid Build Coastguard Worker // Directional prediction, zone 1: 0 < angle < 90
av1_dr_prediction_z1_c(uint8_t * dst,ptrdiff_t stride,int bw,int bh,const uint8_t * above,const uint8_t * left,int upsample_above,int dx,int dy)532*77c1e3ccSAndroid Build Coastguard Worker void av1_dr_prediction_z1_c(uint8_t *dst, ptrdiff_t stride, int bw, int bh,
533*77c1e3ccSAndroid Build Coastguard Worker                             const uint8_t *above, const uint8_t *left,
534*77c1e3ccSAndroid Build Coastguard Worker                             int upsample_above, int dx, int dy) {
535*77c1e3ccSAndroid Build Coastguard Worker   int r, c, x, base, shift, val;
536*77c1e3ccSAndroid Build Coastguard Worker 
537*77c1e3ccSAndroid Build Coastguard Worker   (void)left;
538*77c1e3ccSAndroid Build Coastguard Worker   (void)dy;
539*77c1e3ccSAndroid Build Coastguard Worker   assert(dy == 1);
540*77c1e3ccSAndroid Build Coastguard Worker   assert(dx > 0);
541*77c1e3ccSAndroid Build Coastguard Worker 
542*77c1e3ccSAndroid Build Coastguard Worker   const int max_base_x = ((bw + bh) - 1) << upsample_above;
543*77c1e3ccSAndroid Build Coastguard Worker   const int frac_bits = 6 - upsample_above;
544*77c1e3ccSAndroid Build Coastguard Worker   const int base_inc = 1 << upsample_above;
545*77c1e3ccSAndroid Build Coastguard Worker   x = dx;
546*77c1e3ccSAndroid Build Coastguard Worker   for (r = 0; r < bh; ++r, dst += stride, x += dx) {
547*77c1e3ccSAndroid Build Coastguard Worker     base = x >> frac_bits;
548*77c1e3ccSAndroid Build Coastguard Worker     shift = ((x << upsample_above) & 0x3F) >> 1;
549*77c1e3ccSAndroid Build Coastguard Worker 
550*77c1e3ccSAndroid Build Coastguard Worker     if (base >= max_base_x) {
551*77c1e3ccSAndroid Build Coastguard Worker       for (int i = r; i < bh; ++i) {
552*77c1e3ccSAndroid Build Coastguard Worker         memset(dst, above[max_base_x], bw * sizeof(dst[0]));
553*77c1e3ccSAndroid Build Coastguard Worker         dst += stride;
554*77c1e3ccSAndroid Build Coastguard Worker       }
555*77c1e3ccSAndroid Build Coastguard Worker       return;
556*77c1e3ccSAndroid Build Coastguard Worker     }
557*77c1e3ccSAndroid Build Coastguard Worker 
558*77c1e3ccSAndroid Build Coastguard Worker     for (c = 0; c < bw; ++c, base += base_inc) {
559*77c1e3ccSAndroid Build Coastguard Worker       if (base < max_base_x) {
560*77c1e3ccSAndroid Build Coastguard Worker         val = above[base] * (32 - shift) + above[base + 1] * shift;
561*77c1e3ccSAndroid Build Coastguard Worker         dst[c] = ROUND_POWER_OF_TWO(val, 5);
562*77c1e3ccSAndroid Build Coastguard Worker       } else {
563*77c1e3ccSAndroid Build Coastguard Worker         dst[c] = above[max_base_x];
564*77c1e3ccSAndroid Build Coastguard Worker       }
565*77c1e3ccSAndroid Build Coastguard Worker     }
566*77c1e3ccSAndroid Build Coastguard Worker   }
567*77c1e3ccSAndroid Build Coastguard Worker }
568*77c1e3ccSAndroid Build Coastguard Worker 
569*77c1e3ccSAndroid Build Coastguard Worker // Directional prediction, zone 2: 90 < angle < 180
av1_dr_prediction_z2_c(uint8_t * dst,ptrdiff_t stride,int bw,int bh,const uint8_t * above,const uint8_t * left,int upsample_above,int upsample_left,int dx,int dy)570*77c1e3ccSAndroid Build Coastguard Worker void av1_dr_prediction_z2_c(uint8_t *dst, ptrdiff_t stride, int bw, int bh,
571*77c1e3ccSAndroid Build Coastguard Worker                             const uint8_t *above, const uint8_t *left,
572*77c1e3ccSAndroid Build Coastguard Worker                             int upsample_above, int upsample_left, int dx,
573*77c1e3ccSAndroid Build Coastguard Worker                             int dy) {
574*77c1e3ccSAndroid Build Coastguard Worker   assert(dx > 0);
575*77c1e3ccSAndroid Build Coastguard Worker   assert(dy > 0);
576*77c1e3ccSAndroid Build Coastguard Worker 
577*77c1e3ccSAndroid Build Coastguard Worker   const int min_base_x = -(1 << upsample_above);
578*77c1e3ccSAndroid Build Coastguard Worker   const int min_base_y = -(1 << upsample_left);
579*77c1e3ccSAndroid Build Coastguard Worker   (void)min_base_y;
580*77c1e3ccSAndroid Build Coastguard Worker   const int frac_bits_x = 6 - upsample_above;
581*77c1e3ccSAndroid Build Coastguard Worker   const int frac_bits_y = 6 - upsample_left;
582*77c1e3ccSAndroid Build Coastguard Worker 
583*77c1e3ccSAndroid Build Coastguard Worker   for (int r = 0; r < bh; ++r) {
584*77c1e3ccSAndroid Build Coastguard Worker     for (int c = 0; c < bw; ++c) {
585*77c1e3ccSAndroid Build Coastguard Worker       int val;
586*77c1e3ccSAndroid Build Coastguard Worker       int y = r + 1;
587*77c1e3ccSAndroid Build Coastguard Worker       int x = (c << 6) - y * dx;
588*77c1e3ccSAndroid Build Coastguard Worker       const int base_x = x >> frac_bits_x;
589*77c1e3ccSAndroid Build Coastguard Worker       if (base_x >= min_base_x) {
590*77c1e3ccSAndroid Build Coastguard Worker         const int shift = ((x * (1 << upsample_above)) & 0x3F) >> 1;
591*77c1e3ccSAndroid Build Coastguard Worker         val = above[base_x] * (32 - shift) + above[base_x + 1] * shift;
592*77c1e3ccSAndroid Build Coastguard Worker         val = ROUND_POWER_OF_TWO(val, 5);
593*77c1e3ccSAndroid Build Coastguard Worker       } else {
594*77c1e3ccSAndroid Build Coastguard Worker         x = c + 1;
595*77c1e3ccSAndroid Build Coastguard Worker         y = (r << 6) - x * dy;
596*77c1e3ccSAndroid Build Coastguard Worker         const int base_y = y >> frac_bits_y;
597*77c1e3ccSAndroid Build Coastguard Worker         assert(base_y >= min_base_y);
598*77c1e3ccSAndroid Build Coastguard Worker         const int shift = ((y * (1 << upsample_left)) & 0x3F) >> 1;
599*77c1e3ccSAndroid Build Coastguard Worker         val = left[base_y] * (32 - shift) + left[base_y + 1] * shift;
600*77c1e3ccSAndroid Build Coastguard Worker         val = ROUND_POWER_OF_TWO(val, 5);
601*77c1e3ccSAndroid Build Coastguard Worker       }
602*77c1e3ccSAndroid Build Coastguard Worker       dst[c] = val;
603*77c1e3ccSAndroid Build Coastguard Worker     }
604*77c1e3ccSAndroid Build Coastguard Worker     dst += stride;
605*77c1e3ccSAndroid Build Coastguard Worker   }
606*77c1e3ccSAndroid Build Coastguard Worker }
607*77c1e3ccSAndroid Build Coastguard Worker 
608*77c1e3ccSAndroid Build Coastguard Worker // Directional prediction, zone 3: 180 < angle < 270
av1_dr_prediction_z3_c(uint8_t * dst,ptrdiff_t stride,int bw,int bh,const uint8_t * above,const uint8_t * left,int upsample_left,int dx,int dy)609*77c1e3ccSAndroid Build Coastguard Worker void av1_dr_prediction_z3_c(uint8_t *dst, ptrdiff_t stride, int bw, int bh,
610*77c1e3ccSAndroid Build Coastguard Worker                             const uint8_t *above, const uint8_t *left,
611*77c1e3ccSAndroid Build Coastguard Worker                             int upsample_left, int dx, int dy) {
612*77c1e3ccSAndroid Build Coastguard Worker   int r, c, y, base, shift, val;
613*77c1e3ccSAndroid Build Coastguard Worker 
614*77c1e3ccSAndroid Build Coastguard Worker   (void)above;
615*77c1e3ccSAndroid Build Coastguard Worker   (void)dx;
616*77c1e3ccSAndroid Build Coastguard Worker 
617*77c1e3ccSAndroid Build Coastguard Worker   assert(dx == 1);
618*77c1e3ccSAndroid Build Coastguard Worker   assert(dy > 0);
619*77c1e3ccSAndroid Build Coastguard Worker 
620*77c1e3ccSAndroid Build Coastguard Worker   const int max_base_y = (bw + bh - 1) << upsample_left;
621*77c1e3ccSAndroid Build Coastguard Worker   const int frac_bits = 6 - upsample_left;
622*77c1e3ccSAndroid Build Coastguard Worker   const int base_inc = 1 << upsample_left;
623*77c1e3ccSAndroid Build Coastguard Worker   y = dy;
624*77c1e3ccSAndroid Build Coastguard Worker   for (c = 0; c < bw; ++c, y += dy) {
625*77c1e3ccSAndroid Build Coastguard Worker     base = y >> frac_bits;
626*77c1e3ccSAndroid Build Coastguard Worker     shift = ((y << upsample_left) & 0x3F) >> 1;
627*77c1e3ccSAndroid Build Coastguard Worker 
628*77c1e3ccSAndroid Build Coastguard Worker     for (r = 0; r < bh; ++r, base += base_inc) {
629*77c1e3ccSAndroid Build Coastguard Worker       if (base < max_base_y) {
630*77c1e3ccSAndroid Build Coastguard Worker         val = left[base] * (32 - shift) + left[base + 1] * shift;
631*77c1e3ccSAndroid Build Coastguard Worker         dst[r * stride + c] = ROUND_POWER_OF_TWO(val, 5);
632*77c1e3ccSAndroid Build Coastguard Worker       } else {
633*77c1e3ccSAndroid Build Coastguard Worker         for (; r < bh; ++r) dst[r * stride + c] = left[max_base_y];
634*77c1e3ccSAndroid Build Coastguard Worker         break;
635*77c1e3ccSAndroid Build Coastguard Worker       }
636*77c1e3ccSAndroid Build Coastguard Worker     }
637*77c1e3ccSAndroid Build Coastguard Worker   }
638*77c1e3ccSAndroid Build Coastguard Worker }
639*77c1e3ccSAndroid Build Coastguard Worker 
dr_predictor(uint8_t * dst,ptrdiff_t stride,TX_SIZE tx_size,const uint8_t * above,const uint8_t * left,int upsample_above,int upsample_left,int angle)640*77c1e3ccSAndroid Build Coastguard Worker static void dr_predictor(uint8_t *dst, ptrdiff_t stride, TX_SIZE tx_size,
641*77c1e3ccSAndroid Build Coastguard Worker                          const uint8_t *above, const uint8_t *left,
642*77c1e3ccSAndroid Build Coastguard Worker                          int upsample_above, int upsample_left, int angle) {
643*77c1e3ccSAndroid Build Coastguard Worker   const int dx = av1_get_dx(angle);
644*77c1e3ccSAndroid Build Coastguard Worker   const int dy = av1_get_dy(angle);
645*77c1e3ccSAndroid Build Coastguard Worker   const int bw = tx_size_wide[tx_size];
646*77c1e3ccSAndroid Build Coastguard Worker   const int bh = tx_size_high[tx_size];
647*77c1e3ccSAndroid Build Coastguard Worker   assert(angle > 0 && angle < 270);
648*77c1e3ccSAndroid Build Coastguard Worker 
649*77c1e3ccSAndroid Build Coastguard Worker   if (angle > 0 && angle < 90) {
650*77c1e3ccSAndroid Build Coastguard Worker     av1_dr_prediction_z1(dst, stride, bw, bh, above, left, upsample_above, dx,
651*77c1e3ccSAndroid Build Coastguard Worker                          dy);
652*77c1e3ccSAndroid Build Coastguard Worker   } else if (angle > 90 && angle < 180) {
653*77c1e3ccSAndroid Build Coastguard Worker     av1_dr_prediction_z2(dst, stride, bw, bh, above, left, upsample_above,
654*77c1e3ccSAndroid Build Coastguard Worker                          upsample_left, dx, dy);
655*77c1e3ccSAndroid Build Coastguard Worker   } else if (angle > 180 && angle < 270) {
656*77c1e3ccSAndroid Build Coastguard Worker     av1_dr_prediction_z3(dst, stride, bw, bh, above, left, upsample_left, dx,
657*77c1e3ccSAndroid Build Coastguard Worker                          dy);
658*77c1e3ccSAndroid Build Coastguard Worker   } else if (angle == 90) {
659*77c1e3ccSAndroid Build Coastguard Worker     pred[V_PRED][tx_size](dst, stride, above, left);
660*77c1e3ccSAndroid Build Coastguard Worker   } else if (angle == 180) {
661*77c1e3ccSAndroid Build Coastguard Worker     pred[H_PRED][tx_size](dst, stride, above, left);
662*77c1e3ccSAndroid Build Coastguard Worker   }
663*77c1e3ccSAndroid Build Coastguard Worker }
664*77c1e3ccSAndroid Build Coastguard Worker 
665*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_AV1_HIGHBITDEPTH
666*77c1e3ccSAndroid Build Coastguard Worker // Directional prediction, zone 1: 0 < angle < 90
av1_highbd_dr_prediction_z1_c(uint16_t * dst,ptrdiff_t stride,int bw,int bh,const uint16_t * above,const uint16_t * left,int upsample_above,int dx,int dy,int bd)667*77c1e3ccSAndroid Build Coastguard Worker void av1_highbd_dr_prediction_z1_c(uint16_t *dst, ptrdiff_t stride, int bw,
668*77c1e3ccSAndroid Build Coastguard Worker                                    int bh, const uint16_t *above,
669*77c1e3ccSAndroid Build Coastguard Worker                                    const uint16_t *left, int upsample_above,
670*77c1e3ccSAndroid Build Coastguard Worker                                    int dx, int dy, int bd) {
671*77c1e3ccSAndroid Build Coastguard Worker   int r, c, x, base, shift, val;
672*77c1e3ccSAndroid Build Coastguard Worker 
673*77c1e3ccSAndroid Build Coastguard Worker   (void)left;
674*77c1e3ccSAndroid Build Coastguard Worker   (void)dy;
675*77c1e3ccSAndroid Build Coastguard Worker   (void)bd;
676*77c1e3ccSAndroid Build Coastguard Worker   assert(dy == 1);
677*77c1e3ccSAndroid Build Coastguard Worker   assert(dx > 0);
678*77c1e3ccSAndroid Build Coastguard Worker 
679*77c1e3ccSAndroid Build Coastguard Worker   const int max_base_x = ((bw + bh) - 1) << upsample_above;
680*77c1e3ccSAndroid Build Coastguard Worker   const int frac_bits = 6 - upsample_above;
681*77c1e3ccSAndroid Build Coastguard Worker   const int base_inc = 1 << upsample_above;
682*77c1e3ccSAndroid Build Coastguard Worker   x = dx;
683*77c1e3ccSAndroid Build Coastguard Worker   for (r = 0; r < bh; ++r, dst += stride, x += dx) {
684*77c1e3ccSAndroid Build Coastguard Worker     base = x >> frac_bits;
685*77c1e3ccSAndroid Build Coastguard Worker     shift = ((x << upsample_above) & 0x3F) >> 1;
686*77c1e3ccSAndroid Build Coastguard Worker 
687*77c1e3ccSAndroid Build Coastguard Worker     if (base >= max_base_x) {
688*77c1e3ccSAndroid Build Coastguard Worker       for (int i = r; i < bh; ++i) {
689*77c1e3ccSAndroid Build Coastguard Worker         aom_memset16(dst, above[max_base_x], bw);
690*77c1e3ccSAndroid Build Coastguard Worker         dst += stride;
691*77c1e3ccSAndroid Build Coastguard Worker       }
692*77c1e3ccSAndroid Build Coastguard Worker       return;
693*77c1e3ccSAndroid Build Coastguard Worker     }
694*77c1e3ccSAndroid Build Coastguard Worker 
695*77c1e3ccSAndroid Build Coastguard Worker     for (c = 0; c < bw; ++c, base += base_inc) {
696*77c1e3ccSAndroid Build Coastguard Worker       if (base < max_base_x) {
697*77c1e3ccSAndroid Build Coastguard Worker         val = above[base] * (32 - shift) + above[base + 1] * shift;
698*77c1e3ccSAndroid Build Coastguard Worker         dst[c] = ROUND_POWER_OF_TWO(val, 5);
699*77c1e3ccSAndroid Build Coastguard Worker       } else {
700*77c1e3ccSAndroid Build Coastguard Worker         dst[c] = above[max_base_x];
701*77c1e3ccSAndroid Build Coastguard Worker       }
702*77c1e3ccSAndroid Build Coastguard Worker     }
703*77c1e3ccSAndroid Build Coastguard Worker   }
704*77c1e3ccSAndroid Build Coastguard Worker }
705*77c1e3ccSAndroid Build Coastguard Worker 
706*77c1e3ccSAndroid Build Coastguard Worker // Directional prediction, zone 2: 90 < angle < 180
av1_highbd_dr_prediction_z2_c(uint16_t * dst,ptrdiff_t stride,int bw,int bh,const uint16_t * above,const uint16_t * left,int upsample_above,int upsample_left,int dx,int dy,int bd)707*77c1e3ccSAndroid Build Coastguard Worker void av1_highbd_dr_prediction_z2_c(uint16_t *dst, ptrdiff_t stride, int bw,
708*77c1e3ccSAndroid Build Coastguard Worker                                    int bh, const uint16_t *above,
709*77c1e3ccSAndroid Build Coastguard Worker                                    const uint16_t *left, int upsample_above,
710*77c1e3ccSAndroid Build Coastguard Worker                                    int upsample_left, int dx, int dy, int bd) {
711*77c1e3ccSAndroid Build Coastguard Worker   (void)bd;
712*77c1e3ccSAndroid Build Coastguard Worker   assert(dx > 0);
713*77c1e3ccSAndroid Build Coastguard Worker   assert(dy > 0);
714*77c1e3ccSAndroid Build Coastguard Worker 
715*77c1e3ccSAndroid Build Coastguard Worker   const int min_base_x = -(1 << upsample_above);
716*77c1e3ccSAndroid Build Coastguard Worker   const int min_base_y = -(1 << upsample_left);
717*77c1e3ccSAndroid Build Coastguard Worker   (void)min_base_y;
718*77c1e3ccSAndroid Build Coastguard Worker   const int frac_bits_x = 6 - upsample_above;
719*77c1e3ccSAndroid Build Coastguard Worker   const int frac_bits_y = 6 - upsample_left;
720*77c1e3ccSAndroid Build Coastguard Worker 
721*77c1e3ccSAndroid Build Coastguard Worker   for (int r = 0; r < bh; ++r) {
722*77c1e3ccSAndroid Build Coastguard Worker     for (int c = 0; c < bw; ++c) {
723*77c1e3ccSAndroid Build Coastguard Worker       int val;
724*77c1e3ccSAndroid Build Coastguard Worker       int y = r + 1;
725*77c1e3ccSAndroid Build Coastguard Worker       int x = (c << 6) - y * dx;
726*77c1e3ccSAndroid Build Coastguard Worker       const int base_x = x >> frac_bits_x;
727*77c1e3ccSAndroid Build Coastguard Worker       if (base_x >= min_base_x) {
728*77c1e3ccSAndroid Build Coastguard Worker         const int shift = ((x * (1 << upsample_above)) & 0x3F) >> 1;
729*77c1e3ccSAndroid Build Coastguard Worker         val = above[base_x] * (32 - shift) + above[base_x + 1] * shift;
730*77c1e3ccSAndroid Build Coastguard Worker         val = ROUND_POWER_OF_TWO(val, 5);
731*77c1e3ccSAndroid Build Coastguard Worker       } else {
732*77c1e3ccSAndroid Build Coastguard Worker         x = c + 1;
733*77c1e3ccSAndroid Build Coastguard Worker         y = (r << 6) - x * dy;
734*77c1e3ccSAndroid Build Coastguard Worker         const int base_y = y >> frac_bits_y;
735*77c1e3ccSAndroid Build Coastguard Worker         assert(base_y >= min_base_y);
736*77c1e3ccSAndroid Build Coastguard Worker         const int shift = ((y * (1 << upsample_left)) & 0x3F) >> 1;
737*77c1e3ccSAndroid Build Coastguard Worker         val = left[base_y] * (32 - shift) + left[base_y + 1] * shift;
738*77c1e3ccSAndroid Build Coastguard Worker         val = ROUND_POWER_OF_TWO(val, 5);
739*77c1e3ccSAndroid Build Coastguard Worker       }
740*77c1e3ccSAndroid Build Coastguard Worker       dst[c] = val;
741*77c1e3ccSAndroid Build Coastguard Worker     }
742*77c1e3ccSAndroid Build Coastguard Worker     dst += stride;
743*77c1e3ccSAndroid Build Coastguard Worker   }
744*77c1e3ccSAndroid Build Coastguard Worker }
745*77c1e3ccSAndroid Build Coastguard Worker 
746*77c1e3ccSAndroid Build Coastguard Worker // Directional prediction, zone 3: 180 < angle < 270
av1_highbd_dr_prediction_z3_c(uint16_t * dst,ptrdiff_t stride,int bw,int bh,const uint16_t * above,const uint16_t * left,int upsample_left,int dx,int dy,int bd)747*77c1e3ccSAndroid Build Coastguard Worker void av1_highbd_dr_prediction_z3_c(uint16_t *dst, ptrdiff_t stride, int bw,
748*77c1e3ccSAndroid Build Coastguard Worker                                    int bh, const uint16_t *above,
749*77c1e3ccSAndroid Build Coastguard Worker                                    const uint16_t *left, int upsample_left,
750*77c1e3ccSAndroid Build Coastguard Worker                                    int dx, int dy, int bd) {
751*77c1e3ccSAndroid Build Coastguard Worker   int r, c, y, base, shift, val;
752*77c1e3ccSAndroid Build Coastguard Worker 
753*77c1e3ccSAndroid Build Coastguard Worker   (void)above;
754*77c1e3ccSAndroid Build Coastguard Worker   (void)dx;
755*77c1e3ccSAndroid Build Coastguard Worker   (void)bd;
756*77c1e3ccSAndroid Build Coastguard Worker   assert(dx == 1);
757*77c1e3ccSAndroid Build Coastguard Worker   assert(dy > 0);
758*77c1e3ccSAndroid Build Coastguard Worker 
759*77c1e3ccSAndroid Build Coastguard Worker   const int max_base_y = (bw + bh - 1) << upsample_left;
760*77c1e3ccSAndroid Build Coastguard Worker   const int frac_bits = 6 - upsample_left;
761*77c1e3ccSAndroid Build Coastguard Worker   const int base_inc = 1 << upsample_left;
762*77c1e3ccSAndroid Build Coastguard Worker   y = dy;
763*77c1e3ccSAndroid Build Coastguard Worker   for (c = 0; c < bw; ++c, y += dy) {
764*77c1e3ccSAndroid Build Coastguard Worker     base = y >> frac_bits;
765*77c1e3ccSAndroid Build Coastguard Worker     shift = ((y << upsample_left) & 0x3F) >> 1;
766*77c1e3ccSAndroid Build Coastguard Worker 
767*77c1e3ccSAndroid Build Coastguard Worker     for (r = 0; r < bh; ++r, base += base_inc) {
768*77c1e3ccSAndroid Build Coastguard Worker       if (base < max_base_y) {
769*77c1e3ccSAndroid Build Coastguard Worker         val = left[base] * (32 - shift) + left[base + 1] * shift;
770*77c1e3ccSAndroid Build Coastguard Worker         dst[r * stride + c] = ROUND_POWER_OF_TWO(val, 5);
771*77c1e3ccSAndroid Build Coastguard Worker       } else {
772*77c1e3ccSAndroid Build Coastguard Worker         for (; r < bh; ++r) dst[r * stride + c] = left[max_base_y];
773*77c1e3ccSAndroid Build Coastguard Worker         break;
774*77c1e3ccSAndroid Build Coastguard Worker       }
775*77c1e3ccSAndroid Build Coastguard Worker     }
776*77c1e3ccSAndroid Build Coastguard Worker   }
777*77c1e3ccSAndroid Build Coastguard Worker }
778*77c1e3ccSAndroid Build Coastguard Worker 
highbd_dr_predictor(uint16_t * dst,ptrdiff_t stride,TX_SIZE tx_size,const uint16_t * above,const uint16_t * left,int upsample_above,int upsample_left,int angle,int bd)779*77c1e3ccSAndroid Build Coastguard Worker static void highbd_dr_predictor(uint16_t *dst, ptrdiff_t stride,
780*77c1e3ccSAndroid Build Coastguard Worker                                 TX_SIZE tx_size, const uint16_t *above,
781*77c1e3ccSAndroid Build Coastguard Worker                                 const uint16_t *left, int upsample_above,
782*77c1e3ccSAndroid Build Coastguard Worker                                 int upsample_left, int angle, int bd) {
783*77c1e3ccSAndroid Build Coastguard Worker   const int dx = av1_get_dx(angle);
784*77c1e3ccSAndroid Build Coastguard Worker   const int dy = av1_get_dy(angle);
785*77c1e3ccSAndroid Build Coastguard Worker   const int bw = tx_size_wide[tx_size];
786*77c1e3ccSAndroid Build Coastguard Worker   const int bh = tx_size_high[tx_size];
787*77c1e3ccSAndroid Build Coastguard Worker   assert(angle > 0 && angle < 270);
788*77c1e3ccSAndroid Build Coastguard Worker 
789*77c1e3ccSAndroid Build Coastguard Worker   if (angle > 0 && angle < 90) {
790*77c1e3ccSAndroid Build Coastguard Worker     av1_highbd_dr_prediction_z1(dst, stride, bw, bh, above, left,
791*77c1e3ccSAndroid Build Coastguard Worker                                 upsample_above, dx, dy, bd);
792*77c1e3ccSAndroid Build Coastguard Worker   } else if (angle > 90 && angle < 180) {
793*77c1e3ccSAndroid Build Coastguard Worker     av1_highbd_dr_prediction_z2(dst, stride, bw, bh, above, left,
794*77c1e3ccSAndroid Build Coastguard Worker                                 upsample_above, upsample_left, dx, dy, bd);
795*77c1e3ccSAndroid Build Coastguard Worker   } else if (angle > 180 && angle < 270) {
796*77c1e3ccSAndroid Build Coastguard Worker     av1_highbd_dr_prediction_z3(dst, stride, bw, bh, above, left, upsample_left,
797*77c1e3ccSAndroid Build Coastguard Worker                                 dx, dy, bd);
798*77c1e3ccSAndroid Build Coastguard Worker   } else if (angle == 90) {
799*77c1e3ccSAndroid Build Coastguard Worker     pred_high[V_PRED][tx_size](dst, stride, above, left, bd);
800*77c1e3ccSAndroid Build Coastguard Worker   } else if (angle == 180) {
801*77c1e3ccSAndroid Build Coastguard Worker     pred_high[H_PRED][tx_size](dst, stride, above, left, bd);
802*77c1e3ccSAndroid Build Coastguard Worker   }
803*77c1e3ccSAndroid Build Coastguard Worker }
804*77c1e3ccSAndroid Build Coastguard Worker #endif  // CONFIG_AV1_HIGHBITDEPTH
805*77c1e3ccSAndroid Build Coastguard Worker 
806*77c1e3ccSAndroid Build Coastguard Worker DECLARE_ALIGNED(16, const int8_t,
807*77c1e3ccSAndroid Build Coastguard Worker                 av1_filter_intra_taps[FILTER_INTRA_MODES][8][8]) = {
808*77c1e3ccSAndroid Build Coastguard Worker   {
809*77c1e3ccSAndroid Build Coastguard Worker       { -6, 10, 0, 0, 0, 12, 0, 0 },
810*77c1e3ccSAndroid Build Coastguard Worker       { -5, 2, 10, 0, 0, 9, 0, 0 },
811*77c1e3ccSAndroid Build Coastguard Worker       { -3, 1, 1, 10, 0, 7, 0, 0 },
812*77c1e3ccSAndroid Build Coastguard Worker       { -3, 1, 1, 2, 10, 5, 0, 0 },
813*77c1e3ccSAndroid Build Coastguard Worker       { -4, 6, 0, 0, 0, 2, 12, 0 },
814*77c1e3ccSAndroid Build Coastguard Worker       { -3, 2, 6, 0, 0, 2, 9, 0 },
815*77c1e3ccSAndroid Build Coastguard Worker       { -3, 2, 2, 6, 0, 2, 7, 0 },
816*77c1e3ccSAndroid Build Coastguard Worker       { -3, 1, 2, 2, 6, 3, 5, 0 },
817*77c1e3ccSAndroid Build Coastguard Worker   },
818*77c1e3ccSAndroid Build Coastguard Worker   {
819*77c1e3ccSAndroid Build Coastguard Worker       { -10, 16, 0, 0, 0, 10, 0, 0 },
820*77c1e3ccSAndroid Build Coastguard Worker       { -6, 0, 16, 0, 0, 6, 0, 0 },
821*77c1e3ccSAndroid Build Coastguard Worker       { -4, 0, 0, 16, 0, 4, 0, 0 },
822*77c1e3ccSAndroid Build Coastguard Worker       { -2, 0, 0, 0, 16, 2, 0, 0 },
823*77c1e3ccSAndroid Build Coastguard Worker       { -10, 16, 0, 0, 0, 0, 10, 0 },
824*77c1e3ccSAndroid Build Coastguard Worker       { -6, 0, 16, 0, 0, 0, 6, 0 },
825*77c1e3ccSAndroid Build Coastguard Worker       { -4, 0, 0, 16, 0, 0, 4, 0 },
826*77c1e3ccSAndroid Build Coastguard Worker       { -2, 0, 0, 0, 16, 0, 2, 0 },
827*77c1e3ccSAndroid Build Coastguard Worker   },
828*77c1e3ccSAndroid Build Coastguard Worker   {
829*77c1e3ccSAndroid Build Coastguard Worker       { -8, 8, 0, 0, 0, 16, 0, 0 },
830*77c1e3ccSAndroid Build Coastguard Worker       { -8, 0, 8, 0, 0, 16, 0, 0 },
831*77c1e3ccSAndroid Build Coastguard Worker       { -8, 0, 0, 8, 0, 16, 0, 0 },
832*77c1e3ccSAndroid Build Coastguard Worker       { -8, 0, 0, 0, 8, 16, 0, 0 },
833*77c1e3ccSAndroid Build Coastguard Worker       { -4, 4, 0, 0, 0, 0, 16, 0 },
834*77c1e3ccSAndroid Build Coastguard Worker       { -4, 0, 4, 0, 0, 0, 16, 0 },
835*77c1e3ccSAndroid Build Coastguard Worker       { -4, 0, 0, 4, 0, 0, 16, 0 },
836*77c1e3ccSAndroid Build Coastguard Worker       { -4, 0, 0, 0, 4, 0, 16, 0 },
837*77c1e3ccSAndroid Build Coastguard Worker   },
838*77c1e3ccSAndroid Build Coastguard Worker   {
839*77c1e3ccSAndroid Build Coastguard Worker       { -2, 8, 0, 0, 0, 10, 0, 0 },
840*77c1e3ccSAndroid Build Coastguard Worker       { -1, 3, 8, 0, 0, 6, 0, 0 },
841*77c1e3ccSAndroid Build Coastguard Worker       { -1, 2, 3, 8, 0, 4, 0, 0 },
842*77c1e3ccSAndroid Build Coastguard Worker       { 0, 1, 2, 3, 8, 2, 0, 0 },
843*77c1e3ccSAndroid Build Coastguard Worker       { -1, 4, 0, 0, 0, 3, 10, 0 },
844*77c1e3ccSAndroid Build Coastguard Worker       { -1, 3, 4, 0, 0, 4, 6, 0 },
845*77c1e3ccSAndroid Build Coastguard Worker       { -1, 2, 3, 4, 0, 4, 4, 0 },
846*77c1e3ccSAndroid Build Coastguard Worker       { -1, 2, 2, 3, 4, 3, 3, 0 },
847*77c1e3ccSAndroid Build Coastguard Worker   },
848*77c1e3ccSAndroid Build Coastguard Worker   {
849*77c1e3ccSAndroid Build Coastguard Worker       { -12, 14, 0, 0, 0, 14, 0, 0 },
850*77c1e3ccSAndroid Build Coastguard Worker       { -10, 0, 14, 0, 0, 12, 0, 0 },
851*77c1e3ccSAndroid Build Coastguard Worker       { -9, 0, 0, 14, 0, 11, 0, 0 },
852*77c1e3ccSAndroid Build Coastguard Worker       { -8, 0, 0, 0, 14, 10, 0, 0 },
853*77c1e3ccSAndroid Build Coastguard Worker       { -10, 12, 0, 0, 0, 0, 14, 0 },
854*77c1e3ccSAndroid Build Coastguard Worker       { -9, 1, 12, 0, 0, 0, 12, 0 },
855*77c1e3ccSAndroid Build Coastguard Worker       { -8, 0, 0, 12, 0, 1, 11, 0 },
856*77c1e3ccSAndroid Build Coastguard Worker       { -7, 0, 0, 1, 12, 1, 9, 0 },
857*77c1e3ccSAndroid Build Coastguard Worker   },
858*77c1e3ccSAndroid Build Coastguard Worker };
859*77c1e3ccSAndroid Build Coastguard Worker 
av1_filter_intra_predictor_c(uint8_t * dst,ptrdiff_t stride,TX_SIZE tx_size,const uint8_t * above,const uint8_t * left,int mode)860*77c1e3ccSAndroid Build Coastguard Worker void av1_filter_intra_predictor_c(uint8_t *dst, ptrdiff_t stride,
861*77c1e3ccSAndroid Build Coastguard Worker                                   TX_SIZE tx_size, const uint8_t *above,
862*77c1e3ccSAndroid Build Coastguard Worker                                   const uint8_t *left, int mode) {
863*77c1e3ccSAndroid Build Coastguard Worker   int r, c;
864*77c1e3ccSAndroid Build Coastguard Worker   uint8_t buffer[33][33];
865*77c1e3ccSAndroid Build Coastguard Worker   const int bw = tx_size_wide[tx_size];
866*77c1e3ccSAndroid Build Coastguard Worker   const int bh = tx_size_high[tx_size];
867*77c1e3ccSAndroid Build Coastguard Worker 
868*77c1e3ccSAndroid Build Coastguard Worker   assert(bw <= 32 && bh <= 32);
869*77c1e3ccSAndroid Build Coastguard Worker 
870*77c1e3ccSAndroid Build Coastguard Worker   for (r = 0; r < bh; ++r) buffer[r + 1][0] = left[r];
871*77c1e3ccSAndroid Build Coastguard Worker   memcpy(buffer[0], &above[-1], (bw + 1) * sizeof(uint8_t));
872*77c1e3ccSAndroid Build Coastguard Worker 
873*77c1e3ccSAndroid Build Coastguard Worker   for (r = 1; r < bh + 1; r += 2)
874*77c1e3ccSAndroid Build Coastguard Worker     for (c = 1; c < bw + 1; c += 4) {
875*77c1e3ccSAndroid Build Coastguard Worker       const uint8_t p0 = buffer[r - 1][c - 1];
876*77c1e3ccSAndroid Build Coastguard Worker       const uint8_t p1 = buffer[r - 1][c];
877*77c1e3ccSAndroid Build Coastguard Worker       const uint8_t p2 = buffer[r - 1][c + 1];
878*77c1e3ccSAndroid Build Coastguard Worker       const uint8_t p3 = buffer[r - 1][c + 2];
879*77c1e3ccSAndroid Build Coastguard Worker       const uint8_t p4 = buffer[r - 1][c + 3];
880*77c1e3ccSAndroid Build Coastguard Worker       const uint8_t p5 = buffer[r][c - 1];
881*77c1e3ccSAndroid Build Coastguard Worker       const uint8_t p6 = buffer[r + 1][c - 1];
882*77c1e3ccSAndroid Build Coastguard Worker       for (int k = 0; k < 8; ++k) {
883*77c1e3ccSAndroid Build Coastguard Worker         int r_offset = k >> 2;
884*77c1e3ccSAndroid Build Coastguard Worker         int c_offset = k & 0x03;
885*77c1e3ccSAndroid Build Coastguard Worker         int pr = av1_filter_intra_taps[mode][k][0] * p0 +
886*77c1e3ccSAndroid Build Coastguard Worker                  av1_filter_intra_taps[mode][k][1] * p1 +
887*77c1e3ccSAndroid Build Coastguard Worker                  av1_filter_intra_taps[mode][k][2] * p2 +
888*77c1e3ccSAndroid Build Coastguard Worker                  av1_filter_intra_taps[mode][k][3] * p3 +
889*77c1e3ccSAndroid Build Coastguard Worker                  av1_filter_intra_taps[mode][k][4] * p4 +
890*77c1e3ccSAndroid Build Coastguard Worker                  av1_filter_intra_taps[mode][k][5] * p5 +
891*77c1e3ccSAndroid Build Coastguard Worker                  av1_filter_intra_taps[mode][k][6] * p6;
892*77c1e3ccSAndroid Build Coastguard Worker         // Section 7.11.2.3 specifies the right-hand side of the assignment as
893*77c1e3ccSAndroid Build Coastguard Worker         //   Clip1( Round2Signed( pr, INTRA_FILTER_SCALE_BITS ) ).
894*77c1e3ccSAndroid Build Coastguard Worker         // Since Clip1() clips a negative value to 0, it is safe to replace
895*77c1e3ccSAndroid Build Coastguard Worker         // Round2Signed() with Round2().
896*77c1e3ccSAndroid Build Coastguard Worker         buffer[r + r_offset][c + c_offset] =
897*77c1e3ccSAndroid Build Coastguard Worker             clip_pixel(ROUND_POWER_OF_TWO(pr, FILTER_INTRA_SCALE_BITS));
898*77c1e3ccSAndroid Build Coastguard Worker       }
899*77c1e3ccSAndroid Build Coastguard Worker     }
900*77c1e3ccSAndroid Build Coastguard Worker 
901*77c1e3ccSAndroid Build Coastguard Worker   for (r = 0; r < bh; ++r) {
902*77c1e3ccSAndroid Build Coastguard Worker     memcpy(dst, &buffer[r + 1][1], bw * sizeof(uint8_t));
903*77c1e3ccSAndroid Build Coastguard Worker     dst += stride;
904*77c1e3ccSAndroid Build Coastguard Worker   }
905*77c1e3ccSAndroid Build Coastguard Worker }
906*77c1e3ccSAndroid Build Coastguard Worker 
907*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_AV1_HIGHBITDEPTH
highbd_filter_intra_predictor(uint16_t * dst,ptrdiff_t stride,TX_SIZE tx_size,const uint16_t * above,const uint16_t * left,int mode,int bd)908*77c1e3ccSAndroid Build Coastguard Worker static void highbd_filter_intra_predictor(uint16_t *dst, ptrdiff_t stride,
909*77c1e3ccSAndroid Build Coastguard Worker                                           TX_SIZE tx_size,
910*77c1e3ccSAndroid Build Coastguard Worker                                           const uint16_t *above,
911*77c1e3ccSAndroid Build Coastguard Worker                                           const uint16_t *left, int mode,
912*77c1e3ccSAndroid Build Coastguard Worker                                           int bd) {
913*77c1e3ccSAndroid Build Coastguard Worker   int r, c;
914*77c1e3ccSAndroid Build Coastguard Worker   uint16_t buffer[33][33];
915*77c1e3ccSAndroid Build Coastguard Worker   const int bw = tx_size_wide[tx_size];
916*77c1e3ccSAndroid Build Coastguard Worker   const int bh = tx_size_high[tx_size];
917*77c1e3ccSAndroid Build Coastguard Worker 
918*77c1e3ccSAndroid Build Coastguard Worker   assert(bw <= 32 && bh <= 32);
919*77c1e3ccSAndroid Build Coastguard Worker 
920*77c1e3ccSAndroid Build Coastguard Worker   for (r = 0; r < bh; ++r) buffer[r + 1][0] = left[r];
921*77c1e3ccSAndroid Build Coastguard Worker   memcpy(buffer[0], &above[-1], (bw + 1) * sizeof(buffer[0][0]));
922*77c1e3ccSAndroid Build Coastguard Worker 
923*77c1e3ccSAndroid Build Coastguard Worker   for (r = 1; r < bh + 1; r += 2)
924*77c1e3ccSAndroid Build Coastguard Worker     for (c = 1; c < bw + 1; c += 4) {
925*77c1e3ccSAndroid Build Coastguard Worker       const uint16_t p0 = buffer[r - 1][c - 1];
926*77c1e3ccSAndroid Build Coastguard Worker       const uint16_t p1 = buffer[r - 1][c];
927*77c1e3ccSAndroid Build Coastguard Worker       const uint16_t p2 = buffer[r - 1][c + 1];
928*77c1e3ccSAndroid Build Coastguard Worker       const uint16_t p3 = buffer[r - 1][c + 2];
929*77c1e3ccSAndroid Build Coastguard Worker       const uint16_t p4 = buffer[r - 1][c + 3];
930*77c1e3ccSAndroid Build Coastguard Worker       const uint16_t p5 = buffer[r][c - 1];
931*77c1e3ccSAndroid Build Coastguard Worker       const uint16_t p6 = buffer[r + 1][c - 1];
932*77c1e3ccSAndroid Build Coastguard Worker       for (int k = 0; k < 8; ++k) {
933*77c1e3ccSAndroid Build Coastguard Worker         int r_offset = k >> 2;
934*77c1e3ccSAndroid Build Coastguard Worker         int c_offset = k & 0x03;
935*77c1e3ccSAndroid Build Coastguard Worker         int pr = av1_filter_intra_taps[mode][k][0] * p0 +
936*77c1e3ccSAndroid Build Coastguard Worker                  av1_filter_intra_taps[mode][k][1] * p1 +
937*77c1e3ccSAndroid Build Coastguard Worker                  av1_filter_intra_taps[mode][k][2] * p2 +
938*77c1e3ccSAndroid Build Coastguard Worker                  av1_filter_intra_taps[mode][k][3] * p3 +
939*77c1e3ccSAndroid Build Coastguard Worker                  av1_filter_intra_taps[mode][k][4] * p4 +
940*77c1e3ccSAndroid Build Coastguard Worker                  av1_filter_intra_taps[mode][k][5] * p5 +
941*77c1e3ccSAndroid Build Coastguard Worker                  av1_filter_intra_taps[mode][k][6] * p6;
942*77c1e3ccSAndroid Build Coastguard Worker         // Section 7.11.2.3 specifies the right-hand side of the assignment as
943*77c1e3ccSAndroid Build Coastguard Worker         //   Clip1( Round2Signed( pr, INTRA_FILTER_SCALE_BITS ) ).
944*77c1e3ccSAndroid Build Coastguard Worker         // Since Clip1() clips a negative value to 0, it is safe to replace
945*77c1e3ccSAndroid Build Coastguard Worker         // Round2Signed() with Round2().
946*77c1e3ccSAndroid Build Coastguard Worker         buffer[r + r_offset][c + c_offset] = clip_pixel_highbd(
947*77c1e3ccSAndroid Build Coastguard Worker             ROUND_POWER_OF_TWO(pr, FILTER_INTRA_SCALE_BITS), bd);
948*77c1e3ccSAndroid Build Coastguard Worker       }
949*77c1e3ccSAndroid Build Coastguard Worker     }
950*77c1e3ccSAndroid Build Coastguard Worker 
951*77c1e3ccSAndroid Build Coastguard Worker   for (r = 0; r < bh; ++r) {
952*77c1e3ccSAndroid Build Coastguard Worker     memcpy(dst, &buffer[r + 1][1], bw * sizeof(dst[0]));
953*77c1e3ccSAndroid Build Coastguard Worker     dst += stride;
954*77c1e3ccSAndroid Build Coastguard Worker   }
955*77c1e3ccSAndroid Build Coastguard Worker }
956*77c1e3ccSAndroid Build Coastguard Worker #endif  // CONFIG_AV1_HIGHBITDEPTH
957*77c1e3ccSAndroid Build Coastguard Worker 
is_smooth(const MB_MODE_INFO * mbmi,int plane)958*77c1e3ccSAndroid Build Coastguard Worker static int is_smooth(const MB_MODE_INFO *mbmi, int plane) {
959*77c1e3ccSAndroid Build Coastguard Worker   if (plane == 0) {
960*77c1e3ccSAndroid Build Coastguard Worker     const PREDICTION_MODE mode = mbmi->mode;
961*77c1e3ccSAndroid Build Coastguard Worker     return (mode == SMOOTH_PRED || mode == SMOOTH_V_PRED ||
962*77c1e3ccSAndroid Build Coastguard Worker             mode == SMOOTH_H_PRED);
963*77c1e3ccSAndroid Build Coastguard Worker   } else {
964*77c1e3ccSAndroid Build Coastguard Worker     // uv_mode is not set for inter blocks, so need to explicitly
965*77c1e3ccSAndroid Build Coastguard Worker     // detect that case.
966*77c1e3ccSAndroid Build Coastguard Worker     if (is_inter_block(mbmi)) return 0;
967*77c1e3ccSAndroid Build Coastguard Worker 
968*77c1e3ccSAndroid Build Coastguard Worker     const UV_PREDICTION_MODE uv_mode = mbmi->uv_mode;
969*77c1e3ccSAndroid Build Coastguard Worker     return (uv_mode == UV_SMOOTH_PRED || uv_mode == UV_SMOOTH_V_PRED ||
970*77c1e3ccSAndroid Build Coastguard Worker             uv_mode == UV_SMOOTH_H_PRED);
971*77c1e3ccSAndroid Build Coastguard Worker   }
972*77c1e3ccSAndroid Build Coastguard Worker }
973*77c1e3ccSAndroid Build Coastguard Worker 
get_intra_edge_filter_type(const MACROBLOCKD * xd,int plane)974*77c1e3ccSAndroid Build Coastguard Worker static int get_intra_edge_filter_type(const MACROBLOCKD *xd, int plane) {
975*77c1e3ccSAndroid Build Coastguard Worker   const MB_MODE_INFO *above;
976*77c1e3ccSAndroid Build Coastguard Worker   const MB_MODE_INFO *left;
977*77c1e3ccSAndroid Build Coastguard Worker 
978*77c1e3ccSAndroid Build Coastguard Worker   if (plane == 0) {
979*77c1e3ccSAndroid Build Coastguard Worker     above = xd->above_mbmi;
980*77c1e3ccSAndroid Build Coastguard Worker     left = xd->left_mbmi;
981*77c1e3ccSAndroid Build Coastguard Worker   } else {
982*77c1e3ccSAndroid Build Coastguard Worker     above = xd->chroma_above_mbmi;
983*77c1e3ccSAndroid Build Coastguard Worker     left = xd->chroma_left_mbmi;
984*77c1e3ccSAndroid Build Coastguard Worker   }
985*77c1e3ccSAndroid Build Coastguard Worker 
986*77c1e3ccSAndroid Build Coastguard Worker   return (above && is_smooth(above, plane)) || (left && is_smooth(left, plane));
987*77c1e3ccSAndroid Build Coastguard Worker }
988*77c1e3ccSAndroid Build Coastguard Worker 
intra_edge_filter_strength(int bs0,int bs1,int delta,int type)989*77c1e3ccSAndroid Build Coastguard Worker static int intra_edge_filter_strength(int bs0, int bs1, int delta, int type) {
990*77c1e3ccSAndroid Build Coastguard Worker   const int d = abs(delta);
991*77c1e3ccSAndroid Build Coastguard Worker   int strength = 0;
992*77c1e3ccSAndroid Build Coastguard Worker 
993*77c1e3ccSAndroid Build Coastguard Worker   const int blk_wh = bs0 + bs1;
994*77c1e3ccSAndroid Build Coastguard Worker   if (type == 0) {
995*77c1e3ccSAndroid Build Coastguard Worker     if (blk_wh <= 8) {
996*77c1e3ccSAndroid Build Coastguard Worker       if (d >= 56) strength = 1;
997*77c1e3ccSAndroid Build Coastguard Worker     } else if (blk_wh <= 12) {
998*77c1e3ccSAndroid Build Coastguard Worker       if (d >= 40) strength = 1;
999*77c1e3ccSAndroid Build Coastguard Worker     } else if (blk_wh <= 16) {
1000*77c1e3ccSAndroid Build Coastguard Worker       if (d >= 40) strength = 1;
1001*77c1e3ccSAndroid Build Coastguard Worker     } else if (blk_wh <= 24) {
1002*77c1e3ccSAndroid Build Coastguard Worker       if (d >= 8) strength = 1;
1003*77c1e3ccSAndroid Build Coastguard Worker       if (d >= 16) strength = 2;
1004*77c1e3ccSAndroid Build Coastguard Worker       if (d >= 32) strength = 3;
1005*77c1e3ccSAndroid Build Coastguard Worker     } else if (blk_wh <= 32) {
1006*77c1e3ccSAndroid Build Coastguard Worker       if (d >= 1) strength = 1;
1007*77c1e3ccSAndroid Build Coastguard Worker       if (d >= 4) strength = 2;
1008*77c1e3ccSAndroid Build Coastguard Worker       if (d >= 32) strength = 3;
1009*77c1e3ccSAndroid Build Coastguard Worker     } else {
1010*77c1e3ccSAndroid Build Coastguard Worker       if (d >= 1) strength = 3;
1011*77c1e3ccSAndroid Build Coastguard Worker     }
1012*77c1e3ccSAndroid Build Coastguard Worker   } else {
1013*77c1e3ccSAndroid Build Coastguard Worker     if (blk_wh <= 8) {
1014*77c1e3ccSAndroid Build Coastguard Worker       if (d >= 40) strength = 1;
1015*77c1e3ccSAndroid Build Coastguard Worker       if (d >= 64) strength = 2;
1016*77c1e3ccSAndroid Build Coastguard Worker     } else if (blk_wh <= 16) {
1017*77c1e3ccSAndroid Build Coastguard Worker       if (d >= 20) strength = 1;
1018*77c1e3ccSAndroid Build Coastguard Worker       if (d >= 48) strength = 2;
1019*77c1e3ccSAndroid Build Coastguard Worker     } else if (blk_wh <= 24) {
1020*77c1e3ccSAndroid Build Coastguard Worker       if (d >= 4) strength = 3;
1021*77c1e3ccSAndroid Build Coastguard Worker     } else {
1022*77c1e3ccSAndroid Build Coastguard Worker       if (d >= 1) strength = 3;
1023*77c1e3ccSAndroid Build Coastguard Worker     }
1024*77c1e3ccSAndroid Build Coastguard Worker   }
1025*77c1e3ccSAndroid Build Coastguard Worker   return strength;
1026*77c1e3ccSAndroid Build Coastguard Worker }
1027*77c1e3ccSAndroid Build Coastguard Worker 
av1_filter_intra_edge_c(uint8_t * p,int sz,int strength)1028*77c1e3ccSAndroid Build Coastguard Worker void av1_filter_intra_edge_c(uint8_t *p, int sz, int strength) {
1029*77c1e3ccSAndroid Build Coastguard Worker   if (!strength) return;
1030*77c1e3ccSAndroid Build Coastguard Worker 
1031*77c1e3ccSAndroid Build Coastguard Worker   const int kernel[INTRA_EDGE_FILT][INTRA_EDGE_TAPS] = { { 0, 4, 8, 4, 0 },
1032*77c1e3ccSAndroid Build Coastguard Worker                                                          { 0, 5, 6, 5, 0 },
1033*77c1e3ccSAndroid Build Coastguard Worker                                                          { 2, 4, 4, 4, 2 } };
1034*77c1e3ccSAndroid Build Coastguard Worker   const int filt = strength - 1;
1035*77c1e3ccSAndroid Build Coastguard Worker   uint8_t edge[129];
1036*77c1e3ccSAndroid Build Coastguard Worker 
1037*77c1e3ccSAndroid Build Coastguard Worker   memcpy(edge, p, sz * sizeof(*p));
1038*77c1e3ccSAndroid Build Coastguard Worker   for (int i = 1; i < sz; i++) {
1039*77c1e3ccSAndroid Build Coastguard Worker     int s = 0;
1040*77c1e3ccSAndroid Build Coastguard Worker     for (int j = 0; j < INTRA_EDGE_TAPS; j++) {
1041*77c1e3ccSAndroid Build Coastguard Worker       int k = i - 2 + j;
1042*77c1e3ccSAndroid Build Coastguard Worker       k = (k < 0) ? 0 : k;
1043*77c1e3ccSAndroid Build Coastguard Worker       k = (k > sz - 1) ? sz - 1 : k;
1044*77c1e3ccSAndroid Build Coastguard Worker       s += edge[k] * kernel[filt][j];
1045*77c1e3ccSAndroid Build Coastguard Worker     }
1046*77c1e3ccSAndroid Build Coastguard Worker     s = (s + 8) >> 4;
1047*77c1e3ccSAndroid Build Coastguard Worker     p[i] = s;
1048*77c1e3ccSAndroid Build Coastguard Worker   }
1049*77c1e3ccSAndroid Build Coastguard Worker }
1050*77c1e3ccSAndroid Build Coastguard Worker 
filter_intra_edge_corner(uint8_t * p_above,uint8_t * p_left)1051*77c1e3ccSAndroid Build Coastguard Worker static void filter_intra_edge_corner(uint8_t *p_above, uint8_t *p_left) {
1052*77c1e3ccSAndroid Build Coastguard Worker   const int kernel[3] = { 5, 6, 5 };
1053*77c1e3ccSAndroid Build Coastguard Worker 
1054*77c1e3ccSAndroid Build Coastguard Worker   int s = (p_left[0] * kernel[0]) + (p_above[-1] * kernel[1]) +
1055*77c1e3ccSAndroid Build Coastguard Worker           (p_above[0] * kernel[2]);
1056*77c1e3ccSAndroid Build Coastguard Worker   s = (s + 8) >> 4;
1057*77c1e3ccSAndroid Build Coastguard Worker   p_above[-1] = s;
1058*77c1e3ccSAndroid Build Coastguard Worker   p_left[-1] = s;
1059*77c1e3ccSAndroid Build Coastguard Worker }
1060*77c1e3ccSAndroid Build Coastguard Worker 
av1_upsample_intra_edge_c(uint8_t * p,int sz)1061*77c1e3ccSAndroid Build Coastguard Worker void av1_upsample_intra_edge_c(uint8_t *p, int sz) {
1062*77c1e3ccSAndroid Build Coastguard Worker   // interpolate half-sample positions
1063*77c1e3ccSAndroid Build Coastguard Worker   assert(sz <= MAX_UPSAMPLE_SZ);
1064*77c1e3ccSAndroid Build Coastguard Worker 
1065*77c1e3ccSAndroid Build Coastguard Worker   uint8_t in[MAX_UPSAMPLE_SZ + 3];
1066*77c1e3ccSAndroid Build Coastguard Worker   // copy p[-1..(sz-1)] and extend first and last samples
1067*77c1e3ccSAndroid Build Coastguard Worker   in[0] = p[-1];
1068*77c1e3ccSAndroid Build Coastguard Worker   in[1] = p[-1];
1069*77c1e3ccSAndroid Build Coastguard Worker   for (int i = 0; i < sz; i++) {
1070*77c1e3ccSAndroid Build Coastguard Worker     in[i + 2] = p[i];
1071*77c1e3ccSAndroid Build Coastguard Worker   }
1072*77c1e3ccSAndroid Build Coastguard Worker   in[sz + 2] = p[sz - 1];
1073*77c1e3ccSAndroid Build Coastguard Worker 
1074*77c1e3ccSAndroid Build Coastguard Worker   // interpolate half-sample edge positions
1075*77c1e3ccSAndroid Build Coastguard Worker   p[-2] = in[0];
1076*77c1e3ccSAndroid Build Coastguard Worker   for (int i = 0; i < sz; i++) {
1077*77c1e3ccSAndroid Build Coastguard Worker     int s = -in[i] + (9 * in[i + 1]) + (9 * in[i + 2]) - in[i + 3];
1078*77c1e3ccSAndroid Build Coastguard Worker     s = clip_pixel((s + 8) >> 4);
1079*77c1e3ccSAndroid Build Coastguard Worker     p[2 * i - 1] = s;
1080*77c1e3ccSAndroid Build Coastguard Worker     p[2 * i] = in[i + 2];
1081*77c1e3ccSAndroid Build Coastguard Worker   }
1082*77c1e3ccSAndroid Build Coastguard Worker }
1083*77c1e3ccSAndroid Build Coastguard Worker 
build_directional_and_filter_intra_predictors(const uint8_t * ref,int ref_stride,uint8_t * dst,int dst_stride,PREDICTION_MODE mode,int p_angle,FILTER_INTRA_MODE filter_intra_mode,TX_SIZE tx_size,int disable_edge_filter,int n_top_px,int n_topright_px,int n_left_px,int n_bottomleft_px,int intra_edge_filter_type)1084*77c1e3ccSAndroid Build Coastguard Worker static void build_directional_and_filter_intra_predictors(
1085*77c1e3ccSAndroid Build Coastguard Worker     const uint8_t *ref, int ref_stride, uint8_t *dst, int dst_stride,
1086*77c1e3ccSAndroid Build Coastguard Worker     PREDICTION_MODE mode, int p_angle, FILTER_INTRA_MODE filter_intra_mode,
1087*77c1e3ccSAndroid Build Coastguard Worker     TX_SIZE tx_size, int disable_edge_filter, int n_top_px, int n_topright_px,
1088*77c1e3ccSAndroid Build Coastguard Worker     int n_left_px, int n_bottomleft_px, int intra_edge_filter_type) {
1089*77c1e3ccSAndroid Build Coastguard Worker   int i;
1090*77c1e3ccSAndroid Build Coastguard Worker   const uint8_t *above_ref = ref - ref_stride;
1091*77c1e3ccSAndroid Build Coastguard Worker   const uint8_t *left_ref = ref - 1;
1092*77c1e3ccSAndroid Build Coastguard Worker   DECLARE_ALIGNED(16, uint8_t, left_data[NUM_INTRA_NEIGHBOUR_PIXELS]);
1093*77c1e3ccSAndroid Build Coastguard Worker   DECLARE_ALIGNED(16, uint8_t, above_data[NUM_INTRA_NEIGHBOUR_PIXELS]);
1094*77c1e3ccSAndroid Build Coastguard Worker   uint8_t *const above_row = above_data + 16;
1095*77c1e3ccSAndroid Build Coastguard Worker   uint8_t *const left_col = left_data + 16;
1096*77c1e3ccSAndroid Build Coastguard Worker   const int txwpx = tx_size_wide[tx_size];
1097*77c1e3ccSAndroid Build Coastguard Worker   const int txhpx = tx_size_high[tx_size];
1098*77c1e3ccSAndroid Build Coastguard Worker   int need_left = extend_modes[mode] & NEED_LEFT;
1099*77c1e3ccSAndroid Build Coastguard Worker   int need_above = extend_modes[mode] & NEED_ABOVE;
1100*77c1e3ccSAndroid Build Coastguard Worker   int need_above_left = extend_modes[mode] & NEED_ABOVELEFT;
1101*77c1e3ccSAndroid Build Coastguard Worker   const int is_dr_mode = av1_is_directional_mode(mode);
1102*77c1e3ccSAndroid Build Coastguard Worker   const int use_filter_intra = filter_intra_mode != FILTER_INTRA_MODES;
1103*77c1e3ccSAndroid Build Coastguard Worker   assert(use_filter_intra || is_dr_mode);
1104*77c1e3ccSAndroid Build Coastguard Worker   // The left_data, above_data buffers must be zeroed to fix some intermittent
1105*77c1e3ccSAndroid Build Coastguard Worker   // valgrind errors. Uninitialized reads in intra pred modules (e.g. width = 4
1106*77c1e3ccSAndroid Build Coastguard Worker   // path in av1_dr_prediction_z1_avx2()) from left_data, above_data are seen to
1107*77c1e3ccSAndroid Build Coastguard Worker   // be the potential reason for this issue.
1108*77c1e3ccSAndroid Build Coastguard Worker   memset(left_data, 129, NUM_INTRA_NEIGHBOUR_PIXELS);
1109*77c1e3ccSAndroid Build Coastguard Worker   memset(above_data, 127, NUM_INTRA_NEIGHBOUR_PIXELS);
1110*77c1e3ccSAndroid Build Coastguard Worker 
1111*77c1e3ccSAndroid Build Coastguard Worker   // The default values if ref pixels are not available:
1112*77c1e3ccSAndroid Build Coastguard Worker   // 128 127 127 .. 127 127 127 127 127 127
1113*77c1e3ccSAndroid Build Coastguard Worker   // 129  A   B  ..  Y   Z
1114*77c1e3ccSAndroid Build Coastguard Worker   // 129  C   D  ..  W   X
1115*77c1e3ccSAndroid Build Coastguard Worker   // 129  E   F  ..  U   V
1116*77c1e3ccSAndroid Build Coastguard Worker   // 129  G   H  ..  S   T   T   T   T   T
1117*77c1e3ccSAndroid Build Coastguard Worker   // ..
1118*77c1e3ccSAndroid Build Coastguard Worker 
1119*77c1e3ccSAndroid Build Coastguard Worker   if (is_dr_mode) {
1120*77c1e3ccSAndroid Build Coastguard Worker     if (p_angle <= 90)
1121*77c1e3ccSAndroid Build Coastguard Worker       need_above = 1, need_left = 0, need_above_left = 1;
1122*77c1e3ccSAndroid Build Coastguard Worker     else if (p_angle < 180)
1123*77c1e3ccSAndroid Build Coastguard Worker       need_above = 1, need_left = 1, need_above_left = 1;
1124*77c1e3ccSAndroid Build Coastguard Worker     else
1125*77c1e3ccSAndroid Build Coastguard Worker       need_above = 0, need_left = 1, need_above_left = 1;
1126*77c1e3ccSAndroid Build Coastguard Worker   }
1127*77c1e3ccSAndroid Build Coastguard Worker   if (use_filter_intra) need_left = need_above = need_above_left = 1;
1128*77c1e3ccSAndroid Build Coastguard Worker 
1129*77c1e3ccSAndroid Build Coastguard Worker   assert(n_top_px >= 0);
1130*77c1e3ccSAndroid Build Coastguard Worker   assert(n_topright_px >= -1);
1131*77c1e3ccSAndroid Build Coastguard Worker   assert(n_left_px >= 0);
1132*77c1e3ccSAndroid Build Coastguard Worker   assert(n_bottomleft_px >= -1);
1133*77c1e3ccSAndroid Build Coastguard Worker 
1134*77c1e3ccSAndroid Build Coastguard Worker   if ((!need_above && n_left_px == 0) || (!need_left && n_top_px == 0)) {
1135*77c1e3ccSAndroid Build Coastguard Worker     int val;
1136*77c1e3ccSAndroid Build Coastguard Worker     if (need_left) {
1137*77c1e3ccSAndroid Build Coastguard Worker       val = (n_top_px > 0) ? above_ref[0] : 129;
1138*77c1e3ccSAndroid Build Coastguard Worker     } else {
1139*77c1e3ccSAndroid Build Coastguard Worker       val = (n_left_px > 0) ? left_ref[0] : 127;
1140*77c1e3ccSAndroid Build Coastguard Worker     }
1141*77c1e3ccSAndroid Build Coastguard Worker     for (i = 0; i < txhpx; ++i) {
1142*77c1e3ccSAndroid Build Coastguard Worker       memset(dst, val, txwpx);
1143*77c1e3ccSAndroid Build Coastguard Worker       dst += dst_stride;
1144*77c1e3ccSAndroid Build Coastguard Worker     }
1145*77c1e3ccSAndroid Build Coastguard Worker     return;
1146*77c1e3ccSAndroid Build Coastguard Worker   }
1147*77c1e3ccSAndroid Build Coastguard Worker 
1148*77c1e3ccSAndroid Build Coastguard Worker   // NEED_LEFT
1149*77c1e3ccSAndroid Build Coastguard Worker   if (need_left) {
1150*77c1e3ccSAndroid Build Coastguard Worker     const int num_left_pixels_needed =
1151*77c1e3ccSAndroid Build Coastguard Worker         txhpx + (n_bottomleft_px >= 0 ? txwpx : 0);
1152*77c1e3ccSAndroid Build Coastguard Worker     i = 0;
1153*77c1e3ccSAndroid Build Coastguard Worker     if (n_left_px > 0) {
1154*77c1e3ccSAndroid Build Coastguard Worker       for (; i < n_left_px; i++) left_col[i] = left_ref[i * ref_stride];
1155*77c1e3ccSAndroid Build Coastguard Worker       if (n_bottomleft_px > 0) {
1156*77c1e3ccSAndroid Build Coastguard Worker         assert(i == txhpx);
1157*77c1e3ccSAndroid Build Coastguard Worker         for (; i < txhpx + n_bottomleft_px; i++)
1158*77c1e3ccSAndroid Build Coastguard Worker           left_col[i] = left_ref[i * ref_stride];
1159*77c1e3ccSAndroid Build Coastguard Worker       }
1160*77c1e3ccSAndroid Build Coastguard Worker       if (i < num_left_pixels_needed)
1161*77c1e3ccSAndroid Build Coastguard Worker         memset(&left_col[i], left_col[i - 1], num_left_pixels_needed - i);
1162*77c1e3ccSAndroid Build Coastguard Worker     } else if (n_top_px > 0) {
1163*77c1e3ccSAndroid Build Coastguard Worker       memset(left_col, above_ref[0], num_left_pixels_needed);
1164*77c1e3ccSAndroid Build Coastguard Worker     }
1165*77c1e3ccSAndroid Build Coastguard Worker   }
1166*77c1e3ccSAndroid Build Coastguard Worker 
1167*77c1e3ccSAndroid Build Coastguard Worker   // NEED_ABOVE
1168*77c1e3ccSAndroid Build Coastguard Worker   if (need_above) {
1169*77c1e3ccSAndroid Build Coastguard Worker     const int num_top_pixels_needed = txwpx + (n_topright_px >= 0 ? txhpx : 0);
1170*77c1e3ccSAndroid Build Coastguard Worker     if (n_top_px > 0) {
1171*77c1e3ccSAndroid Build Coastguard Worker       memcpy(above_row, above_ref, n_top_px);
1172*77c1e3ccSAndroid Build Coastguard Worker       i = n_top_px;
1173*77c1e3ccSAndroid Build Coastguard Worker       if (n_topright_px > 0) {
1174*77c1e3ccSAndroid Build Coastguard Worker         assert(n_top_px == txwpx);
1175*77c1e3ccSAndroid Build Coastguard Worker         memcpy(above_row + txwpx, above_ref + txwpx, n_topright_px);
1176*77c1e3ccSAndroid Build Coastguard Worker         i += n_topright_px;
1177*77c1e3ccSAndroid Build Coastguard Worker       }
1178*77c1e3ccSAndroid Build Coastguard Worker       if (i < num_top_pixels_needed)
1179*77c1e3ccSAndroid Build Coastguard Worker         memset(&above_row[i], above_row[i - 1], num_top_pixels_needed - i);
1180*77c1e3ccSAndroid Build Coastguard Worker     } else if (n_left_px > 0) {
1181*77c1e3ccSAndroid Build Coastguard Worker       memset(above_row, left_ref[0], num_top_pixels_needed);
1182*77c1e3ccSAndroid Build Coastguard Worker     }
1183*77c1e3ccSAndroid Build Coastguard Worker   }
1184*77c1e3ccSAndroid Build Coastguard Worker 
1185*77c1e3ccSAndroid Build Coastguard Worker   if (need_above_left) {
1186*77c1e3ccSAndroid Build Coastguard Worker     if (n_top_px > 0 && n_left_px > 0) {
1187*77c1e3ccSAndroid Build Coastguard Worker       above_row[-1] = above_ref[-1];
1188*77c1e3ccSAndroid Build Coastguard Worker     } else if (n_top_px > 0) {
1189*77c1e3ccSAndroid Build Coastguard Worker       above_row[-1] = above_ref[0];
1190*77c1e3ccSAndroid Build Coastguard Worker     } else if (n_left_px > 0) {
1191*77c1e3ccSAndroid Build Coastguard Worker       above_row[-1] = left_ref[0];
1192*77c1e3ccSAndroid Build Coastguard Worker     } else {
1193*77c1e3ccSAndroid Build Coastguard Worker       above_row[-1] = 128;
1194*77c1e3ccSAndroid Build Coastguard Worker     }
1195*77c1e3ccSAndroid Build Coastguard Worker     left_col[-1] = above_row[-1];
1196*77c1e3ccSAndroid Build Coastguard Worker   }
1197*77c1e3ccSAndroid Build Coastguard Worker 
1198*77c1e3ccSAndroid Build Coastguard Worker   if (use_filter_intra) {
1199*77c1e3ccSAndroid Build Coastguard Worker     av1_filter_intra_predictor(dst, dst_stride, tx_size, above_row, left_col,
1200*77c1e3ccSAndroid Build Coastguard Worker                                filter_intra_mode);
1201*77c1e3ccSAndroid Build Coastguard Worker     return;
1202*77c1e3ccSAndroid Build Coastguard Worker   }
1203*77c1e3ccSAndroid Build Coastguard Worker 
1204*77c1e3ccSAndroid Build Coastguard Worker   assert(is_dr_mode);
1205*77c1e3ccSAndroid Build Coastguard Worker   int upsample_above = 0;
1206*77c1e3ccSAndroid Build Coastguard Worker   int upsample_left = 0;
1207*77c1e3ccSAndroid Build Coastguard Worker   if (!disable_edge_filter) {
1208*77c1e3ccSAndroid Build Coastguard Worker     const int need_right = p_angle < 90;
1209*77c1e3ccSAndroid Build Coastguard Worker     const int need_bottom = p_angle > 180;
1210*77c1e3ccSAndroid Build Coastguard Worker     if (p_angle != 90 && p_angle != 180) {
1211*77c1e3ccSAndroid Build Coastguard Worker       assert(need_above_left);
1212*77c1e3ccSAndroid Build Coastguard Worker       const int ab_le = 1;
1213*77c1e3ccSAndroid Build Coastguard Worker       if (need_above && need_left && (txwpx + txhpx >= 24)) {
1214*77c1e3ccSAndroid Build Coastguard Worker         filter_intra_edge_corner(above_row, left_col);
1215*77c1e3ccSAndroid Build Coastguard Worker       }
1216*77c1e3ccSAndroid Build Coastguard Worker       if (need_above && n_top_px > 0) {
1217*77c1e3ccSAndroid Build Coastguard Worker         const int strength = intra_edge_filter_strength(
1218*77c1e3ccSAndroid Build Coastguard Worker             txwpx, txhpx, p_angle - 90, intra_edge_filter_type);
1219*77c1e3ccSAndroid Build Coastguard Worker         const int n_px = n_top_px + ab_le + (need_right ? txhpx : 0);
1220*77c1e3ccSAndroid Build Coastguard Worker         av1_filter_intra_edge(above_row - ab_le, n_px, strength);
1221*77c1e3ccSAndroid Build Coastguard Worker       }
1222*77c1e3ccSAndroid Build Coastguard Worker       if (need_left && n_left_px > 0) {
1223*77c1e3ccSAndroid Build Coastguard Worker         const int strength = intra_edge_filter_strength(
1224*77c1e3ccSAndroid Build Coastguard Worker             txhpx, txwpx, p_angle - 180, intra_edge_filter_type);
1225*77c1e3ccSAndroid Build Coastguard Worker         const int n_px = n_left_px + ab_le + (need_bottom ? txwpx : 0);
1226*77c1e3ccSAndroid Build Coastguard Worker         av1_filter_intra_edge(left_col - ab_le, n_px, strength);
1227*77c1e3ccSAndroid Build Coastguard Worker       }
1228*77c1e3ccSAndroid Build Coastguard Worker     }
1229*77c1e3ccSAndroid Build Coastguard Worker     upsample_above = av1_use_intra_edge_upsample(txwpx, txhpx, p_angle - 90,
1230*77c1e3ccSAndroid Build Coastguard Worker                                                  intra_edge_filter_type);
1231*77c1e3ccSAndroid Build Coastguard Worker     if (need_above && upsample_above) {
1232*77c1e3ccSAndroid Build Coastguard Worker       const int n_px = txwpx + (need_right ? txhpx : 0);
1233*77c1e3ccSAndroid Build Coastguard Worker       av1_upsample_intra_edge(above_row, n_px);
1234*77c1e3ccSAndroid Build Coastguard Worker     }
1235*77c1e3ccSAndroid Build Coastguard Worker     upsample_left = av1_use_intra_edge_upsample(txhpx, txwpx, p_angle - 180,
1236*77c1e3ccSAndroid Build Coastguard Worker                                                 intra_edge_filter_type);
1237*77c1e3ccSAndroid Build Coastguard Worker     if (need_left && upsample_left) {
1238*77c1e3ccSAndroid Build Coastguard Worker       const int n_px = txhpx + (need_bottom ? txwpx : 0);
1239*77c1e3ccSAndroid Build Coastguard Worker       av1_upsample_intra_edge(left_col, n_px);
1240*77c1e3ccSAndroid Build Coastguard Worker     }
1241*77c1e3ccSAndroid Build Coastguard Worker   }
1242*77c1e3ccSAndroid Build Coastguard Worker   dr_predictor(dst, dst_stride, tx_size, above_row, left_col, upsample_above,
1243*77c1e3ccSAndroid Build Coastguard Worker                upsample_left, p_angle);
1244*77c1e3ccSAndroid Build Coastguard Worker }
1245*77c1e3ccSAndroid Build Coastguard Worker 
1246*77c1e3ccSAndroid Build Coastguard Worker // This function generates the pred data of a given block for non-directional
1247*77c1e3ccSAndroid Build Coastguard Worker // intra prediction modes (i.e., DC, SMOOTH, SMOOTH_H, SMOOTH_V and PAETH).
build_non_directional_intra_predictors(const uint8_t * ref,int ref_stride,uint8_t * dst,int dst_stride,PREDICTION_MODE mode,TX_SIZE tx_size,int n_top_px,int n_left_px)1248*77c1e3ccSAndroid Build Coastguard Worker static void build_non_directional_intra_predictors(
1249*77c1e3ccSAndroid Build Coastguard Worker     const uint8_t *ref, int ref_stride, uint8_t *dst, int dst_stride,
1250*77c1e3ccSAndroid Build Coastguard Worker     PREDICTION_MODE mode, TX_SIZE tx_size, int n_top_px, int n_left_px) {
1251*77c1e3ccSAndroid Build Coastguard Worker   const uint8_t *above_ref = ref - ref_stride;
1252*77c1e3ccSAndroid Build Coastguard Worker   const uint8_t *left_ref = ref - 1;
1253*77c1e3ccSAndroid Build Coastguard Worker   const int txwpx = tx_size_wide[tx_size];
1254*77c1e3ccSAndroid Build Coastguard Worker   const int txhpx = tx_size_high[tx_size];
1255*77c1e3ccSAndroid Build Coastguard Worker   const int need_left = extend_modes[mode] & NEED_LEFT;
1256*77c1e3ccSAndroid Build Coastguard Worker   const int need_above = extend_modes[mode] & NEED_ABOVE;
1257*77c1e3ccSAndroid Build Coastguard Worker   const int need_above_left = extend_modes[mode] & NEED_ABOVELEFT;
1258*77c1e3ccSAndroid Build Coastguard Worker   int i = 0;
1259*77c1e3ccSAndroid Build Coastguard Worker   assert(n_top_px >= 0);
1260*77c1e3ccSAndroid Build Coastguard Worker   assert(n_left_px >= 0);
1261*77c1e3ccSAndroid Build Coastguard Worker   assert(mode == DC_PRED || mode == SMOOTH_PRED || mode == SMOOTH_V_PRED ||
1262*77c1e3ccSAndroid Build Coastguard Worker          mode == SMOOTH_H_PRED || mode == PAETH_PRED);
1263*77c1e3ccSAndroid Build Coastguard Worker 
1264*77c1e3ccSAndroid Build Coastguard Worker   if ((!need_above && n_left_px == 0) || (!need_left && n_top_px == 0)) {
1265*77c1e3ccSAndroid Build Coastguard Worker     int val = 0;
1266*77c1e3ccSAndroid Build Coastguard Worker     if (need_left) {
1267*77c1e3ccSAndroid Build Coastguard Worker       val = (n_top_px > 0) ? above_ref[0] : 129;
1268*77c1e3ccSAndroid Build Coastguard Worker     } else {
1269*77c1e3ccSAndroid Build Coastguard Worker       val = (n_left_px > 0) ? left_ref[0] : 127;
1270*77c1e3ccSAndroid Build Coastguard Worker     }
1271*77c1e3ccSAndroid Build Coastguard Worker     for (i = 0; i < txhpx; ++i) {
1272*77c1e3ccSAndroid Build Coastguard Worker       memset(dst, val, txwpx);
1273*77c1e3ccSAndroid Build Coastguard Worker       dst += dst_stride;
1274*77c1e3ccSAndroid Build Coastguard Worker     }
1275*77c1e3ccSAndroid Build Coastguard Worker     return;
1276*77c1e3ccSAndroid Build Coastguard Worker   }
1277*77c1e3ccSAndroid Build Coastguard Worker 
1278*77c1e3ccSAndroid Build Coastguard Worker   DECLARE_ALIGNED(16, uint8_t, left_data[NUM_INTRA_NEIGHBOUR_PIXELS]);
1279*77c1e3ccSAndroid Build Coastguard Worker   DECLARE_ALIGNED(16, uint8_t, above_data[NUM_INTRA_NEIGHBOUR_PIXELS]);
1280*77c1e3ccSAndroid Build Coastguard Worker   uint8_t *const above_row = above_data + 16;
1281*77c1e3ccSAndroid Build Coastguard Worker   uint8_t *const left_col = left_data + 16;
1282*77c1e3ccSAndroid Build Coastguard Worker 
1283*77c1e3ccSAndroid Build Coastguard Worker   if (need_left) {
1284*77c1e3ccSAndroid Build Coastguard Worker     memset(left_data, 129, NUM_INTRA_NEIGHBOUR_PIXELS);
1285*77c1e3ccSAndroid Build Coastguard Worker     if (n_left_px > 0) {
1286*77c1e3ccSAndroid Build Coastguard Worker       for (i = 0; i < n_left_px; i++) left_col[i] = left_ref[i * ref_stride];
1287*77c1e3ccSAndroid Build Coastguard Worker       if (i < txhpx) memset(&left_col[i], left_col[i - 1], txhpx - i);
1288*77c1e3ccSAndroid Build Coastguard Worker     } else if (n_top_px > 0) {
1289*77c1e3ccSAndroid Build Coastguard Worker       memset(left_col, above_ref[0], txhpx);
1290*77c1e3ccSAndroid Build Coastguard Worker     }
1291*77c1e3ccSAndroid Build Coastguard Worker   }
1292*77c1e3ccSAndroid Build Coastguard Worker 
1293*77c1e3ccSAndroid Build Coastguard Worker   if (need_above) {
1294*77c1e3ccSAndroid Build Coastguard Worker     memset(above_data, 127, NUM_INTRA_NEIGHBOUR_PIXELS);
1295*77c1e3ccSAndroid Build Coastguard Worker     if (n_top_px > 0) {
1296*77c1e3ccSAndroid Build Coastguard Worker       memcpy(above_row, above_ref, n_top_px);
1297*77c1e3ccSAndroid Build Coastguard Worker       i = n_top_px;
1298*77c1e3ccSAndroid Build Coastguard Worker       if (i < txwpx) memset(&above_row[i], above_row[i - 1], txwpx - i);
1299*77c1e3ccSAndroid Build Coastguard Worker     } else if (n_left_px > 0) {
1300*77c1e3ccSAndroid Build Coastguard Worker       memset(above_row, left_ref[0], txwpx);
1301*77c1e3ccSAndroid Build Coastguard Worker     }
1302*77c1e3ccSAndroid Build Coastguard Worker   }
1303*77c1e3ccSAndroid Build Coastguard Worker 
1304*77c1e3ccSAndroid Build Coastguard Worker   if (need_above_left) {
1305*77c1e3ccSAndroid Build Coastguard Worker     if (n_top_px > 0 && n_left_px > 0) {
1306*77c1e3ccSAndroid Build Coastguard Worker       above_row[-1] = above_ref[-1];
1307*77c1e3ccSAndroid Build Coastguard Worker     } else if (n_top_px > 0) {
1308*77c1e3ccSAndroid Build Coastguard Worker       above_row[-1] = above_ref[0];
1309*77c1e3ccSAndroid Build Coastguard Worker     } else if (n_left_px > 0) {
1310*77c1e3ccSAndroid Build Coastguard Worker       above_row[-1] = left_ref[0];
1311*77c1e3ccSAndroid Build Coastguard Worker     } else {
1312*77c1e3ccSAndroid Build Coastguard Worker       above_row[-1] = 128;
1313*77c1e3ccSAndroid Build Coastguard Worker     }
1314*77c1e3ccSAndroid Build Coastguard Worker     left_col[-1] = above_row[-1];
1315*77c1e3ccSAndroid Build Coastguard Worker   }
1316*77c1e3ccSAndroid Build Coastguard Worker 
1317*77c1e3ccSAndroid Build Coastguard Worker   if (mode == DC_PRED) {
1318*77c1e3ccSAndroid Build Coastguard Worker     dc_pred[n_left_px > 0][n_top_px > 0][tx_size](dst, dst_stride, above_row,
1319*77c1e3ccSAndroid Build Coastguard Worker                                                   left_col);
1320*77c1e3ccSAndroid Build Coastguard Worker   } else {
1321*77c1e3ccSAndroid Build Coastguard Worker     pred[mode][tx_size](dst, dst_stride, above_row, left_col);
1322*77c1e3ccSAndroid Build Coastguard Worker   }
1323*77c1e3ccSAndroid Build Coastguard Worker }
1324*77c1e3ccSAndroid Build Coastguard Worker 
1325*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_AV1_HIGHBITDEPTH
av1_highbd_filter_intra_edge_c(uint16_t * p,int sz,int strength)1326*77c1e3ccSAndroid Build Coastguard Worker void av1_highbd_filter_intra_edge_c(uint16_t *p, int sz, int strength) {
1327*77c1e3ccSAndroid Build Coastguard Worker   if (!strength) return;
1328*77c1e3ccSAndroid Build Coastguard Worker 
1329*77c1e3ccSAndroid Build Coastguard Worker   const int kernel[INTRA_EDGE_FILT][INTRA_EDGE_TAPS] = { { 0, 4, 8, 4, 0 },
1330*77c1e3ccSAndroid Build Coastguard Worker                                                          { 0, 5, 6, 5, 0 },
1331*77c1e3ccSAndroid Build Coastguard Worker                                                          { 2, 4, 4, 4, 2 } };
1332*77c1e3ccSAndroid Build Coastguard Worker   const int filt = strength - 1;
1333*77c1e3ccSAndroid Build Coastguard Worker   uint16_t edge[129];
1334*77c1e3ccSAndroid Build Coastguard Worker 
1335*77c1e3ccSAndroid Build Coastguard Worker   memcpy(edge, p, sz * sizeof(*p));
1336*77c1e3ccSAndroid Build Coastguard Worker   for (int i = 1; i < sz; i++) {
1337*77c1e3ccSAndroid Build Coastguard Worker     int s = 0;
1338*77c1e3ccSAndroid Build Coastguard Worker     for (int j = 0; j < INTRA_EDGE_TAPS; j++) {
1339*77c1e3ccSAndroid Build Coastguard Worker       int k = i - 2 + j;
1340*77c1e3ccSAndroid Build Coastguard Worker       k = (k < 0) ? 0 : k;
1341*77c1e3ccSAndroid Build Coastguard Worker       k = (k > sz - 1) ? sz - 1 : k;
1342*77c1e3ccSAndroid Build Coastguard Worker       s += edge[k] * kernel[filt][j];
1343*77c1e3ccSAndroid Build Coastguard Worker     }
1344*77c1e3ccSAndroid Build Coastguard Worker     s = (s + 8) >> 4;
1345*77c1e3ccSAndroid Build Coastguard Worker     p[i] = s;
1346*77c1e3ccSAndroid Build Coastguard Worker   }
1347*77c1e3ccSAndroid Build Coastguard Worker }
1348*77c1e3ccSAndroid Build Coastguard Worker 
highbd_filter_intra_edge_corner(uint16_t * p_above,uint16_t * p_left)1349*77c1e3ccSAndroid Build Coastguard Worker static void highbd_filter_intra_edge_corner(uint16_t *p_above,
1350*77c1e3ccSAndroid Build Coastguard Worker                                             uint16_t *p_left) {
1351*77c1e3ccSAndroid Build Coastguard Worker   const int kernel[3] = { 5, 6, 5 };
1352*77c1e3ccSAndroid Build Coastguard Worker 
1353*77c1e3ccSAndroid Build Coastguard Worker   int s = (p_left[0] * kernel[0]) + (p_above[-1] * kernel[1]) +
1354*77c1e3ccSAndroid Build Coastguard Worker           (p_above[0] * kernel[2]);
1355*77c1e3ccSAndroid Build Coastguard Worker   s = (s + 8) >> 4;
1356*77c1e3ccSAndroid Build Coastguard Worker   p_above[-1] = s;
1357*77c1e3ccSAndroid Build Coastguard Worker   p_left[-1] = s;
1358*77c1e3ccSAndroid Build Coastguard Worker }
1359*77c1e3ccSAndroid Build Coastguard Worker 
av1_highbd_upsample_intra_edge_c(uint16_t * p,int sz,int bd)1360*77c1e3ccSAndroid Build Coastguard Worker void av1_highbd_upsample_intra_edge_c(uint16_t *p, int sz, int bd) {
1361*77c1e3ccSAndroid Build Coastguard Worker   // interpolate half-sample positions
1362*77c1e3ccSAndroid Build Coastguard Worker   assert(sz <= MAX_UPSAMPLE_SZ);
1363*77c1e3ccSAndroid Build Coastguard Worker 
1364*77c1e3ccSAndroid Build Coastguard Worker   uint16_t in[MAX_UPSAMPLE_SZ + 3];
1365*77c1e3ccSAndroid Build Coastguard Worker   // copy p[-1..(sz-1)] and extend first and last samples
1366*77c1e3ccSAndroid Build Coastguard Worker   in[0] = p[-1];
1367*77c1e3ccSAndroid Build Coastguard Worker   in[1] = p[-1];
1368*77c1e3ccSAndroid Build Coastguard Worker   for (int i = 0; i < sz; i++) {
1369*77c1e3ccSAndroid Build Coastguard Worker     in[i + 2] = p[i];
1370*77c1e3ccSAndroid Build Coastguard Worker   }
1371*77c1e3ccSAndroid Build Coastguard Worker   in[sz + 2] = p[sz - 1];
1372*77c1e3ccSAndroid Build Coastguard Worker 
1373*77c1e3ccSAndroid Build Coastguard Worker   // interpolate half-sample edge positions
1374*77c1e3ccSAndroid Build Coastguard Worker   p[-2] = in[0];
1375*77c1e3ccSAndroid Build Coastguard Worker   for (int i = 0; i < sz; i++) {
1376*77c1e3ccSAndroid Build Coastguard Worker     int s = -in[i] + (9 * in[i + 1]) + (9 * in[i + 2]) - in[i + 3];
1377*77c1e3ccSAndroid Build Coastguard Worker     s = (s + 8) >> 4;
1378*77c1e3ccSAndroid Build Coastguard Worker     s = clip_pixel_highbd(s, bd);
1379*77c1e3ccSAndroid Build Coastguard Worker     p[2 * i - 1] = s;
1380*77c1e3ccSAndroid Build Coastguard Worker     p[2 * i] = in[i + 2];
1381*77c1e3ccSAndroid Build Coastguard Worker   }
1382*77c1e3ccSAndroid Build Coastguard Worker }
1383*77c1e3ccSAndroid Build Coastguard Worker 
highbd_build_directional_and_filter_intra_predictors(const uint8_t * ref8,int ref_stride,uint8_t * dst8,int dst_stride,PREDICTION_MODE mode,int p_angle,FILTER_INTRA_MODE filter_intra_mode,TX_SIZE tx_size,int disable_edge_filter,int n_top_px,int n_topright_px,int n_left_px,int n_bottomleft_px,int intra_edge_filter_type,int bit_depth)1384*77c1e3ccSAndroid Build Coastguard Worker static void highbd_build_directional_and_filter_intra_predictors(
1385*77c1e3ccSAndroid Build Coastguard Worker     const uint8_t *ref8, int ref_stride, uint8_t *dst8, int dst_stride,
1386*77c1e3ccSAndroid Build Coastguard Worker     PREDICTION_MODE mode, int p_angle, FILTER_INTRA_MODE filter_intra_mode,
1387*77c1e3ccSAndroid Build Coastguard Worker     TX_SIZE tx_size, int disable_edge_filter, int n_top_px, int n_topright_px,
1388*77c1e3ccSAndroid Build Coastguard Worker     int n_left_px, int n_bottomleft_px, int intra_edge_filter_type,
1389*77c1e3ccSAndroid Build Coastguard Worker     int bit_depth) {
1390*77c1e3ccSAndroid Build Coastguard Worker   int i;
1391*77c1e3ccSAndroid Build Coastguard Worker   uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
1392*77c1e3ccSAndroid Build Coastguard Worker   const uint16_t *const ref = CONVERT_TO_SHORTPTR(ref8);
1393*77c1e3ccSAndroid Build Coastguard Worker   DECLARE_ALIGNED(16, uint16_t, left_data[NUM_INTRA_NEIGHBOUR_PIXELS]);
1394*77c1e3ccSAndroid Build Coastguard Worker   DECLARE_ALIGNED(16, uint16_t, above_data[NUM_INTRA_NEIGHBOUR_PIXELS]);
1395*77c1e3ccSAndroid Build Coastguard Worker   uint16_t *const above_row = above_data + 16;
1396*77c1e3ccSAndroid Build Coastguard Worker   uint16_t *const left_col = left_data + 16;
1397*77c1e3ccSAndroid Build Coastguard Worker   const int txwpx = tx_size_wide[tx_size];
1398*77c1e3ccSAndroid Build Coastguard Worker   const int txhpx = tx_size_high[tx_size];
1399*77c1e3ccSAndroid Build Coastguard Worker   int need_left = extend_modes[mode] & NEED_LEFT;
1400*77c1e3ccSAndroid Build Coastguard Worker   int need_above = extend_modes[mode] & NEED_ABOVE;
1401*77c1e3ccSAndroid Build Coastguard Worker   int need_above_left = extend_modes[mode] & NEED_ABOVELEFT;
1402*77c1e3ccSAndroid Build Coastguard Worker   const uint16_t *above_ref = ref - ref_stride;
1403*77c1e3ccSAndroid Build Coastguard Worker   const uint16_t *left_ref = ref - 1;
1404*77c1e3ccSAndroid Build Coastguard Worker   const int is_dr_mode = av1_is_directional_mode(mode);
1405*77c1e3ccSAndroid Build Coastguard Worker   const int use_filter_intra = filter_intra_mode != FILTER_INTRA_MODES;
1406*77c1e3ccSAndroid Build Coastguard Worker   assert(use_filter_intra || is_dr_mode);
1407*77c1e3ccSAndroid Build Coastguard Worker   const int base = 128 << (bit_depth - 8);
1408*77c1e3ccSAndroid Build Coastguard Worker   // The left_data, above_data buffers must be zeroed to fix some intermittent
1409*77c1e3ccSAndroid Build Coastguard Worker   // valgrind errors. Uninitialized reads in intra pred modules (e.g. width = 4
1410*77c1e3ccSAndroid Build Coastguard Worker   // path in av1_highbd_dr_prediction_z2_avx2()) from left_data, above_data are
1411*77c1e3ccSAndroid Build Coastguard Worker   // seen to be the potential reason for this issue.
1412*77c1e3ccSAndroid Build Coastguard Worker   aom_memset16(left_data, base + 1, NUM_INTRA_NEIGHBOUR_PIXELS);
1413*77c1e3ccSAndroid Build Coastguard Worker   aom_memset16(above_data, base - 1, NUM_INTRA_NEIGHBOUR_PIXELS);
1414*77c1e3ccSAndroid Build Coastguard Worker 
1415*77c1e3ccSAndroid Build Coastguard Worker   // The default values if ref pixels are not available:
1416*77c1e3ccSAndroid Build Coastguard Worker   // base   base-1 base-1 .. base-1 base-1 base-1 base-1 base-1 base-1
1417*77c1e3ccSAndroid Build Coastguard Worker   // base+1   A      B  ..     Y      Z
1418*77c1e3ccSAndroid Build Coastguard Worker   // base+1   C      D  ..     W      X
1419*77c1e3ccSAndroid Build Coastguard Worker   // base+1   E      F  ..     U      V
1420*77c1e3ccSAndroid Build Coastguard Worker   // base+1   G      H  ..     S      T      T      T      T      T
1421*77c1e3ccSAndroid Build Coastguard Worker 
1422*77c1e3ccSAndroid Build Coastguard Worker   if (is_dr_mode) {
1423*77c1e3ccSAndroid Build Coastguard Worker     if (p_angle <= 90)
1424*77c1e3ccSAndroid Build Coastguard Worker       need_above = 1, need_left = 0, need_above_left = 1;
1425*77c1e3ccSAndroid Build Coastguard Worker     else if (p_angle < 180)
1426*77c1e3ccSAndroid Build Coastguard Worker       need_above = 1, need_left = 1, need_above_left = 1;
1427*77c1e3ccSAndroid Build Coastguard Worker     else
1428*77c1e3ccSAndroid Build Coastguard Worker       need_above = 0, need_left = 1, need_above_left = 1;
1429*77c1e3ccSAndroid Build Coastguard Worker   }
1430*77c1e3ccSAndroid Build Coastguard Worker   if (use_filter_intra) need_left = need_above = need_above_left = 1;
1431*77c1e3ccSAndroid Build Coastguard Worker 
1432*77c1e3ccSAndroid Build Coastguard Worker   assert(n_top_px >= 0);
1433*77c1e3ccSAndroid Build Coastguard Worker   assert(n_topright_px >= -1);
1434*77c1e3ccSAndroid Build Coastguard Worker   assert(n_left_px >= 0);
1435*77c1e3ccSAndroid Build Coastguard Worker   assert(n_bottomleft_px >= -1);
1436*77c1e3ccSAndroid Build Coastguard Worker 
1437*77c1e3ccSAndroid Build Coastguard Worker   if ((!need_above && n_left_px == 0) || (!need_left && n_top_px == 0)) {
1438*77c1e3ccSAndroid Build Coastguard Worker     int val;
1439*77c1e3ccSAndroid Build Coastguard Worker     if (need_left) {
1440*77c1e3ccSAndroid Build Coastguard Worker       val = (n_top_px > 0) ? above_ref[0] : base + 1;
1441*77c1e3ccSAndroid Build Coastguard Worker     } else {
1442*77c1e3ccSAndroid Build Coastguard Worker       val = (n_left_px > 0) ? left_ref[0] : base - 1;
1443*77c1e3ccSAndroid Build Coastguard Worker     }
1444*77c1e3ccSAndroid Build Coastguard Worker     for (i = 0; i < txhpx; ++i) {
1445*77c1e3ccSAndroid Build Coastguard Worker       aom_memset16(dst, val, txwpx);
1446*77c1e3ccSAndroid Build Coastguard Worker       dst += dst_stride;
1447*77c1e3ccSAndroid Build Coastguard Worker     }
1448*77c1e3ccSAndroid Build Coastguard Worker     return;
1449*77c1e3ccSAndroid Build Coastguard Worker   }
1450*77c1e3ccSAndroid Build Coastguard Worker 
1451*77c1e3ccSAndroid Build Coastguard Worker   // NEED_LEFT
1452*77c1e3ccSAndroid Build Coastguard Worker   if (need_left) {
1453*77c1e3ccSAndroid Build Coastguard Worker     const int num_left_pixels_needed =
1454*77c1e3ccSAndroid Build Coastguard Worker         txhpx + (n_bottomleft_px >= 0 ? txwpx : 0);
1455*77c1e3ccSAndroid Build Coastguard Worker     i = 0;
1456*77c1e3ccSAndroid Build Coastguard Worker     if (n_left_px > 0) {
1457*77c1e3ccSAndroid Build Coastguard Worker       for (; i < n_left_px; i++) left_col[i] = left_ref[i * ref_stride];
1458*77c1e3ccSAndroid Build Coastguard Worker       if (n_bottomleft_px > 0) {
1459*77c1e3ccSAndroid Build Coastguard Worker         assert(i == txhpx);
1460*77c1e3ccSAndroid Build Coastguard Worker         for (; i < txhpx + n_bottomleft_px; i++)
1461*77c1e3ccSAndroid Build Coastguard Worker           left_col[i] = left_ref[i * ref_stride];
1462*77c1e3ccSAndroid Build Coastguard Worker       }
1463*77c1e3ccSAndroid Build Coastguard Worker       if (i < num_left_pixels_needed)
1464*77c1e3ccSAndroid Build Coastguard Worker         aom_memset16(&left_col[i], left_col[i - 1], num_left_pixels_needed - i);
1465*77c1e3ccSAndroid Build Coastguard Worker     } else if (n_top_px > 0) {
1466*77c1e3ccSAndroid Build Coastguard Worker       aom_memset16(left_col, above_ref[0], num_left_pixels_needed);
1467*77c1e3ccSAndroid Build Coastguard Worker     }
1468*77c1e3ccSAndroid Build Coastguard Worker   }
1469*77c1e3ccSAndroid Build Coastguard Worker 
1470*77c1e3ccSAndroid Build Coastguard Worker   // NEED_ABOVE
1471*77c1e3ccSAndroid Build Coastguard Worker   if (need_above) {
1472*77c1e3ccSAndroid Build Coastguard Worker     const int num_top_pixels_needed = txwpx + (n_topright_px >= 0 ? txhpx : 0);
1473*77c1e3ccSAndroid Build Coastguard Worker     if (n_top_px > 0) {
1474*77c1e3ccSAndroid Build Coastguard Worker       memcpy(above_row, above_ref, n_top_px * sizeof(above_ref[0]));
1475*77c1e3ccSAndroid Build Coastguard Worker       i = n_top_px;
1476*77c1e3ccSAndroid Build Coastguard Worker       if (n_topright_px > 0) {
1477*77c1e3ccSAndroid Build Coastguard Worker         assert(n_top_px == txwpx);
1478*77c1e3ccSAndroid Build Coastguard Worker         memcpy(above_row + txwpx, above_ref + txwpx,
1479*77c1e3ccSAndroid Build Coastguard Worker                n_topright_px * sizeof(above_ref[0]));
1480*77c1e3ccSAndroid Build Coastguard Worker         i += n_topright_px;
1481*77c1e3ccSAndroid Build Coastguard Worker       }
1482*77c1e3ccSAndroid Build Coastguard Worker       if (i < num_top_pixels_needed)
1483*77c1e3ccSAndroid Build Coastguard Worker         aom_memset16(&above_row[i], above_row[i - 1],
1484*77c1e3ccSAndroid Build Coastguard Worker                      num_top_pixels_needed - i);
1485*77c1e3ccSAndroid Build Coastguard Worker     } else if (n_left_px > 0) {
1486*77c1e3ccSAndroid Build Coastguard Worker       aom_memset16(above_row, left_ref[0], num_top_pixels_needed);
1487*77c1e3ccSAndroid Build Coastguard Worker     }
1488*77c1e3ccSAndroid Build Coastguard Worker   }
1489*77c1e3ccSAndroid Build Coastguard Worker 
1490*77c1e3ccSAndroid Build Coastguard Worker   if (need_above_left) {
1491*77c1e3ccSAndroid Build Coastguard Worker     if (n_top_px > 0 && n_left_px > 0) {
1492*77c1e3ccSAndroid Build Coastguard Worker       above_row[-1] = above_ref[-1];
1493*77c1e3ccSAndroid Build Coastguard Worker     } else if (n_top_px > 0) {
1494*77c1e3ccSAndroid Build Coastguard Worker       above_row[-1] = above_ref[0];
1495*77c1e3ccSAndroid Build Coastguard Worker     } else if (n_left_px > 0) {
1496*77c1e3ccSAndroid Build Coastguard Worker       above_row[-1] = left_ref[0];
1497*77c1e3ccSAndroid Build Coastguard Worker     } else {
1498*77c1e3ccSAndroid Build Coastguard Worker       above_row[-1] = base;
1499*77c1e3ccSAndroid Build Coastguard Worker     }
1500*77c1e3ccSAndroid Build Coastguard Worker     left_col[-1] = above_row[-1];
1501*77c1e3ccSAndroid Build Coastguard Worker   }
1502*77c1e3ccSAndroid Build Coastguard Worker 
1503*77c1e3ccSAndroid Build Coastguard Worker   if (use_filter_intra) {
1504*77c1e3ccSAndroid Build Coastguard Worker     highbd_filter_intra_predictor(dst, dst_stride, tx_size, above_row, left_col,
1505*77c1e3ccSAndroid Build Coastguard Worker                                   filter_intra_mode, bit_depth);
1506*77c1e3ccSAndroid Build Coastguard Worker     return;
1507*77c1e3ccSAndroid Build Coastguard Worker   }
1508*77c1e3ccSAndroid Build Coastguard Worker 
1509*77c1e3ccSAndroid Build Coastguard Worker   assert(is_dr_mode);
1510*77c1e3ccSAndroid Build Coastguard Worker   int upsample_above = 0;
1511*77c1e3ccSAndroid Build Coastguard Worker   int upsample_left = 0;
1512*77c1e3ccSAndroid Build Coastguard Worker   if (!disable_edge_filter) {
1513*77c1e3ccSAndroid Build Coastguard Worker     const int need_right = p_angle < 90;
1514*77c1e3ccSAndroid Build Coastguard Worker     const int need_bottom = p_angle > 180;
1515*77c1e3ccSAndroid Build Coastguard Worker     if (p_angle != 90 && p_angle != 180) {
1516*77c1e3ccSAndroid Build Coastguard Worker       assert(need_above_left);
1517*77c1e3ccSAndroid Build Coastguard Worker       const int ab_le = 1;
1518*77c1e3ccSAndroid Build Coastguard Worker       if (need_above && need_left && (txwpx + txhpx >= 24)) {
1519*77c1e3ccSAndroid Build Coastguard Worker         highbd_filter_intra_edge_corner(above_row, left_col);
1520*77c1e3ccSAndroid Build Coastguard Worker       }
1521*77c1e3ccSAndroid Build Coastguard Worker       if (need_above && n_top_px > 0) {
1522*77c1e3ccSAndroid Build Coastguard Worker         const int strength = intra_edge_filter_strength(
1523*77c1e3ccSAndroid Build Coastguard Worker             txwpx, txhpx, p_angle - 90, intra_edge_filter_type);
1524*77c1e3ccSAndroid Build Coastguard Worker         const int n_px = n_top_px + ab_le + (need_right ? txhpx : 0);
1525*77c1e3ccSAndroid Build Coastguard Worker         av1_highbd_filter_intra_edge(above_row - ab_le, n_px, strength);
1526*77c1e3ccSAndroid Build Coastguard Worker       }
1527*77c1e3ccSAndroid Build Coastguard Worker       if (need_left && n_left_px > 0) {
1528*77c1e3ccSAndroid Build Coastguard Worker         const int strength = intra_edge_filter_strength(
1529*77c1e3ccSAndroid Build Coastguard Worker             txhpx, txwpx, p_angle - 180, intra_edge_filter_type);
1530*77c1e3ccSAndroid Build Coastguard Worker         const int n_px = n_left_px + ab_le + (need_bottom ? txwpx : 0);
1531*77c1e3ccSAndroid Build Coastguard Worker         av1_highbd_filter_intra_edge(left_col - ab_le, n_px, strength);
1532*77c1e3ccSAndroid Build Coastguard Worker       }
1533*77c1e3ccSAndroid Build Coastguard Worker     }
1534*77c1e3ccSAndroid Build Coastguard Worker     upsample_above = av1_use_intra_edge_upsample(txwpx, txhpx, p_angle - 90,
1535*77c1e3ccSAndroid Build Coastguard Worker                                                  intra_edge_filter_type);
1536*77c1e3ccSAndroid Build Coastguard Worker     if (need_above && upsample_above) {
1537*77c1e3ccSAndroid Build Coastguard Worker       const int n_px = txwpx + (need_right ? txhpx : 0);
1538*77c1e3ccSAndroid Build Coastguard Worker       av1_highbd_upsample_intra_edge(above_row, n_px, bit_depth);
1539*77c1e3ccSAndroid Build Coastguard Worker     }
1540*77c1e3ccSAndroid Build Coastguard Worker     upsample_left = av1_use_intra_edge_upsample(txhpx, txwpx, p_angle - 180,
1541*77c1e3ccSAndroid Build Coastguard Worker                                                 intra_edge_filter_type);
1542*77c1e3ccSAndroid Build Coastguard Worker     if (need_left && upsample_left) {
1543*77c1e3ccSAndroid Build Coastguard Worker       const int n_px = txhpx + (need_bottom ? txwpx : 0);
1544*77c1e3ccSAndroid Build Coastguard Worker       av1_highbd_upsample_intra_edge(left_col, n_px, bit_depth);
1545*77c1e3ccSAndroid Build Coastguard Worker     }
1546*77c1e3ccSAndroid Build Coastguard Worker   }
1547*77c1e3ccSAndroid Build Coastguard Worker   highbd_dr_predictor(dst, dst_stride, tx_size, above_row, left_col,
1548*77c1e3ccSAndroid Build Coastguard Worker                       upsample_above, upsample_left, p_angle, bit_depth);
1549*77c1e3ccSAndroid Build Coastguard Worker }
1550*77c1e3ccSAndroid Build Coastguard Worker 
1551*77c1e3ccSAndroid Build Coastguard Worker // For HBD encode/decode, this function generates the pred data of a given
1552*77c1e3ccSAndroid Build Coastguard Worker // block for non-directional intra prediction modes (i.e., DC, SMOOTH, SMOOTH_H,
1553*77c1e3ccSAndroid Build Coastguard Worker // SMOOTH_V and PAETH).
highbd_build_non_directional_intra_predictors(const uint8_t * ref8,int ref_stride,uint8_t * dst8,int dst_stride,PREDICTION_MODE mode,TX_SIZE tx_size,int n_top_px,int n_left_px,int bit_depth)1554*77c1e3ccSAndroid Build Coastguard Worker static void highbd_build_non_directional_intra_predictors(
1555*77c1e3ccSAndroid Build Coastguard Worker     const uint8_t *ref8, int ref_stride, uint8_t *dst8, int dst_stride,
1556*77c1e3ccSAndroid Build Coastguard Worker     PREDICTION_MODE mode, TX_SIZE tx_size, int n_top_px, int n_left_px,
1557*77c1e3ccSAndroid Build Coastguard Worker     int bit_depth) {
1558*77c1e3ccSAndroid Build Coastguard Worker   int i = 0;
1559*77c1e3ccSAndroid Build Coastguard Worker   uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
1560*77c1e3ccSAndroid Build Coastguard Worker   const uint16_t *const ref = CONVERT_TO_SHORTPTR(ref8);
1561*77c1e3ccSAndroid Build Coastguard Worker   const int txwpx = tx_size_wide[tx_size];
1562*77c1e3ccSAndroid Build Coastguard Worker   const int txhpx = tx_size_high[tx_size];
1563*77c1e3ccSAndroid Build Coastguard Worker   int need_left = extend_modes[mode] & NEED_LEFT;
1564*77c1e3ccSAndroid Build Coastguard Worker   int need_above = extend_modes[mode] & NEED_ABOVE;
1565*77c1e3ccSAndroid Build Coastguard Worker   int need_above_left = extend_modes[mode] & NEED_ABOVELEFT;
1566*77c1e3ccSAndroid Build Coastguard Worker   const uint16_t *above_ref = ref - ref_stride;
1567*77c1e3ccSAndroid Build Coastguard Worker   const uint16_t *left_ref = ref - 1;
1568*77c1e3ccSAndroid Build Coastguard Worker   const int base = 128 << (bit_depth - 8);
1569*77c1e3ccSAndroid Build Coastguard Worker 
1570*77c1e3ccSAndroid Build Coastguard Worker   assert(n_top_px >= 0);
1571*77c1e3ccSAndroid Build Coastguard Worker   assert(n_left_px >= 0);
1572*77c1e3ccSAndroid Build Coastguard Worker   assert(mode == DC_PRED || mode == SMOOTH_PRED || mode == SMOOTH_V_PRED ||
1573*77c1e3ccSAndroid Build Coastguard Worker          mode == SMOOTH_H_PRED || mode == PAETH_PRED);
1574*77c1e3ccSAndroid Build Coastguard Worker 
1575*77c1e3ccSAndroid Build Coastguard Worker   if ((!need_above && n_left_px == 0) || (!need_left && n_top_px == 0)) {
1576*77c1e3ccSAndroid Build Coastguard Worker     int val = 0;
1577*77c1e3ccSAndroid Build Coastguard Worker     if (need_left) {
1578*77c1e3ccSAndroid Build Coastguard Worker       val = (n_top_px > 0) ? above_ref[0] : base + 1;
1579*77c1e3ccSAndroid Build Coastguard Worker     } else {
1580*77c1e3ccSAndroid Build Coastguard Worker       val = (n_left_px > 0) ? left_ref[0] : base - 1;
1581*77c1e3ccSAndroid Build Coastguard Worker     }
1582*77c1e3ccSAndroid Build Coastguard Worker     for (i = 0; i < txhpx; ++i) {
1583*77c1e3ccSAndroid Build Coastguard Worker       aom_memset16(dst, val, txwpx);
1584*77c1e3ccSAndroid Build Coastguard Worker       dst += dst_stride;
1585*77c1e3ccSAndroid Build Coastguard Worker     }
1586*77c1e3ccSAndroid Build Coastguard Worker     return;
1587*77c1e3ccSAndroid Build Coastguard Worker   }
1588*77c1e3ccSAndroid Build Coastguard Worker 
1589*77c1e3ccSAndroid Build Coastguard Worker   DECLARE_ALIGNED(16, uint16_t, left_data[NUM_INTRA_NEIGHBOUR_PIXELS]);
1590*77c1e3ccSAndroid Build Coastguard Worker   DECLARE_ALIGNED(16, uint16_t, above_data[NUM_INTRA_NEIGHBOUR_PIXELS]);
1591*77c1e3ccSAndroid Build Coastguard Worker   uint16_t *const above_row = above_data + 16;
1592*77c1e3ccSAndroid Build Coastguard Worker   uint16_t *const left_col = left_data + 16;
1593*77c1e3ccSAndroid Build Coastguard Worker 
1594*77c1e3ccSAndroid Build Coastguard Worker   if (need_left) {
1595*77c1e3ccSAndroid Build Coastguard Worker     aom_memset16(left_data, base + 1, NUM_INTRA_NEIGHBOUR_PIXELS);
1596*77c1e3ccSAndroid Build Coastguard Worker     if (n_left_px > 0) {
1597*77c1e3ccSAndroid Build Coastguard Worker       for (i = 0; i < n_left_px; i++) left_col[i] = left_ref[i * ref_stride];
1598*77c1e3ccSAndroid Build Coastguard Worker       if (i < txhpx) aom_memset16(&left_col[i], left_col[i - 1], txhpx - i);
1599*77c1e3ccSAndroid Build Coastguard Worker     } else if (n_top_px > 0) {
1600*77c1e3ccSAndroid Build Coastguard Worker       aom_memset16(left_col, above_ref[0], txhpx);
1601*77c1e3ccSAndroid Build Coastguard Worker     }
1602*77c1e3ccSAndroid Build Coastguard Worker   }
1603*77c1e3ccSAndroid Build Coastguard Worker 
1604*77c1e3ccSAndroid Build Coastguard Worker   if (need_above) {
1605*77c1e3ccSAndroid Build Coastguard Worker     aom_memset16(above_data, base - 1, NUM_INTRA_NEIGHBOUR_PIXELS);
1606*77c1e3ccSAndroid Build Coastguard Worker     if (n_top_px > 0) {
1607*77c1e3ccSAndroid Build Coastguard Worker       memcpy(above_row, above_ref, n_top_px * sizeof(above_ref[0]));
1608*77c1e3ccSAndroid Build Coastguard Worker       i = n_top_px;
1609*77c1e3ccSAndroid Build Coastguard Worker       if (i < txwpx) aom_memset16(&above_row[i], above_row[i - 1], (txwpx - i));
1610*77c1e3ccSAndroid Build Coastguard Worker     } else if (n_left_px > 0) {
1611*77c1e3ccSAndroid Build Coastguard Worker       aom_memset16(above_row, left_ref[0], txwpx);
1612*77c1e3ccSAndroid Build Coastguard Worker     }
1613*77c1e3ccSAndroid Build Coastguard Worker   }
1614*77c1e3ccSAndroid Build Coastguard Worker 
1615*77c1e3ccSAndroid Build Coastguard Worker   if (need_above_left) {
1616*77c1e3ccSAndroid Build Coastguard Worker     if (n_top_px > 0 && n_left_px > 0) {
1617*77c1e3ccSAndroid Build Coastguard Worker       above_row[-1] = above_ref[-1];
1618*77c1e3ccSAndroid Build Coastguard Worker     } else if (n_top_px > 0) {
1619*77c1e3ccSAndroid Build Coastguard Worker       above_row[-1] = above_ref[0];
1620*77c1e3ccSAndroid Build Coastguard Worker     } else if (n_left_px > 0) {
1621*77c1e3ccSAndroid Build Coastguard Worker       above_row[-1] = left_ref[0];
1622*77c1e3ccSAndroid Build Coastguard Worker     } else {
1623*77c1e3ccSAndroid Build Coastguard Worker       above_row[-1] = base;
1624*77c1e3ccSAndroid Build Coastguard Worker     }
1625*77c1e3ccSAndroid Build Coastguard Worker     left_col[-1] = above_row[-1];
1626*77c1e3ccSAndroid Build Coastguard Worker   }
1627*77c1e3ccSAndroid Build Coastguard Worker 
1628*77c1e3ccSAndroid Build Coastguard Worker   if (mode == DC_PRED) {
1629*77c1e3ccSAndroid Build Coastguard Worker     dc_pred_high[n_left_px > 0][n_top_px > 0][tx_size](
1630*77c1e3ccSAndroid Build Coastguard Worker         dst, dst_stride, above_row, left_col, bit_depth);
1631*77c1e3ccSAndroid Build Coastguard Worker   } else {
1632*77c1e3ccSAndroid Build Coastguard Worker     pred_high[mode][tx_size](dst, dst_stride, above_row, left_col, bit_depth);
1633*77c1e3ccSAndroid Build Coastguard Worker   }
1634*77c1e3ccSAndroid Build Coastguard Worker }
1635*77c1e3ccSAndroid Build Coastguard Worker #endif  // CONFIG_AV1_HIGHBITDEPTH
1636*77c1e3ccSAndroid Build Coastguard Worker 
scale_chroma_bsize(BLOCK_SIZE bsize,int subsampling_x,int subsampling_y)1637*77c1e3ccSAndroid Build Coastguard Worker static inline BLOCK_SIZE scale_chroma_bsize(BLOCK_SIZE bsize, int subsampling_x,
1638*77c1e3ccSAndroid Build Coastguard Worker                                             int subsampling_y) {
1639*77c1e3ccSAndroid Build Coastguard Worker   assert(subsampling_x >= 0 && subsampling_x < 2);
1640*77c1e3ccSAndroid Build Coastguard Worker   assert(subsampling_y >= 0 && subsampling_y < 2);
1641*77c1e3ccSAndroid Build Coastguard Worker   BLOCK_SIZE bs = bsize;
1642*77c1e3ccSAndroid Build Coastguard Worker   switch (bsize) {
1643*77c1e3ccSAndroid Build Coastguard Worker     case BLOCK_4X4:
1644*77c1e3ccSAndroid Build Coastguard Worker       if (subsampling_x == 1 && subsampling_y == 1)
1645*77c1e3ccSAndroid Build Coastguard Worker         bs = BLOCK_8X8;
1646*77c1e3ccSAndroid Build Coastguard Worker       else if (subsampling_x == 1)
1647*77c1e3ccSAndroid Build Coastguard Worker         bs = BLOCK_8X4;
1648*77c1e3ccSAndroid Build Coastguard Worker       else if (subsampling_y == 1)
1649*77c1e3ccSAndroid Build Coastguard Worker         bs = BLOCK_4X8;
1650*77c1e3ccSAndroid Build Coastguard Worker       break;
1651*77c1e3ccSAndroid Build Coastguard Worker     case BLOCK_4X8:
1652*77c1e3ccSAndroid Build Coastguard Worker       if (subsampling_x == 1 && subsampling_y == 1)
1653*77c1e3ccSAndroid Build Coastguard Worker         bs = BLOCK_8X8;
1654*77c1e3ccSAndroid Build Coastguard Worker       else if (subsampling_x == 1)
1655*77c1e3ccSAndroid Build Coastguard Worker         bs = BLOCK_8X8;
1656*77c1e3ccSAndroid Build Coastguard Worker       else if (subsampling_y == 1)
1657*77c1e3ccSAndroid Build Coastguard Worker         bs = BLOCK_4X8;
1658*77c1e3ccSAndroid Build Coastguard Worker       break;
1659*77c1e3ccSAndroid Build Coastguard Worker     case BLOCK_8X4:
1660*77c1e3ccSAndroid Build Coastguard Worker       if (subsampling_x == 1 && subsampling_y == 1)
1661*77c1e3ccSAndroid Build Coastguard Worker         bs = BLOCK_8X8;
1662*77c1e3ccSAndroid Build Coastguard Worker       else if (subsampling_x == 1)
1663*77c1e3ccSAndroid Build Coastguard Worker         bs = BLOCK_8X4;
1664*77c1e3ccSAndroid Build Coastguard Worker       else if (subsampling_y == 1)
1665*77c1e3ccSAndroid Build Coastguard Worker         bs = BLOCK_8X8;
1666*77c1e3ccSAndroid Build Coastguard Worker       break;
1667*77c1e3ccSAndroid Build Coastguard Worker     case BLOCK_4X16:
1668*77c1e3ccSAndroid Build Coastguard Worker       if (subsampling_x == 1 && subsampling_y == 1)
1669*77c1e3ccSAndroid Build Coastguard Worker         bs = BLOCK_8X16;
1670*77c1e3ccSAndroid Build Coastguard Worker       else if (subsampling_x == 1)
1671*77c1e3ccSAndroid Build Coastguard Worker         bs = BLOCK_8X16;
1672*77c1e3ccSAndroid Build Coastguard Worker       else if (subsampling_y == 1)
1673*77c1e3ccSAndroid Build Coastguard Worker         bs = BLOCK_4X16;
1674*77c1e3ccSAndroid Build Coastguard Worker       break;
1675*77c1e3ccSAndroid Build Coastguard Worker     case BLOCK_16X4:
1676*77c1e3ccSAndroid Build Coastguard Worker       if (subsampling_x == 1 && subsampling_y == 1)
1677*77c1e3ccSAndroid Build Coastguard Worker         bs = BLOCK_16X8;
1678*77c1e3ccSAndroid Build Coastguard Worker       else if (subsampling_x == 1)
1679*77c1e3ccSAndroid Build Coastguard Worker         bs = BLOCK_16X4;
1680*77c1e3ccSAndroid Build Coastguard Worker       else if (subsampling_y == 1)
1681*77c1e3ccSAndroid Build Coastguard Worker         bs = BLOCK_16X8;
1682*77c1e3ccSAndroid Build Coastguard Worker       break;
1683*77c1e3ccSAndroid Build Coastguard Worker     default: break;
1684*77c1e3ccSAndroid Build Coastguard Worker   }
1685*77c1e3ccSAndroid Build Coastguard Worker   return bs;
1686*77c1e3ccSAndroid Build Coastguard Worker }
1687*77c1e3ccSAndroid Build Coastguard Worker 
av1_predict_intra_block(const MACROBLOCKD * xd,BLOCK_SIZE sb_size,int enable_intra_edge_filter,int wpx,int hpx,TX_SIZE tx_size,PREDICTION_MODE mode,int angle_delta,int use_palette,FILTER_INTRA_MODE filter_intra_mode,const uint8_t * ref,int ref_stride,uint8_t * dst,int dst_stride,int col_off,int row_off,int plane)1688*77c1e3ccSAndroid Build Coastguard Worker void av1_predict_intra_block(const MACROBLOCKD *xd, BLOCK_SIZE sb_size,
1689*77c1e3ccSAndroid Build Coastguard Worker                              int enable_intra_edge_filter, int wpx, int hpx,
1690*77c1e3ccSAndroid Build Coastguard Worker                              TX_SIZE tx_size, PREDICTION_MODE mode,
1691*77c1e3ccSAndroid Build Coastguard Worker                              int angle_delta, int use_palette,
1692*77c1e3ccSAndroid Build Coastguard Worker                              FILTER_INTRA_MODE filter_intra_mode,
1693*77c1e3ccSAndroid Build Coastguard Worker                              const uint8_t *ref, int ref_stride, uint8_t *dst,
1694*77c1e3ccSAndroid Build Coastguard Worker                              int dst_stride, int col_off, int row_off,
1695*77c1e3ccSAndroid Build Coastguard Worker                              int plane) {
1696*77c1e3ccSAndroid Build Coastguard Worker   const MB_MODE_INFO *const mbmi = xd->mi[0];
1697*77c1e3ccSAndroid Build Coastguard Worker   const int txwpx = tx_size_wide[tx_size];
1698*77c1e3ccSAndroid Build Coastguard Worker   const int txhpx = tx_size_high[tx_size];
1699*77c1e3ccSAndroid Build Coastguard Worker   const int x = col_off << MI_SIZE_LOG2;
1700*77c1e3ccSAndroid Build Coastguard Worker   const int y = row_off << MI_SIZE_LOG2;
1701*77c1e3ccSAndroid Build Coastguard Worker   const int is_hbd = is_cur_buf_hbd(xd);
1702*77c1e3ccSAndroid Build Coastguard Worker 
1703*77c1e3ccSAndroid Build Coastguard Worker   assert(mode < INTRA_MODES);
1704*77c1e3ccSAndroid Build Coastguard Worker 
1705*77c1e3ccSAndroid Build Coastguard Worker   if (use_palette) {
1706*77c1e3ccSAndroid Build Coastguard Worker     int r, c;
1707*77c1e3ccSAndroid Build Coastguard Worker     const uint8_t *const map = xd->plane[plane != 0].color_index_map +
1708*77c1e3ccSAndroid Build Coastguard Worker                                xd->color_index_map_offset[plane != 0];
1709*77c1e3ccSAndroid Build Coastguard Worker     const uint16_t *const palette =
1710*77c1e3ccSAndroid Build Coastguard Worker         mbmi->palette_mode_info.palette_colors + plane * PALETTE_MAX_SIZE;
1711*77c1e3ccSAndroid Build Coastguard Worker     if (is_hbd) {
1712*77c1e3ccSAndroid Build Coastguard Worker       uint16_t *dst16 = CONVERT_TO_SHORTPTR(dst);
1713*77c1e3ccSAndroid Build Coastguard Worker       for (r = 0; r < txhpx; ++r) {
1714*77c1e3ccSAndroid Build Coastguard Worker         for (c = 0; c < txwpx; ++c) {
1715*77c1e3ccSAndroid Build Coastguard Worker           dst16[r * dst_stride + c] = palette[map[(r + y) * wpx + c + x]];
1716*77c1e3ccSAndroid Build Coastguard Worker         }
1717*77c1e3ccSAndroid Build Coastguard Worker       }
1718*77c1e3ccSAndroid Build Coastguard Worker     } else {
1719*77c1e3ccSAndroid Build Coastguard Worker       for (r = 0; r < txhpx; ++r) {
1720*77c1e3ccSAndroid Build Coastguard Worker         for (c = 0; c < txwpx; ++c) {
1721*77c1e3ccSAndroid Build Coastguard Worker           dst[r * dst_stride + c] =
1722*77c1e3ccSAndroid Build Coastguard Worker               (uint8_t)palette[map[(r + y) * wpx + c + x]];
1723*77c1e3ccSAndroid Build Coastguard Worker         }
1724*77c1e3ccSAndroid Build Coastguard Worker       }
1725*77c1e3ccSAndroid Build Coastguard Worker     }
1726*77c1e3ccSAndroid Build Coastguard Worker     return;
1727*77c1e3ccSAndroid Build Coastguard Worker   }
1728*77c1e3ccSAndroid Build Coastguard Worker 
1729*77c1e3ccSAndroid Build Coastguard Worker   const struct macroblockd_plane *const pd = &xd->plane[plane];
1730*77c1e3ccSAndroid Build Coastguard Worker   const int ss_x = pd->subsampling_x;
1731*77c1e3ccSAndroid Build Coastguard Worker   const int ss_y = pd->subsampling_y;
1732*77c1e3ccSAndroid Build Coastguard Worker   const int have_top =
1733*77c1e3ccSAndroid Build Coastguard Worker       row_off || (ss_y ? xd->chroma_up_available : xd->up_available);
1734*77c1e3ccSAndroid Build Coastguard Worker   const int have_left =
1735*77c1e3ccSAndroid Build Coastguard Worker       col_off || (ss_x ? xd->chroma_left_available : xd->left_available);
1736*77c1e3ccSAndroid Build Coastguard Worker 
1737*77c1e3ccSAndroid Build Coastguard Worker   // Distance between the right edge of this prediction block to
1738*77c1e3ccSAndroid Build Coastguard Worker   // the frame right edge
1739*77c1e3ccSAndroid Build Coastguard Worker   const int xr = (xd->mb_to_right_edge >> (3 + ss_x)) + wpx - x - txwpx;
1740*77c1e3ccSAndroid Build Coastguard Worker   // Distance between the bottom edge of this prediction block to
1741*77c1e3ccSAndroid Build Coastguard Worker   // the frame bottom edge
1742*77c1e3ccSAndroid Build Coastguard Worker   const int yd = (xd->mb_to_bottom_edge >> (3 + ss_y)) + hpx - y - txhpx;
1743*77c1e3ccSAndroid Build Coastguard Worker   const int use_filter_intra = filter_intra_mode != FILTER_INTRA_MODES;
1744*77c1e3ccSAndroid Build Coastguard Worker   const int is_dr_mode = av1_is_directional_mode(mode);
1745*77c1e3ccSAndroid Build Coastguard Worker 
1746*77c1e3ccSAndroid Build Coastguard Worker   // The computations in this function, as well as in build_intra_predictors(),
1747*77c1e3ccSAndroid Build Coastguard Worker   // are generalized for all intra modes. Some of these operations are not
1748*77c1e3ccSAndroid Build Coastguard Worker   // required since non-directional intra modes (i.e., DC, SMOOTH, SMOOTH_H,
1749*77c1e3ccSAndroid Build Coastguard Worker   // SMOOTH_V, and PAETH) specifically require left and top neighbors. Hence, a
1750*77c1e3ccSAndroid Build Coastguard Worker   // separate function build_non_directional_intra_predictors() is introduced
1751*77c1e3ccSAndroid Build Coastguard Worker   // for these modes to avoid redundant computations while generating pred data.
1752*77c1e3ccSAndroid Build Coastguard Worker 
1753*77c1e3ccSAndroid Build Coastguard Worker   const int n_top_px = have_top ? AOMMIN(txwpx, xr + txwpx) : 0;
1754*77c1e3ccSAndroid Build Coastguard Worker   const int n_left_px = have_left ? AOMMIN(txhpx, yd + txhpx) : 0;
1755*77c1e3ccSAndroid Build Coastguard Worker   if (!use_filter_intra && !is_dr_mode) {
1756*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_AV1_HIGHBITDEPTH
1757*77c1e3ccSAndroid Build Coastguard Worker     if (is_hbd) {
1758*77c1e3ccSAndroid Build Coastguard Worker       highbd_build_non_directional_intra_predictors(
1759*77c1e3ccSAndroid Build Coastguard Worker           ref, ref_stride, dst, dst_stride, mode, tx_size, n_top_px, n_left_px,
1760*77c1e3ccSAndroid Build Coastguard Worker           xd->bd);
1761*77c1e3ccSAndroid Build Coastguard Worker       return;
1762*77c1e3ccSAndroid Build Coastguard Worker     }
1763*77c1e3ccSAndroid Build Coastguard Worker #endif  // CONFIG_AV1_HIGHBITDEPTH
1764*77c1e3ccSAndroid Build Coastguard Worker     build_non_directional_intra_predictors(ref, ref_stride, dst, dst_stride,
1765*77c1e3ccSAndroid Build Coastguard Worker                                            mode, tx_size, n_top_px, n_left_px);
1766*77c1e3ccSAndroid Build Coastguard Worker     return;
1767*77c1e3ccSAndroid Build Coastguard Worker   }
1768*77c1e3ccSAndroid Build Coastguard Worker 
1769*77c1e3ccSAndroid Build Coastguard Worker   const int txw = tx_size_wide_unit[tx_size];
1770*77c1e3ccSAndroid Build Coastguard Worker   const int txh = tx_size_high_unit[tx_size];
1771*77c1e3ccSAndroid Build Coastguard Worker   const int mi_row = -xd->mb_to_top_edge >> (3 + MI_SIZE_LOG2);
1772*77c1e3ccSAndroid Build Coastguard Worker   const int mi_col = -xd->mb_to_left_edge >> (3 + MI_SIZE_LOG2);
1773*77c1e3ccSAndroid Build Coastguard Worker   const int right_available =
1774*77c1e3ccSAndroid Build Coastguard Worker       mi_col + ((col_off + txw) << ss_x) < xd->tile.mi_col_end;
1775*77c1e3ccSAndroid Build Coastguard Worker   const int bottom_available =
1776*77c1e3ccSAndroid Build Coastguard Worker       (yd > 0) && (mi_row + ((row_off + txh) << ss_y) < xd->tile.mi_row_end);
1777*77c1e3ccSAndroid Build Coastguard Worker 
1778*77c1e3ccSAndroid Build Coastguard Worker   const PARTITION_TYPE partition = mbmi->partition;
1779*77c1e3ccSAndroid Build Coastguard Worker 
1780*77c1e3ccSAndroid Build Coastguard Worker   BLOCK_SIZE bsize = mbmi->bsize;
1781*77c1e3ccSAndroid Build Coastguard Worker   // force 4x4 chroma component block size.
1782*77c1e3ccSAndroid Build Coastguard Worker   if (ss_x || ss_y) {
1783*77c1e3ccSAndroid Build Coastguard Worker     bsize = scale_chroma_bsize(bsize, ss_x, ss_y);
1784*77c1e3ccSAndroid Build Coastguard Worker   }
1785*77c1e3ccSAndroid Build Coastguard Worker 
1786*77c1e3ccSAndroid Build Coastguard Worker   int p_angle = 0;
1787*77c1e3ccSAndroid Build Coastguard Worker   int need_top_right = extend_modes[mode] & NEED_ABOVERIGHT;
1788*77c1e3ccSAndroid Build Coastguard Worker   int need_bottom_left = extend_modes[mode] & NEED_BOTTOMLEFT;
1789*77c1e3ccSAndroid Build Coastguard Worker 
1790*77c1e3ccSAndroid Build Coastguard Worker   if (use_filter_intra) {
1791*77c1e3ccSAndroid Build Coastguard Worker     need_top_right = 0;
1792*77c1e3ccSAndroid Build Coastguard Worker     need_bottom_left = 0;
1793*77c1e3ccSAndroid Build Coastguard Worker   }
1794*77c1e3ccSAndroid Build Coastguard Worker   if (is_dr_mode) {
1795*77c1e3ccSAndroid Build Coastguard Worker     p_angle = mode_to_angle_map[mode] + angle_delta;
1796*77c1e3ccSAndroid Build Coastguard Worker     need_top_right = p_angle < 90;
1797*77c1e3ccSAndroid Build Coastguard Worker     need_bottom_left = p_angle > 180;
1798*77c1e3ccSAndroid Build Coastguard Worker   }
1799*77c1e3ccSAndroid Build Coastguard Worker 
1800*77c1e3ccSAndroid Build Coastguard Worker   // Possible states for have_top_right(TR) and have_bottom_left(BL)
1801*77c1e3ccSAndroid Build Coastguard Worker   // -1 : TR and BL are not needed
1802*77c1e3ccSAndroid Build Coastguard Worker   //  0 : TR and BL are needed but not available
1803*77c1e3ccSAndroid Build Coastguard Worker   // > 0 : TR and BL are needed and pixels are available
1804*77c1e3ccSAndroid Build Coastguard Worker   const int have_top_right =
1805*77c1e3ccSAndroid Build Coastguard Worker       need_top_right ? has_top_right(sb_size, bsize, mi_row, mi_col, have_top,
1806*77c1e3ccSAndroid Build Coastguard Worker                                      right_available, partition, tx_size,
1807*77c1e3ccSAndroid Build Coastguard Worker                                      row_off, col_off, ss_x, ss_y)
1808*77c1e3ccSAndroid Build Coastguard Worker                      : -1;
1809*77c1e3ccSAndroid Build Coastguard Worker   const int have_bottom_left =
1810*77c1e3ccSAndroid Build Coastguard Worker       need_bottom_left ? has_bottom_left(sb_size, bsize, mi_row, mi_col,
1811*77c1e3ccSAndroid Build Coastguard Worker                                          bottom_available, have_left, partition,
1812*77c1e3ccSAndroid Build Coastguard Worker                                          tx_size, row_off, col_off, ss_x, ss_y)
1813*77c1e3ccSAndroid Build Coastguard Worker                        : -1;
1814*77c1e3ccSAndroid Build Coastguard Worker 
1815*77c1e3ccSAndroid Build Coastguard Worker   const int disable_edge_filter = !enable_intra_edge_filter;
1816*77c1e3ccSAndroid Build Coastguard Worker   const int intra_edge_filter_type = get_intra_edge_filter_type(xd, plane);
1817*77c1e3ccSAndroid Build Coastguard Worker   const int n_topright_px =
1818*77c1e3ccSAndroid Build Coastguard Worker       have_top_right > 0 ? AOMMIN(txwpx, xr) : have_top_right;
1819*77c1e3ccSAndroid Build Coastguard Worker   const int n_bottomleft_px =
1820*77c1e3ccSAndroid Build Coastguard Worker       have_bottom_left > 0 ? AOMMIN(txhpx, yd) : have_bottom_left;
1821*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_AV1_HIGHBITDEPTH
1822*77c1e3ccSAndroid Build Coastguard Worker   if (is_hbd) {
1823*77c1e3ccSAndroid Build Coastguard Worker     highbd_build_directional_and_filter_intra_predictors(
1824*77c1e3ccSAndroid Build Coastguard Worker         ref, ref_stride, dst, dst_stride, mode, p_angle, filter_intra_mode,
1825*77c1e3ccSAndroid Build Coastguard Worker         tx_size, disable_edge_filter, n_top_px, n_topright_px, n_left_px,
1826*77c1e3ccSAndroid Build Coastguard Worker         n_bottomleft_px, intra_edge_filter_type, xd->bd);
1827*77c1e3ccSAndroid Build Coastguard Worker     return;
1828*77c1e3ccSAndroid Build Coastguard Worker   }
1829*77c1e3ccSAndroid Build Coastguard Worker #endif
1830*77c1e3ccSAndroid Build Coastguard Worker   build_directional_and_filter_intra_predictors(
1831*77c1e3ccSAndroid Build Coastguard Worker       ref, ref_stride, dst, dst_stride, mode, p_angle, filter_intra_mode,
1832*77c1e3ccSAndroid Build Coastguard Worker       tx_size, disable_edge_filter, n_top_px, n_topright_px, n_left_px,
1833*77c1e3ccSAndroid Build Coastguard Worker       n_bottomleft_px, intra_edge_filter_type);
1834*77c1e3ccSAndroid Build Coastguard Worker }
1835*77c1e3ccSAndroid Build Coastguard Worker 
av1_predict_intra_block_facade(const AV1_COMMON * cm,MACROBLOCKD * xd,int plane,int blk_col,int blk_row,TX_SIZE tx_size)1836*77c1e3ccSAndroid Build Coastguard Worker void av1_predict_intra_block_facade(const AV1_COMMON *cm, MACROBLOCKD *xd,
1837*77c1e3ccSAndroid Build Coastguard Worker                                     int plane, int blk_col, int blk_row,
1838*77c1e3ccSAndroid Build Coastguard Worker                                     TX_SIZE tx_size) {
1839*77c1e3ccSAndroid Build Coastguard Worker   const MB_MODE_INFO *const mbmi = xd->mi[0];
1840*77c1e3ccSAndroid Build Coastguard Worker   struct macroblockd_plane *const pd = &xd->plane[plane];
1841*77c1e3ccSAndroid Build Coastguard Worker   const int dst_stride = pd->dst.stride;
1842*77c1e3ccSAndroid Build Coastguard Worker   uint8_t *dst = &pd->dst.buf[(blk_row * dst_stride + blk_col) << MI_SIZE_LOG2];
1843*77c1e3ccSAndroid Build Coastguard Worker   const PREDICTION_MODE mode =
1844*77c1e3ccSAndroid Build Coastguard Worker       (plane == AOM_PLANE_Y) ? mbmi->mode : get_uv_mode(mbmi->uv_mode);
1845*77c1e3ccSAndroid Build Coastguard Worker   const int use_palette = mbmi->palette_mode_info.palette_size[plane != 0] > 0;
1846*77c1e3ccSAndroid Build Coastguard Worker   const FILTER_INTRA_MODE filter_intra_mode =
1847*77c1e3ccSAndroid Build Coastguard Worker       (plane == AOM_PLANE_Y && mbmi->filter_intra_mode_info.use_filter_intra)
1848*77c1e3ccSAndroid Build Coastguard Worker           ? mbmi->filter_intra_mode_info.filter_intra_mode
1849*77c1e3ccSAndroid Build Coastguard Worker           : FILTER_INTRA_MODES;
1850*77c1e3ccSAndroid Build Coastguard Worker   const int angle_delta = mbmi->angle_delta[plane != AOM_PLANE_Y] * ANGLE_STEP;
1851*77c1e3ccSAndroid Build Coastguard Worker   const SequenceHeader *seq_params = cm->seq_params;
1852*77c1e3ccSAndroid Build Coastguard Worker 
1853*77c1e3ccSAndroid Build Coastguard Worker #if !CONFIG_REALTIME_ONLY || CONFIG_AV1_DECODER
1854*77c1e3ccSAndroid Build Coastguard Worker   if (plane != AOM_PLANE_Y && mbmi->uv_mode == UV_CFL_PRED) {
1855*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_DEBUG
1856*77c1e3ccSAndroid Build Coastguard Worker     assert(is_cfl_allowed(xd));
1857*77c1e3ccSAndroid Build Coastguard Worker     const BLOCK_SIZE plane_bsize =
1858*77c1e3ccSAndroid Build Coastguard Worker         get_plane_block_size(mbmi->bsize, pd->subsampling_x, pd->subsampling_y);
1859*77c1e3ccSAndroid Build Coastguard Worker     (void)plane_bsize;
1860*77c1e3ccSAndroid Build Coastguard Worker     assert(plane_bsize < BLOCK_SIZES_ALL);
1861*77c1e3ccSAndroid Build Coastguard Worker     if (!xd->lossless[mbmi->segment_id]) {
1862*77c1e3ccSAndroid Build Coastguard Worker       assert(blk_col == 0);
1863*77c1e3ccSAndroid Build Coastguard Worker       assert(blk_row == 0);
1864*77c1e3ccSAndroid Build Coastguard Worker       assert(block_size_wide[plane_bsize] == tx_size_wide[tx_size]);
1865*77c1e3ccSAndroid Build Coastguard Worker       assert(block_size_high[plane_bsize] == tx_size_high[tx_size]);
1866*77c1e3ccSAndroid Build Coastguard Worker     }
1867*77c1e3ccSAndroid Build Coastguard Worker #endif
1868*77c1e3ccSAndroid Build Coastguard Worker     CFL_CTX *const cfl = &xd->cfl;
1869*77c1e3ccSAndroid Build Coastguard Worker     CFL_PRED_TYPE pred_plane = get_cfl_pred_type(plane);
1870*77c1e3ccSAndroid Build Coastguard Worker     if (!cfl->dc_pred_is_cached[pred_plane]) {
1871*77c1e3ccSAndroid Build Coastguard Worker       av1_predict_intra_block(xd, seq_params->sb_size,
1872*77c1e3ccSAndroid Build Coastguard Worker                               seq_params->enable_intra_edge_filter, pd->width,
1873*77c1e3ccSAndroid Build Coastguard Worker                               pd->height, tx_size, mode, angle_delta,
1874*77c1e3ccSAndroid Build Coastguard Worker                               use_palette, filter_intra_mode, dst, dst_stride,
1875*77c1e3ccSAndroid Build Coastguard Worker                               dst, dst_stride, blk_col, blk_row, plane);
1876*77c1e3ccSAndroid Build Coastguard Worker       if (cfl->use_dc_pred_cache) {
1877*77c1e3ccSAndroid Build Coastguard Worker         cfl_store_dc_pred(xd, dst, pred_plane, tx_size_wide[tx_size]);
1878*77c1e3ccSAndroid Build Coastguard Worker         cfl->dc_pred_is_cached[pred_plane] = true;
1879*77c1e3ccSAndroid Build Coastguard Worker       }
1880*77c1e3ccSAndroid Build Coastguard Worker     } else {
1881*77c1e3ccSAndroid Build Coastguard Worker       cfl_load_dc_pred(xd, dst, dst_stride, tx_size, pred_plane);
1882*77c1e3ccSAndroid Build Coastguard Worker     }
1883*77c1e3ccSAndroid Build Coastguard Worker     av1_cfl_predict_block(xd, dst, dst_stride, tx_size, plane);
1884*77c1e3ccSAndroid Build Coastguard Worker     return;
1885*77c1e3ccSAndroid Build Coastguard Worker   }
1886*77c1e3ccSAndroid Build Coastguard Worker #endif  // !CONFIG_REALTIME_ONLY || CONFIG_AV1_DECODER
1887*77c1e3ccSAndroid Build Coastguard Worker   av1_predict_intra_block(
1888*77c1e3ccSAndroid Build Coastguard Worker       xd, seq_params->sb_size, seq_params->enable_intra_edge_filter, pd->width,
1889*77c1e3ccSAndroid Build Coastguard Worker       pd->height, tx_size, mode, angle_delta, use_palette, filter_intra_mode,
1890*77c1e3ccSAndroid Build Coastguard Worker       dst, dst_stride, dst, dst_stride, blk_col, blk_row, plane);
1891*77c1e3ccSAndroid Build Coastguard Worker }
1892*77c1e3ccSAndroid Build Coastguard Worker 
av1_init_intra_predictors(void)1893*77c1e3ccSAndroid Build Coastguard Worker void av1_init_intra_predictors(void) {
1894*77c1e3ccSAndroid Build Coastguard Worker   aom_once(init_intra_predictors_internal);
1895*77c1e3ccSAndroid Build Coastguard Worker }
1896