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 <math.h>
13*77c1e3ccSAndroid Build Coastguard Worker #include <stdbool.h>
14*77c1e3ccSAndroid Build Coastguard Worker #include <string.h>
15*77c1e3ccSAndroid Build Coastguard Worker
16*77c1e3ccSAndroid Build Coastguard Worker #include "config/aom_dsp_rtcd.h"
17*77c1e3ccSAndroid Build Coastguard Worker #include "config/aom_scale_rtcd.h"
18*77c1e3ccSAndroid Build Coastguard Worker
19*77c1e3ccSAndroid Build Coastguard Worker #include "aom/aom_integer.h"
20*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/av1_common_int.h"
21*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/reconinter.h"
22*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/encoder.h"
23*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/ethread.h"
24*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/pickcdef.h"
25*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/mcomp.h"
26*77c1e3ccSAndroid Build Coastguard Worker
27*77c1e3ccSAndroid Build Coastguard Worker // Get primary and secondary filter strength for the given strength index and
28*77c1e3ccSAndroid Build Coastguard Worker // search method
get_cdef_filter_strengths(CDEF_PICK_METHOD pick_method,int * pri_strength,int * sec_strength,int strength_idx)29*77c1e3ccSAndroid Build Coastguard Worker static inline void get_cdef_filter_strengths(CDEF_PICK_METHOD pick_method,
30*77c1e3ccSAndroid Build Coastguard Worker int *pri_strength,
31*77c1e3ccSAndroid Build Coastguard Worker int *sec_strength,
32*77c1e3ccSAndroid Build Coastguard Worker int strength_idx) {
33*77c1e3ccSAndroid Build Coastguard Worker const int tot_sec_filter =
34*77c1e3ccSAndroid Build Coastguard Worker (pick_method == CDEF_FAST_SEARCH_LVL5)
35*77c1e3ccSAndroid Build Coastguard Worker ? REDUCED_SEC_STRENGTHS_LVL5
36*77c1e3ccSAndroid Build Coastguard Worker : ((pick_method >= CDEF_FAST_SEARCH_LVL3) ? REDUCED_SEC_STRENGTHS_LVL3
37*77c1e3ccSAndroid Build Coastguard Worker : CDEF_SEC_STRENGTHS);
38*77c1e3ccSAndroid Build Coastguard Worker const int pri_idx = strength_idx / tot_sec_filter;
39*77c1e3ccSAndroid Build Coastguard Worker const int sec_idx = strength_idx % tot_sec_filter;
40*77c1e3ccSAndroid Build Coastguard Worker *pri_strength = pri_idx;
41*77c1e3ccSAndroid Build Coastguard Worker *sec_strength = sec_idx;
42*77c1e3ccSAndroid Build Coastguard Worker if (pick_method == CDEF_FULL_SEARCH) return;
43*77c1e3ccSAndroid Build Coastguard Worker
44*77c1e3ccSAndroid Build Coastguard Worker switch (pick_method) {
45*77c1e3ccSAndroid Build Coastguard Worker case CDEF_FAST_SEARCH_LVL1:
46*77c1e3ccSAndroid Build Coastguard Worker assert(pri_idx < REDUCED_PRI_STRENGTHS_LVL1);
47*77c1e3ccSAndroid Build Coastguard Worker *pri_strength = priconv_lvl1[pri_idx];
48*77c1e3ccSAndroid Build Coastguard Worker break;
49*77c1e3ccSAndroid Build Coastguard Worker case CDEF_FAST_SEARCH_LVL2:
50*77c1e3ccSAndroid Build Coastguard Worker assert(pri_idx < REDUCED_PRI_STRENGTHS_LVL2);
51*77c1e3ccSAndroid Build Coastguard Worker *pri_strength = priconv_lvl2[pri_idx];
52*77c1e3ccSAndroid Build Coastguard Worker break;
53*77c1e3ccSAndroid Build Coastguard Worker case CDEF_FAST_SEARCH_LVL3:
54*77c1e3ccSAndroid Build Coastguard Worker assert(pri_idx < REDUCED_PRI_STRENGTHS_LVL2);
55*77c1e3ccSAndroid Build Coastguard Worker assert(sec_idx < REDUCED_SEC_STRENGTHS_LVL3);
56*77c1e3ccSAndroid Build Coastguard Worker *pri_strength = priconv_lvl2[pri_idx];
57*77c1e3ccSAndroid Build Coastguard Worker *sec_strength = secconv_lvl3[sec_idx];
58*77c1e3ccSAndroid Build Coastguard Worker break;
59*77c1e3ccSAndroid Build Coastguard Worker case CDEF_FAST_SEARCH_LVL4:
60*77c1e3ccSAndroid Build Coastguard Worker assert(pri_idx < REDUCED_PRI_STRENGTHS_LVL4);
61*77c1e3ccSAndroid Build Coastguard Worker assert(sec_idx < REDUCED_SEC_STRENGTHS_LVL3);
62*77c1e3ccSAndroid Build Coastguard Worker *pri_strength = priconv_lvl4[pri_idx];
63*77c1e3ccSAndroid Build Coastguard Worker *sec_strength = secconv_lvl3[sec_idx];
64*77c1e3ccSAndroid Build Coastguard Worker break;
65*77c1e3ccSAndroid Build Coastguard Worker case CDEF_FAST_SEARCH_LVL5:
66*77c1e3ccSAndroid Build Coastguard Worker assert(pri_idx < REDUCED_PRI_STRENGTHS_LVL4);
67*77c1e3ccSAndroid Build Coastguard Worker assert(sec_idx < REDUCED_SEC_STRENGTHS_LVL5);
68*77c1e3ccSAndroid Build Coastguard Worker *pri_strength = priconv_lvl5[pri_idx];
69*77c1e3ccSAndroid Build Coastguard Worker *sec_strength = secconv_lvl5[sec_idx];
70*77c1e3ccSAndroid Build Coastguard Worker break;
71*77c1e3ccSAndroid Build Coastguard Worker default: assert(0 && "Invalid CDEF search method");
72*77c1e3ccSAndroid Build Coastguard Worker }
73*77c1e3ccSAndroid Build Coastguard Worker }
74*77c1e3ccSAndroid Build Coastguard Worker
75*77c1e3ccSAndroid Build Coastguard Worker // Store CDEF filter strength calculated from strength index for given search
76*77c1e3ccSAndroid Build Coastguard Worker // method
77*77c1e3ccSAndroid Build Coastguard Worker #define STORE_CDEF_FILTER_STRENGTH(cdef_strength, pick_method, strength_idx) \
78*77c1e3ccSAndroid Build Coastguard Worker do { \
79*77c1e3ccSAndroid Build Coastguard Worker get_cdef_filter_strengths((pick_method), &pri_strength, &sec_strength, \
80*77c1e3ccSAndroid Build Coastguard Worker (strength_idx)); \
81*77c1e3ccSAndroid Build Coastguard Worker cdef_strength = pri_strength * CDEF_SEC_STRENGTHS + sec_strength; \
82*77c1e3ccSAndroid Build Coastguard Worker } while (0)
83*77c1e3ccSAndroid Build Coastguard Worker
84*77c1e3ccSAndroid Build Coastguard Worker /* Search for the best strength to add as an option, knowing we
85*77c1e3ccSAndroid Build Coastguard Worker already selected nb_strengths options. */
search_one(int * lev,int nb_strengths,uint64_t mse[][TOTAL_STRENGTHS],int sb_count,CDEF_PICK_METHOD pick_method)86*77c1e3ccSAndroid Build Coastguard Worker static uint64_t search_one(int *lev, int nb_strengths,
87*77c1e3ccSAndroid Build Coastguard Worker uint64_t mse[][TOTAL_STRENGTHS], int sb_count,
88*77c1e3ccSAndroid Build Coastguard Worker CDEF_PICK_METHOD pick_method) {
89*77c1e3ccSAndroid Build Coastguard Worker uint64_t tot_mse[TOTAL_STRENGTHS];
90*77c1e3ccSAndroid Build Coastguard Worker const int total_strengths = nb_cdef_strengths[pick_method];
91*77c1e3ccSAndroid Build Coastguard Worker int i, j;
92*77c1e3ccSAndroid Build Coastguard Worker uint64_t best_tot_mse = (uint64_t)1 << 63;
93*77c1e3ccSAndroid Build Coastguard Worker int best_id = 0;
94*77c1e3ccSAndroid Build Coastguard Worker memset(tot_mse, 0, sizeof(tot_mse));
95*77c1e3ccSAndroid Build Coastguard Worker for (i = 0; i < sb_count; i++) {
96*77c1e3ccSAndroid Build Coastguard Worker int gi;
97*77c1e3ccSAndroid Build Coastguard Worker uint64_t best_mse = (uint64_t)1 << 63;
98*77c1e3ccSAndroid Build Coastguard Worker /* Find best mse among already selected options. */
99*77c1e3ccSAndroid Build Coastguard Worker for (gi = 0; gi < nb_strengths; gi++) {
100*77c1e3ccSAndroid Build Coastguard Worker if (mse[i][lev[gi]] < best_mse) {
101*77c1e3ccSAndroid Build Coastguard Worker best_mse = mse[i][lev[gi]];
102*77c1e3ccSAndroid Build Coastguard Worker }
103*77c1e3ccSAndroid Build Coastguard Worker }
104*77c1e3ccSAndroid Build Coastguard Worker /* Find best mse when adding each possible new option. */
105*77c1e3ccSAndroid Build Coastguard Worker for (j = 0; j < total_strengths; j++) {
106*77c1e3ccSAndroid Build Coastguard Worker uint64_t best = best_mse;
107*77c1e3ccSAndroid Build Coastguard Worker if (mse[i][j] < best) best = mse[i][j];
108*77c1e3ccSAndroid Build Coastguard Worker tot_mse[j] += best;
109*77c1e3ccSAndroid Build Coastguard Worker }
110*77c1e3ccSAndroid Build Coastguard Worker }
111*77c1e3ccSAndroid Build Coastguard Worker for (j = 0; j < total_strengths; j++) {
112*77c1e3ccSAndroid Build Coastguard Worker if (tot_mse[j] < best_tot_mse) {
113*77c1e3ccSAndroid Build Coastguard Worker best_tot_mse = tot_mse[j];
114*77c1e3ccSAndroid Build Coastguard Worker best_id = j;
115*77c1e3ccSAndroid Build Coastguard Worker }
116*77c1e3ccSAndroid Build Coastguard Worker }
117*77c1e3ccSAndroid Build Coastguard Worker lev[nb_strengths] = best_id;
118*77c1e3ccSAndroid Build Coastguard Worker return best_tot_mse;
119*77c1e3ccSAndroid Build Coastguard Worker }
120*77c1e3ccSAndroid Build Coastguard Worker
121*77c1e3ccSAndroid Build Coastguard Worker /* Search for the best luma+chroma strength to add as an option, knowing we
122*77c1e3ccSAndroid Build Coastguard Worker already selected nb_strengths options. */
search_one_dual(int * lev0,int * lev1,int nb_strengths,uint64_t (** mse)[TOTAL_STRENGTHS],int sb_count,CDEF_PICK_METHOD pick_method)123*77c1e3ccSAndroid Build Coastguard Worker static uint64_t search_one_dual(int *lev0, int *lev1, int nb_strengths,
124*77c1e3ccSAndroid Build Coastguard Worker uint64_t (**mse)[TOTAL_STRENGTHS], int sb_count,
125*77c1e3ccSAndroid Build Coastguard Worker CDEF_PICK_METHOD pick_method) {
126*77c1e3ccSAndroid Build Coastguard Worker uint64_t tot_mse[TOTAL_STRENGTHS][TOTAL_STRENGTHS];
127*77c1e3ccSAndroid Build Coastguard Worker int i, j;
128*77c1e3ccSAndroid Build Coastguard Worker uint64_t best_tot_mse = (uint64_t)1 << 63;
129*77c1e3ccSAndroid Build Coastguard Worker int best_id0 = 0;
130*77c1e3ccSAndroid Build Coastguard Worker int best_id1 = 0;
131*77c1e3ccSAndroid Build Coastguard Worker const int total_strengths = nb_cdef_strengths[pick_method];
132*77c1e3ccSAndroid Build Coastguard Worker memset(tot_mse, 0, sizeof(tot_mse));
133*77c1e3ccSAndroid Build Coastguard Worker for (i = 0; i < sb_count; i++) {
134*77c1e3ccSAndroid Build Coastguard Worker int gi;
135*77c1e3ccSAndroid Build Coastguard Worker uint64_t best_mse = (uint64_t)1 << 63;
136*77c1e3ccSAndroid Build Coastguard Worker /* Find best mse among already selected options. */
137*77c1e3ccSAndroid Build Coastguard Worker for (gi = 0; gi < nb_strengths; gi++) {
138*77c1e3ccSAndroid Build Coastguard Worker uint64_t curr = mse[0][i][lev0[gi]];
139*77c1e3ccSAndroid Build Coastguard Worker curr += mse[1][i][lev1[gi]];
140*77c1e3ccSAndroid Build Coastguard Worker if (curr < best_mse) {
141*77c1e3ccSAndroid Build Coastguard Worker best_mse = curr;
142*77c1e3ccSAndroid Build Coastguard Worker }
143*77c1e3ccSAndroid Build Coastguard Worker }
144*77c1e3ccSAndroid Build Coastguard Worker /* Find best mse when adding each possible new option. */
145*77c1e3ccSAndroid Build Coastguard Worker for (j = 0; j < total_strengths; j++) {
146*77c1e3ccSAndroid Build Coastguard Worker int k;
147*77c1e3ccSAndroid Build Coastguard Worker for (k = 0; k < total_strengths; k++) {
148*77c1e3ccSAndroid Build Coastguard Worker uint64_t best = best_mse;
149*77c1e3ccSAndroid Build Coastguard Worker uint64_t curr = mse[0][i][j];
150*77c1e3ccSAndroid Build Coastguard Worker curr += mse[1][i][k];
151*77c1e3ccSAndroid Build Coastguard Worker if (curr < best) best = curr;
152*77c1e3ccSAndroid Build Coastguard Worker tot_mse[j][k] += best;
153*77c1e3ccSAndroid Build Coastguard Worker }
154*77c1e3ccSAndroid Build Coastguard Worker }
155*77c1e3ccSAndroid Build Coastguard Worker }
156*77c1e3ccSAndroid Build Coastguard Worker for (j = 0; j < total_strengths; j++) {
157*77c1e3ccSAndroid Build Coastguard Worker int k;
158*77c1e3ccSAndroid Build Coastguard Worker for (k = 0; k < total_strengths; k++) {
159*77c1e3ccSAndroid Build Coastguard Worker if (tot_mse[j][k] < best_tot_mse) {
160*77c1e3ccSAndroid Build Coastguard Worker best_tot_mse = tot_mse[j][k];
161*77c1e3ccSAndroid Build Coastguard Worker best_id0 = j;
162*77c1e3ccSAndroid Build Coastguard Worker best_id1 = k;
163*77c1e3ccSAndroid Build Coastguard Worker }
164*77c1e3ccSAndroid Build Coastguard Worker }
165*77c1e3ccSAndroid Build Coastguard Worker }
166*77c1e3ccSAndroid Build Coastguard Worker lev0[nb_strengths] = best_id0;
167*77c1e3ccSAndroid Build Coastguard Worker lev1[nb_strengths] = best_id1;
168*77c1e3ccSAndroid Build Coastguard Worker return best_tot_mse;
169*77c1e3ccSAndroid Build Coastguard Worker }
170*77c1e3ccSAndroid Build Coastguard Worker
171*77c1e3ccSAndroid Build Coastguard Worker /* Search for the set of strengths that minimizes mse. */
joint_strength_search(int * best_lev,int nb_strengths,uint64_t mse[][TOTAL_STRENGTHS],int sb_count,CDEF_PICK_METHOD pick_method)172*77c1e3ccSAndroid Build Coastguard Worker static uint64_t joint_strength_search(int *best_lev, int nb_strengths,
173*77c1e3ccSAndroid Build Coastguard Worker uint64_t mse[][TOTAL_STRENGTHS],
174*77c1e3ccSAndroid Build Coastguard Worker int sb_count,
175*77c1e3ccSAndroid Build Coastguard Worker CDEF_PICK_METHOD pick_method) {
176*77c1e3ccSAndroid Build Coastguard Worker uint64_t best_tot_mse;
177*77c1e3ccSAndroid Build Coastguard Worker int fast = (pick_method >= CDEF_FAST_SEARCH_LVL1 &&
178*77c1e3ccSAndroid Build Coastguard Worker pick_method <= CDEF_FAST_SEARCH_LVL5);
179*77c1e3ccSAndroid Build Coastguard Worker int i;
180*77c1e3ccSAndroid Build Coastguard Worker best_tot_mse = (uint64_t)1 << 63;
181*77c1e3ccSAndroid Build Coastguard Worker /* Greedy search: add one strength options at a time. */
182*77c1e3ccSAndroid Build Coastguard Worker for (i = 0; i < nb_strengths; i++) {
183*77c1e3ccSAndroid Build Coastguard Worker best_tot_mse = search_one(best_lev, i, mse, sb_count, pick_method);
184*77c1e3ccSAndroid Build Coastguard Worker }
185*77c1e3ccSAndroid Build Coastguard Worker /* Trying to refine the greedy search by reconsidering each
186*77c1e3ccSAndroid Build Coastguard Worker already-selected option. */
187*77c1e3ccSAndroid Build Coastguard Worker if (!fast) {
188*77c1e3ccSAndroid Build Coastguard Worker for (i = 0; i < 4 * nb_strengths; i++) {
189*77c1e3ccSAndroid Build Coastguard Worker int j;
190*77c1e3ccSAndroid Build Coastguard Worker for (j = 0; j < nb_strengths - 1; j++) best_lev[j] = best_lev[j + 1];
191*77c1e3ccSAndroid Build Coastguard Worker best_tot_mse =
192*77c1e3ccSAndroid Build Coastguard Worker search_one(best_lev, nb_strengths - 1, mse, sb_count, pick_method);
193*77c1e3ccSAndroid Build Coastguard Worker }
194*77c1e3ccSAndroid Build Coastguard Worker }
195*77c1e3ccSAndroid Build Coastguard Worker return best_tot_mse;
196*77c1e3ccSAndroid Build Coastguard Worker }
197*77c1e3ccSAndroid Build Coastguard Worker
198*77c1e3ccSAndroid Build Coastguard Worker /* Search for the set of luma+chroma strengths that minimizes mse. */
joint_strength_search_dual(int * best_lev0,int * best_lev1,int nb_strengths,uint64_t (** mse)[TOTAL_STRENGTHS],int sb_count,CDEF_PICK_METHOD pick_method)199*77c1e3ccSAndroid Build Coastguard Worker static uint64_t joint_strength_search_dual(int *best_lev0, int *best_lev1,
200*77c1e3ccSAndroid Build Coastguard Worker int nb_strengths,
201*77c1e3ccSAndroid Build Coastguard Worker uint64_t (**mse)[TOTAL_STRENGTHS],
202*77c1e3ccSAndroid Build Coastguard Worker int sb_count,
203*77c1e3ccSAndroid Build Coastguard Worker CDEF_PICK_METHOD pick_method) {
204*77c1e3ccSAndroid Build Coastguard Worker uint64_t best_tot_mse;
205*77c1e3ccSAndroid Build Coastguard Worker int i;
206*77c1e3ccSAndroid Build Coastguard Worker best_tot_mse = (uint64_t)1 << 63;
207*77c1e3ccSAndroid Build Coastguard Worker /* Greedy search: add one strength options at a time. */
208*77c1e3ccSAndroid Build Coastguard Worker for (i = 0; i < nb_strengths; i++) {
209*77c1e3ccSAndroid Build Coastguard Worker best_tot_mse =
210*77c1e3ccSAndroid Build Coastguard Worker search_one_dual(best_lev0, best_lev1, i, mse, sb_count, pick_method);
211*77c1e3ccSAndroid Build Coastguard Worker }
212*77c1e3ccSAndroid Build Coastguard Worker /* Trying to refine the greedy search by reconsidering each
213*77c1e3ccSAndroid Build Coastguard Worker already-selected option. */
214*77c1e3ccSAndroid Build Coastguard Worker for (i = 0; i < 4 * nb_strengths; i++) {
215*77c1e3ccSAndroid Build Coastguard Worker int j;
216*77c1e3ccSAndroid Build Coastguard Worker for (j = 0; j < nb_strengths - 1; j++) {
217*77c1e3ccSAndroid Build Coastguard Worker best_lev0[j] = best_lev0[j + 1];
218*77c1e3ccSAndroid Build Coastguard Worker best_lev1[j] = best_lev1[j + 1];
219*77c1e3ccSAndroid Build Coastguard Worker }
220*77c1e3ccSAndroid Build Coastguard Worker best_tot_mse = search_one_dual(best_lev0, best_lev1, nb_strengths - 1, mse,
221*77c1e3ccSAndroid Build Coastguard Worker sb_count, pick_method);
222*77c1e3ccSAndroid Build Coastguard Worker }
223*77c1e3ccSAndroid Build Coastguard Worker return best_tot_mse;
224*77c1e3ccSAndroid Build Coastguard Worker }
225*77c1e3ccSAndroid Build Coastguard Worker
init_src_params(int * src_stride,int * width,int * height,int * width_log2,int * height_log2,BLOCK_SIZE bsize)226*77c1e3ccSAndroid Build Coastguard Worker static inline void init_src_params(int *src_stride, int *width, int *height,
227*77c1e3ccSAndroid Build Coastguard Worker int *width_log2, int *height_log2,
228*77c1e3ccSAndroid Build Coastguard Worker BLOCK_SIZE bsize) {
229*77c1e3ccSAndroid Build Coastguard Worker *src_stride = block_size_wide[bsize];
230*77c1e3ccSAndroid Build Coastguard Worker *width = block_size_wide[bsize];
231*77c1e3ccSAndroid Build Coastguard Worker *height = block_size_high[bsize];
232*77c1e3ccSAndroid Build Coastguard Worker *width_log2 = MI_SIZE_LOG2 + mi_size_wide_log2[bsize];
233*77c1e3ccSAndroid Build Coastguard Worker *height_log2 = MI_SIZE_LOG2 + mi_size_wide_log2[bsize];
234*77c1e3ccSAndroid Build Coastguard Worker }
235*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_AV1_HIGHBITDEPTH
236*77c1e3ccSAndroid Build Coastguard Worker /* Compute MSE only on the blocks we filtered. */
compute_cdef_dist_highbd(void * dst,int dstride,uint16_t * src,cdef_list * dlist,int cdef_count,BLOCK_SIZE bsize,int coeff_shift,int row,int col)237*77c1e3ccSAndroid Build Coastguard Worker static uint64_t compute_cdef_dist_highbd(void *dst, int dstride, uint16_t *src,
238*77c1e3ccSAndroid Build Coastguard Worker cdef_list *dlist, int cdef_count,
239*77c1e3ccSAndroid Build Coastguard Worker BLOCK_SIZE bsize, int coeff_shift,
240*77c1e3ccSAndroid Build Coastguard Worker int row, int col) {
241*77c1e3ccSAndroid Build Coastguard Worker assert(bsize == BLOCK_4X4 || bsize == BLOCK_4X8 || bsize == BLOCK_8X4 ||
242*77c1e3ccSAndroid Build Coastguard Worker bsize == BLOCK_8X8);
243*77c1e3ccSAndroid Build Coastguard Worker uint64_t sum = 0;
244*77c1e3ccSAndroid Build Coastguard Worker int bi, bx, by;
245*77c1e3ccSAndroid Build Coastguard Worker uint16_t *dst16 = CONVERT_TO_SHORTPTR((uint8_t *)dst);
246*77c1e3ccSAndroid Build Coastguard Worker uint16_t *dst_buff = &dst16[row * dstride + col];
247*77c1e3ccSAndroid Build Coastguard Worker int src_stride, width, height, width_log2, height_log2;
248*77c1e3ccSAndroid Build Coastguard Worker init_src_params(&src_stride, &width, &height, &width_log2, &height_log2,
249*77c1e3ccSAndroid Build Coastguard Worker bsize);
250*77c1e3ccSAndroid Build Coastguard Worker for (bi = 0; bi < cdef_count; bi++) {
251*77c1e3ccSAndroid Build Coastguard Worker by = dlist[bi].by;
252*77c1e3ccSAndroid Build Coastguard Worker bx = dlist[bi].bx;
253*77c1e3ccSAndroid Build Coastguard Worker sum += aom_mse_wxh_16bit_highbd(
254*77c1e3ccSAndroid Build Coastguard Worker &dst_buff[(by << height_log2) * dstride + (bx << width_log2)], dstride,
255*77c1e3ccSAndroid Build Coastguard Worker &src[bi << (height_log2 + width_log2)], src_stride, width, height);
256*77c1e3ccSAndroid Build Coastguard Worker }
257*77c1e3ccSAndroid Build Coastguard Worker return sum >> 2 * coeff_shift;
258*77c1e3ccSAndroid Build Coastguard Worker }
259*77c1e3ccSAndroid Build Coastguard Worker #endif
260*77c1e3ccSAndroid Build Coastguard Worker
261*77c1e3ccSAndroid Build Coastguard Worker // Checks dual and quad block processing is applicable for block widths 8 and 4
262*77c1e3ccSAndroid Build Coastguard Worker // respectively.
is_dual_or_quad_applicable(cdef_list * dlist,int width,int cdef_count,int bi,int iter)263*77c1e3ccSAndroid Build Coastguard Worker static inline int is_dual_or_quad_applicable(cdef_list *dlist, int width,
264*77c1e3ccSAndroid Build Coastguard Worker int cdef_count, int bi, int iter) {
265*77c1e3ccSAndroid Build Coastguard Worker assert(width == 8 || width == 4);
266*77c1e3ccSAndroid Build Coastguard Worker const int blk_offset = (width == 8) ? 1 : 3;
267*77c1e3ccSAndroid Build Coastguard Worker if ((iter + blk_offset) >= cdef_count) return 0;
268*77c1e3ccSAndroid Build Coastguard Worker
269*77c1e3ccSAndroid Build Coastguard Worker if (dlist[bi].by == dlist[bi + blk_offset].by &&
270*77c1e3ccSAndroid Build Coastguard Worker dlist[bi].bx + blk_offset == dlist[bi + blk_offset].bx)
271*77c1e3ccSAndroid Build Coastguard Worker return 1;
272*77c1e3ccSAndroid Build Coastguard Worker
273*77c1e3ccSAndroid Build Coastguard Worker return 0;
274*77c1e3ccSAndroid Build Coastguard Worker }
275*77c1e3ccSAndroid Build Coastguard Worker
compute_cdef_dist(void * dst,int dstride,uint16_t * src,cdef_list * dlist,int cdef_count,BLOCK_SIZE bsize,int coeff_shift,int row,int col)276*77c1e3ccSAndroid Build Coastguard Worker static uint64_t compute_cdef_dist(void *dst, int dstride, uint16_t *src,
277*77c1e3ccSAndroid Build Coastguard Worker cdef_list *dlist, int cdef_count,
278*77c1e3ccSAndroid Build Coastguard Worker BLOCK_SIZE bsize, int coeff_shift, int row,
279*77c1e3ccSAndroid Build Coastguard Worker int col) {
280*77c1e3ccSAndroid Build Coastguard Worker assert(bsize == BLOCK_4X4 || bsize == BLOCK_4X8 || bsize == BLOCK_8X4 ||
281*77c1e3ccSAndroid Build Coastguard Worker bsize == BLOCK_8X8);
282*77c1e3ccSAndroid Build Coastguard Worker uint64_t sum = 0;
283*77c1e3ccSAndroid Build Coastguard Worker int bi, bx, by;
284*77c1e3ccSAndroid Build Coastguard Worker int iter = 0;
285*77c1e3ccSAndroid Build Coastguard Worker int inc = 1;
286*77c1e3ccSAndroid Build Coastguard Worker uint8_t *dst8 = (uint8_t *)dst;
287*77c1e3ccSAndroid Build Coastguard Worker uint8_t *dst_buff = &dst8[row * dstride + col];
288*77c1e3ccSAndroid Build Coastguard Worker int src_stride, width, height, width_log2, height_log2;
289*77c1e3ccSAndroid Build Coastguard Worker init_src_params(&src_stride, &width, &height, &width_log2, &height_log2,
290*77c1e3ccSAndroid Build Coastguard Worker bsize);
291*77c1e3ccSAndroid Build Coastguard Worker
292*77c1e3ccSAndroid Build Coastguard Worker const int num_blks = 16 / width;
293*77c1e3ccSAndroid Build Coastguard Worker for (bi = 0; bi < cdef_count; bi += inc) {
294*77c1e3ccSAndroid Build Coastguard Worker by = dlist[bi].by;
295*77c1e3ccSAndroid Build Coastguard Worker bx = dlist[bi].bx;
296*77c1e3ccSAndroid Build Coastguard Worker uint16_t *src_tmp = &src[bi << (height_log2 + width_log2)];
297*77c1e3ccSAndroid Build Coastguard Worker uint8_t *dst_tmp =
298*77c1e3ccSAndroid Build Coastguard Worker &dst_buff[(by << height_log2) * dstride + (bx << width_log2)];
299*77c1e3ccSAndroid Build Coastguard Worker
300*77c1e3ccSAndroid Build Coastguard Worker if (is_dual_or_quad_applicable(dlist, width, cdef_count, bi, iter)) {
301*77c1e3ccSAndroid Build Coastguard Worker sum += aom_mse_16xh_16bit(dst_tmp, dstride, src_tmp, width, height);
302*77c1e3ccSAndroid Build Coastguard Worker iter += num_blks;
303*77c1e3ccSAndroid Build Coastguard Worker inc = num_blks;
304*77c1e3ccSAndroid Build Coastguard Worker } else {
305*77c1e3ccSAndroid Build Coastguard Worker sum += aom_mse_wxh_16bit(dst_tmp, dstride, src_tmp, src_stride, width,
306*77c1e3ccSAndroid Build Coastguard Worker height);
307*77c1e3ccSAndroid Build Coastguard Worker iter += 1;
308*77c1e3ccSAndroid Build Coastguard Worker inc = 1;
309*77c1e3ccSAndroid Build Coastguard Worker }
310*77c1e3ccSAndroid Build Coastguard Worker }
311*77c1e3ccSAndroid Build Coastguard Worker
312*77c1e3ccSAndroid Build Coastguard Worker return sum >> 2 * coeff_shift;
313*77c1e3ccSAndroid Build Coastguard Worker }
314*77c1e3ccSAndroid Build Coastguard Worker
315*77c1e3ccSAndroid Build Coastguard Worker // Fill the boundary regions of the block with CDEF_VERY_LARGE, only if the
316*77c1e3ccSAndroid Build Coastguard Worker // region is outside frame boundary
fill_borders_for_fbs_on_frame_boundary(uint16_t * inbuf,int hfilt_size,int vfilt_size,bool is_fb_on_frm_left_boundary,bool is_fb_on_frm_right_boundary,bool is_fb_on_frm_top_boundary,bool is_fb_on_frm_bottom_boundary)317*77c1e3ccSAndroid Build Coastguard Worker static inline void fill_borders_for_fbs_on_frame_boundary(
318*77c1e3ccSAndroid Build Coastguard Worker uint16_t *inbuf, int hfilt_size, int vfilt_size,
319*77c1e3ccSAndroid Build Coastguard Worker bool is_fb_on_frm_left_boundary, bool is_fb_on_frm_right_boundary,
320*77c1e3ccSAndroid Build Coastguard Worker bool is_fb_on_frm_top_boundary, bool is_fb_on_frm_bottom_boundary) {
321*77c1e3ccSAndroid Build Coastguard Worker if (!is_fb_on_frm_left_boundary && !is_fb_on_frm_right_boundary &&
322*77c1e3ccSAndroid Build Coastguard Worker !is_fb_on_frm_top_boundary && !is_fb_on_frm_bottom_boundary)
323*77c1e3ccSAndroid Build Coastguard Worker return;
324*77c1e3ccSAndroid Build Coastguard Worker if (is_fb_on_frm_bottom_boundary) {
325*77c1e3ccSAndroid Build Coastguard Worker // Fill bottom region of the block
326*77c1e3ccSAndroid Build Coastguard Worker const int buf_offset =
327*77c1e3ccSAndroid Build Coastguard Worker (vfilt_size + CDEF_VBORDER) * CDEF_BSTRIDE + CDEF_HBORDER;
328*77c1e3ccSAndroid Build Coastguard Worker fill_rect(&inbuf[buf_offset], CDEF_BSTRIDE, CDEF_VBORDER, hfilt_size,
329*77c1e3ccSAndroid Build Coastguard Worker CDEF_VERY_LARGE);
330*77c1e3ccSAndroid Build Coastguard Worker }
331*77c1e3ccSAndroid Build Coastguard Worker if (is_fb_on_frm_bottom_boundary || is_fb_on_frm_left_boundary) {
332*77c1e3ccSAndroid Build Coastguard Worker const int buf_offset = (vfilt_size + CDEF_VBORDER) * CDEF_BSTRIDE;
333*77c1e3ccSAndroid Build Coastguard Worker // Fill bottom-left region of the block
334*77c1e3ccSAndroid Build Coastguard Worker fill_rect(&inbuf[buf_offset], CDEF_BSTRIDE, CDEF_VBORDER, CDEF_HBORDER,
335*77c1e3ccSAndroid Build Coastguard Worker CDEF_VERY_LARGE);
336*77c1e3ccSAndroid Build Coastguard Worker }
337*77c1e3ccSAndroid Build Coastguard Worker if (is_fb_on_frm_bottom_boundary || is_fb_on_frm_right_boundary) {
338*77c1e3ccSAndroid Build Coastguard Worker const int buf_offset =
339*77c1e3ccSAndroid Build Coastguard Worker (vfilt_size + CDEF_VBORDER) * CDEF_BSTRIDE + hfilt_size + CDEF_HBORDER;
340*77c1e3ccSAndroid Build Coastguard Worker // Fill bottom-right region of the block
341*77c1e3ccSAndroid Build Coastguard Worker fill_rect(&inbuf[buf_offset], CDEF_BSTRIDE, CDEF_VBORDER, CDEF_HBORDER,
342*77c1e3ccSAndroid Build Coastguard Worker CDEF_VERY_LARGE);
343*77c1e3ccSAndroid Build Coastguard Worker }
344*77c1e3ccSAndroid Build Coastguard Worker if (is_fb_on_frm_top_boundary) {
345*77c1e3ccSAndroid Build Coastguard Worker // Fill top region of the block
346*77c1e3ccSAndroid Build Coastguard Worker fill_rect(&inbuf[CDEF_HBORDER], CDEF_BSTRIDE, CDEF_VBORDER, hfilt_size,
347*77c1e3ccSAndroid Build Coastguard Worker CDEF_VERY_LARGE);
348*77c1e3ccSAndroid Build Coastguard Worker }
349*77c1e3ccSAndroid Build Coastguard Worker if (is_fb_on_frm_top_boundary || is_fb_on_frm_left_boundary) {
350*77c1e3ccSAndroid Build Coastguard Worker // Fill top-left region of the block
351*77c1e3ccSAndroid Build Coastguard Worker fill_rect(inbuf, CDEF_BSTRIDE, CDEF_VBORDER, CDEF_HBORDER, CDEF_VERY_LARGE);
352*77c1e3ccSAndroid Build Coastguard Worker }
353*77c1e3ccSAndroid Build Coastguard Worker if (is_fb_on_frm_top_boundary || is_fb_on_frm_right_boundary) {
354*77c1e3ccSAndroid Build Coastguard Worker const int buf_offset = hfilt_size + CDEF_HBORDER;
355*77c1e3ccSAndroid Build Coastguard Worker // Fill top-right region of the block
356*77c1e3ccSAndroid Build Coastguard Worker fill_rect(&inbuf[buf_offset], CDEF_BSTRIDE, CDEF_VBORDER, CDEF_HBORDER,
357*77c1e3ccSAndroid Build Coastguard Worker CDEF_VERY_LARGE);
358*77c1e3ccSAndroid Build Coastguard Worker }
359*77c1e3ccSAndroid Build Coastguard Worker if (is_fb_on_frm_left_boundary) {
360*77c1e3ccSAndroid Build Coastguard Worker const int buf_offset = CDEF_VBORDER * CDEF_BSTRIDE;
361*77c1e3ccSAndroid Build Coastguard Worker // Fill left region of the block
362*77c1e3ccSAndroid Build Coastguard Worker fill_rect(&inbuf[buf_offset], CDEF_BSTRIDE, vfilt_size, CDEF_HBORDER,
363*77c1e3ccSAndroid Build Coastguard Worker CDEF_VERY_LARGE);
364*77c1e3ccSAndroid Build Coastguard Worker }
365*77c1e3ccSAndroid Build Coastguard Worker if (is_fb_on_frm_right_boundary) {
366*77c1e3ccSAndroid Build Coastguard Worker const int buf_offset = CDEF_VBORDER * CDEF_BSTRIDE;
367*77c1e3ccSAndroid Build Coastguard Worker // Fill right region of the block
368*77c1e3ccSAndroid Build Coastguard Worker fill_rect(&inbuf[buf_offset + hfilt_size + CDEF_HBORDER], CDEF_BSTRIDE,
369*77c1e3ccSAndroid Build Coastguard Worker vfilt_size, CDEF_HBORDER, CDEF_VERY_LARGE);
370*77c1e3ccSAndroid Build Coastguard Worker }
371*77c1e3ccSAndroid Build Coastguard Worker }
372*77c1e3ccSAndroid Build Coastguard Worker
373*77c1e3ccSAndroid Build Coastguard Worker // Calculate the number of 8x8/4x4 filter units for which SSE can be calculated
374*77c1e3ccSAndroid Build Coastguard Worker // after CDEF filtering in single function call
get_error_calc_width_in_filt_units(cdef_list * dlist,int cdef_count,int bi,int subsampling_x,int subsampling_y)375*77c1e3ccSAndroid Build Coastguard Worker static AOM_FORCE_INLINE int get_error_calc_width_in_filt_units(
376*77c1e3ccSAndroid Build Coastguard Worker cdef_list *dlist, int cdef_count, int bi, int subsampling_x,
377*77c1e3ccSAndroid Build Coastguard Worker int subsampling_y) {
378*77c1e3ccSAndroid Build Coastguard Worker // TODO(Ranjit): Extend the optimization for 422
379*77c1e3ccSAndroid Build Coastguard Worker if (subsampling_x != subsampling_y) return 1;
380*77c1e3ccSAndroid Build Coastguard Worker
381*77c1e3ccSAndroid Build Coastguard Worker // Combining more blocks seems to increase encode time due to increase in
382*77c1e3ccSAndroid Build Coastguard Worker // control code
383*77c1e3ccSAndroid Build Coastguard Worker if (bi + 3 < cdef_count && dlist[bi].by == dlist[bi + 3].by &&
384*77c1e3ccSAndroid Build Coastguard Worker dlist[bi].bx + 3 == dlist[bi + 3].bx) {
385*77c1e3ccSAndroid Build Coastguard Worker /* Calculate error for four 8x8/4x4 blocks using 32x8/16x4 block specific
386*77c1e3ccSAndroid Build Coastguard Worker * logic if y co-ordinates match and x co-ordinates are
387*77c1e3ccSAndroid Build Coastguard Worker * separated by 3 for first and fourth 8x8/4x4 blocks in dlist[]. */
388*77c1e3ccSAndroid Build Coastguard Worker return 4;
389*77c1e3ccSAndroid Build Coastguard Worker }
390*77c1e3ccSAndroid Build Coastguard Worker if (bi + 1 < cdef_count && dlist[bi].by == dlist[bi + 1].by &&
391*77c1e3ccSAndroid Build Coastguard Worker dlist[bi].bx + 1 == dlist[bi + 1].bx) {
392*77c1e3ccSAndroid Build Coastguard Worker /* Calculate error for two 8x8/4x4 blocks using 16x8/8x4 block specific
393*77c1e3ccSAndroid Build Coastguard Worker * logic if their y co-ordinates match and x co-ordinates are
394*77c1e3ccSAndroid Build Coastguard Worker * separated by 1 for first and second 8x8/4x4 blocks in dlist[]. */
395*77c1e3ccSAndroid Build Coastguard Worker return 2;
396*77c1e3ccSAndroid Build Coastguard Worker }
397*77c1e3ccSAndroid Build Coastguard Worker return 1;
398*77c1e3ccSAndroid Build Coastguard Worker }
399*77c1e3ccSAndroid Build Coastguard Worker
400*77c1e3ccSAndroid Build Coastguard Worker // Returns the block error after CDEF filtering for a given strength
get_filt_error(const CdefSearchCtx * cdef_search_ctx,const struct macroblockd_plane * pd,cdef_list * dlist,int dir[CDEF_NBLOCKS][CDEF_NBLOCKS],int * dirinit,int var[CDEF_NBLOCKS][CDEF_NBLOCKS],uint16_t * in,uint8_t * ref_buffer,int ref_stride,int row,int col,int pri_strength,int sec_strength,int cdef_count,int pli,int coeff_shift,BLOCK_SIZE bs)401*77c1e3ccSAndroid Build Coastguard Worker static inline uint64_t get_filt_error(
402*77c1e3ccSAndroid Build Coastguard Worker const CdefSearchCtx *cdef_search_ctx, const struct macroblockd_plane *pd,
403*77c1e3ccSAndroid Build Coastguard Worker cdef_list *dlist, int dir[CDEF_NBLOCKS][CDEF_NBLOCKS], int *dirinit,
404*77c1e3ccSAndroid Build Coastguard Worker int var[CDEF_NBLOCKS][CDEF_NBLOCKS], uint16_t *in, uint8_t *ref_buffer,
405*77c1e3ccSAndroid Build Coastguard Worker int ref_stride, int row, int col, int pri_strength, int sec_strength,
406*77c1e3ccSAndroid Build Coastguard Worker int cdef_count, int pli, int coeff_shift, BLOCK_SIZE bs) {
407*77c1e3ccSAndroid Build Coastguard Worker uint64_t curr_sse = 0;
408*77c1e3ccSAndroid Build Coastguard Worker const BLOCK_SIZE plane_bsize =
409*77c1e3ccSAndroid Build Coastguard Worker get_plane_block_size(bs, pd->subsampling_x, pd->subsampling_y);
410*77c1e3ccSAndroid Build Coastguard Worker const int bw_log2 = 3 - pd->subsampling_x;
411*77c1e3ccSAndroid Build Coastguard Worker const int bh_log2 = 3 - pd->subsampling_y;
412*77c1e3ccSAndroid Build Coastguard Worker
413*77c1e3ccSAndroid Build Coastguard Worker // TODO(Ranjit): Extend this optimization for HBD
414*77c1e3ccSAndroid Build Coastguard Worker if (!cdef_search_ctx->use_highbitdepth) {
415*77c1e3ccSAndroid Build Coastguard Worker // If all 8x8/4x4 blocks in CDEF block need to be filtered, calculate the
416*77c1e3ccSAndroid Build Coastguard Worker // error at CDEF block level
417*77c1e3ccSAndroid Build Coastguard Worker const int tot_blk_count =
418*77c1e3ccSAndroid Build Coastguard Worker (block_size_wide[plane_bsize] * block_size_high[plane_bsize]) >>
419*77c1e3ccSAndroid Build Coastguard Worker (bw_log2 + bh_log2);
420*77c1e3ccSAndroid Build Coastguard Worker if (cdef_count == tot_blk_count) {
421*77c1e3ccSAndroid Build Coastguard Worker // Calculate the offset in the buffer based on block position
422*77c1e3ccSAndroid Build Coastguard Worker const FULLPEL_MV this_mv = { row, col };
423*77c1e3ccSAndroid Build Coastguard Worker const int buf_offset = get_offset_from_fullmv(&this_mv, ref_stride);
424*77c1e3ccSAndroid Build Coastguard Worker if (pri_strength == 0 && sec_strength == 0) {
425*77c1e3ccSAndroid Build Coastguard Worker // When CDEF strength is zero, filtering is not applied. Hence
426*77c1e3ccSAndroid Build Coastguard Worker // error is calculated between source and unfiltered pixels
427*77c1e3ccSAndroid Build Coastguard Worker curr_sse =
428*77c1e3ccSAndroid Build Coastguard Worker aom_sse(&ref_buffer[buf_offset], ref_stride,
429*77c1e3ccSAndroid Build Coastguard Worker get_buf_from_fullmv(&pd->dst, &this_mv), pd->dst.stride,
430*77c1e3ccSAndroid Build Coastguard Worker block_size_wide[plane_bsize], block_size_high[plane_bsize]);
431*77c1e3ccSAndroid Build Coastguard Worker } else {
432*77c1e3ccSAndroid Build Coastguard Worker DECLARE_ALIGNED(32, uint8_t, tmp_dst8[1 << (MAX_SB_SIZE_LOG2 * 2)]);
433*77c1e3ccSAndroid Build Coastguard Worker
434*77c1e3ccSAndroid Build Coastguard Worker av1_cdef_filter_fb(tmp_dst8, NULL, (1 << MAX_SB_SIZE_LOG2), in,
435*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->xdec[pli],
436*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->ydec[pli], dir, dirinit, var, pli,
437*77c1e3ccSAndroid Build Coastguard Worker dlist, cdef_count, pri_strength,
438*77c1e3ccSAndroid Build Coastguard Worker sec_strength + (sec_strength == 3),
439*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->damping, coeff_shift);
440*77c1e3ccSAndroid Build Coastguard Worker curr_sse =
441*77c1e3ccSAndroid Build Coastguard Worker aom_sse(&ref_buffer[buf_offset], ref_stride, tmp_dst8,
442*77c1e3ccSAndroid Build Coastguard Worker (1 << MAX_SB_SIZE_LOG2), block_size_wide[plane_bsize],
443*77c1e3ccSAndroid Build Coastguard Worker block_size_high[plane_bsize]);
444*77c1e3ccSAndroid Build Coastguard Worker }
445*77c1e3ccSAndroid Build Coastguard Worker } else {
446*77c1e3ccSAndroid Build Coastguard Worker // If few 8x8/4x4 blocks in CDEF block need to be filtered, filtering
447*77c1e3ccSAndroid Build Coastguard Worker // functions produce 8-bit output and the error is calculated in 8-bit
448*77c1e3ccSAndroid Build Coastguard Worker // domain
449*77c1e3ccSAndroid Build Coastguard Worker if (pri_strength == 0 && sec_strength == 0) {
450*77c1e3ccSAndroid Build Coastguard Worker int num_error_calc_filt_units = 1;
451*77c1e3ccSAndroid Build Coastguard Worker for (int bi = 0; bi < cdef_count; bi = bi + num_error_calc_filt_units) {
452*77c1e3ccSAndroid Build Coastguard Worker const uint8_t by = dlist[bi].by;
453*77c1e3ccSAndroid Build Coastguard Worker const uint8_t bx = dlist[bi].bx;
454*77c1e3ccSAndroid Build Coastguard Worker const int16_t by_pos = (by << bh_log2);
455*77c1e3ccSAndroid Build Coastguard Worker const int16_t bx_pos = (bx << bw_log2);
456*77c1e3ccSAndroid Build Coastguard Worker // Calculate the offset in the buffer based on block position
457*77c1e3ccSAndroid Build Coastguard Worker const FULLPEL_MV this_mv = { row + by_pos, col + bx_pos };
458*77c1e3ccSAndroid Build Coastguard Worker const int buf_offset = get_offset_from_fullmv(&this_mv, ref_stride);
459*77c1e3ccSAndroid Build Coastguard Worker num_error_calc_filt_units = get_error_calc_width_in_filt_units(
460*77c1e3ccSAndroid Build Coastguard Worker dlist, cdef_count, bi, pd->subsampling_x, pd->subsampling_y);
461*77c1e3ccSAndroid Build Coastguard Worker curr_sse += aom_sse(
462*77c1e3ccSAndroid Build Coastguard Worker &ref_buffer[buf_offset], ref_stride,
463*77c1e3ccSAndroid Build Coastguard Worker get_buf_from_fullmv(&pd->dst, &this_mv), pd->dst.stride,
464*77c1e3ccSAndroid Build Coastguard Worker num_error_calc_filt_units * (1 << bw_log2), (1 << bh_log2));
465*77c1e3ccSAndroid Build Coastguard Worker }
466*77c1e3ccSAndroid Build Coastguard Worker } else {
467*77c1e3ccSAndroid Build Coastguard Worker DECLARE_ALIGNED(32, uint8_t, tmp_dst8[1 << (MAX_SB_SIZE_LOG2 * 2)]);
468*77c1e3ccSAndroid Build Coastguard Worker av1_cdef_filter_fb(tmp_dst8, NULL, (1 << MAX_SB_SIZE_LOG2), in,
469*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->xdec[pli],
470*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->ydec[pli], dir, dirinit, var, pli,
471*77c1e3ccSAndroid Build Coastguard Worker dlist, cdef_count, pri_strength,
472*77c1e3ccSAndroid Build Coastguard Worker sec_strength + (sec_strength == 3),
473*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->damping, coeff_shift);
474*77c1e3ccSAndroid Build Coastguard Worker int num_error_calc_filt_units = 1;
475*77c1e3ccSAndroid Build Coastguard Worker for (int bi = 0; bi < cdef_count; bi = bi + num_error_calc_filt_units) {
476*77c1e3ccSAndroid Build Coastguard Worker const uint8_t by = dlist[bi].by;
477*77c1e3ccSAndroid Build Coastguard Worker const uint8_t bx = dlist[bi].bx;
478*77c1e3ccSAndroid Build Coastguard Worker const int16_t by_pos = (by << bh_log2);
479*77c1e3ccSAndroid Build Coastguard Worker const int16_t bx_pos = (bx << bw_log2);
480*77c1e3ccSAndroid Build Coastguard Worker // Calculate the offset in the buffer based on block position
481*77c1e3ccSAndroid Build Coastguard Worker const FULLPEL_MV this_mv = { row + by_pos, col + bx_pos };
482*77c1e3ccSAndroid Build Coastguard Worker const FULLPEL_MV tmp_buf_pos = { by_pos, bx_pos };
483*77c1e3ccSAndroid Build Coastguard Worker const int buf_offset = get_offset_from_fullmv(&this_mv, ref_stride);
484*77c1e3ccSAndroid Build Coastguard Worker const int tmp_buf_offset =
485*77c1e3ccSAndroid Build Coastguard Worker get_offset_from_fullmv(&tmp_buf_pos, (1 << MAX_SB_SIZE_LOG2));
486*77c1e3ccSAndroid Build Coastguard Worker num_error_calc_filt_units = get_error_calc_width_in_filt_units(
487*77c1e3ccSAndroid Build Coastguard Worker dlist, cdef_count, bi, pd->subsampling_x, pd->subsampling_y);
488*77c1e3ccSAndroid Build Coastguard Worker curr_sse += aom_sse(
489*77c1e3ccSAndroid Build Coastguard Worker &ref_buffer[buf_offset], ref_stride, &tmp_dst8[tmp_buf_offset],
490*77c1e3ccSAndroid Build Coastguard Worker (1 << MAX_SB_SIZE_LOG2),
491*77c1e3ccSAndroid Build Coastguard Worker num_error_calc_filt_units * (1 << bw_log2), (1 << bh_log2));
492*77c1e3ccSAndroid Build Coastguard Worker }
493*77c1e3ccSAndroid Build Coastguard Worker }
494*77c1e3ccSAndroid Build Coastguard Worker }
495*77c1e3ccSAndroid Build Coastguard Worker } else {
496*77c1e3ccSAndroid Build Coastguard Worker DECLARE_ALIGNED(32, uint16_t, tmp_dst[1 << (MAX_SB_SIZE_LOG2 * 2)]);
497*77c1e3ccSAndroid Build Coastguard Worker
498*77c1e3ccSAndroid Build Coastguard Worker av1_cdef_filter_fb(NULL, tmp_dst, CDEF_BSTRIDE, in,
499*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->xdec[pli], cdef_search_ctx->ydec[pli],
500*77c1e3ccSAndroid Build Coastguard Worker dir, dirinit, var, pli, dlist, cdef_count, pri_strength,
501*77c1e3ccSAndroid Build Coastguard Worker sec_strength + (sec_strength == 3),
502*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->damping, coeff_shift);
503*77c1e3ccSAndroid Build Coastguard Worker curr_sse = cdef_search_ctx->compute_cdef_dist_fn(
504*77c1e3ccSAndroid Build Coastguard Worker ref_buffer, ref_stride, tmp_dst, dlist, cdef_count,
505*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->bsize[pli], coeff_shift, row, col);
506*77c1e3ccSAndroid Build Coastguard Worker }
507*77c1e3ccSAndroid Build Coastguard Worker return curr_sse;
508*77c1e3ccSAndroid Build Coastguard Worker }
509*77c1e3ccSAndroid Build Coastguard Worker
510*77c1e3ccSAndroid Build Coastguard Worker // Calculates MSE at block level.
511*77c1e3ccSAndroid Build Coastguard Worker // Inputs:
512*77c1e3ccSAndroid Build Coastguard Worker // cdef_search_ctx: Pointer to the structure containing parameters related to
513*77c1e3ccSAndroid Build Coastguard Worker // CDEF search context.
514*77c1e3ccSAndroid Build Coastguard Worker // fbr: Row index in units of 64x64 block
515*77c1e3ccSAndroid Build Coastguard Worker // fbc: Column index in units of 64x64 block
516*77c1e3ccSAndroid Build Coastguard Worker // Returns:
517*77c1e3ccSAndroid Build Coastguard Worker // Nothing will be returned. Contents of cdef_search_ctx will be modified.
av1_cdef_mse_calc_block(CdefSearchCtx * cdef_search_ctx,struct aom_internal_error_info * error_info,int fbr,int fbc,int sb_count)518*77c1e3ccSAndroid Build Coastguard Worker void av1_cdef_mse_calc_block(CdefSearchCtx *cdef_search_ctx,
519*77c1e3ccSAndroid Build Coastguard Worker struct aom_internal_error_info *error_info,
520*77c1e3ccSAndroid Build Coastguard Worker int fbr, int fbc, int sb_count) {
521*77c1e3ccSAndroid Build Coastguard Worker // TODO(aomedia:3276): Pass error_info to the low-level functions as required
522*77c1e3ccSAndroid Build Coastguard Worker // in future to handle error propagation.
523*77c1e3ccSAndroid Build Coastguard Worker (void)error_info;
524*77c1e3ccSAndroid Build Coastguard Worker const CommonModeInfoParams *const mi_params = cdef_search_ctx->mi_params;
525*77c1e3ccSAndroid Build Coastguard Worker const YV12_BUFFER_CONFIG *ref = cdef_search_ctx->ref;
526*77c1e3ccSAndroid Build Coastguard Worker const int coeff_shift = cdef_search_ctx->coeff_shift;
527*77c1e3ccSAndroid Build Coastguard Worker const int *mi_wide_l2 = cdef_search_ctx->mi_wide_l2;
528*77c1e3ccSAndroid Build Coastguard Worker const int *mi_high_l2 = cdef_search_ctx->mi_high_l2;
529*77c1e3ccSAndroid Build Coastguard Worker
530*77c1e3ccSAndroid Build Coastguard Worker // Declare and initialize the temporary buffers.
531*77c1e3ccSAndroid Build Coastguard Worker DECLARE_ALIGNED(32, uint16_t, inbuf[CDEF_INBUF_SIZE]);
532*77c1e3ccSAndroid Build Coastguard Worker cdef_list dlist[MI_SIZE_128X128 * MI_SIZE_128X128];
533*77c1e3ccSAndroid Build Coastguard Worker int dir[CDEF_NBLOCKS][CDEF_NBLOCKS] = { { 0 } };
534*77c1e3ccSAndroid Build Coastguard Worker int var[CDEF_NBLOCKS][CDEF_NBLOCKS] = { { 0 } };
535*77c1e3ccSAndroid Build Coastguard Worker uint16_t *const in = inbuf + CDEF_VBORDER * CDEF_BSTRIDE + CDEF_HBORDER;
536*77c1e3ccSAndroid Build Coastguard Worker int nhb = AOMMIN(MI_SIZE_64X64, mi_params->mi_cols - MI_SIZE_64X64 * fbc);
537*77c1e3ccSAndroid Build Coastguard Worker int nvb = AOMMIN(MI_SIZE_64X64, mi_params->mi_rows - MI_SIZE_64X64 * fbr);
538*77c1e3ccSAndroid Build Coastguard Worker int hb_step = 1, vb_step = 1;
539*77c1e3ccSAndroid Build Coastguard Worker BLOCK_SIZE bs;
540*77c1e3ccSAndroid Build Coastguard Worker
541*77c1e3ccSAndroid Build Coastguard Worker const MB_MODE_INFO *const mbmi =
542*77c1e3ccSAndroid Build Coastguard Worker mi_params->mi_grid_base[MI_SIZE_64X64 * fbr * mi_params->mi_stride +
543*77c1e3ccSAndroid Build Coastguard Worker MI_SIZE_64X64 * fbc];
544*77c1e3ccSAndroid Build Coastguard Worker
545*77c1e3ccSAndroid Build Coastguard Worker uint8_t *ref_buffer[MAX_MB_PLANE] = { ref->y_buffer, ref->u_buffer,
546*77c1e3ccSAndroid Build Coastguard Worker ref->v_buffer };
547*77c1e3ccSAndroid Build Coastguard Worker int ref_stride[MAX_MB_PLANE] = { ref->y_stride, ref->uv_stride,
548*77c1e3ccSAndroid Build Coastguard Worker ref->uv_stride };
549*77c1e3ccSAndroid Build Coastguard Worker
550*77c1e3ccSAndroid Build Coastguard Worker if (mbmi->bsize == BLOCK_128X128 || mbmi->bsize == BLOCK_128X64 ||
551*77c1e3ccSAndroid Build Coastguard Worker mbmi->bsize == BLOCK_64X128) {
552*77c1e3ccSAndroid Build Coastguard Worker bs = mbmi->bsize;
553*77c1e3ccSAndroid Build Coastguard Worker if (bs == BLOCK_128X128 || bs == BLOCK_128X64) {
554*77c1e3ccSAndroid Build Coastguard Worker nhb = AOMMIN(MI_SIZE_128X128, mi_params->mi_cols - MI_SIZE_64X64 * fbc);
555*77c1e3ccSAndroid Build Coastguard Worker hb_step = 2;
556*77c1e3ccSAndroid Build Coastguard Worker }
557*77c1e3ccSAndroid Build Coastguard Worker if (bs == BLOCK_128X128 || bs == BLOCK_64X128) {
558*77c1e3ccSAndroid Build Coastguard Worker nvb = AOMMIN(MI_SIZE_128X128, mi_params->mi_rows - MI_SIZE_64X64 * fbr);
559*77c1e3ccSAndroid Build Coastguard Worker vb_step = 2;
560*77c1e3ccSAndroid Build Coastguard Worker }
561*77c1e3ccSAndroid Build Coastguard Worker } else {
562*77c1e3ccSAndroid Build Coastguard Worker bs = BLOCK_64X64;
563*77c1e3ccSAndroid Build Coastguard Worker }
564*77c1e3ccSAndroid Build Coastguard Worker // Get number of 8x8 blocks which are not skip. Cdef processing happens for
565*77c1e3ccSAndroid Build Coastguard Worker // 8x8 blocks which are not skip.
566*77c1e3ccSAndroid Build Coastguard Worker const int cdef_count = av1_cdef_compute_sb_list(
567*77c1e3ccSAndroid Build Coastguard Worker mi_params, fbr * MI_SIZE_64X64, fbc * MI_SIZE_64X64, dlist, bs);
568*77c1e3ccSAndroid Build Coastguard Worker const bool is_fb_on_frm_left_boundary = (fbc == 0);
569*77c1e3ccSAndroid Build Coastguard Worker const bool is_fb_on_frm_right_boundary =
570*77c1e3ccSAndroid Build Coastguard Worker (fbc + hb_step == cdef_search_ctx->nhfb);
571*77c1e3ccSAndroid Build Coastguard Worker const bool is_fb_on_frm_top_boundary = (fbr == 0);
572*77c1e3ccSAndroid Build Coastguard Worker const bool is_fb_on_frm_bottom_boundary =
573*77c1e3ccSAndroid Build Coastguard Worker (fbr + vb_step == cdef_search_ctx->nvfb);
574*77c1e3ccSAndroid Build Coastguard Worker const int yoff = CDEF_VBORDER * (!is_fb_on_frm_top_boundary);
575*77c1e3ccSAndroid Build Coastguard Worker const int xoff = CDEF_HBORDER * (!is_fb_on_frm_left_boundary);
576*77c1e3ccSAndroid Build Coastguard Worker int dirinit = 0;
577*77c1e3ccSAndroid Build Coastguard Worker for (int pli = 0; pli < cdef_search_ctx->num_planes; pli++) {
578*77c1e3ccSAndroid Build Coastguard Worker /* We avoid filtering the pixels for which some of the pixels to
579*77c1e3ccSAndroid Build Coastguard Worker average are outside the frame. We could change the filter instead,
580*77c1e3ccSAndroid Build Coastguard Worker but it would add special cases for any future vectorization. */
581*77c1e3ccSAndroid Build Coastguard Worker const int hfilt_size = (nhb << mi_wide_l2[pli]);
582*77c1e3ccSAndroid Build Coastguard Worker const int vfilt_size = (nvb << mi_high_l2[pli]);
583*77c1e3ccSAndroid Build Coastguard Worker const int ysize =
584*77c1e3ccSAndroid Build Coastguard Worker vfilt_size + CDEF_VBORDER * (!is_fb_on_frm_bottom_boundary) + yoff;
585*77c1e3ccSAndroid Build Coastguard Worker const int xsize =
586*77c1e3ccSAndroid Build Coastguard Worker hfilt_size + CDEF_HBORDER * (!is_fb_on_frm_right_boundary) + xoff;
587*77c1e3ccSAndroid Build Coastguard Worker const int row = fbr * MI_SIZE_64X64 << mi_high_l2[pli];
588*77c1e3ccSAndroid Build Coastguard Worker const int col = fbc * MI_SIZE_64X64 << mi_wide_l2[pli];
589*77c1e3ccSAndroid Build Coastguard Worker struct macroblockd_plane pd = cdef_search_ctx->plane[pli];
590*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->copy_fn(&in[(-yoff * CDEF_BSTRIDE - xoff)], CDEF_BSTRIDE,
591*77c1e3ccSAndroid Build Coastguard Worker pd.dst.buf, row - yoff, col - xoff, pd.dst.stride,
592*77c1e3ccSAndroid Build Coastguard Worker ysize, xsize);
593*77c1e3ccSAndroid Build Coastguard Worker fill_borders_for_fbs_on_frame_boundary(
594*77c1e3ccSAndroid Build Coastguard Worker inbuf, hfilt_size, vfilt_size, is_fb_on_frm_left_boundary,
595*77c1e3ccSAndroid Build Coastguard Worker is_fb_on_frm_right_boundary, is_fb_on_frm_top_boundary,
596*77c1e3ccSAndroid Build Coastguard Worker is_fb_on_frm_bottom_boundary);
597*77c1e3ccSAndroid Build Coastguard Worker for (int gi = 0; gi < cdef_search_ctx->total_strengths; gi++) {
598*77c1e3ccSAndroid Build Coastguard Worker int pri_strength, sec_strength;
599*77c1e3ccSAndroid Build Coastguard Worker get_cdef_filter_strengths(cdef_search_ctx->pick_method, &pri_strength,
600*77c1e3ccSAndroid Build Coastguard Worker &sec_strength, gi);
601*77c1e3ccSAndroid Build Coastguard Worker const uint64_t curr_mse = get_filt_error(
602*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx, &pd, dlist, dir, &dirinit, var, in, ref_buffer[pli],
603*77c1e3ccSAndroid Build Coastguard Worker ref_stride[pli], row, col, pri_strength, sec_strength, cdef_count,
604*77c1e3ccSAndroid Build Coastguard Worker pli, coeff_shift, bs);
605*77c1e3ccSAndroid Build Coastguard Worker if (pli < 2)
606*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->mse[pli][sb_count][gi] = curr_mse;
607*77c1e3ccSAndroid Build Coastguard Worker else
608*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->mse[1][sb_count][gi] += curr_mse;
609*77c1e3ccSAndroid Build Coastguard Worker }
610*77c1e3ccSAndroid Build Coastguard Worker }
611*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->sb_index[sb_count] =
612*77c1e3ccSAndroid Build Coastguard Worker MI_SIZE_64X64 * fbr * mi_params->mi_stride + MI_SIZE_64X64 * fbc;
613*77c1e3ccSAndroid Build Coastguard Worker }
614*77c1e3ccSAndroid Build Coastguard Worker
615*77c1e3ccSAndroid Build Coastguard Worker // MSE calculation at frame level.
616*77c1e3ccSAndroid Build Coastguard Worker // Inputs:
617*77c1e3ccSAndroid Build Coastguard Worker // cdef_search_ctx: Pointer to the structure containing parameters related to
618*77c1e3ccSAndroid Build Coastguard Worker // CDEF search context.
619*77c1e3ccSAndroid Build Coastguard Worker // Returns:
620*77c1e3ccSAndroid Build Coastguard Worker // Nothing will be returned. Contents of cdef_search_ctx will be modified.
cdef_mse_calc_frame(CdefSearchCtx * cdef_search_ctx,struct aom_internal_error_info * error_info)621*77c1e3ccSAndroid Build Coastguard Worker static void cdef_mse_calc_frame(CdefSearchCtx *cdef_search_ctx,
622*77c1e3ccSAndroid Build Coastguard Worker struct aom_internal_error_info *error_info) {
623*77c1e3ccSAndroid Build Coastguard Worker // Loop over each sb.
624*77c1e3ccSAndroid Build Coastguard Worker for (int fbr = 0; fbr < cdef_search_ctx->nvfb; ++fbr) {
625*77c1e3ccSAndroid Build Coastguard Worker for (int fbc = 0; fbc < cdef_search_ctx->nhfb; ++fbc) {
626*77c1e3ccSAndroid Build Coastguard Worker // Checks if cdef processing can be skipped for particular sb.
627*77c1e3ccSAndroid Build Coastguard Worker if (cdef_sb_skip(cdef_search_ctx->mi_params, fbr, fbc)) continue;
628*77c1e3ccSAndroid Build Coastguard Worker // Calculate mse for each sb and store the relevant sb index.
629*77c1e3ccSAndroid Build Coastguard Worker av1_cdef_mse_calc_block(cdef_search_ctx, error_info, fbr, fbc,
630*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->sb_count);
631*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->sb_count++;
632*77c1e3ccSAndroid Build Coastguard Worker }
633*77c1e3ccSAndroid Build Coastguard Worker }
634*77c1e3ccSAndroid Build Coastguard Worker }
635*77c1e3ccSAndroid Build Coastguard Worker
636*77c1e3ccSAndroid Build Coastguard Worker // Allocates memory for members of CdefSearchCtx.
637*77c1e3ccSAndroid Build Coastguard Worker // Inputs:
638*77c1e3ccSAndroid Build Coastguard Worker // cdef_search_ctx: Pointer to the structure containing parameters
639*77c1e3ccSAndroid Build Coastguard Worker // related to CDEF search context.
640*77c1e3ccSAndroid Build Coastguard Worker // Returns:
641*77c1e3ccSAndroid Build Coastguard Worker // Nothing will be returned. Contents of cdef_search_ctx will be modified.
cdef_alloc_data(AV1_COMMON * cm,CdefSearchCtx * cdef_search_ctx)642*77c1e3ccSAndroid Build Coastguard Worker static void cdef_alloc_data(AV1_COMMON *cm, CdefSearchCtx *cdef_search_ctx) {
643*77c1e3ccSAndroid Build Coastguard Worker const int nvfb = cdef_search_ctx->nvfb;
644*77c1e3ccSAndroid Build Coastguard Worker const int nhfb = cdef_search_ctx->nhfb;
645*77c1e3ccSAndroid Build Coastguard Worker CHECK_MEM_ERROR(
646*77c1e3ccSAndroid Build Coastguard Worker cm, cdef_search_ctx->sb_index,
647*77c1e3ccSAndroid Build Coastguard Worker aom_malloc(nvfb * nhfb * sizeof(cdef_search_ctx->sb_index[0])));
648*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->sb_count = 0;
649*77c1e3ccSAndroid Build Coastguard Worker CHECK_MEM_ERROR(cm, cdef_search_ctx->mse[0],
650*77c1e3ccSAndroid Build Coastguard Worker aom_malloc(sizeof(**cdef_search_ctx->mse) * nvfb * nhfb));
651*77c1e3ccSAndroid Build Coastguard Worker CHECK_MEM_ERROR(cm, cdef_search_ctx->mse[1],
652*77c1e3ccSAndroid Build Coastguard Worker aom_malloc(sizeof(**cdef_search_ctx->mse) * nvfb * nhfb));
653*77c1e3ccSAndroid Build Coastguard Worker }
654*77c1e3ccSAndroid Build Coastguard Worker
655*77c1e3ccSAndroid Build Coastguard Worker // Deallocates the memory allocated for members of CdefSearchCtx.
656*77c1e3ccSAndroid Build Coastguard Worker // Inputs:
657*77c1e3ccSAndroid Build Coastguard Worker // cdef_search_ctx: Pointer to the structure containing parameters
658*77c1e3ccSAndroid Build Coastguard Worker // related to CDEF search context.
659*77c1e3ccSAndroid Build Coastguard Worker // Returns:
660*77c1e3ccSAndroid Build Coastguard Worker // Nothing will be returned.
av1_cdef_dealloc_data(CdefSearchCtx * cdef_search_ctx)661*77c1e3ccSAndroid Build Coastguard Worker void av1_cdef_dealloc_data(CdefSearchCtx *cdef_search_ctx) {
662*77c1e3ccSAndroid Build Coastguard Worker if (cdef_search_ctx) {
663*77c1e3ccSAndroid Build Coastguard Worker aom_free(cdef_search_ctx->mse[0]);
664*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->mse[0] = NULL;
665*77c1e3ccSAndroid Build Coastguard Worker aom_free(cdef_search_ctx->mse[1]);
666*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->mse[1] = NULL;
667*77c1e3ccSAndroid Build Coastguard Worker aom_free(cdef_search_ctx->sb_index);
668*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->sb_index = NULL;
669*77c1e3ccSAndroid Build Coastguard Worker }
670*77c1e3ccSAndroid Build Coastguard Worker }
671*77c1e3ccSAndroid Build Coastguard Worker
672*77c1e3ccSAndroid Build Coastguard Worker // Initialize the parameters related to CDEF search context.
673*77c1e3ccSAndroid Build Coastguard Worker // Inputs:
674*77c1e3ccSAndroid Build Coastguard Worker // frame: Pointer to compressed frame buffer
675*77c1e3ccSAndroid Build Coastguard Worker // ref: Pointer to the frame buffer holding the source frame
676*77c1e3ccSAndroid Build Coastguard Worker // cm: Pointer to top level common structure
677*77c1e3ccSAndroid Build Coastguard Worker // xd: Pointer to common current coding block structure
678*77c1e3ccSAndroid Build Coastguard Worker // cdef_search_ctx: Pointer to the structure containing parameters related to
679*77c1e3ccSAndroid Build Coastguard Worker // CDEF search context.
680*77c1e3ccSAndroid Build Coastguard Worker // pick_method: Search method used to select CDEF parameters
681*77c1e3ccSAndroid Build Coastguard Worker // Returns:
682*77c1e3ccSAndroid Build Coastguard Worker // Nothing will be returned. Contents of cdef_search_ctx will be modified.
cdef_params_init(const YV12_BUFFER_CONFIG * frame,const YV12_BUFFER_CONFIG * ref,AV1_COMMON * cm,MACROBLOCKD * xd,CdefSearchCtx * cdef_search_ctx,CDEF_PICK_METHOD pick_method)683*77c1e3ccSAndroid Build Coastguard Worker static inline void cdef_params_init(const YV12_BUFFER_CONFIG *frame,
684*77c1e3ccSAndroid Build Coastguard Worker const YV12_BUFFER_CONFIG *ref,
685*77c1e3ccSAndroid Build Coastguard Worker AV1_COMMON *cm, MACROBLOCKD *xd,
686*77c1e3ccSAndroid Build Coastguard Worker CdefSearchCtx *cdef_search_ctx,
687*77c1e3ccSAndroid Build Coastguard Worker CDEF_PICK_METHOD pick_method) {
688*77c1e3ccSAndroid Build Coastguard Worker const CommonModeInfoParams *const mi_params = &cm->mi_params;
689*77c1e3ccSAndroid Build Coastguard Worker const int num_planes = av1_num_planes(cm);
690*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->mi_params = &cm->mi_params;
691*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->ref = ref;
692*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->nvfb =
693*77c1e3ccSAndroid Build Coastguard Worker (mi_params->mi_rows + MI_SIZE_64X64 - 1) / MI_SIZE_64X64;
694*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->nhfb =
695*77c1e3ccSAndroid Build Coastguard Worker (mi_params->mi_cols + MI_SIZE_64X64 - 1) / MI_SIZE_64X64;
696*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->coeff_shift = AOMMAX(cm->seq_params->bit_depth - 8, 0);
697*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->damping = 3 + (cm->quant_params.base_qindex >> 6);
698*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->total_strengths = nb_cdef_strengths[pick_method];
699*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->num_planes = num_planes;
700*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->pick_method = pick_method;
701*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->sb_count = 0;
702*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->use_highbitdepth = cm->seq_params->use_highbitdepth;
703*77c1e3ccSAndroid Build Coastguard Worker av1_setup_dst_planes(xd->plane, cm->seq_params->sb_size, frame, 0, 0, 0,
704*77c1e3ccSAndroid Build Coastguard Worker num_planes);
705*77c1e3ccSAndroid Build Coastguard Worker // Initialize plane wise information.
706*77c1e3ccSAndroid Build Coastguard Worker for (int pli = 0; pli < num_planes; pli++) {
707*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->xdec[pli] = xd->plane[pli].subsampling_x;
708*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->ydec[pli] = xd->plane[pli].subsampling_y;
709*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->bsize[pli] =
710*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->ydec[pli]
711*77c1e3ccSAndroid Build Coastguard Worker ? (cdef_search_ctx->xdec[pli] ? BLOCK_4X4 : BLOCK_8X4)
712*77c1e3ccSAndroid Build Coastguard Worker : (cdef_search_ctx->xdec[pli] ? BLOCK_4X8 : BLOCK_8X8);
713*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->mi_wide_l2[pli] =
714*77c1e3ccSAndroid Build Coastguard Worker MI_SIZE_LOG2 - xd->plane[pli].subsampling_x;
715*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->mi_high_l2[pli] =
716*77c1e3ccSAndroid Build Coastguard Worker MI_SIZE_LOG2 - xd->plane[pli].subsampling_y;
717*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->plane[pli] = xd->plane[pli];
718*77c1e3ccSAndroid Build Coastguard Worker }
719*77c1e3ccSAndroid Build Coastguard Worker // Function pointer initialization.
720*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_AV1_HIGHBITDEPTH
721*77c1e3ccSAndroid Build Coastguard Worker if (cm->seq_params->use_highbitdepth) {
722*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->copy_fn = av1_cdef_copy_sb8_16_highbd;
723*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->compute_cdef_dist_fn = compute_cdef_dist_highbd;
724*77c1e3ccSAndroid Build Coastguard Worker } else {
725*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->copy_fn = av1_cdef_copy_sb8_16_lowbd;
726*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->compute_cdef_dist_fn = compute_cdef_dist;
727*77c1e3ccSAndroid Build Coastguard Worker }
728*77c1e3ccSAndroid Build Coastguard Worker #else
729*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->copy_fn = av1_cdef_copy_sb8_16_lowbd;
730*77c1e3ccSAndroid Build Coastguard Worker cdef_search_ctx->compute_cdef_dist_fn = compute_cdef_dist;
731*77c1e3ccSAndroid Build Coastguard Worker #endif
732*77c1e3ccSAndroid Build Coastguard Worker }
733*77c1e3ccSAndroid Build Coastguard Worker
av1_pick_cdef_from_qp(AV1_COMMON * const cm,int skip_cdef,int is_screen_content)734*77c1e3ccSAndroid Build Coastguard Worker void av1_pick_cdef_from_qp(AV1_COMMON *const cm, int skip_cdef,
735*77c1e3ccSAndroid Build Coastguard Worker int is_screen_content) {
736*77c1e3ccSAndroid Build Coastguard Worker const int bd = cm->seq_params->bit_depth;
737*77c1e3ccSAndroid Build Coastguard Worker const int q =
738*77c1e3ccSAndroid Build Coastguard Worker av1_ac_quant_QTX(cm->quant_params.base_qindex, 0, bd) >> (bd - 8);
739*77c1e3ccSAndroid Build Coastguard Worker CdefInfo *const cdef_info = &cm->cdef_info;
740*77c1e3ccSAndroid Build Coastguard Worker // Check the speed feature to avoid extra signaling.
741*77c1e3ccSAndroid Build Coastguard Worker if (skip_cdef) {
742*77c1e3ccSAndroid Build Coastguard Worker cdef_info->cdef_bits = 1;
743*77c1e3ccSAndroid Build Coastguard Worker cdef_info->nb_cdef_strengths = 2;
744*77c1e3ccSAndroid Build Coastguard Worker } else {
745*77c1e3ccSAndroid Build Coastguard Worker cdef_info->cdef_bits = 0;
746*77c1e3ccSAndroid Build Coastguard Worker cdef_info->nb_cdef_strengths = 1;
747*77c1e3ccSAndroid Build Coastguard Worker }
748*77c1e3ccSAndroid Build Coastguard Worker cdef_info->cdef_damping = 3 + (cm->quant_params.base_qindex >> 6);
749*77c1e3ccSAndroid Build Coastguard Worker
750*77c1e3ccSAndroid Build Coastguard Worker int predicted_y_f1 = 0;
751*77c1e3ccSAndroid Build Coastguard Worker int predicted_y_f2 = 0;
752*77c1e3ccSAndroid Build Coastguard Worker int predicted_uv_f1 = 0;
753*77c1e3ccSAndroid Build Coastguard Worker int predicted_uv_f2 = 0;
754*77c1e3ccSAndroid Build Coastguard Worker if (is_screen_content) {
755*77c1e3ccSAndroid Build Coastguard Worker predicted_y_f1 =
756*77c1e3ccSAndroid Build Coastguard Worker (int)(5.88217781e-06 * q * q + 6.10391455e-03 * q + 9.95043102e-02);
757*77c1e3ccSAndroid Build Coastguard Worker predicted_y_f2 =
758*77c1e3ccSAndroid Build Coastguard Worker (int)(-7.79934857e-06 * q * q + 6.58957830e-03 * q + 8.81045025e-01);
759*77c1e3ccSAndroid Build Coastguard Worker predicted_uv_f1 =
760*77c1e3ccSAndroid Build Coastguard Worker (int)(-6.79500136e-06 * q * q + 1.02695586e-02 * q + 1.36126802e-01);
761*77c1e3ccSAndroid Build Coastguard Worker predicted_uv_f2 =
762*77c1e3ccSAndroid Build Coastguard Worker (int)(-9.99613695e-08 * q * q - 1.79361339e-05 * q + 1.17022324e+0);
763*77c1e3ccSAndroid Build Coastguard Worker predicted_y_f1 = clamp(predicted_y_f1, 0, 15);
764*77c1e3ccSAndroid Build Coastguard Worker predicted_y_f2 = clamp(predicted_y_f2, 0, 3);
765*77c1e3ccSAndroid Build Coastguard Worker predicted_uv_f1 = clamp(predicted_uv_f1, 0, 15);
766*77c1e3ccSAndroid Build Coastguard Worker predicted_uv_f2 = clamp(predicted_uv_f2, 0, 3);
767*77c1e3ccSAndroid Build Coastguard Worker } else {
768*77c1e3ccSAndroid Build Coastguard Worker if (!frame_is_intra_only(cm)) {
769*77c1e3ccSAndroid Build Coastguard Worker predicted_y_f1 = clamp((int)roundf(q * q * -0.0000023593946f +
770*77c1e3ccSAndroid Build Coastguard Worker q * 0.0068615186f + 0.02709886f),
771*77c1e3ccSAndroid Build Coastguard Worker 0, 15);
772*77c1e3ccSAndroid Build Coastguard Worker predicted_y_f2 = clamp((int)roundf(q * q * -0.00000057629734f +
773*77c1e3ccSAndroid Build Coastguard Worker q * 0.0013993345f + 0.03831067f),
774*77c1e3ccSAndroid Build Coastguard Worker 0, 3);
775*77c1e3ccSAndroid Build Coastguard Worker predicted_uv_f1 = clamp((int)roundf(q * q * -0.0000007095069f +
776*77c1e3ccSAndroid Build Coastguard Worker q * 0.0034628846f + 0.00887099f),
777*77c1e3ccSAndroid Build Coastguard Worker 0, 15);
778*77c1e3ccSAndroid Build Coastguard Worker predicted_uv_f2 = clamp((int)roundf(q * q * 0.00000023874085f +
779*77c1e3ccSAndroid Build Coastguard Worker q * 0.00028223585f + 0.05576307f),
780*77c1e3ccSAndroid Build Coastguard Worker 0, 3);
781*77c1e3ccSAndroid Build Coastguard Worker } else {
782*77c1e3ccSAndroid Build Coastguard Worker predicted_y_f1 = clamp(
783*77c1e3ccSAndroid Build Coastguard Worker (int)roundf(q * q * 0.0000033731974f + q * 0.008070594f + 0.0187634f),
784*77c1e3ccSAndroid Build Coastguard Worker 0, 15);
785*77c1e3ccSAndroid Build Coastguard Worker predicted_y_f2 = clamp((int)roundf(q * q * 0.0000029167343f +
786*77c1e3ccSAndroid Build Coastguard Worker q * 0.0027798624f + 0.0079405f),
787*77c1e3ccSAndroid Build Coastguard Worker 0, 3);
788*77c1e3ccSAndroid Build Coastguard Worker predicted_uv_f1 = clamp((int)roundf(q * q * -0.0000130790995f +
789*77c1e3ccSAndroid Build Coastguard Worker q * 0.012892405f - 0.00748388f),
790*77c1e3ccSAndroid Build Coastguard Worker 0, 15);
791*77c1e3ccSAndroid Build Coastguard Worker predicted_uv_f2 = clamp((int)roundf(q * q * 0.0000032651783f +
792*77c1e3ccSAndroid Build Coastguard Worker q * 0.00035520183f + 0.00228092f),
793*77c1e3ccSAndroid Build Coastguard Worker 0, 3);
794*77c1e3ccSAndroid Build Coastguard Worker }
795*77c1e3ccSAndroid Build Coastguard Worker }
796*77c1e3ccSAndroid Build Coastguard Worker cdef_info->cdef_strengths[0] =
797*77c1e3ccSAndroid Build Coastguard Worker predicted_y_f1 * CDEF_SEC_STRENGTHS + predicted_y_f2;
798*77c1e3ccSAndroid Build Coastguard Worker cdef_info->cdef_uv_strengths[0] =
799*77c1e3ccSAndroid Build Coastguard Worker predicted_uv_f1 * CDEF_SEC_STRENGTHS + predicted_uv_f2;
800*77c1e3ccSAndroid Build Coastguard Worker
801*77c1e3ccSAndroid Build Coastguard Worker // mbmi->cdef_strength is already set in the encoding stage. We don't need to
802*77c1e3ccSAndroid Build Coastguard Worker // set it again here.
803*77c1e3ccSAndroid Build Coastguard Worker if (skip_cdef) {
804*77c1e3ccSAndroid Build Coastguard Worker cdef_info->cdef_strengths[1] = 0;
805*77c1e3ccSAndroid Build Coastguard Worker cdef_info->cdef_uv_strengths[1] = 0;
806*77c1e3ccSAndroid Build Coastguard Worker return;
807*77c1e3ccSAndroid Build Coastguard Worker }
808*77c1e3ccSAndroid Build Coastguard Worker
809*77c1e3ccSAndroid Build Coastguard Worker const CommonModeInfoParams *const mi_params = &cm->mi_params;
810*77c1e3ccSAndroid Build Coastguard Worker const int nvfb = (mi_params->mi_rows + MI_SIZE_64X64 - 1) / MI_SIZE_64X64;
811*77c1e3ccSAndroid Build Coastguard Worker const int nhfb = (mi_params->mi_cols + MI_SIZE_64X64 - 1) / MI_SIZE_64X64;
812*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO **mbmi = mi_params->mi_grid_base;
813*77c1e3ccSAndroid Build Coastguard Worker // mbmi is NULL when real-time rate control library is used.
814*77c1e3ccSAndroid Build Coastguard Worker if (!mbmi) return;
815*77c1e3ccSAndroid Build Coastguard Worker for (int r = 0; r < nvfb; ++r) {
816*77c1e3ccSAndroid Build Coastguard Worker for (int c = 0; c < nhfb; ++c) {
817*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *current_mbmi = mbmi[MI_SIZE_64X64 * c];
818*77c1e3ccSAndroid Build Coastguard Worker current_mbmi->cdef_strength = 0;
819*77c1e3ccSAndroid Build Coastguard Worker }
820*77c1e3ccSAndroid Build Coastguard Worker mbmi += MI_SIZE_64X64 * mi_params->mi_stride;
821*77c1e3ccSAndroid Build Coastguard Worker }
822*77c1e3ccSAndroid Build Coastguard Worker }
823*77c1e3ccSAndroid Build Coastguard Worker
av1_cdef_search(AV1_COMP * cpi)824*77c1e3ccSAndroid Build Coastguard Worker void av1_cdef_search(AV1_COMP *cpi) {
825*77c1e3ccSAndroid Build Coastguard Worker AV1_COMMON *cm = &cpi->common;
826*77c1e3ccSAndroid Build Coastguard Worker CDEF_CONTROL cdef_control = cpi->oxcf.tool_cfg.cdef_control;
827*77c1e3ccSAndroid Build Coastguard Worker
828*77c1e3ccSAndroid Build Coastguard Worker assert(cdef_control != CDEF_NONE);
829*77c1e3ccSAndroid Build Coastguard Worker if (cdef_control == CDEF_REFERENCE && cpi->ppi->rtc_ref.non_reference_frame) {
830*77c1e3ccSAndroid Build Coastguard Worker CdefInfo *const cdef_info = &cm->cdef_info;
831*77c1e3ccSAndroid Build Coastguard Worker cdef_info->nb_cdef_strengths = 1;
832*77c1e3ccSAndroid Build Coastguard Worker cdef_info->cdef_bits = 0;
833*77c1e3ccSAndroid Build Coastguard Worker cdef_info->cdef_strengths[0] = 0;
834*77c1e3ccSAndroid Build Coastguard Worker cdef_info->cdef_uv_strengths[0] = 0;
835*77c1e3ccSAndroid Build Coastguard Worker return;
836*77c1e3ccSAndroid Build Coastguard Worker }
837*77c1e3ccSAndroid Build Coastguard Worker
838*77c1e3ccSAndroid Build Coastguard Worker // Indicate if external RC is used for testing
839*77c1e3ccSAndroid Build Coastguard Worker const int rtc_ext_rc = cpi->rc.rtc_external_ratectrl;
840*77c1e3ccSAndroid Build Coastguard Worker if (rtc_ext_rc) {
841*77c1e3ccSAndroid Build Coastguard Worker av1_pick_cdef_from_qp(cm, 0, 0);
842*77c1e3ccSAndroid Build Coastguard Worker return;
843*77c1e3ccSAndroid Build Coastguard Worker }
844*77c1e3ccSAndroid Build Coastguard Worker CDEF_PICK_METHOD pick_method = cpi->sf.lpf_sf.cdef_pick_method;
845*77c1e3ccSAndroid Build Coastguard Worker if (pick_method == CDEF_PICK_FROM_Q) {
846*77c1e3ccSAndroid Build Coastguard Worker const int use_screen_content_model =
847*77c1e3ccSAndroid Build Coastguard Worker cm->quant_params.base_qindex >
848*77c1e3ccSAndroid Build Coastguard Worker AOMMAX(cpi->sf.rt_sf.screen_content_cdef_filter_qindex_thresh,
849*77c1e3ccSAndroid Build Coastguard Worker cpi->rc.best_quality + 5) &&
850*77c1e3ccSAndroid Build Coastguard Worker cpi->oxcf.tune_cfg.content == AOM_CONTENT_SCREEN;
851*77c1e3ccSAndroid Build Coastguard Worker av1_pick_cdef_from_qp(cm, cpi->sf.rt_sf.skip_cdef_sb,
852*77c1e3ccSAndroid Build Coastguard Worker use_screen_content_model);
853*77c1e3ccSAndroid Build Coastguard Worker return;
854*77c1e3ccSAndroid Build Coastguard Worker }
855*77c1e3ccSAndroid Build Coastguard Worker const CommonModeInfoParams *const mi_params = &cm->mi_params;
856*77c1e3ccSAndroid Build Coastguard Worker const int damping = 3 + (cm->quant_params.base_qindex >> 6);
857*77c1e3ccSAndroid Build Coastguard Worker const int fast = (pick_method >= CDEF_FAST_SEARCH_LVL1 &&
858*77c1e3ccSAndroid Build Coastguard Worker pick_method <= CDEF_FAST_SEARCH_LVL5);
859*77c1e3ccSAndroid Build Coastguard Worker const int num_planes = av1_num_planes(cm);
860*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *xd = &cpi->td.mb.e_mbd;
861*77c1e3ccSAndroid Build Coastguard Worker
862*77c1e3ccSAndroid Build Coastguard Worker if (!cpi->cdef_search_ctx)
863*77c1e3ccSAndroid Build Coastguard Worker CHECK_MEM_ERROR(cm, cpi->cdef_search_ctx,
864*77c1e3ccSAndroid Build Coastguard Worker aom_malloc(sizeof(*cpi->cdef_search_ctx)));
865*77c1e3ccSAndroid Build Coastguard Worker CdefSearchCtx *cdef_search_ctx = cpi->cdef_search_ctx;
866*77c1e3ccSAndroid Build Coastguard Worker
867*77c1e3ccSAndroid Build Coastguard Worker // Initialize parameters related to CDEF search context.
868*77c1e3ccSAndroid Build Coastguard Worker cdef_params_init(&cm->cur_frame->buf, cpi->source, cm, xd, cdef_search_ctx,
869*77c1e3ccSAndroid Build Coastguard Worker pick_method);
870*77c1e3ccSAndroid Build Coastguard Worker // Allocate CDEF search context buffers.
871*77c1e3ccSAndroid Build Coastguard Worker cdef_alloc_data(cm, cdef_search_ctx);
872*77c1e3ccSAndroid Build Coastguard Worker // Frame level mse calculation.
873*77c1e3ccSAndroid Build Coastguard Worker if (cpi->mt_info.num_workers > 1) {
874*77c1e3ccSAndroid Build Coastguard Worker av1_cdef_mse_calc_frame_mt(cpi);
875*77c1e3ccSAndroid Build Coastguard Worker } else {
876*77c1e3ccSAndroid Build Coastguard Worker cdef_mse_calc_frame(cdef_search_ctx, cm->error);
877*77c1e3ccSAndroid Build Coastguard Worker }
878*77c1e3ccSAndroid Build Coastguard Worker
879*77c1e3ccSAndroid Build Coastguard Worker /* Search for different number of signaling bits. */
880*77c1e3ccSAndroid Build Coastguard Worker int nb_strength_bits = 0;
881*77c1e3ccSAndroid Build Coastguard Worker uint64_t best_rd = UINT64_MAX;
882*77c1e3ccSAndroid Build Coastguard Worker CdefInfo *const cdef_info = &cm->cdef_info;
883*77c1e3ccSAndroid Build Coastguard Worker int sb_count = cdef_search_ctx->sb_count;
884*77c1e3ccSAndroid Build Coastguard Worker uint64_t(*mse[2])[TOTAL_STRENGTHS];
885*77c1e3ccSAndroid Build Coastguard Worker mse[0] = cdef_search_ctx->mse[0];
886*77c1e3ccSAndroid Build Coastguard Worker mse[1] = cdef_search_ctx->mse[1];
887*77c1e3ccSAndroid Build Coastguard Worker /* Calculate the maximum number of bits required to signal CDEF strengths at
888*77c1e3ccSAndroid Build Coastguard Worker * block level */
889*77c1e3ccSAndroid Build Coastguard Worker const int total_strengths = nb_cdef_strengths[pick_method];
890*77c1e3ccSAndroid Build Coastguard Worker const int joint_strengths =
891*77c1e3ccSAndroid Build Coastguard Worker num_planes > 1 ? total_strengths * total_strengths : total_strengths;
892*77c1e3ccSAndroid Build Coastguard Worker const int max_signaling_bits =
893*77c1e3ccSAndroid Build Coastguard Worker joint_strengths == 1 ? 0 : get_msb(joint_strengths - 1) + 1;
894*77c1e3ccSAndroid Build Coastguard Worker int rdmult = cpi->td.mb.rdmult;
895*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i <= 3; i++) {
896*77c1e3ccSAndroid Build Coastguard Worker if (i > max_signaling_bits) break;
897*77c1e3ccSAndroid Build Coastguard Worker int best_lev0[CDEF_MAX_STRENGTHS] = { 0 };
898*77c1e3ccSAndroid Build Coastguard Worker int best_lev1[CDEF_MAX_STRENGTHS] = { 0 };
899*77c1e3ccSAndroid Build Coastguard Worker const int nb_strengths = 1 << i;
900*77c1e3ccSAndroid Build Coastguard Worker uint64_t tot_mse;
901*77c1e3ccSAndroid Build Coastguard Worker if (num_planes > 1) {
902*77c1e3ccSAndroid Build Coastguard Worker tot_mse = joint_strength_search_dual(best_lev0, best_lev1, nb_strengths,
903*77c1e3ccSAndroid Build Coastguard Worker mse, sb_count, pick_method);
904*77c1e3ccSAndroid Build Coastguard Worker } else {
905*77c1e3ccSAndroid Build Coastguard Worker tot_mse = joint_strength_search(best_lev0, nb_strengths, mse[0], sb_count,
906*77c1e3ccSAndroid Build Coastguard Worker pick_method);
907*77c1e3ccSAndroid Build Coastguard Worker }
908*77c1e3ccSAndroid Build Coastguard Worker
909*77c1e3ccSAndroid Build Coastguard Worker const int total_bits = sb_count * i + nb_strengths * CDEF_STRENGTH_BITS *
910*77c1e3ccSAndroid Build Coastguard Worker (num_planes > 1 ? 2 : 1);
911*77c1e3ccSAndroid Build Coastguard Worker const int rate_cost = av1_cost_literal(total_bits);
912*77c1e3ccSAndroid Build Coastguard Worker const uint64_t dist = tot_mse * 16;
913*77c1e3ccSAndroid Build Coastguard Worker const uint64_t rd = RDCOST(rdmult, rate_cost, dist);
914*77c1e3ccSAndroid Build Coastguard Worker if (rd < best_rd) {
915*77c1e3ccSAndroid Build Coastguard Worker best_rd = rd;
916*77c1e3ccSAndroid Build Coastguard Worker nb_strength_bits = i;
917*77c1e3ccSAndroid Build Coastguard Worker memcpy(cdef_info->cdef_strengths, best_lev0,
918*77c1e3ccSAndroid Build Coastguard Worker nb_strengths * sizeof(best_lev0[0]));
919*77c1e3ccSAndroid Build Coastguard Worker if (num_planes > 1) {
920*77c1e3ccSAndroid Build Coastguard Worker memcpy(cdef_info->cdef_uv_strengths, best_lev1,
921*77c1e3ccSAndroid Build Coastguard Worker nb_strengths * sizeof(best_lev1[0]));
922*77c1e3ccSAndroid Build Coastguard Worker }
923*77c1e3ccSAndroid Build Coastguard Worker }
924*77c1e3ccSAndroid Build Coastguard Worker }
925*77c1e3ccSAndroid Build Coastguard Worker
926*77c1e3ccSAndroid Build Coastguard Worker cdef_info->cdef_bits = nb_strength_bits;
927*77c1e3ccSAndroid Build Coastguard Worker cdef_info->nb_cdef_strengths = 1 << nb_strength_bits;
928*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < sb_count; i++) {
929*77c1e3ccSAndroid Build Coastguard Worker uint64_t best_mse = UINT64_MAX;
930*77c1e3ccSAndroid Build Coastguard Worker int best_gi = 0;
931*77c1e3ccSAndroid Build Coastguard Worker for (int gi = 0; gi < cdef_info->nb_cdef_strengths; gi++) {
932*77c1e3ccSAndroid Build Coastguard Worker uint64_t curr = mse[0][i][cdef_info->cdef_strengths[gi]];
933*77c1e3ccSAndroid Build Coastguard Worker if (num_planes > 1) curr += mse[1][i][cdef_info->cdef_uv_strengths[gi]];
934*77c1e3ccSAndroid Build Coastguard Worker if (curr < best_mse) {
935*77c1e3ccSAndroid Build Coastguard Worker best_gi = gi;
936*77c1e3ccSAndroid Build Coastguard Worker best_mse = curr;
937*77c1e3ccSAndroid Build Coastguard Worker }
938*77c1e3ccSAndroid Build Coastguard Worker }
939*77c1e3ccSAndroid Build Coastguard Worker mi_params->mi_grid_base[cdef_search_ctx->sb_index[i]]->cdef_strength =
940*77c1e3ccSAndroid Build Coastguard Worker best_gi;
941*77c1e3ccSAndroid Build Coastguard Worker }
942*77c1e3ccSAndroid Build Coastguard Worker if (fast) {
943*77c1e3ccSAndroid Build Coastguard Worker for (int j = 0; j < cdef_info->nb_cdef_strengths; j++) {
944*77c1e3ccSAndroid Build Coastguard Worker const int luma_strength = cdef_info->cdef_strengths[j];
945*77c1e3ccSAndroid Build Coastguard Worker const int chroma_strength = cdef_info->cdef_uv_strengths[j];
946*77c1e3ccSAndroid Build Coastguard Worker int pri_strength, sec_strength;
947*77c1e3ccSAndroid Build Coastguard Worker
948*77c1e3ccSAndroid Build Coastguard Worker STORE_CDEF_FILTER_STRENGTH(cdef_info->cdef_strengths[j], pick_method,
949*77c1e3ccSAndroid Build Coastguard Worker luma_strength);
950*77c1e3ccSAndroid Build Coastguard Worker STORE_CDEF_FILTER_STRENGTH(cdef_info->cdef_uv_strengths[j], pick_method,
951*77c1e3ccSAndroid Build Coastguard Worker chroma_strength);
952*77c1e3ccSAndroid Build Coastguard Worker }
953*77c1e3ccSAndroid Build Coastguard Worker }
954*77c1e3ccSAndroid Build Coastguard Worker
955*77c1e3ccSAndroid Build Coastguard Worker cdef_info->cdef_damping = damping;
956*77c1e3ccSAndroid Build Coastguard Worker // Deallocate CDEF search context buffers.
957*77c1e3ccSAndroid Build Coastguard Worker av1_cdef_dealloc_data(cdef_search_ctx);
958*77c1e3ccSAndroid Build Coastguard Worker }
959