1*77c1e3ccSAndroid Build Coastguard Worker /*
2*77c1e3ccSAndroid Build Coastguard Worker * Copyright (c) 2021, 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 "av1/encoder/txb_rdopt.h"
13*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/txb_rdopt_utils.h"
14*77c1e3ccSAndroid Build Coastguard Worker
15*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/idct.h"
16*77c1e3ccSAndroid Build Coastguard Worker
update_coeff_general(int * accu_rate,int64_t * accu_dist,int si,int eob,TX_SIZE tx_size,TX_CLASS tx_class,int bhl,int width,int64_t rdmult,int shift,int dc_sign_ctx,const int16_t * dequant,const int16_t * scan,const LV_MAP_COEFF_COST * txb_costs,const tran_low_t * tcoeff,tran_low_t * qcoeff,tran_low_t * dqcoeff,uint8_t * levels,const qm_val_t * iqmatrix,const qm_val_t * qmatrix)17*77c1e3ccSAndroid Build Coastguard Worker static inline void update_coeff_general(
18*77c1e3ccSAndroid Build Coastguard Worker int *accu_rate, int64_t *accu_dist, int si, int eob, TX_SIZE tx_size,
19*77c1e3ccSAndroid Build Coastguard Worker TX_CLASS tx_class, int bhl, int width, int64_t rdmult, int shift,
20*77c1e3ccSAndroid Build Coastguard Worker int dc_sign_ctx, const int16_t *dequant, const int16_t *scan,
21*77c1e3ccSAndroid Build Coastguard Worker const LV_MAP_COEFF_COST *txb_costs, const tran_low_t *tcoeff,
22*77c1e3ccSAndroid Build Coastguard Worker tran_low_t *qcoeff, tran_low_t *dqcoeff, uint8_t *levels,
23*77c1e3ccSAndroid Build Coastguard Worker const qm_val_t *iqmatrix, const qm_val_t *qmatrix) {
24*77c1e3ccSAndroid Build Coastguard Worker const int dqv = get_dqv(dequant, scan[si], iqmatrix);
25*77c1e3ccSAndroid Build Coastguard Worker const int ci = scan[si];
26*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t qc = qcoeff[ci];
27*77c1e3ccSAndroid Build Coastguard Worker const int is_last = si == (eob - 1);
28*77c1e3ccSAndroid Build Coastguard Worker const int coeff_ctx = get_lower_levels_ctx_general(
29*77c1e3ccSAndroid Build Coastguard Worker is_last, si, bhl, width, levels, ci, tx_size, tx_class);
30*77c1e3ccSAndroid Build Coastguard Worker if (qc == 0) {
31*77c1e3ccSAndroid Build Coastguard Worker *accu_rate += txb_costs->base_cost[coeff_ctx][0];
32*77c1e3ccSAndroid Build Coastguard Worker } else {
33*77c1e3ccSAndroid Build Coastguard Worker const int sign = (qc < 0) ? 1 : 0;
34*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t abs_qc = abs(qc);
35*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t tqc = tcoeff[ci];
36*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t dqc = dqcoeff[ci];
37*77c1e3ccSAndroid Build Coastguard Worker const int64_t dist = get_coeff_dist(tqc, dqc, shift, qmatrix, ci);
38*77c1e3ccSAndroid Build Coastguard Worker const int64_t dist0 = get_coeff_dist(tqc, 0, shift, qmatrix, ci);
39*77c1e3ccSAndroid Build Coastguard Worker const int rate =
40*77c1e3ccSAndroid Build Coastguard Worker get_coeff_cost_general(is_last, ci, abs_qc, sign, coeff_ctx,
41*77c1e3ccSAndroid Build Coastguard Worker dc_sign_ctx, txb_costs, bhl, tx_class, levels);
42*77c1e3ccSAndroid Build Coastguard Worker const int64_t rd = RDCOST(rdmult, rate, dist);
43*77c1e3ccSAndroid Build Coastguard Worker
44*77c1e3ccSAndroid Build Coastguard Worker tran_low_t qc_low, dqc_low;
45*77c1e3ccSAndroid Build Coastguard Worker tran_low_t abs_qc_low;
46*77c1e3ccSAndroid Build Coastguard Worker int64_t dist_low, rd_low;
47*77c1e3ccSAndroid Build Coastguard Worker int rate_low;
48*77c1e3ccSAndroid Build Coastguard Worker if (abs_qc == 1) {
49*77c1e3ccSAndroid Build Coastguard Worker abs_qc_low = qc_low = dqc_low = 0;
50*77c1e3ccSAndroid Build Coastguard Worker dist_low = dist0;
51*77c1e3ccSAndroid Build Coastguard Worker rate_low = txb_costs->base_cost[coeff_ctx][0];
52*77c1e3ccSAndroid Build Coastguard Worker } else {
53*77c1e3ccSAndroid Build Coastguard Worker get_qc_dqc_low(abs_qc, sign, dqv, shift, &qc_low, &dqc_low);
54*77c1e3ccSAndroid Build Coastguard Worker abs_qc_low = abs_qc - 1;
55*77c1e3ccSAndroid Build Coastguard Worker dist_low = get_coeff_dist(tqc, dqc_low, shift, qmatrix, ci);
56*77c1e3ccSAndroid Build Coastguard Worker rate_low =
57*77c1e3ccSAndroid Build Coastguard Worker get_coeff_cost_general(is_last, ci, abs_qc_low, sign, coeff_ctx,
58*77c1e3ccSAndroid Build Coastguard Worker dc_sign_ctx, txb_costs, bhl, tx_class, levels);
59*77c1e3ccSAndroid Build Coastguard Worker }
60*77c1e3ccSAndroid Build Coastguard Worker
61*77c1e3ccSAndroid Build Coastguard Worker rd_low = RDCOST(rdmult, rate_low, dist_low);
62*77c1e3ccSAndroid Build Coastguard Worker if (rd_low < rd) {
63*77c1e3ccSAndroid Build Coastguard Worker qcoeff[ci] = qc_low;
64*77c1e3ccSAndroid Build Coastguard Worker dqcoeff[ci] = dqc_low;
65*77c1e3ccSAndroid Build Coastguard Worker levels[get_padded_idx(ci, bhl)] = AOMMIN(abs_qc_low, INT8_MAX);
66*77c1e3ccSAndroid Build Coastguard Worker *accu_rate += rate_low;
67*77c1e3ccSAndroid Build Coastguard Worker *accu_dist += dist_low - dist0;
68*77c1e3ccSAndroid Build Coastguard Worker } else {
69*77c1e3ccSAndroid Build Coastguard Worker *accu_rate += rate;
70*77c1e3ccSAndroid Build Coastguard Worker *accu_dist += dist - dist0;
71*77c1e3ccSAndroid Build Coastguard Worker }
72*77c1e3ccSAndroid Build Coastguard Worker }
73*77c1e3ccSAndroid Build Coastguard Worker }
74*77c1e3ccSAndroid Build Coastguard Worker
update_coeff_simple(int * accu_rate,int si,int eob,TX_SIZE tx_size,TX_CLASS tx_class,int bhl,int64_t rdmult,int shift,const int16_t * dequant,const int16_t * scan,const LV_MAP_COEFF_COST * txb_costs,const tran_low_t * tcoeff,tran_low_t * qcoeff,tran_low_t * dqcoeff,uint8_t * levels,const qm_val_t * iqmatrix,const qm_val_t * qmatrix)75*77c1e3ccSAndroid Build Coastguard Worker static AOM_FORCE_INLINE void update_coeff_simple(
76*77c1e3ccSAndroid Build Coastguard Worker int *accu_rate, int si, int eob, TX_SIZE tx_size, TX_CLASS tx_class,
77*77c1e3ccSAndroid Build Coastguard Worker int bhl, int64_t rdmult, int shift, const int16_t *dequant,
78*77c1e3ccSAndroid Build Coastguard Worker const int16_t *scan, const LV_MAP_COEFF_COST *txb_costs,
79*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t *tcoeff, tran_low_t *qcoeff, tran_low_t *dqcoeff,
80*77c1e3ccSAndroid Build Coastguard Worker uint8_t *levels, const qm_val_t *iqmatrix, const qm_val_t *qmatrix) {
81*77c1e3ccSAndroid Build Coastguard Worker const int dqv = get_dqv(dequant, scan[si], iqmatrix);
82*77c1e3ccSAndroid Build Coastguard Worker (void)eob;
83*77c1e3ccSAndroid Build Coastguard Worker // this simple version assumes the coeff's scan_idx is not DC (scan_idx != 0)
84*77c1e3ccSAndroid Build Coastguard Worker // and not the last (scan_idx != eob - 1)
85*77c1e3ccSAndroid Build Coastguard Worker assert(si != eob - 1);
86*77c1e3ccSAndroid Build Coastguard Worker assert(si > 0);
87*77c1e3ccSAndroid Build Coastguard Worker const int ci = scan[si];
88*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t qc = qcoeff[ci];
89*77c1e3ccSAndroid Build Coastguard Worker const int coeff_ctx =
90*77c1e3ccSAndroid Build Coastguard Worker get_lower_levels_ctx(levels, ci, bhl, tx_size, tx_class);
91*77c1e3ccSAndroid Build Coastguard Worker if (qc == 0) {
92*77c1e3ccSAndroid Build Coastguard Worker *accu_rate += txb_costs->base_cost[coeff_ctx][0];
93*77c1e3ccSAndroid Build Coastguard Worker } else {
94*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t abs_qc = abs(qc);
95*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t abs_tqc = abs(tcoeff[ci]);
96*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t abs_dqc = abs(dqcoeff[ci]);
97*77c1e3ccSAndroid Build Coastguard Worker int rate_low = 0;
98*77c1e3ccSAndroid Build Coastguard Worker const int rate = get_two_coeff_cost_simple(
99*77c1e3ccSAndroid Build Coastguard Worker ci, abs_qc, coeff_ctx, txb_costs, bhl, tx_class, levels, &rate_low);
100*77c1e3ccSAndroid Build Coastguard Worker if (abs_dqc < abs_tqc) {
101*77c1e3ccSAndroid Build Coastguard Worker *accu_rate += rate;
102*77c1e3ccSAndroid Build Coastguard Worker return;
103*77c1e3ccSAndroid Build Coastguard Worker }
104*77c1e3ccSAndroid Build Coastguard Worker
105*77c1e3ccSAndroid Build Coastguard Worker const int64_t dist = get_coeff_dist(abs_tqc, abs_dqc, shift, qmatrix, ci);
106*77c1e3ccSAndroid Build Coastguard Worker const int64_t rd = RDCOST(rdmult, rate, dist);
107*77c1e3ccSAndroid Build Coastguard Worker
108*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t abs_qc_low = abs_qc - 1;
109*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t abs_dqc_low = (abs_qc_low * dqv) >> shift;
110*77c1e3ccSAndroid Build Coastguard Worker const int64_t dist_low =
111*77c1e3ccSAndroid Build Coastguard Worker get_coeff_dist(abs_tqc, abs_dqc_low, shift, qmatrix, ci);
112*77c1e3ccSAndroid Build Coastguard Worker const int64_t rd_low = RDCOST(rdmult, rate_low, dist_low);
113*77c1e3ccSAndroid Build Coastguard Worker
114*77c1e3ccSAndroid Build Coastguard Worker if (rd_low < rd) {
115*77c1e3ccSAndroid Build Coastguard Worker const int sign = (qc < 0) ? 1 : 0;
116*77c1e3ccSAndroid Build Coastguard Worker qcoeff[ci] = (-sign ^ abs_qc_low) + sign;
117*77c1e3ccSAndroid Build Coastguard Worker dqcoeff[ci] = (-sign ^ abs_dqc_low) + sign;
118*77c1e3ccSAndroid Build Coastguard Worker levels[get_padded_idx(ci, bhl)] = AOMMIN(abs_qc_low, INT8_MAX);
119*77c1e3ccSAndroid Build Coastguard Worker *accu_rate += rate_low;
120*77c1e3ccSAndroid Build Coastguard Worker } else {
121*77c1e3ccSAndroid Build Coastguard Worker *accu_rate += rate;
122*77c1e3ccSAndroid Build Coastguard Worker }
123*77c1e3ccSAndroid Build Coastguard Worker }
124*77c1e3ccSAndroid Build Coastguard Worker }
125*77c1e3ccSAndroid Build Coastguard Worker
update_coeff_eob(int * accu_rate,int64_t * accu_dist,int * eob,int * nz_num,int * nz_ci,int si,TX_SIZE tx_size,TX_CLASS tx_class,int bhl,int width,int dc_sign_ctx,int64_t rdmult,int shift,const int16_t * dequant,const int16_t * scan,const LV_MAP_EOB_COST * txb_eob_costs,const LV_MAP_COEFF_COST * txb_costs,const tran_low_t * tcoeff,tran_low_t * qcoeff,tran_low_t * dqcoeff,uint8_t * levels,int sharpness,const qm_val_t * iqmatrix,const qm_val_t * qmatrix)126*77c1e3ccSAndroid Build Coastguard Worker static AOM_FORCE_INLINE void update_coeff_eob(
127*77c1e3ccSAndroid Build Coastguard Worker int *accu_rate, int64_t *accu_dist, int *eob, int *nz_num, int *nz_ci,
128*77c1e3ccSAndroid Build Coastguard Worker int si, TX_SIZE tx_size, TX_CLASS tx_class, int bhl, int width,
129*77c1e3ccSAndroid Build Coastguard Worker int dc_sign_ctx, int64_t rdmult, int shift, const int16_t *dequant,
130*77c1e3ccSAndroid Build Coastguard Worker const int16_t *scan, const LV_MAP_EOB_COST *txb_eob_costs,
131*77c1e3ccSAndroid Build Coastguard Worker const LV_MAP_COEFF_COST *txb_costs, const tran_low_t *tcoeff,
132*77c1e3ccSAndroid Build Coastguard Worker tran_low_t *qcoeff, tran_low_t *dqcoeff, uint8_t *levels, int sharpness,
133*77c1e3ccSAndroid Build Coastguard Worker const qm_val_t *iqmatrix, const qm_val_t *qmatrix) {
134*77c1e3ccSAndroid Build Coastguard Worker const int dqv = get_dqv(dequant, scan[si], iqmatrix);
135*77c1e3ccSAndroid Build Coastguard Worker assert(si != *eob - 1);
136*77c1e3ccSAndroid Build Coastguard Worker const int ci = scan[si];
137*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t qc = qcoeff[ci];
138*77c1e3ccSAndroid Build Coastguard Worker const int coeff_ctx =
139*77c1e3ccSAndroid Build Coastguard Worker get_lower_levels_ctx(levels, ci, bhl, tx_size, tx_class);
140*77c1e3ccSAndroid Build Coastguard Worker if (qc == 0) {
141*77c1e3ccSAndroid Build Coastguard Worker *accu_rate += txb_costs->base_cost[coeff_ctx][0];
142*77c1e3ccSAndroid Build Coastguard Worker } else {
143*77c1e3ccSAndroid Build Coastguard Worker int lower_level = 0;
144*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t abs_qc = abs(qc);
145*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t tqc = tcoeff[ci];
146*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t dqc = dqcoeff[ci];
147*77c1e3ccSAndroid Build Coastguard Worker const int sign = (qc < 0) ? 1 : 0;
148*77c1e3ccSAndroid Build Coastguard Worker const int64_t dist0 = get_coeff_dist(tqc, 0, shift, qmatrix, ci);
149*77c1e3ccSAndroid Build Coastguard Worker int64_t dist = get_coeff_dist(tqc, dqc, shift, qmatrix, ci) - dist0;
150*77c1e3ccSAndroid Build Coastguard Worker int rate =
151*77c1e3ccSAndroid Build Coastguard Worker get_coeff_cost_general(0, ci, abs_qc, sign, coeff_ctx, dc_sign_ctx,
152*77c1e3ccSAndroid Build Coastguard Worker txb_costs, bhl, tx_class, levels);
153*77c1e3ccSAndroid Build Coastguard Worker int64_t rd = RDCOST(rdmult, *accu_rate + rate, *accu_dist + dist);
154*77c1e3ccSAndroid Build Coastguard Worker
155*77c1e3ccSAndroid Build Coastguard Worker tran_low_t qc_low, dqc_low;
156*77c1e3ccSAndroid Build Coastguard Worker tran_low_t abs_qc_low;
157*77c1e3ccSAndroid Build Coastguard Worker int64_t dist_low, rd_low;
158*77c1e3ccSAndroid Build Coastguard Worker int rate_low;
159*77c1e3ccSAndroid Build Coastguard Worker
160*77c1e3ccSAndroid Build Coastguard Worker if (abs_qc == 1) {
161*77c1e3ccSAndroid Build Coastguard Worker abs_qc_low = 0;
162*77c1e3ccSAndroid Build Coastguard Worker dqc_low = qc_low = 0;
163*77c1e3ccSAndroid Build Coastguard Worker dist_low = 0;
164*77c1e3ccSAndroid Build Coastguard Worker rate_low = txb_costs->base_cost[coeff_ctx][0];
165*77c1e3ccSAndroid Build Coastguard Worker rd_low = RDCOST(rdmult, *accu_rate + rate_low, *accu_dist);
166*77c1e3ccSAndroid Build Coastguard Worker } else {
167*77c1e3ccSAndroid Build Coastguard Worker get_qc_dqc_low(abs_qc, sign, dqv, shift, &qc_low, &dqc_low);
168*77c1e3ccSAndroid Build Coastguard Worker abs_qc_low = abs_qc - 1;
169*77c1e3ccSAndroid Build Coastguard Worker dist_low = get_coeff_dist(tqc, dqc_low, shift, qmatrix, ci) - dist0;
170*77c1e3ccSAndroid Build Coastguard Worker rate_low =
171*77c1e3ccSAndroid Build Coastguard Worker get_coeff_cost_general(0, ci, abs_qc_low, sign, coeff_ctx,
172*77c1e3ccSAndroid Build Coastguard Worker dc_sign_ctx, txb_costs, bhl, tx_class, levels);
173*77c1e3ccSAndroid Build Coastguard Worker rd_low = RDCOST(rdmult, *accu_rate + rate_low, *accu_dist + dist_low);
174*77c1e3ccSAndroid Build Coastguard Worker }
175*77c1e3ccSAndroid Build Coastguard Worker
176*77c1e3ccSAndroid Build Coastguard Worker int lower_level_new_eob = 0;
177*77c1e3ccSAndroid Build Coastguard Worker const int new_eob = si + 1;
178*77c1e3ccSAndroid Build Coastguard Worker const int coeff_ctx_new_eob = get_lower_levels_ctx_eob(bhl, width, si);
179*77c1e3ccSAndroid Build Coastguard Worker const int new_eob_cost =
180*77c1e3ccSAndroid Build Coastguard Worker get_eob_cost(new_eob, txb_eob_costs, txb_costs, tx_class);
181*77c1e3ccSAndroid Build Coastguard Worker int rate_coeff_eob =
182*77c1e3ccSAndroid Build Coastguard Worker new_eob_cost + get_coeff_cost_eob(ci, abs_qc, sign, coeff_ctx_new_eob,
183*77c1e3ccSAndroid Build Coastguard Worker dc_sign_ctx, txb_costs, bhl,
184*77c1e3ccSAndroid Build Coastguard Worker tx_class);
185*77c1e3ccSAndroid Build Coastguard Worker int64_t dist_new_eob = dist;
186*77c1e3ccSAndroid Build Coastguard Worker int64_t rd_new_eob = RDCOST(rdmult, rate_coeff_eob, dist_new_eob);
187*77c1e3ccSAndroid Build Coastguard Worker
188*77c1e3ccSAndroid Build Coastguard Worker if (abs_qc_low > 0) {
189*77c1e3ccSAndroid Build Coastguard Worker const int rate_coeff_eob_low =
190*77c1e3ccSAndroid Build Coastguard Worker new_eob_cost + get_coeff_cost_eob(ci, abs_qc_low, sign,
191*77c1e3ccSAndroid Build Coastguard Worker coeff_ctx_new_eob, dc_sign_ctx,
192*77c1e3ccSAndroid Build Coastguard Worker txb_costs, bhl, tx_class);
193*77c1e3ccSAndroid Build Coastguard Worker const int64_t dist_new_eob_low = dist_low;
194*77c1e3ccSAndroid Build Coastguard Worker const int64_t rd_new_eob_low =
195*77c1e3ccSAndroid Build Coastguard Worker RDCOST(rdmult, rate_coeff_eob_low, dist_new_eob_low);
196*77c1e3ccSAndroid Build Coastguard Worker if (rd_new_eob_low < rd_new_eob) {
197*77c1e3ccSAndroid Build Coastguard Worker lower_level_new_eob = 1;
198*77c1e3ccSAndroid Build Coastguard Worker rd_new_eob = rd_new_eob_low;
199*77c1e3ccSAndroid Build Coastguard Worker rate_coeff_eob = rate_coeff_eob_low;
200*77c1e3ccSAndroid Build Coastguard Worker dist_new_eob = dist_new_eob_low;
201*77c1e3ccSAndroid Build Coastguard Worker }
202*77c1e3ccSAndroid Build Coastguard Worker }
203*77c1e3ccSAndroid Build Coastguard Worker
204*77c1e3ccSAndroid Build Coastguard Worker if (sharpness == 0 || abs_qc > 1) {
205*77c1e3ccSAndroid Build Coastguard Worker if (rd_low < rd) {
206*77c1e3ccSAndroid Build Coastguard Worker lower_level = 1;
207*77c1e3ccSAndroid Build Coastguard Worker rd = rd_low;
208*77c1e3ccSAndroid Build Coastguard Worker rate = rate_low;
209*77c1e3ccSAndroid Build Coastguard Worker dist = dist_low;
210*77c1e3ccSAndroid Build Coastguard Worker }
211*77c1e3ccSAndroid Build Coastguard Worker }
212*77c1e3ccSAndroid Build Coastguard Worker
213*77c1e3ccSAndroid Build Coastguard Worker if (sharpness == 0 && rd_new_eob < rd) {
214*77c1e3ccSAndroid Build Coastguard Worker for (int ni = 0; ni < *nz_num; ++ni) {
215*77c1e3ccSAndroid Build Coastguard Worker int last_ci = nz_ci[ni];
216*77c1e3ccSAndroid Build Coastguard Worker levels[get_padded_idx(last_ci, bhl)] = 0;
217*77c1e3ccSAndroid Build Coastguard Worker qcoeff[last_ci] = 0;
218*77c1e3ccSAndroid Build Coastguard Worker dqcoeff[last_ci] = 0;
219*77c1e3ccSAndroid Build Coastguard Worker }
220*77c1e3ccSAndroid Build Coastguard Worker *eob = new_eob;
221*77c1e3ccSAndroid Build Coastguard Worker *nz_num = 0;
222*77c1e3ccSAndroid Build Coastguard Worker *accu_rate = rate_coeff_eob;
223*77c1e3ccSAndroid Build Coastguard Worker *accu_dist = dist_new_eob;
224*77c1e3ccSAndroid Build Coastguard Worker lower_level = lower_level_new_eob;
225*77c1e3ccSAndroid Build Coastguard Worker } else {
226*77c1e3ccSAndroid Build Coastguard Worker *accu_rate += rate;
227*77c1e3ccSAndroid Build Coastguard Worker *accu_dist += dist;
228*77c1e3ccSAndroid Build Coastguard Worker }
229*77c1e3ccSAndroid Build Coastguard Worker
230*77c1e3ccSAndroid Build Coastguard Worker if (lower_level) {
231*77c1e3ccSAndroid Build Coastguard Worker qcoeff[ci] = qc_low;
232*77c1e3ccSAndroid Build Coastguard Worker dqcoeff[ci] = dqc_low;
233*77c1e3ccSAndroid Build Coastguard Worker levels[get_padded_idx(ci, bhl)] = AOMMIN(abs_qc_low, INT8_MAX);
234*77c1e3ccSAndroid Build Coastguard Worker }
235*77c1e3ccSAndroid Build Coastguard Worker if (qcoeff[ci]) {
236*77c1e3ccSAndroid Build Coastguard Worker nz_ci[*nz_num] = ci;
237*77c1e3ccSAndroid Build Coastguard Worker ++*nz_num;
238*77c1e3ccSAndroid Build Coastguard Worker }
239*77c1e3ccSAndroid Build Coastguard Worker }
240*77c1e3ccSAndroid Build Coastguard Worker }
241*77c1e3ccSAndroid Build Coastguard Worker
update_skip(int * accu_rate,int64_t accu_dist,int * eob,int nz_num,int * nz_ci,int64_t rdmult,int skip_cost,int non_skip_cost,tran_low_t * qcoeff,tran_low_t * dqcoeff)242*77c1e3ccSAndroid Build Coastguard Worker static inline void update_skip(int *accu_rate, int64_t accu_dist, int *eob,
243*77c1e3ccSAndroid Build Coastguard Worker int nz_num, int *nz_ci, int64_t rdmult,
244*77c1e3ccSAndroid Build Coastguard Worker int skip_cost, int non_skip_cost,
245*77c1e3ccSAndroid Build Coastguard Worker tran_low_t *qcoeff, tran_low_t *dqcoeff) {
246*77c1e3ccSAndroid Build Coastguard Worker const int64_t rd = RDCOST(rdmult, *accu_rate + non_skip_cost, accu_dist);
247*77c1e3ccSAndroid Build Coastguard Worker const int64_t rd_new_eob = RDCOST(rdmult, skip_cost, 0);
248*77c1e3ccSAndroid Build Coastguard Worker if (rd_new_eob < rd) {
249*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < nz_num; ++i) {
250*77c1e3ccSAndroid Build Coastguard Worker const int ci = nz_ci[i];
251*77c1e3ccSAndroid Build Coastguard Worker qcoeff[ci] = 0;
252*77c1e3ccSAndroid Build Coastguard Worker dqcoeff[ci] = 0;
253*77c1e3ccSAndroid Build Coastguard Worker // no need to set up levels because this is the last step
254*77c1e3ccSAndroid Build Coastguard Worker // levels[get_padded_idx(ci, bhl)] = 0;
255*77c1e3ccSAndroid Build Coastguard Worker }
256*77c1e3ccSAndroid Build Coastguard Worker *accu_rate = 0;
257*77c1e3ccSAndroid Build Coastguard Worker *eob = 0;
258*77c1e3ccSAndroid Build Coastguard Worker }
259*77c1e3ccSAndroid Build Coastguard Worker }
260*77c1e3ccSAndroid Build Coastguard Worker
261*77c1e3ccSAndroid Build Coastguard Worker // TODO(angiebird): use this function whenever it's possible
get_tx_type_cost(const MACROBLOCK * x,const MACROBLOCKD * xd,int plane,TX_SIZE tx_size,TX_TYPE tx_type,int reduced_tx_set_used)262*77c1e3ccSAndroid Build Coastguard Worker static int get_tx_type_cost(const MACROBLOCK *x, const MACROBLOCKD *xd,
263*77c1e3ccSAndroid Build Coastguard Worker int plane, TX_SIZE tx_size, TX_TYPE tx_type,
264*77c1e3ccSAndroid Build Coastguard Worker int reduced_tx_set_used) {
265*77c1e3ccSAndroid Build Coastguard Worker if (plane > 0) return 0;
266*77c1e3ccSAndroid Build Coastguard Worker
267*77c1e3ccSAndroid Build Coastguard Worker const TX_SIZE square_tx_size = txsize_sqr_map[tx_size];
268*77c1e3ccSAndroid Build Coastguard Worker
269*77c1e3ccSAndroid Build Coastguard Worker const MB_MODE_INFO *mbmi = xd->mi[0];
270*77c1e3ccSAndroid Build Coastguard Worker const int is_inter = is_inter_block(mbmi);
271*77c1e3ccSAndroid Build Coastguard Worker if (get_ext_tx_types(tx_size, is_inter, reduced_tx_set_used) > 1 &&
272*77c1e3ccSAndroid Build Coastguard Worker !xd->lossless[xd->mi[0]->segment_id]) {
273*77c1e3ccSAndroid Build Coastguard Worker const int ext_tx_set =
274*77c1e3ccSAndroid Build Coastguard Worker get_ext_tx_set(tx_size, is_inter, reduced_tx_set_used);
275*77c1e3ccSAndroid Build Coastguard Worker if (is_inter) {
276*77c1e3ccSAndroid Build Coastguard Worker if (ext_tx_set > 0)
277*77c1e3ccSAndroid Build Coastguard Worker return x->mode_costs
278*77c1e3ccSAndroid Build Coastguard Worker .inter_tx_type_costs[ext_tx_set][square_tx_size][tx_type];
279*77c1e3ccSAndroid Build Coastguard Worker } else {
280*77c1e3ccSAndroid Build Coastguard Worker if (ext_tx_set > 0) {
281*77c1e3ccSAndroid Build Coastguard Worker PREDICTION_MODE intra_dir;
282*77c1e3ccSAndroid Build Coastguard Worker if (mbmi->filter_intra_mode_info.use_filter_intra)
283*77c1e3ccSAndroid Build Coastguard Worker intra_dir = fimode_to_intradir[mbmi->filter_intra_mode_info
284*77c1e3ccSAndroid Build Coastguard Worker .filter_intra_mode];
285*77c1e3ccSAndroid Build Coastguard Worker else
286*77c1e3ccSAndroid Build Coastguard Worker intra_dir = mbmi->mode;
287*77c1e3ccSAndroid Build Coastguard Worker return x->mode_costs.intra_tx_type_costs[ext_tx_set][square_tx_size]
288*77c1e3ccSAndroid Build Coastguard Worker [intra_dir][tx_type];
289*77c1e3ccSAndroid Build Coastguard Worker }
290*77c1e3ccSAndroid Build Coastguard Worker }
291*77c1e3ccSAndroid Build Coastguard Worker }
292*77c1e3ccSAndroid Build Coastguard Worker return 0;
293*77c1e3ccSAndroid Build Coastguard Worker }
294*77c1e3ccSAndroid Build Coastguard Worker
av1_optimize_txb(const struct AV1_COMP * cpi,MACROBLOCK * x,int plane,int block,TX_SIZE tx_size,TX_TYPE tx_type,const TXB_CTX * const txb_ctx,int * rate_cost,int sharpness)295*77c1e3ccSAndroid Build Coastguard Worker int av1_optimize_txb(const struct AV1_COMP *cpi, MACROBLOCK *x, int plane,
296*77c1e3ccSAndroid Build Coastguard Worker int block, TX_SIZE tx_size, TX_TYPE tx_type,
297*77c1e3ccSAndroid Build Coastguard Worker const TXB_CTX *const txb_ctx, int *rate_cost,
298*77c1e3ccSAndroid Build Coastguard Worker int sharpness) {
299*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *xd = &x->e_mbd;
300*77c1e3ccSAndroid Build Coastguard Worker const struct macroblock_plane *p = &x->plane[plane];
301*77c1e3ccSAndroid Build Coastguard Worker const SCAN_ORDER *scan_order = get_scan(tx_size, tx_type);
302*77c1e3ccSAndroid Build Coastguard Worker const int16_t *scan = scan_order->scan;
303*77c1e3ccSAndroid Build Coastguard Worker const int shift = av1_get_tx_scale(tx_size);
304*77c1e3ccSAndroid Build Coastguard Worker int eob = p->eobs[block];
305*77c1e3ccSAndroid Build Coastguard Worker const int16_t *dequant = p->dequant_QTX;
306*77c1e3ccSAndroid Build Coastguard Worker const qm_val_t *iqmatrix =
307*77c1e3ccSAndroid Build Coastguard Worker av1_get_iqmatrix(&cpi->common.quant_params, xd, plane, tx_size, tx_type);
308*77c1e3ccSAndroid Build Coastguard Worker const qm_val_t *qmatrix =
309*77c1e3ccSAndroid Build Coastguard Worker cpi->oxcf.tune_cfg.dist_metric == AOM_DIST_METRIC_QM_PSNR
310*77c1e3ccSAndroid Build Coastguard Worker ? av1_get_qmatrix(&cpi->common.quant_params, xd, plane, tx_size,
311*77c1e3ccSAndroid Build Coastguard Worker tx_type)
312*77c1e3ccSAndroid Build Coastguard Worker : NULL;
313*77c1e3ccSAndroid Build Coastguard Worker const int block_offset = BLOCK_OFFSET(block);
314*77c1e3ccSAndroid Build Coastguard Worker tran_low_t *qcoeff = p->qcoeff + block_offset;
315*77c1e3ccSAndroid Build Coastguard Worker tran_low_t *dqcoeff = p->dqcoeff + block_offset;
316*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t *tcoeff = p->coeff + block_offset;
317*77c1e3ccSAndroid Build Coastguard Worker const CoeffCosts *coeff_costs = &x->coeff_costs;
318*77c1e3ccSAndroid Build Coastguard Worker
319*77c1e3ccSAndroid Build Coastguard Worker // This function is not called if eob = 0.
320*77c1e3ccSAndroid Build Coastguard Worker assert(eob > 0);
321*77c1e3ccSAndroid Build Coastguard Worker
322*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *cm = &cpi->common;
323*77c1e3ccSAndroid Build Coastguard Worker const PLANE_TYPE plane_type = get_plane_type(plane);
324*77c1e3ccSAndroid Build Coastguard Worker const TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
325*77c1e3ccSAndroid Build Coastguard Worker const TX_CLASS tx_class = tx_type_to_class[tx_type];
326*77c1e3ccSAndroid Build Coastguard Worker const MB_MODE_INFO *mbmi = xd->mi[0];
327*77c1e3ccSAndroid Build Coastguard Worker const int bhl = get_txb_bhl(tx_size);
328*77c1e3ccSAndroid Build Coastguard Worker const int width = get_txb_wide(tx_size);
329*77c1e3ccSAndroid Build Coastguard Worker const int height = get_txb_high(tx_size);
330*77c1e3ccSAndroid Build Coastguard Worker assert(height == (1 << bhl));
331*77c1e3ccSAndroid Build Coastguard Worker const int is_inter = is_inter_block(mbmi);
332*77c1e3ccSAndroid Build Coastguard Worker const LV_MAP_COEFF_COST *txb_costs =
333*77c1e3ccSAndroid Build Coastguard Worker &coeff_costs->coeff_costs[txs_ctx][plane_type];
334*77c1e3ccSAndroid Build Coastguard Worker const int eob_multi_size = txsize_log2_minus4[tx_size];
335*77c1e3ccSAndroid Build Coastguard Worker const LV_MAP_EOB_COST *txb_eob_costs =
336*77c1e3ccSAndroid Build Coastguard Worker &coeff_costs->eob_costs[eob_multi_size][plane_type];
337*77c1e3ccSAndroid Build Coastguard Worker
338*77c1e3ccSAndroid Build Coastguard Worker const int rshift = 2;
339*77c1e3ccSAndroid Build Coastguard Worker
340*77c1e3ccSAndroid Build Coastguard Worker const int64_t rdmult =
341*77c1e3ccSAndroid Build Coastguard Worker (((int64_t)x->rdmult *
342*77c1e3ccSAndroid Build Coastguard Worker (plane_rd_mult[is_inter][plane_type] << (2 * (xd->bd - 8)))) +
343*77c1e3ccSAndroid Build Coastguard Worker 2) >>
344*77c1e3ccSAndroid Build Coastguard Worker rshift;
345*77c1e3ccSAndroid Build Coastguard Worker
346*77c1e3ccSAndroid Build Coastguard Worker uint8_t levels_buf[TX_PAD_2D];
347*77c1e3ccSAndroid Build Coastguard Worker uint8_t *const levels = set_levels(levels_buf, height);
348*77c1e3ccSAndroid Build Coastguard Worker
349*77c1e3ccSAndroid Build Coastguard Worker if (eob > 1) av1_txb_init_levels(qcoeff, width, height, levels);
350*77c1e3ccSAndroid Build Coastguard Worker
351*77c1e3ccSAndroid Build Coastguard Worker // TODO(angirbird): check iqmatrix
352*77c1e3ccSAndroid Build Coastguard Worker
353*77c1e3ccSAndroid Build Coastguard Worker const int non_skip_cost = txb_costs->txb_skip_cost[txb_ctx->txb_skip_ctx][0];
354*77c1e3ccSAndroid Build Coastguard Worker const int skip_cost = txb_costs->txb_skip_cost[txb_ctx->txb_skip_ctx][1];
355*77c1e3ccSAndroid Build Coastguard Worker const int eob_cost = get_eob_cost(eob, txb_eob_costs, txb_costs, tx_class);
356*77c1e3ccSAndroid Build Coastguard Worker int accu_rate = eob_cost;
357*77c1e3ccSAndroid Build Coastguard Worker int64_t accu_dist = 0;
358*77c1e3ccSAndroid Build Coastguard Worker int si = eob - 1;
359*77c1e3ccSAndroid Build Coastguard Worker const int ci = scan[si];
360*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t qc = qcoeff[ci];
361*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t abs_qc = abs(qc);
362*77c1e3ccSAndroid Build Coastguard Worker const int sign = qc < 0;
363*77c1e3ccSAndroid Build Coastguard Worker const int max_nz_num = 2;
364*77c1e3ccSAndroid Build Coastguard Worker int nz_num = 1;
365*77c1e3ccSAndroid Build Coastguard Worker int nz_ci[3] = { ci, 0, 0 };
366*77c1e3ccSAndroid Build Coastguard Worker if (abs_qc >= 2) {
367*77c1e3ccSAndroid Build Coastguard Worker update_coeff_general(&accu_rate, &accu_dist, si, eob, tx_size, tx_class,
368*77c1e3ccSAndroid Build Coastguard Worker bhl, width, rdmult, shift, txb_ctx->dc_sign_ctx,
369*77c1e3ccSAndroid Build Coastguard Worker dequant, scan, txb_costs, tcoeff, qcoeff, dqcoeff,
370*77c1e3ccSAndroid Build Coastguard Worker levels, iqmatrix, qmatrix);
371*77c1e3ccSAndroid Build Coastguard Worker --si;
372*77c1e3ccSAndroid Build Coastguard Worker } else {
373*77c1e3ccSAndroid Build Coastguard Worker assert(abs_qc == 1);
374*77c1e3ccSAndroid Build Coastguard Worker const int coeff_ctx = get_lower_levels_ctx_eob(bhl, width, si);
375*77c1e3ccSAndroid Build Coastguard Worker accu_rate +=
376*77c1e3ccSAndroid Build Coastguard Worker get_coeff_cost_eob(ci, abs_qc, sign, coeff_ctx, txb_ctx->dc_sign_ctx,
377*77c1e3ccSAndroid Build Coastguard Worker txb_costs, bhl, tx_class);
378*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t tqc = tcoeff[ci];
379*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t dqc = dqcoeff[ci];
380*77c1e3ccSAndroid Build Coastguard Worker const int64_t dist = get_coeff_dist(tqc, dqc, shift, qmatrix, ci);
381*77c1e3ccSAndroid Build Coastguard Worker const int64_t dist0 = get_coeff_dist(tqc, 0, shift, qmatrix, ci);
382*77c1e3ccSAndroid Build Coastguard Worker accu_dist += dist - dist0;
383*77c1e3ccSAndroid Build Coastguard Worker --si;
384*77c1e3ccSAndroid Build Coastguard Worker }
385*77c1e3ccSAndroid Build Coastguard Worker
386*77c1e3ccSAndroid Build Coastguard Worker #define UPDATE_COEFF_EOB_CASE(tx_class_literal) \
387*77c1e3ccSAndroid Build Coastguard Worker case tx_class_literal: \
388*77c1e3ccSAndroid Build Coastguard Worker for (; si >= 0 && nz_num <= max_nz_num; --si) { \
389*77c1e3ccSAndroid Build Coastguard Worker update_coeff_eob(&accu_rate, &accu_dist, &eob, &nz_num, nz_ci, si, \
390*77c1e3ccSAndroid Build Coastguard Worker tx_size, tx_class_literal, bhl, width, \
391*77c1e3ccSAndroid Build Coastguard Worker txb_ctx->dc_sign_ctx, rdmult, shift, dequant, scan, \
392*77c1e3ccSAndroid Build Coastguard Worker txb_eob_costs, txb_costs, tcoeff, qcoeff, dqcoeff, \
393*77c1e3ccSAndroid Build Coastguard Worker levels, sharpness, iqmatrix, qmatrix); \
394*77c1e3ccSAndroid Build Coastguard Worker } \
395*77c1e3ccSAndroid Build Coastguard Worker break
396*77c1e3ccSAndroid Build Coastguard Worker switch (tx_class) {
397*77c1e3ccSAndroid Build Coastguard Worker UPDATE_COEFF_EOB_CASE(TX_CLASS_2D);
398*77c1e3ccSAndroid Build Coastguard Worker UPDATE_COEFF_EOB_CASE(TX_CLASS_HORIZ);
399*77c1e3ccSAndroid Build Coastguard Worker UPDATE_COEFF_EOB_CASE(TX_CLASS_VERT);
400*77c1e3ccSAndroid Build Coastguard Worker #undef UPDATE_COEFF_EOB_CASE
401*77c1e3ccSAndroid Build Coastguard Worker default: assert(false);
402*77c1e3ccSAndroid Build Coastguard Worker }
403*77c1e3ccSAndroid Build Coastguard Worker
404*77c1e3ccSAndroid Build Coastguard Worker if (si == -1 && nz_num <= max_nz_num && sharpness == 0) {
405*77c1e3ccSAndroid Build Coastguard Worker update_skip(&accu_rate, accu_dist, &eob, nz_num, nz_ci, rdmult, skip_cost,
406*77c1e3ccSAndroid Build Coastguard Worker non_skip_cost, qcoeff, dqcoeff);
407*77c1e3ccSAndroid Build Coastguard Worker }
408*77c1e3ccSAndroid Build Coastguard Worker
409*77c1e3ccSAndroid Build Coastguard Worker #define UPDATE_COEFF_SIMPLE_CASE(tx_class_literal) \
410*77c1e3ccSAndroid Build Coastguard Worker case tx_class_literal: \
411*77c1e3ccSAndroid Build Coastguard Worker for (; si >= 1; --si) { \
412*77c1e3ccSAndroid Build Coastguard Worker update_coeff_simple(&accu_rate, si, eob, tx_size, tx_class_literal, bhl, \
413*77c1e3ccSAndroid Build Coastguard Worker rdmult, shift, dequant, scan, txb_costs, tcoeff, \
414*77c1e3ccSAndroid Build Coastguard Worker qcoeff, dqcoeff, levels, iqmatrix, qmatrix); \
415*77c1e3ccSAndroid Build Coastguard Worker } \
416*77c1e3ccSAndroid Build Coastguard Worker break
417*77c1e3ccSAndroid Build Coastguard Worker switch (tx_class) {
418*77c1e3ccSAndroid Build Coastguard Worker UPDATE_COEFF_SIMPLE_CASE(TX_CLASS_2D);
419*77c1e3ccSAndroid Build Coastguard Worker UPDATE_COEFF_SIMPLE_CASE(TX_CLASS_HORIZ);
420*77c1e3ccSAndroid Build Coastguard Worker UPDATE_COEFF_SIMPLE_CASE(TX_CLASS_VERT);
421*77c1e3ccSAndroid Build Coastguard Worker #undef UPDATE_COEFF_SIMPLE_CASE
422*77c1e3ccSAndroid Build Coastguard Worker default: assert(false);
423*77c1e3ccSAndroid Build Coastguard Worker }
424*77c1e3ccSAndroid Build Coastguard Worker
425*77c1e3ccSAndroid Build Coastguard Worker // DC position
426*77c1e3ccSAndroid Build Coastguard Worker if (si == 0) {
427*77c1e3ccSAndroid Build Coastguard Worker // no need to update accu_dist because it's not used after this point
428*77c1e3ccSAndroid Build Coastguard Worker int64_t dummy_dist = 0;
429*77c1e3ccSAndroid Build Coastguard Worker update_coeff_general(&accu_rate, &dummy_dist, si, eob, tx_size, tx_class,
430*77c1e3ccSAndroid Build Coastguard Worker bhl, width, rdmult, shift, txb_ctx->dc_sign_ctx,
431*77c1e3ccSAndroid Build Coastguard Worker dequant, scan, txb_costs, tcoeff, qcoeff, dqcoeff,
432*77c1e3ccSAndroid Build Coastguard Worker levels, iqmatrix, qmatrix);
433*77c1e3ccSAndroid Build Coastguard Worker }
434*77c1e3ccSAndroid Build Coastguard Worker
435*77c1e3ccSAndroid Build Coastguard Worker const int tx_type_cost = get_tx_type_cost(x, xd, plane, tx_size, tx_type,
436*77c1e3ccSAndroid Build Coastguard Worker cm->features.reduced_tx_set_used);
437*77c1e3ccSAndroid Build Coastguard Worker if (eob == 0)
438*77c1e3ccSAndroid Build Coastguard Worker accu_rate += skip_cost;
439*77c1e3ccSAndroid Build Coastguard Worker else
440*77c1e3ccSAndroid Build Coastguard Worker accu_rate += non_skip_cost + tx_type_cost;
441*77c1e3ccSAndroid Build Coastguard Worker
442*77c1e3ccSAndroid Build Coastguard Worker p->eobs[block] = eob;
443*77c1e3ccSAndroid Build Coastguard Worker p->txb_entropy_ctx[block] =
444*77c1e3ccSAndroid Build Coastguard Worker av1_get_txb_entropy_context(qcoeff, scan_order, p->eobs[block]);
445*77c1e3ccSAndroid Build Coastguard Worker
446*77c1e3ccSAndroid Build Coastguard Worker *rate_cost = accu_rate;
447*77c1e3ccSAndroid Build Coastguard Worker return eob;
448*77c1e3ccSAndroid Build Coastguard Worker }
449*77c1e3ccSAndroid Build Coastguard Worker
warehouse_efficients_txb(const MACROBLOCK * x,const int plane,const int block,const TX_SIZE tx_size,const TXB_CTX * const txb_ctx,const struct macroblock_plane * p,const int eob,const PLANE_TYPE plane_type,const LV_MAP_COEFF_COST * const coeff_costs,const MACROBLOCKD * const xd,const TX_TYPE tx_type,const TX_CLASS tx_class,int reduced_tx_set_used)450*77c1e3ccSAndroid Build Coastguard Worker static AOM_FORCE_INLINE int warehouse_efficients_txb(
451*77c1e3ccSAndroid Build Coastguard Worker const MACROBLOCK *x, const int plane, const int block,
452*77c1e3ccSAndroid Build Coastguard Worker const TX_SIZE tx_size, const TXB_CTX *const txb_ctx,
453*77c1e3ccSAndroid Build Coastguard Worker const struct macroblock_plane *p, const int eob,
454*77c1e3ccSAndroid Build Coastguard Worker const PLANE_TYPE plane_type, const LV_MAP_COEFF_COST *const coeff_costs,
455*77c1e3ccSAndroid Build Coastguard Worker const MACROBLOCKD *const xd, const TX_TYPE tx_type, const TX_CLASS tx_class,
456*77c1e3ccSAndroid Build Coastguard Worker int reduced_tx_set_used) {
457*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t *const qcoeff = p->qcoeff + BLOCK_OFFSET(block);
458*77c1e3ccSAndroid Build Coastguard Worker const int txb_skip_ctx = txb_ctx->txb_skip_ctx;
459*77c1e3ccSAndroid Build Coastguard Worker const int bhl = get_txb_bhl(tx_size);
460*77c1e3ccSAndroid Build Coastguard Worker const int width = get_txb_wide(tx_size);
461*77c1e3ccSAndroid Build Coastguard Worker const int height = get_txb_high(tx_size);
462*77c1e3ccSAndroid Build Coastguard Worker const SCAN_ORDER *const scan_order = get_scan(tx_size, tx_type);
463*77c1e3ccSAndroid Build Coastguard Worker const int16_t *const scan = scan_order->scan;
464*77c1e3ccSAndroid Build Coastguard Worker uint8_t levels_buf[TX_PAD_2D];
465*77c1e3ccSAndroid Build Coastguard Worker uint8_t *const levels = set_levels(levels_buf, height);
466*77c1e3ccSAndroid Build Coastguard Worker DECLARE_ALIGNED(16, int8_t, coeff_contexts[MAX_TX_SQUARE]);
467*77c1e3ccSAndroid Build Coastguard Worker const int eob_multi_size = txsize_log2_minus4[tx_size];
468*77c1e3ccSAndroid Build Coastguard Worker const LV_MAP_EOB_COST *const eob_costs =
469*77c1e3ccSAndroid Build Coastguard Worker &x->coeff_costs.eob_costs[eob_multi_size][plane_type];
470*77c1e3ccSAndroid Build Coastguard Worker int cost = coeff_costs->txb_skip_cost[txb_skip_ctx][0];
471*77c1e3ccSAndroid Build Coastguard Worker
472*77c1e3ccSAndroid Build Coastguard Worker av1_txb_init_levels(qcoeff, width, height, levels);
473*77c1e3ccSAndroid Build Coastguard Worker
474*77c1e3ccSAndroid Build Coastguard Worker cost += get_tx_type_cost(x, xd, plane, tx_size, tx_type, reduced_tx_set_used);
475*77c1e3ccSAndroid Build Coastguard Worker
476*77c1e3ccSAndroid Build Coastguard Worker cost += get_eob_cost(eob, eob_costs, coeff_costs, tx_class);
477*77c1e3ccSAndroid Build Coastguard Worker
478*77c1e3ccSAndroid Build Coastguard Worker av1_get_nz_map_contexts(levels, scan, eob, tx_size, tx_class, coeff_contexts);
479*77c1e3ccSAndroid Build Coastguard Worker
480*77c1e3ccSAndroid Build Coastguard Worker const int(*lps_cost)[COEFF_BASE_RANGE + 1 + COEFF_BASE_RANGE + 1] =
481*77c1e3ccSAndroid Build Coastguard Worker coeff_costs->lps_cost;
482*77c1e3ccSAndroid Build Coastguard Worker int c = eob - 1;
483*77c1e3ccSAndroid Build Coastguard Worker {
484*77c1e3ccSAndroid Build Coastguard Worker const int pos = scan[c];
485*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t v = qcoeff[pos];
486*77c1e3ccSAndroid Build Coastguard Worker const int sign = AOMSIGN(v);
487*77c1e3ccSAndroid Build Coastguard Worker const int level = (v ^ sign) - sign;
488*77c1e3ccSAndroid Build Coastguard Worker const int coeff_ctx = coeff_contexts[pos];
489*77c1e3ccSAndroid Build Coastguard Worker cost += coeff_costs->base_eob_cost[coeff_ctx][AOMMIN(level, 3) - 1];
490*77c1e3ccSAndroid Build Coastguard Worker
491*77c1e3ccSAndroid Build Coastguard Worker if (v) {
492*77c1e3ccSAndroid Build Coastguard Worker // sign bit cost
493*77c1e3ccSAndroid Build Coastguard Worker if (level > NUM_BASE_LEVELS) {
494*77c1e3ccSAndroid Build Coastguard Worker const int ctx = get_br_ctx_eob(pos, bhl, tx_class);
495*77c1e3ccSAndroid Build Coastguard Worker cost += get_br_cost(level, lps_cost[ctx]);
496*77c1e3ccSAndroid Build Coastguard Worker }
497*77c1e3ccSAndroid Build Coastguard Worker if (c) {
498*77c1e3ccSAndroid Build Coastguard Worker cost += av1_cost_literal(1);
499*77c1e3ccSAndroid Build Coastguard Worker } else {
500*77c1e3ccSAndroid Build Coastguard Worker const int sign01 = (sign ^ sign) - sign;
501*77c1e3ccSAndroid Build Coastguard Worker const int dc_sign_ctx = txb_ctx->dc_sign_ctx;
502*77c1e3ccSAndroid Build Coastguard Worker cost += coeff_costs->dc_sign_cost[dc_sign_ctx][sign01];
503*77c1e3ccSAndroid Build Coastguard Worker return cost;
504*77c1e3ccSAndroid Build Coastguard Worker }
505*77c1e3ccSAndroid Build Coastguard Worker }
506*77c1e3ccSAndroid Build Coastguard Worker }
507*77c1e3ccSAndroid Build Coastguard Worker const int(*base_cost)[8] = coeff_costs->base_cost;
508*77c1e3ccSAndroid Build Coastguard Worker for (c = eob - 2; c >= 1; --c) {
509*77c1e3ccSAndroid Build Coastguard Worker const int pos = scan[c];
510*77c1e3ccSAndroid Build Coastguard Worker const int coeff_ctx = coeff_contexts[pos];
511*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t v = qcoeff[pos];
512*77c1e3ccSAndroid Build Coastguard Worker const int level = abs(v);
513*77c1e3ccSAndroid Build Coastguard Worker cost += base_cost[coeff_ctx][AOMMIN(level, 3)];
514*77c1e3ccSAndroid Build Coastguard Worker if (v) {
515*77c1e3ccSAndroid Build Coastguard Worker // sign bit cost
516*77c1e3ccSAndroid Build Coastguard Worker cost += av1_cost_literal(1);
517*77c1e3ccSAndroid Build Coastguard Worker if (level > NUM_BASE_LEVELS) {
518*77c1e3ccSAndroid Build Coastguard Worker const int ctx = get_br_ctx(levels, pos, bhl, tx_class);
519*77c1e3ccSAndroid Build Coastguard Worker cost += get_br_cost(level, lps_cost[ctx]);
520*77c1e3ccSAndroid Build Coastguard Worker }
521*77c1e3ccSAndroid Build Coastguard Worker }
522*77c1e3ccSAndroid Build Coastguard Worker }
523*77c1e3ccSAndroid Build Coastguard Worker // c == 0 after previous loop
524*77c1e3ccSAndroid Build Coastguard Worker {
525*77c1e3ccSAndroid Build Coastguard Worker const int pos = scan[c];
526*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t v = qcoeff[pos];
527*77c1e3ccSAndroid Build Coastguard Worker const int coeff_ctx = coeff_contexts[pos];
528*77c1e3ccSAndroid Build Coastguard Worker const int sign = AOMSIGN(v);
529*77c1e3ccSAndroid Build Coastguard Worker const int level = (v ^ sign) - sign;
530*77c1e3ccSAndroid Build Coastguard Worker cost += base_cost[coeff_ctx][AOMMIN(level, 3)];
531*77c1e3ccSAndroid Build Coastguard Worker
532*77c1e3ccSAndroid Build Coastguard Worker if (v) {
533*77c1e3ccSAndroid Build Coastguard Worker // sign bit cost
534*77c1e3ccSAndroid Build Coastguard Worker const int sign01 = (sign ^ sign) - sign;
535*77c1e3ccSAndroid Build Coastguard Worker const int dc_sign_ctx = txb_ctx->dc_sign_ctx;
536*77c1e3ccSAndroid Build Coastguard Worker cost += coeff_costs->dc_sign_cost[dc_sign_ctx][sign01];
537*77c1e3ccSAndroid Build Coastguard Worker if (level > NUM_BASE_LEVELS) {
538*77c1e3ccSAndroid Build Coastguard Worker const int ctx = get_br_ctx(levels, pos, bhl, tx_class);
539*77c1e3ccSAndroid Build Coastguard Worker cost += get_br_cost(level, lps_cost[ctx]);
540*77c1e3ccSAndroid Build Coastguard Worker }
541*77c1e3ccSAndroid Build Coastguard Worker }
542*77c1e3ccSAndroid Build Coastguard Worker }
543*77c1e3ccSAndroid Build Coastguard Worker return cost;
544*77c1e3ccSAndroid Build Coastguard Worker }
545*77c1e3ccSAndroid Build Coastguard Worker
av1_cost_coeffs_txb_estimate(const MACROBLOCK * x,const int plane,const int block,const TX_SIZE tx_size,const TX_TYPE tx_type)546*77c1e3ccSAndroid Build Coastguard Worker int av1_cost_coeffs_txb_estimate(const MACROBLOCK *x, const int plane,
547*77c1e3ccSAndroid Build Coastguard Worker const int block, const TX_SIZE tx_size,
548*77c1e3ccSAndroid Build Coastguard Worker const TX_TYPE tx_type) {
549*77c1e3ccSAndroid Build Coastguard Worker assert(plane == 0);
550*77c1e3ccSAndroid Build Coastguard Worker
551*77c1e3ccSAndroid Build Coastguard Worker int cost = 0;
552*77c1e3ccSAndroid Build Coastguard Worker const struct macroblock_plane *p = &x->plane[plane];
553*77c1e3ccSAndroid Build Coastguard Worker const SCAN_ORDER *scan_order = get_scan(tx_size, tx_type);
554*77c1e3ccSAndroid Build Coastguard Worker const int16_t *scan = scan_order->scan;
555*77c1e3ccSAndroid Build Coastguard Worker tran_low_t *qcoeff = p->qcoeff + BLOCK_OFFSET(block);
556*77c1e3ccSAndroid Build Coastguard Worker
557*77c1e3ccSAndroid Build Coastguard Worker int eob = p->eobs[block];
558*77c1e3ccSAndroid Build Coastguard Worker
559*77c1e3ccSAndroid Build Coastguard Worker // coeffs
560*77c1e3ccSAndroid Build Coastguard Worker int c = eob - 1;
561*77c1e3ccSAndroid Build Coastguard Worker // eob
562*77c1e3ccSAndroid Build Coastguard Worker {
563*77c1e3ccSAndroid Build Coastguard Worker const int pos = scan[c];
564*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t v = abs(qcoeff[pos]) - 1;
565*77c1e3ccSAndroid Build Coastguard Worker cost += (v << (AV1_PROB_COST_SHIFT + 2));
566*77c1e3ccSAndroid Build Coastguard Worker }
567*77c1e3ccSAndroid Build Coastguard Worker // other coeffs
568*77c1e3ccSAndroid Build Coastguard Worker for (c = eob - 2; c >= 0; c--) {
569*77c1e3ccSAndroid Build Coastguard Worker const int pos = scan[c];
570*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t v = abs(qcoeff[pos]);
571*77c1e3ccSAndroid Build Coastguard Worker const int idx = AOMMIN(v, 14);
572*77c1e3ccSAndroid Build Coastguard Worker
573*77c1e3ccSAndroid Build Coastguard Worker cost += costLUT[idx];
574*77c1e3ccSAndroid Build Coastguard Worker }
575*77c1e3ccSAndroid Build Coastguard Worker
576*77c1e3ccSAndroid Build Coastguard Worker // const_term does not contain DC, and log(e) does not contain eob, so both
577*77c1e3ccSAndroid Build Coastguard Worker // (eob-1)
578*77c1e3ccSAndroid Build Coastguard Worker cost += (const_term + loge_par) * (eob - 1);
579*77c1e3ccSAndroid Build Coastguard Worker
580*77c1e3ccSAndroid Build Coastguard Worker return cost;
581*77c1e3ccSAndroid Build Coastguard Worker }
582*77c1e3ccSAndroid Build Coastguard Worker
warehouse_efficients_txb_laplacian(const MACROBLOCK * x,const int plane,const int block,const TX_SIZE tx_size,const TXB_CTX * const txb_ctx,const int eob,const PLANE_TYPE plane_type,const LV_MAP_COEFF_COST * const coeff_costs,const MACROBLOCKD * const xd,const TX_TYPE tx_type,const TX_CLASS tx_class,int reduced_tx_set_used)583*77c1e3ccSAndroid Build Coastguard Worker static AOM_FORCE_INLINE int warehouse_efficients_txb_laplacian(
584*77c1e3ccSAndroid Build Coastguard Worker const MACROBLOCK *x, const int plane, const int block,
585*77c1e3ccSAndroid Build Coastguard Worker const TX_SIZE tx_size, const TXB_CTX *const txb_ctx, const int eob,
586*77c1e3ccSAndroid Build Coastguard Worker const PLANE_TYPE plane_type, const LV_MAP_COEFF_COST *const coeff_costs,
587*77c1e3ccSAndroid Build Coastguard Worker const MACROBLOCKD *const xd, const TX_TYPE tx_type, const TX_CLASS tx_class,
588*77c1e3ccSAndroid Build Coastguard Worker int reduced_tx_set_used) {
589*77c1e3ccSAndroid Build Coastguard Worker const int txb_skip_ctx = txb_ctx->txb_skip_ctx;
590*77c1e3ccSAndroid Build Coastguard Worker
591*77c1e3ccSAndroid Build Coastguard Worker const int eob_multi_size = txsize_log2_minus4[tx_size];
592*77c1e3ccSAndroid Build Coastguard Worker const LV_MAP_EOB_COST *const eob_costs =
593*77c1e3ccSAndroid Build Coastguard Worker &x->coeff_costs.eob_costs[eob_multi_size][plane_type];
594*77c1e3ccSAndroid Build Coastguard Worker int cost = coeff_costs->txb_skip_cost[txb_skip_ctx][0];
595*77c1e3ccSAndroid Build Coastguard Worker
596*77c1e3ccSAndroid Build Coastguard Worker cost += get_tx_type_cost(x, xd, plane, tx_size, tx_type, reduced_tx_set_used);
597*77c1e3ccSAndroid Build Coastguard Worker
598*77c1e3ccSAndroid Build Coastguard Worker cost += get_eob_cost(eob, eob_costs, coeff_costs, tx_class);
599*77c1e3ccSAndroid Build Coastguard Worker
600*77c1e3ccSAndroid Build Coastguard Worker cost += av1_cost_coeffs_txb_estimate(x, plane, block, tx_size, tx_type);
601*77c1e3ccSAndroid Build Coastguard Worker return cost;
602*77c1e3ccSAndroid Build Coastguard Worker }
603*77c1e3ccSAndroid Build Coastguard Worker
av1_cost_coeffs_txb(const MACROBLOCK * x,const int plane,const int block,const TX_SIZE tx_size,const TX_TYPE tx_type,const TXB_CTX * const txb_ctx,int reduced_tx_set_used)604*77c1e3ccSAndroid Build Coastguard Worker int av1_cost_coeffs_txb(const MACROBLOCK *x, const int plane, const int block,
605*77c1e3ccSAndroid Build Coastguard Worker const TX_SIZE tx_size, const TX_TYPE tx_type,
606*77c1e3ccSAndroid Build Coastguard Worker const TXB_CTX *const txb_ctx, int reduced_tx_set_used) {
607*77c1e3ccSAndroid Build Coastguard Worker const struct macroblock_plane *p = &x->plane[plane];
608*77c1e3ccSAndroid Build Coastguard Worker const int eob = p->eobs[block];
609*77c1e3ccSAndroid Build Coastguard Worker const TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
610*77c1e3ccSAndroid Build Coastguard Worker const PLANE_TYPE plane_type = get_plane_type(plane);
611*77c1e3ccSAndroid Build Coastguard Worker const LV_MAP_COEFF_COST *const coeff_costs =
612*77c1e3ccSAndroid Build Coastguard Worker &x->coeff_costs.coeff_costs[txs_ctx][plane_type];
613*77c1e3ccSAndroid Build Coastguard Worker if (eob == 0) {
614*77c1e3ccSAndroid Build Coastguard Worker return coeff_costs->txb_skip_cost[txb_ctx->txb_skip_ctx][1];
615*77c1e3ccSAndroid Build Coastguard Worker }
616*77c1e3ccSAndroid Build Coastguard Worker
617*77c1e3ccSAndroid Build Coastguard Worker const MACROBLOCKD *const xd = &x->e_mbd;
618*77c1e3ccSAndroid Build Coastguard Worker const TX_CLASS tx_class = tx_type_to_class[tx_type];
619*77c1e3ccSAndroid Build Coastguard Worker
620*77c1e3ccSAndroid Build Coastguard Worker return warehouse_efficients_txb(x, plane, block, tx_size, txb_ctx, p, eob,
621*77c1e3ccSAndroid Build Coastguard Worker plane_type, coeff_costs, xd, tx_type,
622*77c1e3ccSAndroid Build Coastguard Worker tx_class, reduced_tx_set_used);
623*77c1e3ccSAndroid Build Coastguard Worker }
624*77c1e3ccSAndroid Build Coastguard Worker
av1_cost_coeffs_txb_laplacian(const MACROBLOCK * x,const int plane,const int block,const TX_SIZE tx_size,const TX_TYPE tx_type,const TXB_CTX * const txb_ctx,const int reduced_tx_set_used,const int adjust_eob)625*77c1e3ccSAndroid Build Coastguard Worker int av1_cost_coeffs_txb_laplacian(const MACROBLOCK *x, const int plane,
626*77c1e3ccSAndroid Build Coastguard Worker const int block, const TX_SIZE tx_size,
627*77c1e3ccSAndroid Build Coastguard Worker const TX_TYPE tx_type,
628*77c1e3ccSAndroid Build Coastguard Worker const TXB_CTX *const txb_ctx,
629*77c1e3ccSAndroid Build Coastguard Worker const int reduced_tx_set_used,
630*77c1e3ccSAndroid Build Coastguard Worker const int adjust_eob) {
631*77c1e3ccSAndroid Build Coastguard Worker const struct macroblock_plane *p = &x->plane[plane];
632*77c1e3ccSAndroid Build Coastguard Worker int eob = p->eobs[block];
633*77c1e3ccSAndroid Build Coastguard Worker
634*77c1e3ccSAndroid Build Coastguard Worker if (adjust_eob) {
635*77c1e3ccSAndroid Build Coastguard Worker const SCAN_ORDER *scan_order = get_scan(tx_size, tx_type);
636*77c1e3ccSAndroid Build Coastguard Worker const int16_t *scan = scan_order->scan;
637*77c1e3ccSAndroid Build Coastguard Worker tran_low_t *tcoeff = p->coeff + BLOCK_OFFSET(block);
638*77c1e3ccSAndroid Build Coastguard Worker tran_low_t *qcoeff = p->qcoeff + BLOCK_OFFSET(block);
639*77c1e3ccSAndroid Build Coastguard Worker tran_low_t *dqcoeff = p->dqcoeff + BLOCK_OFFSET(block);
640*77c1e3ccSAndroid Build Coastguard Worker update_coeff_eob_fast(&eob, av1_get_tx_scale(tx_size), p->dequant_QTX, scan,
641*77c1e3ccSAndroid Build Coastguard Worker tcoeff, qcoeff, dqcoeff);
642*77c1e3ccSAndroid Build Coastguard Worker p->eobs[block] = eob;
643*77c1e3ccSAndroid Build Coastguard Worker }
644*77c1e3ccSAndroid Build Coastguard Worker
645*77c1e3ccSAndroid Build Coastguard Worker const TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
646*77c1e3ccSAndroid Build Coastguard Worker const PLANE_TYPE plane_type = get_plane_type(plane);
647*77c1e3ccSAndroid Build Coastguard Worker const LV_MAP_COEFF_COST *const coeff_costs =
648*77c1e3ccSAndroid Build Coastguard Worker &x->coeff_costs.coeff_costs[txs_ctx][plane_type];
649*77c1e3ccSAndroid Build Coastguard Worker if (eob == 0) {
650*77c1e3ccSAndroid Build Coastguard Worker return coeff_costs->txb_skip_cost[txb_ctx->txb_skip_ctx][1];
651*77c1e3ccSAndroid Build Coastguard Worker }
652*77c1e3ccSAndroid Build Coastguard Worker
653*77c1e3ccSAndroid Build Coastguard Worker const MACROBLOCKD *const xd = &x->e_mbd;
654*77c1e3ccSAndroid Build Coastguard Worker const TX_CLASS tx_class = tx_type_to_class[tx_type];
655*77c1e3ccSAndroid Build Coastguard Worker
656*77c1e3ccSAndroid Build Coastguard Worker return warehouse_efficients_txb_laplacian(
657*77c1e3ccSAndroid Build Coastguard Worker x, plane, block, tx_size, txb_ctx, eob, plane_type, coeff_costs, xd,
658*77c1e3ccSAndroid Build Coastguard Worker tx_type, tx_class, reduced_tx_set_used);
659*77c1e3ccSAndroid Build Coastguard Worker }
660