1*77c1e3ccSAndroid Build Coastguard Worker /*
2*77c1e3ccSAndroid Build Coastguard Worker * Copyright (c) 2016, Alliance for Open Media. All rights reserved.
3*77c1e3ccSAndroid Build Coastguard Worker *
4*77c1e3ccSAndroid Build Coastguard Worker * This source code is subject to the terms of the BSD 2 Clause License and
5*77c1e3ccSAndroid Build Coastguard Worker * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6*77c1e3ccSAndroid Build Coastguard Worker * was not distributed with this source code in the LICENSE file, you can
7*77c1e3ccSAndroid Build Coastguard Worker * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8*77c1e3ccSAndroid Build Coastguard Worker * Media Patent License 1.0 was not distributed with this source code in the
9*77c1e3ccSAndroid Build Coastguard Worker * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10*77c1e3ccSAndroid Build Coastguard Worker */
11*77c1e3ccSAndroid Build Coastguard Worker
12*77c1e3ccSAndroid Build Coastguard Worker #include <assert.h>
13*77c1e3ccSAndroid Build Coastguard Worker #include <math.h>
14*77c1e3ccSAndroid Build Coastguard Worker #include <stdbool.h>
15*77c1e3ccSAndroid Build Coastguard Worker
16*77c1e3ccSAndroid Build Coastguard Worker #include "config/aom_config.h"
17*77c1e3ccSAndroid Build Coastguard Worker #include "config/aom_dsp_rtcd.h"
18*77c1e3ccSAndroid Build Coastguard Worker #include "config/av1_rtcd.h"
19*77c1e3ccSAndroid Build Coastguard Worker
20*77c1e3ccSAndroid Build Coastguard Worker #include "aom_dsp/aom_dsp_common.h"
21*77c1e3ccSAndroid Build Coastguard Worker #include "aom_dsp/blend.h"
22*77c1e3ccSAndroid Build Coastguard Worker #include "aom_mem/aom_mem.h"
23*77c1e3ccSAndroid Build Coastguard Worker #include "aom_ports/aom_timer.h"
24*77c1e3ccSAndroid Build Coastguard Worker #include "aom_ports/mem.h"
25*77c1e3ccSAndroid Build Coastguard Worker
26*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/av1_common_int.h"
27*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/cfl.h"
28*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/blockd.h"
29*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/common.h"
30*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/common_data.h"
31*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/entropy.h"
32*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/entropymode.h"
33*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/idct.h"
34*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/mvref_common.h"
35*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/obmc.h"
36*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/pred_common.h"
37*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/quant_common.h"
38*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/reconinter.h"
39*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/reconintra.h"
40*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/scan.h"
41*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/seg_common.h"
42*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/txb_common.h"
43*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/warped_motion.h"
44*77c1e3ccSAndroid Build Coastguard Worker
45*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/aq_variance.h"
46*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/av1_quantize.h"
47*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/cost.h"
48*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/compound_type.h"
49*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/encodemb.h"
50*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/encodemv.h"
51*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/encoder.h"
52*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/encodetxb.h"
53*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/hybrid_fwd_txfm.h"
54*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/interp_search.h"
55*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/intra_mode_search.h"
56*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/intra_mode_search_utils.h"
57*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/mcomp.h"
58*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/ml.h"
59*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/mode_prune_model_weights.h"
60*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/model_rd.h"
61*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/motion_search_facade.h"
62*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/palette.h"
63*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/pustats.h"
64*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/random.h"
65*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/ratectrl.h"
66*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/rd.h"
67*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/rdopt.h"
68*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/reconinter_enc.h"
69*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/tokenize.h"
70*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/tpl_model.h"
71*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/tx_search.h"
72*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/var_based_part.h"
73*77c1e3ccSAndroid Build Coastguard Worker
74*77c1e3ccSAndroid Build Coastguard Worker #define LAST_NEW_MV_INDEX 6
75*77c1e3ccSAndroid Build Coastguard Worker
76*77c1e3ccSAndroid Build Coastguard Worker // Mode_threshold multiplication factor table for prune_inter_modes_if_skippable
77*77c1e3ccSAndroid Build Coastguard Worker // The values are kept in Q12 format and equation used to derive is
78*77c1e3ccSAndroid Build Coastguard Worker // (2.5 - ((float)x->qindex / MAXQ) * 1.5)
79*77c1e3ccSAndroid Build Coastguard Worker #define MODE_THRESH_QBITS 12
80*77c1e3ccSAndroid Build Coastguard Worker static const int mode_threshold_mul_factor[QINDEX_RANGE] = {
81*77c1e3ccSAndroid Build Coastguard Worker 10240, 10216, 10192, 10168, 10144, 10120, 10095, 10071, 10047, 10023, 9999,
82*77c1e3ccSAndroid Build Coastguard Worker 9975, 9951, 9927, 9903, 9879, 9854, 9830, 9806, 9782, 9758, 9734,
83*77c1e3ccSAndroid Build Coastguard Worker 9710, 9686, 9662, 9638, 9614, 9589, 9565, 9541, 9517, 9493, 9469,
84*77c1e3ccSAndroid Build Coastguard Worker 9445, 9421, 9397, 9373, 9349, 9324, 9300, 9276, 9252, 9228, 9204,
85*77c1e3ccSAndroid Build Coastguard Worker 9180, 9156, 9132, 9108, 9083, 9059, 9035, 9011, 8987, 8963, 8939,
86*77c1e3ccSAndroid Build Coastguard Worker 8915, 8891, 8867, 8843, 8818, 8794, 8770, 8746, 8722, 8698, 8674,
87*77c1e3ccSAndroid Build Coastguard Worker 8650, 8626, 8602, 8578, 8553, 8529, 8505, 8481, 8457, 8433, 8409,
88*77c1e3ccSAndroid Build Coastguard Worker 8385, 8361, 8337, 8312, 8288, 8264, 8240, 8216, 8192, 8168, 8144,
89*77c1e3ccSAndroid Build Coastguard Worker 8120, 8096, 8072, 8047, 8023, 7999, 7975, 7951, 7927, 7903, 7879,
90*77c1e3ccSAndroid Build Coastguard Worker 7855, 7831, 7806, 7782, 7758, 7734, 7710, 7686, 7662, 7638, 7614,
91*77c1e3ccSAndroid Build Coastguard Worker 7590, 7566, 7541, 7517, 7493, 7469, 7445, 7421, 7397, 7373, 7349,
92*77c1e3ccSAndroid Build Coastguard Worker 7325, 7301, 7276, 7252, 7228, 7204, 7180, 7156, 7132, 7108, 7084,
93*77c1e3ccSAndroid Build Coastguard Worker 7060, 7035, 7011, 6987, 6963, 6939, 6915, 6891, 6867, 6843, 6819,
94*77c1e3ccSAndroid Build Coastguard Worker 6795, 6770, 6746, 6722, 6698, 6674, 6650, 6626, 6602, 6578, 6554,
95*77c1e3ccSAndroid Build Coastguard Worker 6530, 6505, 6481, 6457, 6433, 6409, 6385, 6361, 6337, 6313, 6289,
96*77c1e3ccSAndroid Build Coastguard Worker 6264, 6240, 6216, 6192, 6168, 6144, 6120, 6096, 6072, 6048, 6024,
97*77c1e3ccSAndroid Build Coastguard Worker 5999, 5975, 5951, 5927, 5903, 5879, 5855, 5831, 5807, 5783, 5758,
98*77c1e3ccSAndroid Build Coastguard Worker 5734, 5710, 5686, 5662, 5638, 5614, 5590, 5566, 5542, 5518, 5493,
99*77c1e3ccSAndroid Build Coastguard Worker 5469, 5445, 5421, 5397, 5373, 5349, 5325, 5301, 5277, 5253, 5228,
100*77c1e3ccSAndroid Build Coastguard Worker 5204, 5180, 5156, 5132, 5108, 5084, 5060, 5036, 5012, 4987, 4963,
101*77c1e3ccSAndroid Build Coastguard Worker 4939, 4915, 4891, 4867, 4843, 4819, 4795, 4771, 4747, 4722, 4698,
102*77c1e3ccSAndroid Build Coastguard Worker 4674, 4650, 4626, 4602, 4578, 4554, 4530, 4506, 4482, 4457, 4433,
103*77c1e3ccSAndroid Build Coastguard Worker 4409, 4385, 4361, 4337, 4313, 4289, 4265, 4241, 4216, 4192, 4168,
104*77c1e3ccSAndroid Build Coastguard Worker 4144, 4120, 4096
105*77c1e3ccSAndroid Build Coastguard Worker };
106*77c1e3ccSAndroid Build Coastguard Worker
107*77c1e3ccSAndroid Build Coastguard Worker static const THR_MODES av1_default_mode_order[MAX_MODES] = {
108*77c1e3ccSAndroid Build Coastguard Worker THR_NEARESTMV,
109*77c1e3ccSAndroid Build Coastguard Worker THR_NEARESTL2,
110*77c1e3ccSAndroid Build Coastguard Worker THR_NEARESTL3,
111*77c1e3ccSAndroid Build Coastguard Worker THR_NEARESTB,
112*77c1e3ccSAndroid Build Coastguard Worker THR_NEARESTA2,
113*77c1e3ccSAndroid Build Coastguard Worker THR_NEARESTA,
114*77c1e3ccSAndroid Build Coastguard Worker THR_NEARESTG,
115*77c1e3ccSAndroid Build Coastguard Worker
116*77c1e3ccSAndroid Build Coastguard Worker THR_NEWMV,
117*77c1e3ccSAndroid Build Coastguard Worker THR_NEWL2,
118*77c1e3ccSAndroid Build Coastguard Worker THR_NEWL3,
119*77c1e3ccSAndroid Build Coastguard Worker THR_NEWB,
120*77c1e3ccSAndroid Build Coastguard Worker THR_NEWA2,
121*77c1e3ccSAndroid Build Coastguard Worker THR_NEWA,
122*77c1e3ccSAndroid Build Coastguard Worker THR_NEWG,
123*77c1e3ccSAndroid Build Coastguard Worker
124*77c1e3ccSAndroid Build Coastguard Worker THR_NEARMV,
125*77c1e3ccSAndroid Build Coastguard Worker THR_NEARL2,
126*77c1e3ccSAndroid Build Coastguard Worker THR_NEARL3,
127*77c1e3ccSAndroid Build Coastguard Worker THR_NEARB,
128*77c1e3ccSAndroid Build Coastguard Worker THR_NEARA2,
129*77c1e3ccSAndroid Build Coastguard Worker THR_NEARA,
130*77c1e3ccSAndroid Build Coastguard Worker THR_NEARG,
131*77c1e3ccSAndroid Build Coastguard Worker
132*77c1e3ccSAndroid Build Coastguard Worker THR_GLOBALMV,
133*77c1e3ccSAndroid Build Coastguard Worker THR_GLOBALL2,
134*77c1e3ccSAndroid Build Coastguard Worker THR_GLOBALL3,
135*77c1e3ccSAndroid Build Coastguard Worker THR_GLOBALB,
136*77c1e3ccSAndroid Build Coastguard Worker THR_GLOBALA2,
137*77c1e3ccSAndroid Build Coastguard Worker THR_GLOBALA,
138*77c1e3ccSAndroid Build Coastguard Worker THR_GLOBALG,
139*77c1e3ccSAndroid Build Coastguard Worker
140*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAREST_NEARESTLA,
141*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAREST_NEARESTL2A,
142*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAREST_NEARESTL3A,
143*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAREST_NEARESTGA,
144*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAREST_NEARESTLB,
145*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAREST_NEARESTL2B,
146*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAREST_NEARESTL3B,
147*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAREST_NEARESTGB,
148*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAREST_NEARESTLA2,
149*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAREST_NEARESTL2A2,
150*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAREST_NEARESTL3A2,
151*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAREST_NEARESTGA2,
152*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAREST_NEARESTLL2,
153*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAREST_NEARESTLL3,
154*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAREST_NEARESTLG,
155*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAREST_NEARESTBA,
156*77c1e3ccSAndroid Build Coastguard Worker
157*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAR_NEARLB,
158*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEWLB,
159*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEARESTLB,
160*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAREST_NEWLB,
161*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEARLB,
162*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAR_NEWLB,
163*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_GLOBAL_GLOBALLB,
164*77c1e3ccSAndroid Build Coastguard Worker
165*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAR_NEARLA,
166*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEWLA,
167*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEARESTLA,
168*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAREST_NEWLA,
169*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEARLA,
170*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAR_NEWLA,
171*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_GLOBAL_GLOBALLA,
172*77c1e3ccSAndroid Build Coastguard Worker
173*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAR_NEARL2A,
174*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEWL2A,
175*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEARESTL2A,
176*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAREST_NEWL2A,
177*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEARL2A,
178*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAR_NEWL2A,
179*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_GLOBAL_GLOBALL2A,
180*77c1e3ccSAndroid Build Coastguard Worker
181*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAR_NEARL3A,
182*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEWL3A,
183*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEARESTL3A,
184*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAREST_NEWL3A,
185*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEARL3A,
186*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAR_NEWL3A,
187*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_GLOBAL_GLOBALL3A,
188*77c1e3ccSAndroid Build Coastguard Worker
189*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAR_NEARGA,
190*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEWGA,
191*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEARESTGA,
192*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAREST_NEWGA,
193*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEARGA,
194*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAR_NEWGA,
195*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_GLOBAL_GLOBALGA,
196*77c1e3ccSAndroid Build Coastguard Worker
197*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAR_NEARL2B,
198*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEWL2B,
199*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEARESTL2B,
200*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAREST_NEWL2B,
201*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEARL2B,
202*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAR_NEWL2B,
203*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_GLOBAL_GLOBALL2B,
204*77c1e3ccSAndroid Build Coastguard Worker
205*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAR_NEARL3B,
206*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEWL3B,
207*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEARESTL3B,
208*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAREST_NEWL3B,
209*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEARL3B,
210*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAR_NEWL3B,
211*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_GLOBAL_GLOBALL3B,
212*77c1e3ccSAndroid Build Coastguard Worker
213*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAR_NEARGB,
214*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEWGB,
215*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEARESTGB,
216*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAREST_NEWGB,
217*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEARGB,
218*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAR_NEWGB,
219*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_GLOBAL_GLOBALGB,
220*77c1e3ccSAndroid Build Coastguard Worker
221*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAR_NEARLA2,
222*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEWLA2,
223*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEARESTLA2,
224*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAREST_NEWLA2,
225*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEARLA2,
226*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAR_NEWLA2,
227*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_GLOBAL_GLOBALLA2,
228*77c1e3ccSAndroid Build Coastguard Worker
229*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAR_NEARL2A2,
230*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEWL2A2,
231*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEARESTL2A2,
232*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAREST_NEWL2A2,
233*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEARL2A2,
234*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAR_NEWL2A2,
235*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_GLOBAL_GLOBALL2A2,
236*77c1e3ccSAndroid Build Coastguard Worker
237*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAR_NEARL3A2,
238*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEWL3A2,
239*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEARESTL3A2,
240*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAREST_NEWL3A2,
241*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEARL3A2,
242*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAR_NEWL3A2,
243*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_GLOBAL_GLOBALL3A2,
244*77c1e3ccSAndroid Build Coastguard Worker
245*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAR_NEARGA2,
246*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEWGA2,
247*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEARESTGA2,
248*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAREST_NEWGA2,
249*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEARGA2,
250*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAR_NEWGA2,
251*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_GLOBAL_GLOBALGA2,
252*77c1e3ccSAndroid Build Coastguard Worker
253*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAR_NEARLL2,
254*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEWLL2,
255*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEARESTLL2,
256*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAREST_NEWLL2,
257*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEARLL2,
258*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAR_NEWLL2,
259*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_GLOBAL_GLOBALLL2,
260*77c1e3ccSAndroid Build Coastguard Worker
261*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAR_NEARLL3,
262*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEWLL3,
263*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEARESTLL3,
264*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAREST_NEWLL3,
265*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEARLL3,
266*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAR_NEWLL3,
267*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_GLOBAL_GLOBALLL3,
268*77c1e3ccSAndroid Build Coastguard Worker
269*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAR_NEARLG,
270*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEWLG,
271*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEARESTLG,
272*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAREST_NEWLG,
273*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEARLG,
274*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAR_NEWLG,
275*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_GLOBAL_GLOBALLG,
276*77c1e3ccSAndroid Build Coastguard Worker
277*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAR_NEARBA,
278*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEWBA,
279*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEARESTBA,
280*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAREST_NEWBA,
281*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEW_NEARBA,
282*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_NEAR_NEWBA,
283*77c1e3ccSAndroid Build Coastguard Worker THR_COMP_GLOBAL_GLOBALBA,
284*77c1e3ccSAndroid Build Coastguard Worker
285*77c1e3ccSAndroid Build Coastguard Worker THR_DC,
286*77c1e3ccSAndroid Build Coastguard Worker THR_PAETH,
287*77c1e3ccSAndroid Build Coastguard Worker THR_SMOOTH,
288*77c1e3ccSAndroid Build Coastguard Worker THR_SMOOTH_V,
289*77c1e3ccSAndroid Build Coastguard Worker THR_SMOOTH_H,
290*77c1e3ccSAndroid Build Coastguard Worker THR_H_PRED,
291*77c1e3ccSAndroid Build Coastguard Worker THR_V_PRED,
292*77c1e3ccSAndroid Build Coastguard Worker THR_D135_PRED,
293*77c1e3ccSAndroid Build Coastguard Worker THR_D203_PRED,
294*77c1e3ccSAndroid Build Coastguard Worker THR_D157_PRED,
295*77c1e3ccSAndroid Build Coastguard Worker THR_D67_PRED,
296*77c1e3ccSAndroid Build Coastguard Worker THR_D113_PRED,
297*77c1e3ccSAndroid Build Coastguard Worker THR_D45_PRED,
298*77c1e3ccSAndroid Build Coastguard Worker };
299*77c1e3ccSAndroid Build Coastguard Worker
300*77c1e3ccSAndroid Build Coastguard Worker /*!\cond */
301*77c1e3ccSAndroid Build Coastguard Worker typedef struct SingleInterModeState {
302*77c1e3ccSAndroid Build Coastguard Worker int64_t rd;
303*77c1e3ccSAndroid Build Coastguard Worker MV_REFERENCE_FRAME ref_frame;
304*77c1e3ccSAndroid Build Coastguard Worker int valid;
305*77c1e3ccSAndroid Build Coastguard Worker } SingleInterModeState;
306*77c1e3ccSAndroid Build Coastguard Worker
307*77c1e3ccSAndroid Build Coastguard Worker typedef struct InterModeSearchState {
308*77c1e3ccSAndroid Build Coastguard Worker int64_t best_rd;
309*77c1e3ccSAndroid Build Coastguard Worker int64_t best_skip_rd[2];
310*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO best_mbmode;
311*77c1e3ccSAndroid Build Coastguard Worker int best_rate_y;
312*77c1e3ccSAndroid Build Coastguard Worker int best_rate_uv;
313*77c1e3ccSAndroid Build Coastguard Worker int best_mode_skippable;
314*77c1e3ccSAndroid Build Coastguard Worker int best_skip2;
315*77c1e3ccSAndroid Build Coastguard Worker THR_MODES best_mode_index;
316*77c1e3ccSAndroid Build Coastguard Worker int num_available_refs;
317*77c1e3ccSAndroid Build Coastguard Worker int64_t dist_refs[REF_FRAMES];
318*77c1e3ccSAndroid Build Coastguard Worker int dist_order_refs[REF_FRAMES];
319*77c1e3ccSAndroid Build Coastguard Worker int64_t mode_threshold[MAX_MODES];
320*77c1e3ccSAndroid Build Coastguard Worker int64_t best_intra_rd;
321*77c1e3ccSAndroid Build Coastguard Worker unsigned int best_pred_sse;
322*77c1e3ccSAndroid Build Coastguard Worker
323*77c1e3ccSAndroid Build Coastguard Worker /*!
324*77c1e3ccSAndroid Build Coastguard Worker * \brief Keep track of best intra rd for use in compound mode.
325*77c1e3ccSAndroid Build Coastguard Worker */
326*77c1e3ccSAndroid Build Coastguard Worker int64_t best_pred_rd[REFERENCE_MODES];
327*77c1e3ccSAndroid Build Coastguard Worker // Save a set of single_newmv for each checked ref_mv.
328*77c1e3ccSAndroid Build Coastguard Worker int_mv single_newmv[MAX_REF_MV_SEARCH][REF_FRAMES];
329*77c1e3ccSAndroid Build Coastguard Worker int single_newmv_rate[MAX_REF_MV_SEARCH][REF_FRAMES];
330*77c1e3ccSAndroid Build Coastguard Worker int single_newmv_valid[MAX_REF_MV_SEARCH][REF_FRAMES];
331*77c1e3ccSAndroid Build Coastguard Worker int64_t modelled_rd[MB_MODE_COUNT][MAX_REF_MV_SEARCH][REF_FRAMES];
332*77c1e3ccSAndroid Build Coastguard Worker // The rd of simple translation in single inter modes
333*77c1e3ccSAndroid Build Coastguard Worker int64_t simple_rd[MB_MODE_COUNT][MAX_REF_MV_SEARCH][REF_FRAMES];
334*77c1e3ccSAndroid Build Coastguard Worker int64_t best_single_rd[REF_FRAMES];
335*77c1e3ccSAndroid Build Coastguard Worker PREDICTION_MODE best_single_mode[REF_FRAMES];
336*77c1e3ccSAndroid Build Coastguard Worker
337*77c1e3ccSAndroid Build Coastguard Worker // Single search results by [directions][modes][reference frames]
338*77c1e3ccSAndroid Build Coastguard Worker SingleInterModeState single_state[2][SINGLE_INTER_MODE_NUM][FWD_REFS];
339*77c1e3ccSAndroid Build Coastguard Worker int single_state_cnt[2][SINGLE_INTER_MODE_NUM];
340*77c1e3ccSAndroid Build Coastguard Worker SingleInterModeState single_state_modelled[2][SINGLE_INTER_MODE_NUM]
341*77c1e3ccSAndroid Build Coastguard Worker [FWD_REFS];
342*77c1e3ccSAndroid Build Coastguard Worker int single_state_modelled_cnt[2][SINGLE_INTER_MODE_NUM];
343*77c1e3ccSAndroid Build Coastguard Worker MV_REFERENCE_FRAME single_rd_order[2][SINGLE_INTER_MODE_NUM][FWD_REFS];
344*77c1e3ccSAndroid Build Coastguard Worker IntraModeSearchState intra_search_state;
345*77c1e3ccSAndroid Build Coastguard Worker RD_STATS best_y_rdcost;
346*77c1e3ccSAndroid Build Coastguard Worker } InterModeSearchState;
347*77c1e3ccSAndroid Build Coastguard Worker /*!\endcond */
348*77c1e3ccSAndroid Build Coastguard Worker
av1_inter_mode_data_init(TileDataEnc * tile_data)349*77c1e3ccSAndroid Build Coastguard Worker void av1_inter_mode_data_init(TileDataEnc *tile_data) {
350*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < BLOCK_SIZES_ALL; ++i) {
351*77c1e3ccSAndroid Build Coastguard Worker InterModeRdModel *md = &tile_data->inter_mode_rd_models[i];
352*77c1e3ccSAndroid Build Coastguard Worker md->ready = 0;
353*77c1e3ccSAndroid Build Coastguard Worker md->num = 0;
354*77c1e3ccSAndroid Build Coastguard Worker md->dist_sum = 0;
355*77c1e3ccSAndroid Build Coastguard Worker md->ld_sum = 0;
356*77c1e3ccSAndroid Build Coastguard Worker md->sse_sum = 0;
357*77c1e3ccSAndroid Build Coastguard Worker md->sse_sse_sum = 0;
358*77c1e3ccSAndroid Build Coastguard Worker md->sse_ld_sum = 0;
359*77c1e3ccSAndroid Build Coastguard Worker }
360*77c1e3ccSAndroid Build Coastguard Worker }
361*77c1e3ccSAndroid Build Coastguard Worker
get_est_rate_dist(const TileDataEnc * tile_data,BLOCK_SIZE bsize,int64_t sse,int * est_residue_cost,int64_t * est_dist)362*77c1e3ccSAndroid Build Coastguard Worker static int get_est_rate_dist(const TileDataEnc *tile_data, BLOCK_SIZE bsize,
363*77c1e3ccSAndroid Build Coastguard Worker int64_t sse, int *est_residue_cost,
364*77c1e3ccSAndroid Build Coastguard Worker int64_t *est_dist) {
365*77c1e3ccSAndroid Build Coastguard Worker const InterModeRdModel *md = &tile_data->inter_mode_rd_models[bsize];
366*77c1e3ccSAndroid Build Coastguard Worker if (md->ready) {
367*77c1e3ccSAndroid Build Coastguard Worker if (sse < md->dist_mean) {
368*77c1e3ccSAndroid Build Coastguard Worker *est_residue_cost = 0;
369*77c1e3ccSAndroid Build Coastguard Worker *est_dist = sse;
370*77c1e3ccSAndroid Build Coastguard Worker } else {
371*77c1e3ccSAndroid Build Coastguard Worker *est_dist = (int64_t)round(md->dist_mean);
372*77c1e3ccSAndroid Build Coastguard Worker const double est_ld = md->a * sse + md->b;
373*77c1e3ccSAndroid Build Coastguard Worker // Clamp estimated rate cost by INT_MAX / 2.
374*77c1e3ccSAndroid Build Coastguard Worker // TODO([email protected]): find better solution than clamping.
375*77c1e3ccSAndroid Build Coastguard Worker if (fabs(est_ld) < 1e-2) {
376*77c1e3ccSAndroid Build Coastguard Worker *est_residue_cost = INT_MAX / 2;
377*77c1e3ccSAndroid Build Coastguard Worker } else {
378*77c1e3ccSAndroid Build Coastguard Worker double est_residue_cost_dbl = ((sse - md->dist_mean) / est_ld);
379*77c1e3ccSAndroid Build Coastguard Worker if (est_residue_cost_dbl < 0) {
380*77c1e3ccSAndroid Build Coastguard Worker *est_residue_cost = 0;
381*77c1e3ccSAndroid Build Coastguard Worker } else {
382*77c1e3ccSAndroid Build Coastguard Worker *est_residue_cost =
383*77c1e3ccSAndroid Build Coastguard Worker (int)AOMMIN((int64_t)round(est_residue_cost_dbl), INT_MAX / 2);
384*77c1e3ccSAndroid Build Coastguard Worker }
385*77c1e3ccSAndroid Build Coastguard Worker }
386*77c1e3ccSAndroid Build Coastguard Worker if (*est_residue_cost <= 0) {
387*77c1e3ccSAndroid Build Coastguard Worker *est_residue_cost = 0;
388*77c1e3ccSAndroid Build Coastguard Worker *est_dist = sse;
389*77c1e3ccSAndroid Build Coastguard Worker }
390*77c1e3ccSAndroid Build Coastguard Worker }
391*77c1e3ccSAndroid Build Coastguard Worker return 1;
392*77c1e3ccSAndroid Build Coastguard Worker }
393*77c1e3ccSAndroid Build Coastguard Worker return 0;
394*77c1e3ccSAndroid Build Coastguard Worker }
395*77c1e3ccSAndroid Build Coastguard Worker
av1_inter_mode_data_fit(TileDataEnc * tile_data,int rdmult)396*77c1e3ccSAndroid Build Coastguard Worker void av1_inter_mode_data_fit(TileDataEnc *tile_data, int rdmult) {
397*77c1e3ccSAndroid Build Coastguard Worker for (int bsize = 0; bsize < BLOCK_SIZES_ALL; ++bsize) {
398*77c1e3ccSAndroid Build Coastguard Worker const int block_idx = inter_mode_data_block_idx(bsize);
399*77c1e3ccSAndroid Build Coastguard Worker InterModeRdModel *md = &tile_data->inter_mode_rd_models[bsize];
400*77c1e3ccSAndroid Build Coastguard Worker if (block_idx == -1) continue;
401*77c1e3ccSAndroid Build Coastguard Worker if ((md->ready == 0 && md->num < 200) || (md->ready == 1 && md->num < 64)) {
402*77c1e3ccSAndroid Build Coastguard Worker continue;
403*77c1e3ccSAndroid Build Coastguard Worker } else {
404*77c1e3ccSAndroid Build Coastguard Worker if (md->ready == 0) {
405*77c1e3ccSAndroid Build Coastguard Worker md->dist_mean = md->dist_sum / md->num;
406*77c1e3ccSAndroid Build Coastguard Worker md->ld_mean = md->ld_sum / md->num;
407*77c1e3ccSAndroid Build Coastguard Worker md->sse_mean = md->sse_sum / md->num;
408*77c1e3ccSAndroid Build Coastguard Worker md->sse_sse_mean = md->sse_sse_sum / md->num;
409*77c1e3ccSAndroid Build Coastguard Worker md->sse_ld_mean = md->sse_ld_sum / md->num;
410*77c1e3ccSAndroid Build Coastguard Worker } else {
411*77c1e3ccSAndroid Build Coastguard Worker const double factor = 3;
412*77c1e3ccSAndroid Build Coastguard Worker md->dist_mean =
413*77c1e3ccSAndroid Build Coastguard Worker (md->dist_mean * factor + (md->dist_sum / md->num)) / (factor + 1);
414*77c1e3ccSAndroid Build Coastguard Worker md->ld_mean =
415*77c1e3ccSAndroid Build Coastguard Worker (md->ld_mean * factor + (md->ld_sum / md->num)) / (factor + 1);
416*77c1e3ccSAndroid Build Coastguard Worker md->sse_mean =
417*77c1e3ccSAndroid Build Coastguard Worker (md->sse_mean * factor + (md->sse_sum / md->num)) / (factor + 1);
418*77c1e3ccSAndroid Build Coastguard Worker md->sse_sse_mean =
419*77c1e3ccSAndroid Build Coastguard Worker (md->sse_sse_mean * factor + (md->sse_sse_sum / md->num)) /
420*77c1e3ccSAndroid Build Coastguard Worker (factor + 1);
421*77c1e3ccSAndroid Build Coastguard Worker md->sse_ld_mean =
422*77c1e3ccSAndroid Build Coastguard Worker (md->sse_ld_mean * factor + (md->sse_ld_sum / md->num)) /
423*77c1e3ccSAndroid Build Coastguard Worker (factor + 1);
424*77c1e3ccSAndroid Build Coastguard Worker }
425*77c1e3ccSAndroid Build Coastguard Worker
426*77c1e3ccSAndroid Build Coastguard Worker const double my = md->ld_mean;
427*77c1e3ccSAndroid Build Coastguard Worker const double mx = md->sse_mean;
428*77c1e3ccSAndroid Build Coastguard Worker const double dx = sqrt(md->sse_sse_mean);
429*77c1e3ccSAndroid Build Coastguard Worker const double dxy = md->sse_ld_mean;
430*77c1e3ccSAndroid Build Coastguard Worker
431*77c1e3ccSAndroid Build Coastguard Worker md->a = (dxy - mx * my) / (dx * dx - mx * mx);
432*77c1e3ccSAndroid Build Coastguard Worker md->b = my - md->a * mx;
433*77c1e3ccSAndroid Build Coastguard Worker md->ready = 1;
434*77c1e3ccSAndroid Build Coastguard Worker
435*77c1e3ccSAndroid Build Coastguard Worker md->num = 0;
436*77c1e3ccSAndroid Build Coastguard Worker md->dist_sum = 0;
437*77c1e3ccSAndroid Build Coastguard Worker md->ld_sum = 0;
438*77c1e3ccSAndroid Build Coastguard Worker md->sse_sum = 0;
439*77c1e3ccSAndroid Build Coastguard Worker md->sse_sse_sum = 0;
440*77c1e3ccSAndroid Build Coastguard Worker md->sse_ld_sum = 0;
441*77c1e3ccSAndroid Build Coastguard Worker }
442*77c1e3ccSAndroid Build Coastguard Worker (void)rdmult;
443*77c1e3ccSAndroid Build Coastguard Worker }
444*77c1e3ccSAndroid Build Coastguard Worker }
445*77c1e3ccSAndroid Build Coastguard Worker
inter_mode_data_push(TileDataEnc * tile_data,BLOCK_SIZE bsize,int64_t sse,int64_t dist,int residue_cost)446*77c1e3ccSAndroid Build Coastguard Worker static inline void inter_mode_data_push(TileDataEnc *tile_data,
447*77c1e3ccSAndroid Build Coastguard Worker BLOCK_SIZE bsize, int64_t sse,
448*77c1e3ccSAndroid Build Coastguard Worker int64_t dist, int residue_cost) {
449*77c1e3ccSAndroid Build Coastguard Worker if (residue_cost == 0 || sse == dist) return;
450*77c1e3ccSAndroid Build Coastguard Worker const int block_idx = inter_mode_data_block_idx(bsize);
451*77c1e3ccSAndroid Build Coastguard Worker if (block_idx == -1) return;
452*77c1e3ccSAndroid Build Coastguard Worker InterModeRdModel *rd_model = &tile_data->inter_mode_rd_models[bsize];
453*77c1e3ccSAndroid Build Coastguard Worker if (rd_model->num < INTER_MODE_RD_DATA_OVERALL_SIZE) {
454*77c1e3ccSAndroid Build Coastguard Worker const double ld = (sse - dist) * 1. / residue_cost;
455*77c1e3ccSAndroid Build Coastguard Worker ++rd_model->num;
456*77c1e3ccSAndroid Build Coastguard Worker rd_model->dist_sum += dist;
457*77c1e3ccSAndroid Build Coastguard Worker rd_model->ld_sum += ld;
458*77c1e3ccSAndroid Build Coastguard Worker rd_model->sse_sum += sse;
459*77c1e3ccSAndroid Build Coastguard Worker rd_model->sse_sse_sum += (double)sse * (double)sse;
460*77c1e3ccSAndroid Build Coastguard Worker rd_model->sse_ld_sum += sse * ld;
461*77c1e3ccSAndroid Build Coastguard Worker }
462*77c1e3ccSAndroid Build Coastguard Worker }
463*77c1e3ccSAndroid Build Coastguard Worker
inter_modes_info_push(InterModesInfo * inter_modes_info,int mode_rate,int64_t sse,int64_t rd,RD_STATS * rd_cost,RD_STATS * rd_cost_y,RD_STATS * rd_cost_uv,const MB_MODE_INFO * mbmi)464*77c1e3ccSAndroid Build Coastguard Worker static inline void inter_modes_info_push(InterModesInfo *inter_modes_info,
465*77c1e3ccSAndroid Build Coastguard Worker int mode_rate, int64_t sse, int64_t rd,
466*77c1e3ccSAndroid Build Coastguard Worker RD_STATS *rd_cost, RD_STATS *rd_cost_y,
467*77c1e3ccSAndroid Build Coastguard Worker RD_STATS *rd_cost_uv,
468*77c1e3ccSAndroid Build Coastguard Worker const MB_MODE_INFO *mbmi) {
469*77c1e3ccSAndroid Build Coastguard Worker const int num = inter_modes_info->num;
470*77c1e3ccSAndroid Build Coastguard Worker assert(num < MAX_INTER_MODES);
471*77c1e3ccSAndroid Build Coastguard Worker inter_modes_info->mbmi_arr[num] = *mbmi;
472*77c1e3ccSAndroid Build Coastguard Worker inter_modes_info->mode_rate_arr[num] = mode_rate;
473*77c1e3ccSAndroid Build Coastguard Worker inter_modes_info->sse_arr[num] = sse;
474*77c1e3ccSAndroid Build Coastguard Worker inter_modes_info->est_rd_arr[num] = rd;
475*77c1e3ccSAndroid Build Coastguard Worker inter_modes_info->rd_cost_arr[num] = *rd_cost;
476*77c1e3ccSAndroid Build Coastguard Worker inter_modes_info->rd_cost_y_arr[num] = *rd_cost_y;
477*77c1e3ccSAndroid Build Coastguard Worker inter_modes_info->rd_cost_uv_arr[num] = *rd_cost_uv;
478*77c1e3ccSAndroid Build Coastguard Worker ++inter_modes_info->num;
479*77c1e3ccSAndroid Build Coastguard Worker }
480*77c1e3ccSAndroid Build Coastguard Worker
compare_rd_idx_pair(const void * a,const void * b)481*77c1e3ccSAndroid Build Coastguard Worker static int compare_rd_idx_pair(const void *a, const void *b) {
482*77c1e3ccSAndroid Build Coastguard Worker if (((RdIdxPair *)a)->rd == ((RdIdxPair *)b)->rd) {
483*77c1e3ccSAndroid Build Coastguard Worker // To avoid inconsistency in qsort() ordering when two elements are equal,
484*77c1e3ccSAndroid Build Coastguard Worker // using idx as tie breaker. Refer aomedia:2928
485*77c1e3ccSAndroid Build Coastguard Worker if (((RdIdxPair *)a)->idx == ((RdIdxPair *)b)->idx)
486*77c1e3ccSAndroid Build Coastguard Worker return 0;
487*77c1e3ccSAndroid Build Coastguard Worker else if (((RdIdxPair *)a)->idx > ((RdIdxPair *)b)->idx)
488*77c1e3ccSAndroid Build Coastguard Worker return 1;
489*77c1e3ccSAndroid Build Coastguard Worker else
490*77c1e3ccSAndroid Build Coastguard Worker return -1;
491*77c1e3ccSAndroid Build Coastguard Worker } else if (((const RdIdxPair *)a)->rd > ((const RdIdxPair *)b)->rd) {
492*77c1e3ccSAndroid Build Coastguard Worker return 1;
493*77c1e3ccSAndroid Build Coastguard Worker } else {
494*77c1e3ccSAndroid Build Coastguard Worker return -1;
495*77c1e3ccSAndroid Build Coastguard Worker }
496*77c1e3ccSAndroid Build Coastguard Worker }
497*77c1e3ccSAndroid Build Coastguard Worker
inter_modes_info_sort(const InterModesInfo * inter_modes_info,RdIdxPair * rd_idx_pair_arr)498*77c1e3ccSAndroid Build Coastguard Worker static inline void inter_modes_info_sort(const InterModesInfo *inter_modes_info,
499*77c1e3ccSAndroid Build Coastguard Worker RdIdxPair *rd_idx_pair_arr) {
500*77c1e3ccSAndroid Build Coastguard Worker if (inter_modes_info->num == 0) {
501*77c1e3ccSAndroid Build Coastguard Worker return;
502*77c1e3ccSAndroid Build Coastguard Worker }
503*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < inter_modes_info->num; ++i) {
504*77c1e3ccSAndroid Build Coastguard Worker rd_idx_pair_arr[i].idx = i;
505*77c1e3ccSAndroid Build Coastguard Worker rd_idx_pair_arr[i].rd = inter_modes_info->est_rd_arr[i];
506*77c1e3ccSAndroid Build Coastguard Worker }
507*77c1e3ccSAndroid Build Coastguard Worker qsort(rd_idx_pair_arr, inter_modes_info->num, sizeof(rd_idx_pair_arr[0]),
508*77c1e3ccSAndroid Build Coastguard Worker compare_rd_idx_pair);
509*77c1e3ccSAndroid Build Coastguard Worker }
510*77c1e3ccSAndroid Build Coastguard Worker
511*77c1e3ccSAndroid Build Coastguard Worker // Similar to get_horver_correlation, but also takes into account first
512*77c1e3ccSAndroid Build Coastguard Worker // row/column, when computing horizontal/vertical correlation.
av1_get_horver_correlation_full_c(const int16_t * diff,int stride,int width,int height,float * hcorr,float * vcorr)513*77c1e3ccSAndroid Build Coastguard Worker void av1_get_horver_correlation_full_c(const int16_t *diff, int stride,
514*77c1e3ccSAndroid Build Coastguard Worker int width, int height, float *hcorr,
515*77c1e3ccSAndroid Build Coastguard Worker float *vcorr) {
516*77c1e3ccSAndroid Build Coastguard Worker // The following notation is used:
517*77c1e3ccSAndroid Build Coastguard Worker // x - current pixel
518*77c1e3ccSAndroid Build Coastguard Worker // y - left neighbor pixel
519*77c1e3ccSAndroid Build Coastguard Worker // z - top neighbor pixel
520*77c1e3ccSAndroid Build Coastguard Worker int64_t x_sum = 0, x2_sum = 0, xy_sum = 0, xz_sum = 0;
521*77c1e3ccSAndroid Build Coastguard Worker int64_t x_firstrow = 0, x_finalrow = 0, x_firstcol = 0, x_finalcol = 0;
522*77c1e3ccSAndroid Build Coastguard Worker int64_t x2_firstrow = 0, x2_finalrow = 0, x2_firstcol = 0, x2_finalcol = 0;
523*77c1e3ccSAndroid Build Coastguard Worker
524*77c1e3ccSAndroid Build Coastguard Worker // First, process horizontal correlation on just the first row
525*77c1e3ccSAndroid Build Coastguard Worker x_sum += diff[0];
526*77c1e3ccSAndroid Build Coastguard Worker x2_sum += diff[0] * diff[0];
527*77c1e3ccSAndroid Build Coastguard Worker x_firstrow += diff[0];
528*77c1e3ccSAndroid Build Coastguard Worker x2_firstrow += diff[0] * diff[0];
529*77c1e3ccSAndroid Build Coastguard Worker for (int j = 1; j < width; ++j) {
530*77c1e3ccSAndroid Build Coastguard Worker const int16_t x = diff[j];
531*77c1e3ccSAndroid Build Coastguard Worker const int16_t y = diff[j - 1];
532*77c1e3ccSAndroid Build Coastguard Worker x_sum += x;
533*77c1e3ccSAndroid Build Coastguard Worker x_firstrow += x;
534*77c1e3ccSAndroid Build Coastguard Worker x2_sum += x * x;
535*77c1e3ccSAndroid Build Coastguard Worker x2_firstrow += x * x;
536*77c1e3ccSAndroid Build Coastguard Worker xy_sum += x * y;
537*77c1e3ccSAndroid Build Coastguard Worker }
538*77c1e3ccSAndroid Build Coastguard Worker
539*77c1e3ccSAndroid Build Coastguard Worker // Process vertical correlation in the first column
540*77c1e3ccSAndroid Build Coastguard Worker x_firstcol += diff[0];
541*77c1e3ccSAndroid Build Coastguard Worker x2_firstcol += diff[0] * diff[0];
542*77c1e3ccSAndroid Build Coastguard Worker for (int i = 1; i < height; ++i) {
543*77c1e3ccSAndroid Build Coastguard Worker const int16_t x = diff[i * stride];
544*77c1e3ccSAndroid Build Coastguard Worker const int16_t z = diff[(i - 1) * stride];
545*77c1e3ccSAndroid Build Coastguard Worker x_sum += x;
546*77c1e3ccSAndroid Build Coastguard Worker x_firstcol += x;
547*77c1e3ccSAndroid Build Coastguard Worker x2_sum += x * x;
548*77c1e3ccSAndroid Build Coastguard Worker x2_firstcol += x * x;
549*77c1e3ccSAndroid Build Coastguard Worker xz_sum += x * z;
550*77c1e3ccSAndroid Build Coastguard Worker }
551*77c1e3ccSAndroid Build Coastguard Worker
552*77c1e3ccSAndroid Build Coastguard Worker // Now process horiz and vert correlation through the rest unit
553*77c1e3ccSAndroid Build Coastguard Worker for (int i = 1; i < height; ++i) {
554*77c1e3ccSAndroid Build Coastguard Worker for (int j = 1; j < width; ++j) {
555*77c1e3ccSAndroid Build Coastguard Worker const int16_t x = diff[i * stride + j];
556*77c1e3ccSAndroid Build Coastguard Worker const int16_t y = diff[i * stride + j - 1];
557*77c1e3ccSAndroid Build Coastguard Worker const int16_t z = diff[(i - 1) * stride + j];
558*77c1e3ccSAndroid Build Coastguard Worker x_sum += x;
559*77c1e3ccSAndroid Build Coastguard Worker x2_sum += x * x;
560*77c1e3ccSAndroid Build Coastguard Worker xy_sum += x * y;
561*77c1e3ccSAndroid Build Coastguard Worker xz_sum += x * z;
562*77c1e3ccSAndroid Build Coastguard Worker }
563*77c1e3ccSAndroid Build Coastguard Worker }
564*77c1e3ccSAndroid Build Coastguard Worker
565*77c1e3ccSAndroid Build Coastguard Worker for (int j = 0; j < width; ++j) {
566*77c1e3ccSAndroid Build Coastguard Worker x_finalrow += diff[(height - 1) * stride + j];
567*77c1e3ccSAndroid Build Coastguard Worker x2_finalrow +=
568*77c1e3ccSAndroid Build Coastguard Worker diff[(height - 1) * stride + j] * diff[(height - 1) * stride + j];
569*77c1e3ccSAndroid Build Coastguard Worker }
570*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < height; ++i) {
571*77c1e3ccSAndroid Build Coastguard Worker x_finalcol += diff[i * stride + width - 1];
572*77c1e3ccSAndroid Build Coastguard Worker x2_finalcol += diff[i * stride + width - 1] * diff[i * stride + width - 1];
573*77c1e3ccSAndroid Build Coastguard Worker }
574*77c1e3ccSAndroid Build Coastguard Worker
575*77c1e3ccSAndroid Build Coastguard Worker int64_t xhor_sum = x_sum - x_finalcol;
576*77c1e3ccSAndroid Build Coastguard Worker int64_t xver_sum = x_sum - x_finalrow;
577*77c1e3ccSAndroid Build Coastguard Worker int64_t y_sum = x_sum - x_firstcol;
578*77c1e3ccSAndroid Build Coastguard Worker int64_t z_sum = x_sum - x_firstrow;
579*77c1e3ccSAndroid Build Coastguard Worker int64_t x2hor_sum = x2_sum - x2_finalcol;
580*77c1e3ccSAndroid Build Coastguard Worker int64_t x2ver_sum = x2_sum - x2_finalrow;
581*77c1e3ccSAndroid Build Coastguard Worker int64_t y2_sum = x2_sum - x2_firstcol;
582*77c1e3ccSAndroid Build Coastguard Worker int64_t z2_sum = x2_sum - x2_firstrow;
583*77c1e3ccSAndroid Build Coastguard Worker
584*77c1e3ccSAndroid Build Coastguard Worker const float num_hor = (float)(height * (width - 1));
585*77c1e3ccSAndroid Build Coastguard Worker const float num_ver = (float)((height - 1) * width);
586*77c1e3ccSAndroid Build Coastguard Worker
587*77c1e3ccSAndroid Build Coastguard Worker const float xhor_var_n = x2hor_sum - (xhor_sum * xhor_sum) / num_hor;
588*77c1e3ccSAndroid Build Coastguard Worker const float xver_var_n = x2ver_sum - (xver_sum * xver_sum) / num_ver;
589*77c1e3ccSAndroid Build Coastguard Worker
590*77c1e3ccSAndroid Build Coastguard Worker const float y_var_n = y2_sum - (y_sum * y_sum) / num_hor;
591*77c1e3ccSAndroid Build Coastguard Worker const float z_var_n = z2_sum - (z_sum * z_sum) / num_ver;
592*77c1e3ccSAndroid Build Coastguard Worker
593*77c1e3ccSAndroid Build Coastguard Worker const float xy_var_n = xy_sum - (xhor_sum * y_sum) / num_hor;
594*77c1e3ccSAndroid Build Coastguard Worker const float xz_var_n = xz_sum - (xver_sum * z_sum) / num_ver;
595*77c1e3ccSAndroid Build Coastguard Worker
596*77c1e3ccSAndroid Build Coastguard Worker if (xhor_var_n > 0 && y_var_n > 0) {
597*77c1e3ccSAndroid Build Coastguard Worker *hcorr = xy_var_n / sqrtf(xhor_var_n * y_var_n);
598*77c1e3ccSAndroid Build Coastguard Worker *hcorr = *hcorr < 0 ? 0 : *hcorr;
599*77c1e3ccSAndroid Build Coastguard Worker } else {
600*77c1e3ccSAndroid Build Coastguard Worker *hcorr = 1.0;
601*77c1e3ccSAndroid Build Coastguard Worker }
602*77c1e3ccSAndroid Build Coastguard Worker if (xver_var_n > 0 && z_var_n > 0) {
603*77c1e3ccSAndroid Build Coastguard Worker *vcorr = xz_var_n / sqrtf(xver_var_n * z_var_n);
604*77c1e3ccSAndroid Build Coastguard Worker *vcorr = *vcorr < 0 ? 0 : *vcorr;
605*77c1e3ccSAndroid Build Coastguard Worker } else {
606*77c1e3ccSAndroid Build Coastguard Worker *vcorr = 1.0;
607*77c1e3ccSAndroid Build Coastguard Worker }
608*77c1e3ccSAndroid Build Coastguard Worker }
609*77c1e3ccSAndroid Build Coastguard Worker
get_sse(const AV1_COMP * cpi,const MACROBLOCK * x,int64_t * sse_y)610*77c1e3ccSAndroid Build Coastguard Worker static int64_t get_sse(const AV1_COMP *cpi, const MACROBLOCK *x,
611*77c1e3ccSAndroid Build Coastguard Worker int64_t *sse_y) {
612*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *cm = &cpi->common;
613*77c1e3ccSAndroid Build Coastguard Worker const int num_planes = av1_num_planes(cm);
614*77c1e3ccSAndroid Build Coastguard Worker const MACROBLOCKD *xd = &x->e_mbd;
615*77c1e3ccSAndroid Build Coastguard Worker const MB_MODE_INFO *mbmi = xd->mi[0];
616*77c1e3ccSAndroid Build Coastguard Worker int64_t total_sse = 0;
617*77c1e3ccSAndroid Build Coastguard Worker for (int plane = 0; plane < num_planes; ++plane) {
618*77c1e3ccSAndroid Build Coastguard Worker if (plane && !xd->is_chroma_ref) break;
619*77c1e3ccSAndroid Build Coastguard Worker const struct macroblock_plane *const p = &x->plane[plane];
620*77c1e3ccSAndroid Build Coastguard Worker const struct macroblockd_plane *const pd = &xd->plane[plane];
621*77c1e3ccSAndroid Build Coastguard Worker const BLOCK_SIZE bs =
622*77c1e3ccSAndroid Build Coastguard Worker get_plane_block_size(mbmi->bsize, pd->subsampling_x, pd->subsampling_y);
623*77c1e3ccSAndroid Build Coastguard Worker unsigned int sse;
624*77c1e3ccSAndroid Build Coastguard Worker
625*77c1e3ccSAndroid Build Coastguard Worker cpi->ppi->fn_ptr[bs].vf(p->src.buf, p->src.stride, pd->dst.buf,
626*77c1e3ccSAndroid Build Coastguard Worker pd->dst.stride, &sse);
627*77c1e3ccSAndroid Build Coastguard Worker total_sse += sse;
628*77c1e3ccSAndroid Build Coastguard Worker if (!plane && sse_y) *sse_y = sse;
629*77c1e3ccSAndroid Build Coastguard Worker }
630*77c1e3ccSAndroid Build Coastguard Worker total_sse <<= 4;
631*77c1e3ccSAndroid Build Coastguard Worker return total_sse;
632*77c1e3ccSAndroid Build Coastguard Worker }
633*77c1e3ccSAndroid Build Coastguard Worker
av1_block_error_c(const tran_low_t * coeff,const tran_low_t * dqcoeff,intptr_t block_size,int64_t * ssz)634*77c1e3ccSAndroid Build Coastguard Worker int64_t av1_block_error_c(const tran_low_t *coeff, const tran_low_t *dqcoeff,
635*77c1e3ccSAndroid Build Coastguard Worker intptr_t block_size, int64_t *ssz) {
636*77c1e3ccSAndroid Build Coastguard Worker int i;
637*77c1e3ccSAndroid Build Coastguard Worker int64_t error = 0, sqcoeff = 0;
638*77c1e3ccSAndroid Build Coastguard Worker
639*77c1e3ccSAndroid Build Coastguard Worker for (i = 0; i < block_size; i++) {
640*77c1e3ccSAndroid Build Coastguard Worker const int diff = coeff[i] - dqcoeff[i];
641*77c1e3ccSAndroid Build Coastguard Worker error += diff * diff;
642*77c1e3ccSAndroid Build Coastguard Worker sqcoeff += coeff[i] * coeff[i];
643*77c1e3ccSAndroid Build Coastguard Worker }
644*77c1e3ccSAndroid Build Coastguard Worker
645*77c1e3ccSAndroid Build Coastguard Worker *ssz = sqcoeff;
646*77c1e3ccSAndroid Build Coastguard Worker return error;
647*77c1e3ccSAndroid Build Coastguard Worker }
648*77c1e3ccSAndroid Build Coastguard Worker
av1_block_error_lp_c(const int16_t * coeff,const int16_t * dqcoeff,intptr_t block_size)649*77c1e3ccSAndroid Build Coastguard Worker int64_t av1_block_error_lp_c(const int16_t *coeff, const int16_t *dqcoeff,
650*77c1e3ccSAndroid Build Coastguard Worker intptr_t block_size) {
651*77c1e3ccSAndroid Build Coastguard Worker int64_t error = 0;
652*77c1e3ccSAndroid Build Coastguard Worker
653*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < block_size; i++) {
654*77c1e3ccSAndroid Build Coastguard Worker const int diff = coeff[i] - dqcoeff[i];
655*77c1e3ccSAndroid Build Coastguard Worker error += diff * diff;
656*77c1e3ccSAndroid Build Coastguard Worker }
657*77c1e3ccSAndroid Build Coastguard Worker
658*77c1e3ccSAndroid Build Coastguard Worker return error;
659*77c1e3ccSAndroid Build Coastguard Worker }
660*77c1e3ccSAndroid Build Coastguard Worker
661*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_AV1_HIGHBITDEPTH
av1_highbd_block_error_c(const tran_low_t * coeff,const tran_low_t * dqcoeff,intptr_t block_size,int64_t * ssz,int bd)662*77c1e3ccSAndroid Build Coastguard Worker int64_t av1_highbd_block_error_c(const tran_low_t *coeff,
663*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t *dqcoeff, intptr_t block_size,
664*77c1e3ccSAndroid Build Coastguard Worker int64_t *ssz, int bd) {
665*77c1e3ccSAndroid Build Coastguard Worker int i;
666*77c1e3ccSAndroid Build Coastguard Worker int64_t error = 0, sqcoeff = 0;
667*77c1e3ccSAndroid Build Coastguard Worker int shift = 2 * (bd - 8);
668*77c1e3ccSAndroid Build Coastguard Worker int rounding = shift > 0 ? 1 << (shift - 1) : 0;
669*77c1e3ccSAndroid Build Coastguard Worker
670*77c1e3ccSAndroid Build Coastguard Worker for (i = 0; i < block_size; i++) {
671*77c1e3ccSAndroid Build Coastguard Worker const int64_t diff = coeff[i] - dqcoeff[i];
672*77c1e3ccSAndroid Build Coastguard Worker error += diff * diff;
673*77c1e3ccSAndroid Build Coastguard Worker sqcoeff += (int64_t)coeff[i] * (int64_t)coeff[i];
674*77c1e3ccSAndroid Build Coastguard Worker }
675*77c1e3ccSAndroid Build Coastguard Worker assert(error >= 0 && sqcoeff >= 0);
676*77c1e3ccSAndroid Build Coastguard Worker error = (error + rounding) >> shift;
677*77c1e3ccSAndroid Build Coastguard Worker sqcoeff = (sqcoeff + rounding) >> shift;
678*77c1e3ccSAndroid Build Coastguard Worker
679*77c1e3ccSAndroid Build Coastguard Worker *ssz = sqcoeff;
680*77c1e3ccSAndroid Build Coastguard Worker return error;
681*77c1e3ccSAndroid Build Coastguard Worker }
682*77c1e3ccSAndroid Build Coastguard Worker #endif
683*77c1e3ccSAndroid Build Coastguard Worker
conditional_skipintra(PREDICTION_MODE mode,PREDICTION_MODE best_intra_mode)684*77c1e3ccSAndroid Build Coastguard Worker static int conditional_skipintra(PREDICTION_MODE mode,
685*77c1e3ccSAndroid Build Coastguard Worker PREDICTION_MODE best_intra_mode) {
686*77c1e3ccSAndroid Build Coastguard Worker if (mode == D113_PRED && best_intra_mode != V_PRED &&
687*77c1e3ccSAndroid Build Coastguard Worker best_intra_mode != D135_PRED)
688*77c1e3ccSAndroid Build Coastguard Worker return 1;
689*77c1e3ccSAndroid Build Coastguard Worker if (mode == D67_PRED && best_intra_mode != V_PRED &&
690*77c1e3ccSAndroid Build Coastguard Worker best_intra_mode != D45_PRED)
691*77c1e3ccSAndroid Build Coastguard Worker return 1;
692*77c1e3ccSAndroid Build Coastguard Worker if (mode == D203_PRED && best_intra_mode != H_PRED &&
693*77c1e3ccSAndroid Build Coastguard Worker best_intra_mode != D45_PRED)
694*77c1e3ccSAndroid Build Coastguard Worker return 1;
695*77c1e3ccSAndroid Build Coastguard Worker if (mode == D157_PRED && best_intra_mode != H_PRED &&
696*77c1e3ccSAndroid Build Coastguard Worker best_intra_mode != D135_PRED)
697*77c1e3ccSAndroid Build Coastguard Worker return 1;
698*77c1e3ccSAndroid Build Coastguard Worker return 0;
699*77c1e3ccSAndroid Build Coastguard Worker }
700*77c1e3ccSAndroid Build Coastguard Worker
cost_mv_ref(const ModeCosts * const mode_costs,PREDICTION_MODE mode,int16_t mode_context)701*77c1e3ccSAndroid Build Coastguard Worker static int cost_mv_ref(const ModeCosts *const mode_costs, PREDICTION_MODE mode,
702*77c1e3ccSAndroid Build Coastguard Worker int16_t mode_context) {
703*77c1e3ccSAndroid Build Coastguard Worker if (is_inter_compound_mode(mode)) {
704*77c1e3ccSAndroid Build Coastguard Worker return mode_costs
705*77c1e3ccSAndroid Build Coastguard Worker ->inter_compound_mode_cost[mode_context][INTER_COMPOUND_OFFSET(mode)];
706*77c1e3ccSAndroid Build Coastguard Worker }
707*77c1e3ccSAndroid Build Coastguard Worker
708*77c1e3ccSAndroid Build Coastguard Worker int mode_cost = 0;
709*77c1e3ccSAndroid Build Coastguard Worker int16_t mode_ctx = mode_context & NEWMV_CTX_MASK;
710*77c1e3ccSAndroid Build Coastguard Worker
711*77c1e3ccSAndroid Build Coastguard Worker assert(is_inter_mode(mode));
712*77c1e3ccSAndroid Build Coastguard Worker
713*77c1e3ccSAndroid Build Coastguard Worker if (mode == NEWMV) {
714*77c1e3ccSAndroid Build Coastguard Worker mode_cost = mode_costs->newmv_mode_cost[mode_ctx][0];
715*77c1e3ccSAndroid Build Coastguard Worker return mode_cost;
716*77c1e3ccSAndroid Build Coastguard Worker } else {
717*77c1e3ccSAndroid Build Coastguard Worker mode_cost = mode_costs->newmv_mode_cost[mode_ctx][1];
718*77c1e3ccSAndroid Build Coastguard Worker mode_ctx = (mode_context >> GLOBALMV_OFFSET) & GLOBALMV_CTX_MASK;
719*77c1e3ccSAndroid Build Coastguard Worker
720*77c1e3ccSAndroid Build Coastguard Worker if (mode == GLOBALMV) {
721*77c1e3ccSAndroid Build Coastguard Worker mode_cost += mode_costs->zeromv_mode_cost[mode_ctx][0];
722*77c1e3ccSAndroid Build Coastguard Worker return mode_cost;
723*77c1e3ccSAndroid Build Coastguard Worker } else {
724*77c1e3ccSAndroid Build Coastguard Worker mode_cost += mode_costs->zeromv_mode_cost[mode_ctx][1];
725*77c1e3ccSAndroid Build Coastguard Worker mode_ctx = (mode_context >> REFMV_OFFSET) & REFMV_CTX_MASK;
726*77c1e3ccSAndroid Build Coastguard Worker mode_cost += mode_costs->refmv_mode_cost[mode_ctx][mode != NEARESTMV];
727*77c1e3ccSAndroid Build Coastguard Worker return mode_cost;
728*77c1e3ccSAndroid Build Coastguard Worker }
729*77c1e3ccSAndroid Build Coastguard Worker }
730*77c1e3ccSAndroid Build Coastguard Worker }
731*77c1e3ccSAndroid Build Coastguard Worker
get_single_mode(PREDICTION_MODE this_mode,int ref_idx)732*77c1e3ccSAndroid Build Coastguard Worker static inline PREDICTION_MODE get_single_mode(PREDICTION_MODE this_mode,
733*77c1e3ccSAndroid Build Coastguard Worker int ref_idx) {
734*77c1e3ccSAndroid Build Coastguard Worker return ref_idx ? compound_ref1_mode(this_mode)
735*77c1e3ccSAndroid Build Coastguard Worker : compound_ref0_mode(this_mode);
736*77c1e3ccSAndroid Build Coastguard Worker }
737*77c1e3ccSAndroid Build Coastguard Worker
estimate_ref_frame_costs(const AV1_COMMON * cm,const MACROBLOCKD * xd,const ModeCosts * mode_costs,int segment_id,unsigned int * ref_costs_single,unsigned int (* ref_costs_comp)[REF_FRAMES])738*77c1e3ccSAndroid Build Coastguard Worker static inline void estimate_ref_frame_costs(
739*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *cm, const MACROBLOCKD *xd, const ModeCosts *mode_costs,
740*77c1e3ccSAndroid Build Coastguard Worker int segment_id, unsigned int *ref_costs_single,
741*77c1e3ccSAndroid Build Coastguard Worker unsigned int (*ref_costs_comp)[REF_FRAMES]) {
742*77c1e3ccSAndroid Build Coastguard Worker int seg_ref_active =
743*77c1e3ccSAndroid Build Coastguard Worker segfeature_active(&cm->seg, segment_id, SEG_LVL_REF_FRAME);
744*77c1e3ccSAndroid Build Coastguard Worker if (seg_ref_active) {
745*77c1e3ccSAndroid Build Coastguard Worker memset(ref_costs_single, 0, REF_FRAMES * sizeof(*ref_costs_single));
746*77c1e3ccSAndroid Build Coastguard Worker int ref_frame;
747*77c1e3ccSAndroid Build Coastguard Worker for (ref_frame = 0; ref_frame < REF_FRAMES; ++ref_frame)
748*77c1e3ccSAndroid Build Coastguard Worker memset(ref_costs_comp[ref_frame], 0,
749*77c1e3ccSAndroid Build Coastguard Worker REF_FRAMES * sizeof((*ref_costs_comp)[0]));
750*77c1e3ccSAndroid Build Coastguard Worker } else {
751*77c1e3ccSAndroid Build Coastguard Worker int intra_inter_ctx = av1_get_intra_inter_context(xd);
752*77c1e3ccSAndroid Build Coastguard Worker ref_costs_single[INTRA_FRAME] =
753*77c1e3ccSAndroid Build Coastguard Worker mode_costs->intra_inter_cost[intra_inter_ctx][0];
754*77c1e3ccSAndroid Build Coastguard Worker unsigned int base_cost = mode_costs->intra_inter_cost[intra_inter_ctx][1];
755*77c1e3ccSAndroid Build Coastguard Worker
756*77c1e3ccSAndroid Build Coastguard Worker for (int i = LAST_FRAME; i <= ALTREF_FRAME; ++i)
757*77c1e3ccSAndroid Build Coastguard Worker ref_costs_single[i] = base_cost;
758*77c1e3ccSAndroid Build Coastguard Worker
759*77c1e3ccSAndroid Build Coastguard Worker const int ctx_p1 = av1_get_pred_context_single_ref_p1(xd);
760*77c1e3ccSAndroid Build Coastguard Worker const int ctx_p2 = av1_get_pred_context_single_ref_p2(xd);
761*77c1e3ccSAndroid Build Coastguard Worker const int ctx_p3 = av1_get_pred_context_single_ref_p3(xd);
762*77c1e3ccSAndroid Build Coastguard Worker const int ctx_p4 = av1_get_pred_context_single_ref_p4(xd);
763*77c1e3ccSAndroid Build Coastguard Worker const int ctx_p5 = av1_get_pred_context_single_ref_p5(xd);
764*77c1e3ccSAndroid Build Coastguard Worker const int ctx_p6 = av1_get_pred_context_single_ref_p6(xd);
765*77c1e3ccSAndroid Build Coastguard Worker
766*77c1e3ccSAndroid Build Coastguard Worker // Determine cost of a single ref frame, where frame types are represented
767*77c1e3ccSAndroid Build Coastguard Worker // by a tree:
768*77c1e3ccSAndroid Build Coastguard Worker // Level 0: add cost whether this ref is a forward or backward ref
769*77c1e3ccSAndroid Build Coastguard Worker ref_costs_single[LAST_FRAME] += mode_costs->single_ref_cost[ctx_p1][0][0];
770*77c1e3ccSAndroid Build Coastguard Worker ref_costs_single[LAST2_FRAME] += mode_costs->single_ref_cost[ctx_p1][0][0];
771*77c1e3ccSAndroid Build Coastguard Worker ref_costs_single[LAST3_FRAME] += mode_costs->single_ref_cost[ctx_p1][0][0];
772*77c1e3ccSAndroid Build Coastguard Worker ref_costs_single[GOLDEN_FRAME] += mode_costs->single_ref_cost[ctx_p1][0][0];
773*77c1e3ccSAndroid Build Coastguard Worker ref_costs_single[BWDREF_FRAME] += mode_costs->single_ref_cost[ctx_p1][0][1];
774*77c1e3ccSAndroid Build Coastguard Worker ref_costs_single[ALTREF2_FRAME] +=
775*77c1e3ccSAndroid Build Coastguard Worker mode_costs->single_ref_cost[ctx_p1][0][1];
776*77c1e3ccSAndroid Build Coastguard Worker ref_costs_single[ALTREF_FRAME] += mode_costs->single_ref_cost[ctx_p1][0][1];
777*77c1e3ccSAndroid Build Coastguard Worker
778*77c1e3ccSAndroid Build Coastguard Worker // Level 1: if this ref is forward ref,
779*77c1e3ccSAndroid Build Coastguard Worker // add cost whether it is last/last2 or last3/golden
780*77c1e3ccSAndroid Build Coastguard Worker ref_costs_single[LAST_FRAME] += mode_costs->single_ref_cost[ctx_p3][2][0];
781*77c1e3ccSAndroid Build Coastguard Worker ref_costs_single[LAST2_FRAME] += mode_costs->single_ref_cost[ctx_p3][2][0];
782*77c1e3ccSAndroid Build Coastguard Worker ref_costs_single[LAST3_FRAME] += mode_costs->single_ref_cost[ctx_p3][2][1];
783*77c1e3ccSAndroid Build Coastguard Worker ref_costs_single[GOLDEN_FRAME] += mode_costs->single_ref_cost[ctx_p3][2][1];
784*77c1e3ccSAndroid Build Coastguard Worker
785*77c1e3ccSAndroid Build Coastguard Worker // Level 1: if this ref is backward ref
786*77c1e3ccSAndroid Build Coastguard Worker // then add cost whether this ref is altref or backward ref
787*77c1e3ccSAndroid Build Coastguard Worker ref_costs_single[BWDREF_FRAME] += mode_costs->single_ref_cost[ctx_p2][1][0];
788*77c1e3ccSAndroid Build Coastguard Worker ref_costs_single[ALTREF2_FRAME] +=
789*77c1e3ccSAndroid Build Coastguard Worker mode_costs->single_ref_cost[ctx_p2][1][0];
790*77c1e3ccSAndroid Build Coastguard Worker ref_costs_single[ALTREF_FRAME] += mode_costs->single_ref_cost[ctx_p2][1][1];
791*77c1e3ccSAndroid Build Coastguard Worker
792*77c1e3ccSAndroid Build Coastguard Worker // Level 2: further add cost whether this ref is last or last2
793*77c1e3ccSAndroid Build Coastguard Worker ref_costs_single[LAST_FRAME] += mode_costs->single_ref_cost[ctx_p4][3][0];
794*77c1e3ccSAndroid Build Coastguard Worker ref_costs_single[LAST2_FRAME] += mode_costs->single_ref_cost[ctx_p4][3][1];
795*77c1e3ccSAndroid Build Coastguard Worker
796*77c1e3ccSAndroid Build Coastguard Worker // Level 2: last3 or golden
797*77c1e3ccSAndroid Build Coastguard Worker ref_costs_single[LAST3_FRAME] += mode_costs->single_ref_cost[ctx_p5][4][0];
798*77c1e3ccSAndroid Build Coastguard Worker ref_costs_single[GOLDEN_FRAME] += mode_costs->single_ref_cost[ctx_p5][4][1];
799*77c1e3ccSAndroid Build Coastguard Worker
800*77c1e3ccSAndroid Build Coastguard Worker // Level 2: bwdref or altref2
801*77c1e3ccSAndroid Build Coastguard Worker ref_costs_single[BWDREF_FRAME] += mode_costs->single_ref_cost[ctx_p6][5][0];
802*77c1e3ccSAndroid Build Coastguard Worker ref_costs_single[ALTREF2_FRAME] +=
803*77c1e3ccSAndroid Build Coastguard Worker mode_costs->single_ref_cost[ctx_p6][5][1];
804*77c1e3ccSAndroid Build Coastguard Worker
805*77c1e3ccSAndroid Build Coastguard Worker if (cm->current_frame.reference_mode != SINGLE_REFERENCE) {
806*77c1e3ccSAndroid Build Coastguard Worker // Similar to single ref, determine cost of compound ref frames.
807*77c1e3ccSAndroid Build Coastguard Worker // cost_compound_refs = cost_first_ref + cost_second_ref
808*77c1e3ccSAndroid Build Coastguard Worker const int bwdref_comp_ctx_p = av1_get_pred_context_comp_bwdref_p(xd);
809*77c1e3ccSAndroid Build Coastguard Worker const int bwdref_comp_ctx_p1 = av1_get_pred_context_comp_bwdref_p1(xd);
810*77c1e3ccSAndroid Build Coastguard Worker const int ref_comp_ctx_p = av1_get_pred_context_comp_ref_p(xd);
811*77c1e3ccSAndroid Build Coastguard Worker const int ref_comp_ctx_p1 = av1_get_pred_context_comp_ref_p1(xd);
812*77c1e3ccSAndroid Build Coastguard Worker const int ref_comp_ctx_p2 = av1_get_pred_context_comp_ref_p2(xd);
813*77c1e3ccSAndroid Build Coastguard Worker
814*77c1e3ccSAndroid Build Coastguard Worker const int comp_ref_type_ctx = av1_get_comp_reference_type_context(xd);
815*77c1e3ccSAndroid Build Coastguard Worker unsigned int ref_bicomp_costs[REF_FRAMES] = { 0 };
816*77c1e3ccSAndroid Build Coastguard Worker
817*77c1e3ccSAndroid Build Coastguard Worker ref_bicomp_costs[LAST_FRAME] = ref_bicomp_costs[LAST2_FRAME] =
818*77c1e3ccSAndroid Build Coastguard Worker ref_bicomp_costs[LAST3_FRAME] = ref_bicomp_costs[GOLDEN_FRAME] =
819*77c1e3ccSAndroid Build Coastguard Worker base_cost + mode_costs->comp_ref_type_cost[comp_ref_type_ctx][1];
820*77c1e3ccSAndroid Build Coastguard Worker ref_bicomp_costs[BWDREF_FRAME] = ref_bicomp_costs[ALTREF2_FRAME] = 0;
821*77c1e3ccSAndroid Build Coastguard Worker ref_bicomp_costs[ALTREF_FRAME] = 0;
822*77c1e3ccSAndroid Build Coastguard Worker
823*77c1e3ccSAndroid Build Coastguard Worker // cost of first ref frame
824*77c1e3ccSAndroid Build Coastguard Worker ref_bicomp_costs[LAST_FRAME] +=
825*77c1e3ccSAndroid Build Coastguard Worker mode_costs->comp_ref_cost[ref_comp_ctx_p][0][0];
826*77c1e3ccSAndroid Build Coastguard Worker ref_bicomp_costs[LAST2_FRAME] +=
827*77c1e3ccSAndroid Build Coastguard Worker mode_costs->comp_ref_cost[ref_comp_ctx_p][0][0];
828*77c1e3ccSAndroid Build Coastguard Worker ref_bicomp_costs[LAST3_FRAME] +=
829*77c1e3ccSAndroid Build Coastguard Worker mode_costs->comp_ref_cost[ref_comp_ctx_p][0][1];
830*77c1e3ccSAndroid Build Coastguard Worker ref_bicomp_costs[GOLDEN_FRAME] +=
831*77c1e3ccSAndroid Build Coastguard Worker mode_costs->comp_ref_cost[ref_comp_ctx_p][0][1];
832*77c1e3ccSAndroid Build Coastguard Worker
833*77c1e3ccSAndroid Build Coastguard Worker ref_bicomp_costs[LAST_FRAME] +=
834*77c1e3ccSAndroid Build Coastguard Worker mode_costs->comp_ref_cost[ref_comp_ctx_p1][1][0];
835*77c1e3ccSAndroid Build Coastguard Worker ref_bicomp_costs[LAST2_FRAME] +=
836*77c1e3ccSAndroid Build Coastguard Worker mode_costs->comp_ref_cost[ref_comp_ctx_p1][1][1];
837*77c1e3ccSAndroid Build Coastguard Worker
838*77c1e3ccSAndroid Build Coastguard Worker ref_bicomp_costs[LAST3_FRAME] +=
839*77c1e3ccSAndroid Build Coastguard Worker mode_costs->comp_ref_cost[ref_comp_ctx_p2][2][0];
840*77c1e3ccSAndroid Build Coastguard Worker ref_bicomp_costs[GOLDEN_FRAME] +=
841*77c1e3ccSAndroid Build Coastguard Worker mode_costs->comp_ref_cost[ref_comp_ctx_p2][2][1];
842*77c1e3ccSAndroid Build Coastguard Worker
843*77c1e3ccSAndroid Build Coastguard Worker // cost of second ref frame
844*77c1e3ccSAndroid Build Coastguard Worker ref_bicomp_costs[BWDREF_FRAME] +=
845*77c1e3ccSAndroid Build Coastguard Worker mode_costs->comp_bwdref_cost[bwdref_comp_ctx_p][0][0];
846*77c1e3ccSAndroid Build Coastguard Worker ref_bicomp_costs[ALTREF2_FRAME] +=
847*77c1e3ccSAndroid Build Coastguard Worker mode_costs->comp_bwdref_cost[bwdref_comp_ctx_p][0][0];
848*77c1e3ccSAndroid Build Coastguard Worker ref_bicomp_costs[ALTREF_FRAME] +=
849*77c1e3ccSAndroid Build Coastguard Worker mode_costs->comp_bwdref_cost[bwdref_comp_ctx_p][0][1];
850*77c1e3ccSAndroid Build Coastguard Worker
851*77c1e3ccSAndroid Build Coastguard Worker ref_bicomp_costs[BWDREF_FRAME] +=
852*77c1e3ccSAndroid Build Coastguard Worker mode_costs->comp_bwdref_cost[bwdref_comp_ctx_p1][1][0];
853*77c1e3ccSAndroid Build Coastguard Worker ref_bicomp_costs[ALTREF2_FRAME] +=
854*77c1e3ccSAndroid Build Coastguard Worker mode_costs->comp_bwdref_cost[bwdref_comp_ctx_p1][1][1];
855*77c1e3ccSAndroid Build Coastguard Worker
856*77c1e3ccSAndroid Build Coastguard Worker // cost: if one ref frame is forward ref, the other ref is backward ref
857*77c1e3ccSAndroid Build Coastguard Worker int ref0, ref1;
858*77c1e3ccSAndroid Build Coastguard Worker for (ref0 = LAST_FRAME; ref0 <= GOLDEN_FRAME; ++ref0) {
859*77c1e3ccSAndroid Build Coastguard Worker for (ref1 = BWDREF_FRAME; ref1 <= ALTREF_FRAME; ++ref1) {
860*77c1e3ccSAndroid Build Coastguard Worker ref_costs_comp[ref0][ref1] =
861*77c1e3ccSAndroid Build Coastguard Worker ref_bicomp_costs[ref0] + ref_bicomp_costs[ref1];
862*77c1e3ccSAndroid Build Coastguard Worker }
863*77c1e3ccSAndroid Build Coastguard Worker }
864*77c1e3ccSAndroid Build Coastguard Worker
865*77c1e3ccSAndroid Build Coastguard Worker // cost: if both ref frames are the same side.
866*77c1e3ccSAndroid Build Coastguard Worker const int uni_comp_ref_ctx_p = av1_get_pred_context_uni_comp_ref_p(xd);
867*77c1e3ccSAndroid Build Coastguard Worker const int uni_comp_ref_ctx_p1 = av1_get_pred_context_uni_comp_ref_p1(xd);
868*77c1e3ccSAndroid Build Coastguard Worker const int uni_comp_ref_ctx_p2 = av1_get_pred_context_uni_comp_ref_p2(xd);
869*77c1e3ccSAndroid Build Coastguard Worker ref_costs_comp[LAST_FRAME][LAST2_FRAME] =
870*77c1e3ccSAndroid Build Coastguard Worker base_cost + mode_costs->comp_ref_type_cost[comp_ref_type_ctx][0] +
871*77c1e3ccSAndroid Build Coastguard Worker mode_costs->uni_comp_ref_cost[uni_comp_ref_ctx_p][0][0] +
872*77c1e3ccSAndroid Build Coastguard Worker mode_costs->uni_comp_ref_cost[uni_comp_ref_ctx_p1][1][0];
873*77c1e3ccSAndroid Build Coastguard Worker ref_costs_comp[LAST_FRAME][LAST3_FRAME] =
874*77c1e3ccSAndroid Build Coastguard Worker base_cost + mode_costs->comp_ref_type_cost[comp_ref_type_ctx][0] +
875*77c1e3ccSAndroid Build Coastguard Worker mode_costs->uni_comp_ref_cost[uni_comp_ref_ctx_p][0][0] +
876*77c1e3ccSAndroid Build Coastguard Worker mode_costs->uni_comp_ref_cost[uni_comp_ref_ctx_p1][1][1] +
877*77c1e3ccSAndroid Build Coastguard Worker mode_costs->uni_comp_ref_cost[uni_comp_ref_ctx_p2][2][0];
878*77c1e3ccSAndroid Build Coastguard Worker ref_costs_comp[LAST_FRAME][GOLDEN_FRAME] =
879*77c1e3ccSAndroid Build Coastguard Worker base_cost + mode_costs->comp_ref_type_cost[comp_ref_type_ctx][0] +
880*77c1e3ccSAndroid Build Coastguard Worker mode_costs->uni_comp_ref_cost[uni_comp_ref_ctx_p][0][0] +
881*77c1e3ccSAndroid Build Coastguard Worker mode_costs->uni_comp_ref_cost[uni_comp_ref_ctx_p1][1][1] +
882*77c1e3ccSAndroid Build Coastguard Worker mode_costs->uni_comp_ref_cost[uni_comp_ref_ctx_p2][2][1];
883*77c1e3ccSAndroid Build Coastguard Worker ref_costs_comp[BWDREF_FRAME][ALTREF_FRAME] =
884*77c1e3ccSAndroid Build Coastguard Worker base_cost + mode_costs->comp_ref_type_cost[comp_ref_type_ctx][0] +
885*77c1e3ccSAndroid Build Coastguard Worker mode_costs->uni_comp_ref_cost[uni_comp_ref_ctx_p][0][1];
886*77c1e3ccSAndroid Build Coastguard Worker } else {
887*77c1e3ccSAndroid Build Coastguard Worker int ref0, ref1;
888*77c1e3ccSAndroid Build Coastguard Worker for (ref0 = LAST_FRAME; ref0 <= GOLDEN_FRAME; ++ref0) {
889*77c1e3ccSAndroid Build Coastguard Worker for (ref1 = BWDREF_FRAME; ref1 <= ALTREF_FRAME; ++ref1)
890*77c1e3ccSAndroid Build Coastguard Worker ref_costs_comp[ref0][ref1] = 512;
891*77c1e3ccSAndroid Build Coastguard Worker }
892*77c1e3ccSAndroid Build Coastguard Worker ref_costs_comp[LAST_FRAME][LAST2_FRAME] = 512;
893*77c1e3ccSAndroid Build Coastguard Worker ref_costs_comp[LAST_FRAME][LAST3_FRAME] = 512;
894*77c1e3ccSAndroid Build Coastguard Worker ref_costs_comp[LAST_FRAME][GOLDEN_FRAME] = 512;
895*77c1e3ccSAndroid Build Coastguard Worker ref_costs_comp[BWDREF_FRAME][ALTREF_FRAME] = 512;
896*77c1e3ccSAndroid Build Coastguard Worker }
897*77c1e3ccSAndroid Build Coastguard Worker }
898*77c1e3ccSAndroid Build Coastguard Worker }
899*77c1e3ccSAndroid Build Coastguard Worker
store_coding_context(MACROBLOCK * x,PICK_MODE_CONTEXT * ctx,int mode_index,int skippable)900*77c1e3ccSAndroid Build Coastguard Worker static inline void store_coding_context(
901*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_INTERNAL_STATS
902*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCK *x, PICK_MODE_CONTEXT *ctx, int mode_index,
903*77c1e3ccSAndroid Build Coastguard Worker #else
904*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCK *x, PICK_MODE_CONTEXT *ctx,
905*77c1e3ccSAndroid Build Coastguard Worker #endif // CONFIG_INTERNAL_STATS
906*77c1e3ccSAndroid Build Coastguard Worker int skippable) {
907*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *const xd = &x->e_mbd;
908*77c1e3ccSAndroid Build Coastguard Worker
909*77c1e3ccSAndroid Build Coastguard Worker // Take a snapshot of the coding context so it can be
910*77c1e3ccSAndroid Build Coastguard Worker // restored if we decide to encode this way
911*77c1e3ccSAndroid Build Coastguard Worker ctx->rd_stats.skip_txfm = x->txfm_search_info.skip_txfm;
912*77c1e3ccSAndroid Build Coastguard Worker ctx->skippable = skippable;
913*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_INTERNAL_STATS
914*77c1e3ccSAndroid Build Coastguard Worker ctx->best_mode_index = mode_index;
915*77c1e3ccSAndroid Build Coastguard Worker #endif // CONFIG_INTERNAL_STATS
916*77c1e3ccSAndroid Build Coastguard Worker ctx->mic = *xd->mi[0];
917*77c1e3ccSAndroid Build Coastguard Worker av1_copy_mbmi_ext_to_mbmi_ext_frame(&ctx->mbmi_ext_best, &x->mbmi_ext,
918*77c1e3ccSAndroid Build Coastguard Worker av1_ref_frame_type(xd->mi[0]->ref_frame));
919*77c1e3ccSAndroid Build Coastguard Worker }
920*77c1e3ccSAndroid Build Coastguard Worker
setup_buffer_ref_mvs_inter(const AV1_COMP * const cpi,MACROBLOCK * x,MV_REFERENCE_FRAME ref_frame,BLOCK_SIZE block_size,struct buf_2d yv12_mb[REF_FRAMES][MAX_MB_PLANE])921*77c1e3ccSAndroid Build Coastguard Worker static inline void setup_buffer_ref_mvs_inter(
922*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMP *const cpi, MACROBLOCK *x, MV_REFERENCE_FRAME ref_frame,
923*77c1e3ccSAndroid Build Coastguard Worker BLOCK_SIZE block_size, struct buf_2d yv12_mb[REF_FRAMES][MAX_MB_PLANE]) {
924*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *cm = &cpi->common;
925*77c1e3ccSAndroid Build Coastguard Worker const int num_planes = av1_num_planes(cm);
926*77c1e3ccSAndroid Build Coastguard Worker const YV12_BUFFER_CONFIG *scaled_ref_frame =
927*77c1e3ccSAndroid Build Coastguard Worker av1_get_scaled_ref_frame(cpi, ref_frame);
928*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *const xd = &x->e_mbd;
929*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *const mbmi = xd->mi[0];
930*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO_EXT *const mbmi_ext = &x->mbmi_ext;
931*77c1e3ccSAndroid Build Coastguard Worker const struct scale_factors *const sf =
932*77c1e3ccSAndroid Build Coastguard Worker get_ref_scale_factors_const(cm, ref_frame);
933*77c1e3ccSAndroid Build Coastguard Worker const YV12_BUFFER_CONFIG *yv12 = get_ref_frame_yv12_buf(cm, ref_frame);
934*77c1e3ccSAndroid Build Coastguard Worker assert(yv12 != NULL);
935*77c1e3ccSAndroid Build Coastguard Worker
936*77c1e3ccSAndroid Build Coastguard Worker if (scaled_ref_frame) {
937*77c1e3ccSAndroid Build Coastguard Worker // Setup pred block based on scaled reference, because av1_mv_pred() doesn't
938*77c1e3ccSAndroid Build Coastguard Worker // support scaling.
939*77c1e3ccSAndroid Build Coastguard Worker av1_setup_pred_block(xd, yv12_mb[ref_frame], scaled_ref_frame, NULL, NULL,
940*77c1e3ccSAndroid Build Coastguard Worker num_planes);
941*77c1e3ccSAndroid Build Coastguard Worker } else {
942*77c1e3ccSAndroid Build Coastguard Worker av1_setup_pred_block(xd, yv12_mb[ref_frame], yv12, sf, sf, num_planes);
943*77c1e3ccSAndroid Build Coastguard Worker }
944*77c1e3ccSAndroid Build Coastguard Worker
945*77c1e3ccSAndroid Build Coastguard Worker // Gets an initial list of candidate vectors from neighbours and orders them
946*77c1e3ccSAndroid Build Coastguard Worker av1_find_mv_refs(cm, xd, mbmi, ref_frame, mbmi_ext->ref_mv_count,
947*77c1e3ccSAndroid Build Coastguard Worker xd->ref_mv_stack, xd->weight, NULL, mbmi_ext->global_mvs,
948*77c1e3ccSAndroid Build Coastguard Worker mbmi_ext->mode_context);
949*77c1e3ccSAndroid Build Coastguard Worker // TODO(Ravi): Populate mbmi_ext->ref_mv_stack[ref_frame][4] and
950*77c1e3ccSAndroid Build Coastguard Worker // mbmi_ext->weight[ref_frame][4] inside av1_find_mv_refs.
951*77c1e3ccSAndroid Build Coastguard Worker av1_copy_usable_ref_mv_stack_and_weight(xd, mbmi_ext, ref_frame);
952*77c1e3ccSAndroid Build Coastguard Worker // Further refinement that is encode side only to test the top few candidates
953*77c1e3ccSAndroid Build Coastguard Worker // in full and choose the best as the center point for subsequent searches.
954*77c1e3ccSAndroid Build Coastguard Worker // The current implementation doesn't support scaling.
955*77c1e3ccSAndroid Build Coastguard Worker av1_mv_pred(cpi, x, yv12_mb[ref_frame][0].buf, yv12_mb[ref_frame][0].stride,
956*77c1e3ccSAndroid Build Coastguard Worker ref_frame, block_size);
957*77c1e3ccSAndroid Build Coastguard Worker
958*77c1e3ccSAndroid Build Coastguard Worker // Go back to unscaled reference.
959*77c1e3ccSAndroid Build Coastguard Worker if (scaled_ref_frame) {
960*77c1e3ccSAndroid Build Coastguard Worker // We had temporarily setup pred block based on scaled reference above. Go
961*77c1e3ccSAndroid Build Coastguard Worker // back to unscaled reference now, for subsequent use.
962*77c1e3ccSAndroid Build Coastguard Worker av1_setup_pred_block(xd, yv12_mb[ref_frame], yv12, sf, sf, num_planes);
963*77c1e3ccSAndroid Build Coastguard Worker }
964*77c1e3ccSAndroid Build Coastguard Worker }
965*77c1e3ccSAndroid Build Coastguard Worker
966*77c1e3ccSAndroid Build Coastguard Worker #define LEFT_TOP_MARGIN ((AOM_BORDER_IN_PIXELS - AOM_INTERP_EXTEND) << 3)
967*77c1e3ccSAndroid Build Coastguard Worker #define RIGHT_BOTTOM_MARGIN ((AOM_BORDER_IN_PIXELS - AOM_INTERP_EXTEND) << 3)
968*77c1e3ccSAndroid Build Coastguard Worker
969*77c1e3ccSAndroid Build Coastguard Worker // TODO(jingning): this mv clamping function should be block size dependent.
clamp_mv2(MV * mv,const MACROBLOCKD * xd)970*77c1e3ccSAndroid Build Coastguard Worker static inline void clamp_mv2(MV *mv, const MACROBLOCKD *xd) {
971*77c1e3ccSAndroid Build Coastguard Worker const SubpelMvLimits mv_limits = { xd->mb_to_left_edge - LEFT_TOP_MARGIN,
972*77c1e3ccSAndroid Build Coastguard Worker xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN,
973*77c1e3ccSAndroid Build Coastguard Worker xd->mb_to_top_edge - LEFT_TOP_MARGIN,
974*77c1e3ccSAndroid Build Coastguard Worker xd->mb_to_bottom_edge +
975*77c1e3ccSAndroid Build Coastguard Worker RIGHT_BOTTOM_MARGIN };
976*77c1e3ccSAndroid Build Coastguard Worker clamp_mv(mv, &mv_limits);
977*77c1e3ccSAndroid Build Coastguard Worker }
978*77c1e3ccSAndroid Build Coastguard Worker
979*77c1e3ccSAndroid Build Coastguard Worker /* If the current mode shares the same mv with other modes with higher cost,
980*77c1e3ccSAndroid Build Coastguard Worker * skip this mode. */
skip_repeated_mv(const AV1_COMMON * const cm,const MACROBLOCK * const x,PREDICTION_MODE this_mode,const MV_REFERENCE_FRAME ref_frames[2],InterModeSearchState * search_state)981*77c1e3ccSAndroid Build Coastguard Worker static int skip_repeated_mv(const AV1_COMMON *const cm,
982*77c1e3ccSAndroid Build Coastguard Worker const MACROBLOCK *const x,
983*77c1e3ccSAndroid Build Coastguard Worker PREDICTION_MODE this_mode,
984*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME ref_frames[2],
985*77c1e3ccSAndroid Build Coastguard Worker InterModeSearchState *search_state) {
986*77c1e3ccSAndroid Build Coastguard Worker const int is_comp_pred = ref_frames[1] > INTRA_FRAME;
987*77c1e3ccSAndroid Build Coastguard Worker const uint8_t ref_frame_type = av1_ref_frame_type(ref_frames);
988*77c1e3ccSAndroid Build Coastguard Worker const MB_MODE_INFO_EXT *const mbmi_ext = &x->mbmi_ext;
989*77c1e3ccSAndroid Build Coastguard Worker const int ref_mv_count = mbmi_ext->ref_mv_count[ref_frame_type];
990*77c1e3ccSAndroid Build Coastguard Worker PREDICTION_MODE compare_mode = MB_MODE_COUNT;
991*77c1e3ccSAndroid Build Coastguard Worker if (!is_comp_pred) {
992*77c1e3ccSAndroid Build Coastguard Worker if (this_mode == NEARMV) {
993*77c1e3ccSAndroid Build Coastguard Worker if (ref_mv_count == 0) {
994*77c1e3ccSAndroid Build Coastguard Worker // NEARMV has the same motion vector as NEARESTMV
995*77c1e3ccSAndroid Build Coastguard Worker compare_mode = NEARESTMV;
996*77c1e3ccSAndroid Build Coastguard Worker }
997*77c1e3ccSAndroid Build Coastguard Worker if (ref_mv_count == 1 &&
998*77c1e3ccSAndroid Build Coastguard Worker cm->global_motion[ref_frames[0]].wmtype <= TRANSLATION) {
999*77c1e3ccSAndroid Build Coastguard Worker // NEARMV has the same motion vector as GLOBALMV
1000*77c1e3ccSAndroid Build Coastguard Worker compare_mode = GLOBALMV;
1001*77c1e3ccSAndroid Build Coastguard Worker }
1002*77c1e3ccSAndroid Build Coastguard Worker }
1003*77c1e3ccSAndroid Build Coastguard Worker if (this_mode == GLOBALMV) {
1004*77c1e3ccSAndroid Build Coastguard Worker if (ref_mv_count == 0 &&
1005*77c1e3ccSAndroid Build Coastguard Worker cm->global_motion[ref_frames[0]].wmtype <= TRANSLATION) {
1006*77c1e3ccSAndroid Build Coastguard Worker // GLOBALMV has the same motion vector as NEARESTMV
1007*77c1e3ccSAndroid Build Coastguard Worker compare_mode = NEARESTMV;
1008*77c1e3ccSAndroid Build Coastguard Worker }
1009*77c1e3ccSAndroid Build Coastguard Worker if (ref_mv_count == 1) {
1010*77c1e3ccSAndroid Build Coastguard Worker // GLOBALMV has the same motion vector as NEARMV
1011*77c1e3ccSAndroid Build Coastguard Worker compare_mode = NEARMV;
1012*77c1e3ccSAndroid Build Coastguard Worker }
1013*77c1e3ccSAndroid Build Coastguard Worker }
1014*77c1e3ccSAndroid Build Coastguard Worker
1015*77c1e3ccSAndroid Build Coastguard Worker if (compare_mode != MB_MODE_COUNT) {
1016*77c1e3ccSAndroid Build Coastguard Worker // Use modelled_rd to check whether compare mode was searched
1017*77c1e3ccSAndroid Build Coastguard Worker if (search_state->modelled_rd[compare_mode][0][ref_frames[0]] !=
1018*77c1e3ccSAndroid Build Coastguard Worker INT64_MAX) {
1019*77c1e3ccSAndroid Build Coastguard Worker const int16_t mode_ctx =
1020*77c1e3ccSAndroid Build Coastguard Worker av1_mode_context_analyzer(mbmi_ext->mode_context, ref_frames);
1021*77c1e3ccSAndroid Build Coastguard Worker const int compare_cost =
1022*77c1e3ccSAndroid Build Coastguard Worker cost_mv_ref(&x->mode_costs, compare_mode, mode_ctx);
1023*77c1e3ccSAndroid Build Coastguard Worker const int this_cost = cost_mv_ref(&x->mode_costs, this_mode, mode_ctx);
1024*77c1e3ccSAndroid Build Coastguard Worker
1025*77c1e3ccSAndroid Build Coastguard Worker // Only skip if the mode cost is larger than compare mode cost
1026*77c1e3ccSAndroid Build Coastguard Worker if (this_cost > compare_cost) {
1027*77c1e3ccSAndroid Build Coastguard Worker search_state->modelled_rd[this_mode][0][ref_frames[0]] =
1028*77c1e3ccSAndroid Build Coastguard Worker search_state->modelled_rd[compare_mode][0][ref_frames[0]];
1029*77c1e3ccSAndroid Build Coastguard Worker return 1;
1030*77c1e3ccSAndroid Build Coastguard Worker }
1031*77c1e3ccSAndroid Build Coastguard Worker }
1032*77c1e3ccSAndroid Build Coastguard Worker }
1033*77c1e3ccSAndroid Build Coastguard Worker }
1034*77c1e3ccSAndroid Build Coastguard Worker return 0;
1035*77c1e3ccSAndroid Build Coastguard Worker }
1036*77c1e3ccSAndroid Build Coastguard Worker
clamp_and_check_mv(int_mv * out_mv,int_mv in_mv,const AV1_COMMON * cm,const MACROBLOCK * x)1037*77c1e3ccSAndroid Build Coastguard Worker static inline int clamp_and_check_mv(int_mv *out_mv, int_mv in_mv,
1038*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *cm,
1039*77c1e3ccSAndroid Build Coastguard Worker const MACROBLOCK *x) {
1040*77c1e3ccSAndroid Build Coastguard Worker const MACROBLOCKD *const xd = &x->e_mbd;
1041*77c1e3ccSAndroid Build Coastguard Worker *out_mv = in_mv;
1042*77c1e3ccSAndroid Build Coastguard Worker lower_mv_precision(&out_mv->as_mv, cm->features.allow_high_precision_mv,
1043*77c1e3ccSAndroid Build Coastguard Worker cm->features.cur_frame_force_integer_mv);
1044*77c1e3ccSAndroid Build Coastguard Worker clamp_mv2(&out_mv->as_mv, xd);
1045*77c1e3ccSAndroid Build Coastguard Worker return av1_is_fullmv_in_range(&x->mv_limits,
1046*77c1e3ccSAndroid Build Coastguard Worker get_fullmv_from_mv(&out_mv->as_mv));
1047*77c1e3ccSAndroid Build Coastguard Worker }
1048*77c1e3ccSAndroid Build Coastguard Worker
1049*77c1e3ccSAndroid Build Coastguard Worker // To use single newmv directly for compound modes, need to clamp the mv to the
1050*77c1e3ccSAndroid Build Coastguard Worker // valid mv range. Without this, encoder would generate out of range mv, and
1051*77c1e3ccSAndroid Build Coastguard Worker // this is seen in 8k encoding.
clamp_mv_in_range(MACROBLOCK * const x,int_mv * mv,int ref_idx)1052*77c1e3ccSAndroid Build Coastguard Worker static inline void clamp_mv_in_range(MACROBLOCK *const x, int_mv *mv,
1053*77c1e3ccSAndroid Build Coastguard Worker int ref_idx) {
1054*77c1e3ccSAndroid Build Coastguard Worker const int_mv ref_mv = av1_get_ref_mv(x, ref_idx);
1055*77c1e3ccSAndroid Build Coastguard Worker SubpelMvLimits mv_limits;
1056*77c1e3ccSAndroid Build Coastguard Worker
1057*77c1e3ccSAndroid Build Coastguard Worker av1_set_subpel_mv_search_range(&mv_limits, &x->mv_limits, &ref_mv.as_mv);
1058*77c1e3ccSAndroid Build Coastguard Worker clamp_mv(&mv->as_mv, &mv_limits);
1059*77c1e3ccSAndroid Build Coastguard Worker }
1060*77c1e3ccSAndroid Build Coastguard Worker
handle_newmv(const AV1_COMP * const cpi,MACROBLOCK * const x,const BLOCK_SIZE bsize,int_mv * cur_mv,int * const rate_mv,HandleInterModeArgs * const args,inter_mode_info * mode_info)1061*77c1e3ccSAndroid Build Coastguard Worker static int64_t handle_newmv(const AV1_COMP *const cpi, MACROBLOCK *const x,
1062*77c1e3ccSAndroid Build Coastguard Worker const BLOCK_SIZE bsize, int_mv *cur_mv,
1063*77c1e3ccSAndroid Build Coastguard Worker int *const rate_mv, HandleInterModeArgs *const args,
1064*77c1e3ccSAndroid Build Coastguard Worker inter_mode_info *mode_info) {
1065*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *const xd = &x->e_mbd;
1066*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *const mbmi = xd->mi[0];
1067*77c1e3ccSAndroid Build Coastguard Worker const int is_comp_pred = has_second_ref(mbmi);
1068*77c1e3ccSAndroid Build Coastguard Worker const PREDICTION_MODE this_mode = mbmi->mode;
1069*77c1e3ccSAndroid Build Coastguard Worker const int refs[2] = { mbmi->ref_frame[0],
1070*77c1e3ccSAndroid Build Coastguard Worker mbmi->ref_frame[1] < 0 ? 0 : mbmi->ref_frame[1] };
1071*77c1e3ccSAndroid Build Coastguard Worker const int ref_mv_idx = mbmi->ref_mv_idx;
1072*77c1e3ccSAndroid Build Coastguard Worker
1073*77c1e3ccSAndroid Build Coastguard Worker if (is_comp_pred) {
1074*77c1e3ccSAndroid Build Coastguard Worker const int valid_mv0 = args->single_newmv_valid[ref_mv_idx][refs[0]];
1075*77c1e3ccSAndroid Build Coastguard Worker const int valid_mv1 = args->single_newmv_valid[ref_mv_idx][refs[1]];
1076*77c1e3ccSAndroid Build Coastguard Worker if (this_mode == NEW_NEWMV) {
1077*77c1e3ccSAndroid Build Coastguard Worker if (valid_mv0) {
1078*77c1e3ccSAndroid Build Coastguard Worker cur_mv[0].as_int = args->single_newmv[ref_mv_idx][refs[0]].as_int;
1079*77c1e3ccSAndroid Build Coastguard Worker clamp_mv_in_range(x, &cur_mv[0], 0);
1080*77c1e3ccSAndroid Build Coastguard Worker }
1081*77c1e3ccSAndroid Build Coastguard Worker if (valid_mv1) {
1082*77c1e3ccSAndroid Build Coastguard Worker cur_mv[1].as_int = args->single_newmv[ref_mv_idx][refs[1]].as_int;
1083*77c1e3ccSAndroid Build Coastguard Worker clamp_mv_in_range(x, &cur_mv[1], 1);
1084*77c1e3ccSAndroid Build Coastguard Worker }
1085*77c1e3ccSAndroid Build Coastguard Worker *rate_mv = 0;
1086*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < 2; ++i) {
1087*77c1e3ccSAndroid Build Coastguard Worker const int_mv ref_mv = av1_get_ref_mv(x, i);
1088*77c1e3ccSAndroid Build Coastguard Worker *rate_mv += av1_mv_bit_cost(&cur_mv[i].as_mv, &ref_mv.as_mv,
1089*77c1e3ccSAndroid Build Coastguard Worker x->mv_costs->nmv_joint_cost,
1090*77c1e3ccSAndroid Build Coastguard Worker x->mv_costs->mv_cost_stack, MV_COST_WEIGHT);
1091*77c1e3ccSAndroid Build Coastguard Worker }
1092*77c1e3ccSAndroid Build Coastguard Worker } else if (this_mode == NEAREST_NEWMV || this_mode == NEAR_NEWMV) {
1093*77c1e3ccSAndroid Build Coastguard Worker if (valid_mv1) {
1094*77c1e3ccSAndroid Build Coastguard Worker cur_mv[1].as_int = args->single_newmv[ref_mv_idx][refs[1]].as_int;
1095*77c1e3ccSAndroid Build Coastguard Worker clamp_mv_in_range(x, &cur_mv[1], 1);
1096*77c1e3ccSAndroid Build Coastguard Worker }
1097*77c1e3ccSAndroid Build Coastguard Worker const int_mv ref_mv = av1_get_ref_mv(x, 1);
1098*77c1e3ccSAndroid Build Coastguard Worker *rate_mv = av1_mv_bit_cost(&cur_mv[1].as_mv, &ref_mv.as_mv,
1099*77c1e3ccSAndroid Build Coastguard Worker x->mv_costs->nmv_joint_cost,
1100*77c1e3ccSAndroid Build Coastguard Worker x->mv_costs->mv_cost_stack, MV_COST_WEIGHT);
1101*77c1e3ccSAndroid Build Coastguard Worker } else {
1102*77c1e3ccSAndroid Build Coastguard Worker assert(this_mode == NEW_NEARESTMV || this_mode == NEW_NEARMV);
1103*77c1e3ccSAndroid Build Coastguard Worker if (valid_mv0) {
1104*77c1e3ccSAndroid Build Coastguard Worker cur_mv[0].as_int = args->single_newmv[ref_mv_idx][refs[0]].as_int;
1105*77c1e3ccSAndroid Build Coastguard Worker clamp_mv_in_range(x, &cur_mv[0], 0);
1106*77c1e3ccSAndroid Build Coastguard Worker }
1107*77c1e3ccSAndroid Build Coastguard Worker const int_mv ref_mv = av1_get_ref_mv(x, 0);
1108*77c1e3ccSAndroid Build Coastguard Worker *rate_mv = av1_mv_bit_cost(&cur_mv[0].as_mv, &ref_mv.as_mv,
1109*77c1e3ccSAndroid Build Coastguard Worker x->mv_costs->nmv_joint_cost,
1110*77c1e3ccSAndroid Build Coastguard Worker x->mv_costs->mv_cost_stack, MV_COST_WEIGHT);
1111*77c1e3ccSAndroid Build Coastguard Worker }
1112*77c1e3ccSAndroid Build Coastguard Worker } else {
1113*77c1e3ccSAndroid Build Coastguard Worker // Single ref case.
1114*77c1e3ccSAndroid Build Coastguard Worker const int ref_idx = 0;
1115*77c1e3ccSAndroid Build Coastguard Worker int search_range = INT_MAX;
1116*77c1e3ccSAndroid Build Coastguard Worker
1117*77c1e3ccSAndroid Build Coastguard Worker if (cpi->sf.mv_sf.reduce_search_range && mbmi->ref_mv_idx > 0) {
1118*77c1e3ccSAndroid Build Coastguard Worker const MV ref_mv = av1_get_ref_mv(x, ref_idx).as_mv;
1119*77c1e3ccSAndroid Build Coastguard Worker int min_mv_diff = INT_MAX;
1120*77c1e3ccSAndroid Build Coastguard Worker int best_match = -1;
1121*77c1e3ccSAndroid Build Coastguard Worker MV prev_ref_mv[2] = { { 0 } };
1122*77c1e3ccSAndroid Build Coastguard Worker for (int idx = 0; idx < mbmi->ref_mv_idx; ++idx) {
1123*77c1e3ccSAndroid Build Coastguard Worker prev_ref_mv[idx] = av1_get_ref_mv_from_stack(ref_idx, mbmi->ref_frame,
1124*77c1e3ccSAndroid Build Coastguard Worker idx, &x->mbmi_ext)
1125*77c1e3ccSAndroid Build Coastguard Worker .as_mv;
1126*77c1e3ccSAndroid Build Coastguard Worker const int ref_mv_diff = AOMMAX(abs(ref_mv.row - prev_ref_mv[idx].row),
1127*77c1e3ccSAndroid Build Coastguard Worker abs(ref_mv.col - prev_ref_mv[idx].col));
1128*77c1e3ccSAndroid Build Coastguard Worker
1129*77c1e3ccSAndroid Build Coastguard Worker if (min_mv_diff > ref_mv_diff) {
1130*77c1e3ccSAndroid Build Coastguard Worker min_mv_diff = ref_mv_diff;
1131*77c1e3ccSAndroid Build Coastguard Worker best_match = idx;
1132*77c1e3ccSAndroid Build Coastguard Worker }
1133*77c1e3ccSAndroid Build Coastguard Worker }
1134*77c1e3ccSAndroid Build Coastguard Worker
1135*77c1e3ccSAndroid Build Coastguard Worker if (min_mv_diff < (16 << 3)) {
1136*77c1e3ccSAndroid Build Coastguard Worker if (args->single_newmv_valid[best_match][refs[0]]) {
1137*77c1e3ccSAndroid Build Coastguard Worker search_range = min_mv_diff;
1138*77c1e3ccSAndroid Build Coastguard Worker search_range +=
1139*77c1e3ccSAndroid Build Coastguard Worker AOMMAX(abs(args->single_newmv[best_match][refs[0]].as_mv.row -
1140*77c1e3ccSAndroid Build Coastguard Worker prev_ref_mv[best_match].row),
1141*77c1e3ccSAndroid Build Coastguard Worker abs(args->single_newmv[best_match][refs[0]].as_mv.col -
1142*77c1e3ccSAndroid Build Coastguard Worker prev_ref_mv[best_match].col));
1143*77c1e3ccSAndroid Build Coastguard Worker // Get full pixel search range.
1144*77c1e3ccSAndroid Build Coastguard Worker search_range = (search_range + 4) >> 3;
1145*77c1e3ccSAndroid Build Coastguard Worker }
1146*77c1e3ccSAndroid Build Coastguard Worker }
1147*77c1e3ccSAndroid Build Coastguard Worker }
1148*77c1e3ccSAndroid Build Coastguard Worker
1149*77c1e3ccSAndroid Build Coastguard Worker int_mv best_mv;
1150*77c1e3ccSAndroid Build Coastguard Worker av1_single_motion_search(cpi, x, bsize, ref_idx, rate_mv, search_range,
1151*77c1e3ccSAndroid Build Coastguard Worker mode_info, &best_mv, args);
1152*77c1e3ccSAndroid Build Coastguard Worker if (best_mv.as_int == INVALID_MV) return INT64_MAX;
1153*77c1e3ccSAndroid Build Coastguard Worker
1154*77c1e3ccSAndroid Build Coastguard Worker args->single_newmv[ref_mv_idx][refs[0]] = best_mv;
1155*77c1e3ccSAndroid Build Coastguard Worker args->single_newmv_rate[ref_mv_idx][refs[0]] = *rate_mv;
1156*77c1e3ccSAndroid Build Coastguard Worker args->single_newmv_valid[ref_mv_idx][refs[0]] = 1;
1157*77c1e3ccSAndroid Build Coastguard Worker cur_mv[0].as_int = best_mv.as_int;
1158*77c1e3ccSAndroid Build Coastguard Worker
1159*77c1e3ccSAndroid Build Coastguard Worker // Return after single_newmv is set.
1160*77c1e3ccSAndroid Build Coastguard Worker if (mode_info[mbmi->ref_mv_idx].skip) return INT64_MAX;
1161*77c1e3ccSAndroid Build Coastguard Worker }
1162*77c1e3ccSAndroid Build Coastguard Worker
1163*77c1e3ccSAndroid Build Coastguard Worker return 0;
1164*77c1e3ccSAndroid Build Coastguard Worker }
1165*77c1e3ccSAndroid Build Coastguard Worker
update_mode_start_end_index(const AV1_COMP * const cpi,const MB_MODE_INFO * const mbmi,int * mode_index_start,int * mode_index_end,int last_motion_mode_allowed,int interintra_allowed,int eval_motion_mode)1166*77c1e3ccSAndroid Build Coastguard Worker static inline void update_mode_start_end_index(
1167*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMP *const cpi, const MB_MODE_INFO *const mbmi,
1168*77c1e3ccSAndroid Build Coastguard Worker int *mode_index_start, int *mode_index_end, int last_motion_mode_allowed,
1169*77c1e3ccSAndroid Build Coastguard Worker int interintra_allowed, int eval_motion_mode) {
1170*77c1e3ccSAndroid Build Coastguard Worker *mode_index_start = (int)SIMPLE_TRANSLATION;
1171*77c1e3ccSAndroid Build Coastguard Worker *mode_index_end = (int)last_motion_mode_allowed + interintra_allowed;
1172*77c1e3ccSAndroid Build Coastguard Worker if (cpi->sf.winner_mode_sf.motion_mode_for_winner_cand) {
1173*77c1e3ccSAndroid Build Coastguard Worker if (!eval_motion_mode) {
1174*77c1e3ccSAndroid Build Coastguard Worker *mode_index_end = (int)SIMPLE_TRANSLATION;
1175*77c1e3ccSAndroid Build Coastguard Worker } else {
1176*77c1e3ccSAndroid Build Coastguard Worker // Set the start index appropriately to process motion modes other than
1177*77c1e3ccSAndroid Build Coastguard Worker // simple translation
1178*77c1e3ccSAndroid Build Coastguard Worker *mode_index_start = 1;
1179*77c1e3ccSAndroid Build Coastguard Worker }
1180*77c1e3ccSAndroid Build Coastguard Worker }
1181*77c1e3ccSAndroid Build Coastguard Worker if (cpi->sf.inter_sf.extra_prune_warped && mbmi->bsize > BLOCK_16X16)
1182*77c1e3ccSAndroid Build Coastguard Worker *mode_index_end = SIMPLE_TRANSLATION;
1183*77c1e3ccSAndroid Build Coastguard Worker }
1184*77c1e3ccSAndroid Build Coastguard Worker
1185*77c1e3ccSAndroid Build Coastguard Worker /*!\brief AV1 motion mode search
1186*77c1e3ccSAndroid Build Coastguard Worker *
1187*77c1e3ccSAndroid Build Coastguard Worker * \ingroup inter_mode_search
1188*77c1e3ccSAndroid Build Coastguard Worker * Function to search over and determine the motion mode. It will update
1189*77c1e3ccSAndroid Build Coastguard Worker * mbmi->motion_mode to one of SIMPLE_TRANSLATION, OBMC_CAUSAL, or
1190*77c1e3ccSAndroid Build Coastguard Worker * WARPED_CAUSAL and determine any necessary side information for the selected
1191*77c1e3ccSAndroid Build Coastguard Worker * motion mode. It will also perform the full transform search, unless the
1192*77c1e3ccSAndroid Build Coastguard Worker * input parameter do_tx_search indicates to do an estimation of the RD rather
1193*77c1e3ccSAndroid Build Coastguard Worker * than an RD corresponding to a full transform search. It will return the
1194*77c1e3ccSAndroid Build Coastguard Worker * RD for the final motion_mode.
1195*77c1e3ccSAndroid Build Coastguard Worker * Do the RD search for a given inter mode and compute all information relevant
1196*77c1e3ccSAndroid Build Coastguard Worker * to the input mode. It will compute the best MV,
1197*77c1e3ccSAndroid Build Coastguard Worker * compound parameters (if the mode is a compound mode) and interpolation filter
1198*77c1e3ccSAndroid Build Coastguard Worker * parameters.
1199*77c1e3ccSAndroid Build Coastguard Worker *
1200*77c1e3ccSAndroid Build Coastguard Worker * \param[in] cpi Top-level encoder structure.
1201*77c1e3ccSAndroid Build Coastguard Worker * \param[in] tile_data Pointer to struct holding adaptive
1202*77c1e3ccSAndroid Build Coastguard Worker * data/contexts/models for the tile during
1203*77c1e3ccSAndroid Build Coastguard Worker * encoding.
1204*77c1e3ccSAndroid Build Coastguard Worker * \param[in] x Pointer to struct holding all the data for
1205*77c1e3ccSAndroid Build Coastguard Worker * the current macroblock.
1206*77c1e3ccSAndroid Build Coastguard Worker * \param[in] bsize Current block size.
1207*77c1e3ccSAndroid Build Coastguard Worker * \param[in,out] rd_stats Struct to keep track of the overall RD
1208*77c1e3ccSAndroid Build Coastguard Worker * information.
1209*77c1e3ccSAndroid Build Coastguard Worker * \param[in,out] rd_stats_y Struct to keep track of the RD information
1210*77c1e3ccSAndroid Build Coastguard Worker * for only the Y plane.
1211*77c1e3ccSAndroid Build Coastguard Worker * \param[in,out] rd_stats_uv Struct to keep track of the RD information
1212*77c1e3ccSAndroid Build Coastguard Worker * for only the UV planes.
1213*77c1e3ccSAndroid Build Coastguard Worker * \param[in] args HandleInterModeArgs struct holding
1214*77c1e3ccSAndroid Build Coastguard Worker * miscellaneous arguments for inter mode
1215*77c1e3ccSAndroid Build Coastguard Worker * search. See the documentation for this
1216*77c1e3ccSAndroid Build Coastguard Worker * struct for a description of each member.
1217*77c1e3ccSAndroid Build Coastguard Worker * \param[in] ref_best_rd Best RD found so far for this block.
1218*77c1e3ccSAndroid Build Coastguard Worker * It is used for early termination of this
1219*77c1e3ccSAndroid Build Coastguard Worker * search if the RD exceeds this value.
1220*77c1e3ccSAndroid Build Coastguard Worker * \param[in,out] ref_skip_rd A length 2 array, where skip_rd[0] is the
1221*77c1e3ccSAndroid Build Coastguard Worker * best total RD for a skip mode so far, and
1222*77c1e3ccSAndroid Build Coastguard Worker * skip_rd[1] is the best RD for a skip mode so
1223*77c1e3ccSAndroid Build Coastguard Worker * far in luma. This is used as a speed feature
1224*77c1e3ccSAndroid Build Coastguard Worker * to skip the transform search if the computed
1225*77c1e3ccSAndroid Build Coastguard Worker * skip RD for the current mode is not better
1226*77c1e3ccSAndroid Build Coastguard Worker * than the best skip_rd so far.
1227*77c1e3ccSAndroid Build Coastguard Worker * \param[in,out] rate_mv The rate associated with the motion vectors.
1228*77c1e3ccSAndroid Build Coastguard Worker * This will be modified if a motion search is
1229*77c1e3ccSAndroid Build Coastguard Worker * done in the motion mode search.
1230*77c1e3ccSAndroid Build Coastguard Worker * \param[in,out] orig_dst A prediction buffer to hold a computed
1231*77c1e3ccSAndroid Build Coastguard Worker * prediction. This will eventually hold the
1232*77c1e3ccSAndroid Build Coastguard Worker * final prediction, and the tmp_dst info will
1233*77c1e3ccSAndroid Build Coastguard Worker * be copied here.
1234*77c1e3ccSAndroid Build Coastguard Worker * \param[in,out] best_est_rd Estimated RD for motion mode search if
1235*77c1e3ccSAndroid Build Coastguard Worker * do_tx_search (see below) is 0.
1236*77c1e3ccSAndroid Build Coastguard Worker * \param[in] do_tx_search Parameter to indicate whether or not to do
1237*77c1e3ccSAndroid Build Coastguard Worker * a full transform search. This will compute
1238*77c1e3ccSAndroid Build Coastguard Worker * an estimated RD for the modes without the
1239*77c1e3ccSAndroid Build Coastguard Worker * transform search and later perform the full
1240*77c1e3ccSAndroid Build Coastguard Worker * transform search on the best candidates.
1241*77c1e3ccSAndroid Build Coastguard Worker * \param[in] inter_modes_info InterModesInfo struct to hold inter mode
1242*77c1e3ccSAndroid Build Coastguard Worker * information to perform a full transform
1243*77c1e3ccSAndroid Build Coastguard Worker * search only on winning candidates searched
1244*77c1e3ccSAndroid Build Coastguard Worker * with an estimate for transform coding RD.
1245*77c1e3ccSAndroid Build Coastguard Worker * \param[in] eval_motion_mode Boolean whether or not to evaluate motion
1246*77c1e3ccSAndroid Build Coastguard Worker * motion modes other than SIMPLE_TRANSLATION.
1247*77c1e3ccSAndroid Build Coastguard Worker * \param[out] yrd Stores the rdcost corresponding to encoding
1248*77c1e3ccSAndroid Build Coastguard Worker * the luma plane.
1249*77c1e3ccSAndroid Build Coastguard Worker * \return Returns INT64_MAX if the determined motion mode is invalid and the
1250*77c1e3ccSAndroid Build Coastguard Worker * current motion mode being tested should be skipped. It returns 0 if the
1251*77c1e3ccSAndroid Build Coastguard Worker * motion mode search is a success.
1252*77c1e3ccSAndroid Build Coastguard Worker */
motion_mode_rd(const AV1_COMP * const cpi,TileDataEnc * tile_data,MACROBLOCK * const x,BLOCK_SIZE bsize,RD_STATS * rd_stats,RD_STATS * rd_stats_y,RD_STATS * rd_stats_uv,HandleInterModeArgs * const args,int64_t ref_best_rd,int64_t * ref_skip_rd,int * rate_mv,const BUFFER_SET * orig_dst,int64_t * best_est_rd,int do_tx_search,InterModesInfo * inter_modes_info,int eval_motion_mode,int64_t * yrd)1253*77c1e3ccSAndroid Build Coastguard Worker static int64_t motion_mode_rd(
1254*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMP *const cpi, TileDataEnc *tile_data, MACROBLOCK *const x,
1255*77c1e3ccSAndroid Build Coastguard Worker BLOCK_SIZE bsize, RD_STATS *rd_stats, RD_STATS *rd_stats_y,
1256*77c1e3ccSAndroid Build Coastguard Worker RD_STATS *rd_stats_uv, HandleInterModeArgs *const args, int64_t ref_best_rd,
1257*77c1e3ccSAndroid Build Coastguard Worker int64_t *ref_skip_rd, int *rate_mv, const BUFFER_SET *orig_dst,
1258*77c1e3ccSAndroid Build Coastguard Worker int64_t *best_est_rd, int do_tx_search, InterModesInfo *inter_modes_info,
1259*77c1e3ccSAndroid Build Coastguard Worker int eval_motion_mode, int64_t *yrd) {
1260*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *const cm = &cpi->common;
1261*77c1e3ccSAndroid Build Coastguard Worker const FeatureFlags *const features = &cm->features;
1262*77c1e3ccSAndroid Build Coastguard Worker TxfmSearchInfo *txfm_info = &x->txfm_search_info;
1263*77c1e3ccSAndroid Build Coastguard Worker const int num_planes = av1_num_planes(cm);
1264*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *xd = &x->e_mbd;
1265*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *mbmi = xd->mi[0];
1266*77c1e3ccSAndroid Build Coastguard Worker const int is_comp_pred = has_second_ref(mbmi);
1267*77c1e3ccSAndroid Build Coastguard Worker const PREDICTION_MODE this_mode = mbmi->mode;
1268*77c1e3ccSAndroid Build Coastguard Worker const int rate2_nocoeff = rd_stats->rate;
1269*77c1e3ccSAndroid Build Coastguard Worker int best_xskip_txfm = 0;
1270*77c1e3ccSAndroid Build Coastguard Worker RD_STATS best_rd_stats, best_rd_stats_y, best_rd_stats_uv;
1271*77c1e3ccSAndroid Build Coastguard Worker uint8_t best_blk_skip[MAX_MIB_SIZE * MAX_MIB_SIZE];
1272*77c1e3ccSAndroid Build Coastguard Worker uint8_t best_tx_type_map[MAX_MIB_SIZE * MAX_MIB_SIZE];
1273*77c1e3ccSAndroid Build Coastguard Worker const int rate_mv0 = *rate_mv;
1274*77c1e3ccSAndroid Build Coastguard Worker const int interintra_allowed = cm->seq_params->enable_interintra_compound &&
1275*77c1e3ccSAndroid Build Coastguard Worker is_interintra_allowed(mbmi) &&
1276*77c1e3ccSAndroid Build Coastguard Worker mbmi->compound_idx;
1277*77c1e3ccSAndroid Build Coastguard Worker WARP_SAMPLE_INFO *const warp_sample_info =
1278*77c1e3ccSAndroid Build Coastguard Worker &x->warp_sample_info[mbmi->ref_frame[0]];
1279*77c1e3ccSAndroid Build Coastguard Worker int *pts0 = warp_sample_info->pts;
1280*77c1e3ccSAndroid Build Coastguard Worker int *pts_inref0 = warp_sample_info->pts_inref;
1281*77c1e3ccSAndroid Build Coastguard Worker
1282*77c1e3ccSAndroid Build Coastguard Worker assert(mbmi->ref_frame[1] != INTRA_FRAME);
1283*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME ref_frame_1 = mbmi->ref_frame[1];
1284*77c1e3ccSAndroid Build Coastguard Worker av1_invalid_rd_stats(&best_rd_stats);
1285*77c1e3ccSAndroid Build Coastguard Worker mbmi->num_proj_ref = 1; // assume num_proj_ref >=1
1286*77c1e3ccSAndroid Build Coastguard Worker MOTION_MODE last_motion_mode_allowed = SIMPLE_TRANSLATION;
1287*77c1e3ccSAndroid Build Coastguard Worker *yrd = INT64_MAX;
1288*77c1e3ccSAndroid Build Coastguard Worker if (features->switchable_motion_mode) {
1289*77c1e3ccSAndroid Build Coastguard Worker // Determine which motion modes to search if more than SIMPLE_TRANSLATION
1290*77c1e3ccSAndroid Build Coastguard Worker // is allowed.
1291*77c1e3ccSAndroid Build Coastguard Worker last_motion_mode_allowed = motion_mode_allowed(
1292*77c1e3ccSAndroid Build Coastguard Worker xd->global_motion, xd, mbmi, features->allow_warped_motion);
1293*77c1e3ccSAndroid Build Coastguard Worker }
1294*77c1e3ccSAndroid Build Coastguard Worker
1295*77c1e3ccSAndroid Build Coastguard Worker if (last_motion_mode_allowed == WARPED_CAUSAL) {
1296*77c1e3ccSAndroid Build Coastguard Worker // Collect projection samples used in least squares approximation of
1297*77c1e3ccSAndroid Build Coastguard Worker // the warped motion parameters if WARPED_CAUSAL is going to be searched.
1298*77c1e3ccSAndroid Build Coastguard Worker if (warp_sample_info->num < 0) {
1299*77c1e3ccSAndroid Build Coastguard Worker warp_sample_info->num = av1_findSamples(cm, xd, pts0, pts_inref0);
1300*77c1e3ccSAndroid Build Coastguard Worker }
1301*77c1e3ccSAndroid Build Coastguard Worker mbmi->num_proj_ref = warp_sample_info->num;
1302*77c1e3ccSAndroid Build Coastguard Worker }
1303*77c1e3ccSAndroid Build Coastguard Worker const int total_samples = mbmi->num_proj_ref;
1304*77c1e3ccSAndroid Build Coastguard Worker if (total_samples == 0) {
1305*77c1e3ccSAndroid Build Coastguard Worker // Do not search WARPED_CAUSAL if there are no samples to use to determine
1306*77c1e3ccSAndroid Build Coastguard Worker // warped parameters.
1307*77c1e3ccSAndroid Build Coastguard Worker last_motion_mode_allowed = OBMC_CAUSAL;
1308*77c1e3ccSAndroid Build Coastguard Worker }
1309*77c1e3ccSAndroid Build Coastguard Worker
1310*77c1e3ccSAndroid Build Coastguard Worker const MB_MODE_INFO base_mbmi = *mbmi;
1311*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO best_mbmi;
1312*77c1e3ccSAndroid Build Coastguard Worker const int interp_filter = features->interp_filter;
1313*77c1e3ccSAndroid Build Coastguard Worker const int switchable_rate =
1314*77c1e3ccSAndroid Build Coastguard Worker av1_is_interp_needed(xd)
1315*77c1e3ccSAndroid Build Coastguard Worker ? av1_get_switchable_rate(x, xd, interp_filter,
1316*77c1e3ccSAndroid Build Coastguard Worker cm->seq_params->enable_dual_filter)
1317*77c1e3ccSAndroid Build Coastguard Worker : 0;
1318*77c1e3ccSAndroid Build Coastguard Worker int64_t best_rd = INT64_MAX;
1319*77c1e3ccSAndroid Build Coastguard Worker int best_rate_mv = rate_mv0;
1320*77c1e3ccSAndroid Build Coastguard Worker const int mi_row = xd->mi_row;
1321*77c1e3ccSAndroid Build Coastguard Worker const int mi_col = xd->mi_col;
1322*77c1e3ccSAndroid Build Coastguard Worker int mode_index_start, mode_index_end;
1323*77c1e3ccSAndroid Build Coastguard Worker const int txfm_rd_gate_level =
1324*77c1e3ccSAndroid Build Coastguard Worker get_txfm_rd_gate_level(cm->seq_params->enable_masked_compound,
1325*77c1e3ccSAndroid Build Coastguard Worker cpi->sf.inter_sf.txfm_rd_gate_level, bsize,
1326*77c1e3ccSAndroid Build Coastguard Worker TX_SEARCH_MOTION_MODE, eval_motion_mode);
1327*77c1e3ccSAndroid Build Coastguard Worker
1328*77c1e3ccSAndroid Build Coastguard Worker // Modify the start and end index according to speed features. For example,
1329*77c1e3ccSAndroid Build Coastguard Worker // if SIMPLE_TRANSLATION has already been searched according to
1330*77c1e3ccSAndroid Build Coastguard Worker // the motion_mode_for_winner_cand speed feature, update the mode_index_start
1331*77c1e3ccSAndroid Build Coastguard Worker // to avoid searching it again.
1332*77c1e3ccSAndroid Build Coastguard Worker update_mode_start_end_index(cpi, mbmi, &mode_index_start, &mode_index_end,
1333*77c1e3ccSAndroid Build Coastguard Worker last_motion_mode_allowed, interintra_allowed,
1334*77c1e3ccSAndroid Build Coastguard Worker eval_motion_mode);
1335*77c1e3ccSAndroid Build Coastguard Worker // Main function loop. This loops over all of the possible motion modes and
1336*77c1e3ccSAndroid Build Coastguard Worker // computes RD to determine the best one. This process includes computing
1337*77c1e3ccSAndroid Build Coastguard Worker // any necessary side information for the motion mode and performing the
1338*77c1e3ccSAndroid Build Coastguard Worker // transform search.
1339*77c1e3ccSAndroid Build Coastguard Worker for (int mode_index = mode_index_start; mode_index <= mode_index_end;
1340*77c1e3ccSAndroid Build Coastguard Worker mode_index++) {
1341*77c1e3ccSAndroid Build Coastguard Worker if (args->skip_motion_mode && mode_index) continue;
1342*77c1e3ccSAndroid Build Coastguard Worker int tmp_rate2 = rate2_nocoeff;
1343*77c1e3ccSAndroid Build Coastguard Worker const int is_interintra_mode = mode_index > (int)last_motion_mode_allowed;
1344*77c1e3ccSAndroid Build Coastguard Worker int tmp_rate_mv = rate_mv0;
1345*77c1e3ccSAndroid Build Coastguard Worker
1346*77c1e3ccSAndroid Build Coastguard Worker *mbmi = base_mbmi;
1347*77c1e3ccSAndroid Build Coastguard Worker if (is_interintra_mode) {
1348*77c1e3ccSAndroid Build Coastguard Worker // Only use SIMPLE_TRANSLATION for interintra
1349*77c1e3ccSAndroid Build Coastguard Worker mbmi->motion_mode = SIMPLE_TRANSLATION;
1350*77c1e3ccSAndroid Build Coastguard Worker } else {
1351*77c1e3ccSAndroid Build Coastguard Worker mbmi->motion_mode = (MOTION_MODE)mode_index;
1352*77c1e3ccSAndroid Build Coastguard Worker assert(mbmi->ref_frame[1] != INTRA_FRAME);
1353*77c1e3ccSAndroid Build Coastguard Worker }
1354*77c1e3ccSAndroid Build Coastguard Worker
1355*77c1e3ccSAndroid Build Coastguard Worker // Do not search OBMC if the probability of selecting it is below a
1356*77c1e3ccSAndroid Build Coastguard Worker // predetermined threshold for this update_type and block size.
1357*77c1e3ccSAndroid Build Coastguard Worker const FRAME_UPDATE_TYPE update_type =
1358*77c1e3ccSAndroid Build Coastguard Worker get_frame_update_type(&cpi->ppi->gf_group, cpi->gf_frame_index);
1359*77c1e3ccSAndroid Build Coastguard Worker int use_actual_frame_probs = 1;
1360*77c1e3ccSAndroid Build Coastguard Worker int prune_obmc;
1361*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_FPMT_TEST
1362*77c1e3ccSAndroid Build Coastguard Worker use_actual_frame_probs =
1363*77c1e3ccSAndroid Build Coastguard Worker (cpi->ppi->fpmt_unit_test_cfg == PARALLEL_SIMULATION_ENCODE) ? 0 : 1;
1364*77c1e3ccSAndroid Build Coastguard Worker if (!use_actual_frame_probs) {
1365*77c1e3ccSAndroid Build Coastguard Worker prune_obmc = cpi->ppi->temp_frame_probs.obmc_probs[update_type][bsize] <
1366*77c1e3ccSAndroid Build Coastguard Worker cpi->sf.inter_sf.prune_obmc_prob_thresh;
1367*77c1e3ccSAndroid Build Coastguard Worker }
1368*77c1e3ccSAndroid Build Coastguard Worker #endif
1369*77c1e3ccSAndroid Build Coastguard Worker if (use_actual_frame_probs) {
1370*77c1e3ccSAndroid Build Coastguard Worker prune_obmc = cpi->ppi->frame_probs.obmc_probs[update_type][bsize] <
1371*77c1e3ccSAndroid Build Coastguard Worker cpi->sf.inter_sf.prune_obmc_prob_thresh;
1372*77c1e3ccSAndroid Build Coastguard Worker }
1373*77c1e3ccSAndroid Build Coastguard Worker if ((!cpi->oxcf.motion_mode_cfg.enable_obmc || prune_obmc) &&
1374*77c1e3ccSAndroid Build Coastguard Worker mbmi->motion_mode == OBMC_CAUSAL)
1375*77c1e3ccSAndroid Build Coastguard Worker continue;
1376*77c1e3ccSAndroid Build Coastguard Worker
1377*77c1e3ccSAndroid Build Coastguard Worker if (mbmi->motion_mode == SIMPLE_TRANSLATION && !is_interintra_mode) {
1378*77c1e3ccSAndroid Build Coastguard Worker // SIMPLE_TRANSLATION mode: no need to recalculate.
1379*77c1e3ccSAndroid Build Coastguard Worker // The prediction is calculated before motion_mode_rd() is called in
1380*77c1e3ccSAndroid Build Coastguard Worker // handle_inter_mode()
1381*77c1e3ccSAndroid Build Coastguard Worker } else if (mbmi->motion_mode == OBMC_CAUSAL) {
1382*77c1e3ccSAndroid Build Coastguard Worker const uint32_t cur_mv = mbmi->mv[0].as_int;
1383*77c1e3ccSAndroid Build Coastguard Worker // OBMC_CAUSAL not allowed for compound prediction
1384*77c1e3ccSAndroid Build Coastguard Worker assert(!is_comp_pred);
1385*77c1e3ccSAndroid Build Coastguard Worker if (have_newmv_in_inter_mode(this_mode)) {
1386*77c1e3ccSAndroid Build Coastguard Worker av1_single_motion_search(cpi, x, bsize, 0, &tmp_rate_mv, INT_MAX, NULL,
1387*77c1e3ccSAndroid Build Coastguard Worker &mbmi->mv[0], NULL);
1388*77c1e3ccSAndroid Build Coastguard Worker tmp_rate2 = rate2_nocoeff - rate_mv0 + tmp_rate_mv;
1389*77c1e3ccSAndroid Build Coastguard Worker }
1390*77c1e3ccSAndroid Build Coastguard Worker if ((mbmi->mv[0].as_int != cur_mv) || eval_motion_mode) {
1391*77c1e3ccSAndroid Build Coastguard Worker // Build the predictor according to the current motion vector if it has
1392*77c1e3ccSAndroid Build Coastguard Worker // not already been built
1393*77c1e3ccSAndroid Build Coastguard Worker av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, orig_dst, bsize,
1394*77c1e3ccSAndroid Build Coastguard Worker 0, av1_num_planes(cm) - 1);
1395*77c1e3ccSAndroid Build Coastguard Worker }
1396*77c1e3ccSAndroid Build Coastguard Worker // Build the inter predictor by blending the predictor corresponding to
1397*77c1e3ccSAndroid Build Coastguard Worker // this MV, and the neighboring blocks using the OBMC model
1398*77c1e3ccSAndroid Build Coastguard Worker av1_build_obmc_inter_prediction(
1399*77c1e3ccSAndroid Build Coastguard Worker cm, xd, args->above_pred_buf, args->above_pred_stride,
1400*77c1e3ccSAndroid Build Coastguard Worker args->left_pred_buf, args->left_pred_stride);
1401*77c1e3ccSAndroid Build Coastguard Worker #if !CONFIG_REALTIME_ONLY
1402*77c1e3ccSAndroid Build Coastguard Worker } else if (mbmi->motion_mode == WARPED_CAUSAL) {
1403*77c1e3ccSAndroid Build Coastguard Worker int pts[SAMPLES_ARRAY_SIZE], pts_inref[SAMPLES_ARRAY_SIZE];
1404*77c1e3ccSAndroid Build Coastguard Worker mbmi->motion_mode = WARPED_CAUSAL;
1405*77c1e3ccSAndroid Build Coastguard Worker mbmi->wm_params.wmtype = DEFAULT_WMTYPE;
1406*77c1e3ccSAndroid Build Coastguard Worker mbmi->interp_filters =
1407*77c1e3ccSAndroid Build Coastguard Worker av1_broadcast_interp_filter(av1_unswitchable_filter(interp_filter));
1408*77c1e3ccSAndroid Build Coastguard Worker
1409*77c1e3ccSAndroid Build Coastguard Worker memcpy(pts, pts0, total_samples * 2 * sizeof(*pts0));
1410*77c1e3ccSAndroid Build Coastguard Worker memcpy(pts_inref, pts_inref0, total_samples * 2 * sizeof(*pts_inref0));
1411*77c1e3ccSAndroid Build Coastguard Worker // Select the samples according to motion vector difference
1412*77c1e3ccSAndroid Build Coastguard Worker if (mbmi->num_proj_ref > 1) {
1413*77c1e3ccSAndroid Build Coastguard Worker mbmi->num_proj_ref = av1_selectSamples(
1414*77c1e3ccSAndroid Build Coastguard Worker &mbmi->mv[0].as_mv, pts, pts_inref, mbmi->num_proj_ref, bsize);
1415*77c1e3ccSAndroid Build Coastguard Worker }
1416*77c1e3ccSAndroid Build Coastguard Worker
1417*77c1e3ccSAndroid Build Coastguard Worker // Compute the warped motion parameters with a least squares fit
1418*77c1e3ccSAndroid Build Coastguard Worker // using the collected samples
1419*77c1e3ccSAndroid Build Coastguard Worker if (!av1_find_projection(mbmi->num_proj_ref, pts, pts_inref, bsize,
1420*77c1e3ccSAndroid Build Coastguard Worker mbmi->mv[0].as_mv.row, mbmi->mv[0].as_mv.col,
1421*77c1e3ccSAndroid Build Coastguard Worker &mbmi->wm_params, mi_row, mi_col)) {
1422*77c1e3ccSAndroid Build Coastguard Worker assert(!is_comp_pred);
1423*77c1e3ccSAndroid Build Coastguard Worker if (have_newmv_in_inter_mode(this_mode)) {
1424*77c1e3ccSAndroid Build Coastguard Worker // Refine MV for NEWMV mode
1425*77c1e3ccSAndroid Build Coastguard Worker const int_mv mv0 = mbmi->mv[0];
1426*77c1e3ccSAndroid Build Coastguard Worker const WarpedMotionParams wm_params0 = mbmi->wm_params;
1427*77c1e3ccSAndroid Build Coastguard Worker const int num_proj_ref0 = mbmi->num_proj_ref;
1428*77c1e3ccSAndroid Build Coastguard Worker
1429*77c1e3ccSAndroid Build Coastguard Worker const int_mv ref_mv = av1_get_ref_mv(x, 0);
1430*77c1e3ccSAndroid Build Coastguard Worker SUBPEL_MOTION_SEARCH_PARAMS ms_params;
1431*77c1e3ccSAndroid Build Coastguard Worker av1_make_default_subpel_ms_params(&ms_params, cpi, x, bsize,
1432*77c1e3ccSAndroid Build Coastguard Worker &ref_mv.as_mv, NULL);
1433*77c1e3ccSAndroid Build Coastguard Worker
1434*77c1e3ccSAndroid Build Coastguard Worker // Refine MV in a small range.
1435*77c1e3ccSAndroid Build Coastguard Worker av1_refine_warped_mv(xd, cm, &ms_params, bsize, pts0, pts_inref0,
1436*77c1e3ccSAndroid Build Coastguard Worker total_samples, cpi->sf.mv_sf.warp_search_method,
1437*77c1e3ccSAndroid Build Coastguard Worker cpi->sf.mv_sf.warp_search_iters);
1438*77c1e3ccSAndroid Build Coastguard Worker
1439*77c1e3ccSAndroid Build Coastguard Worker if (mv0.as_int != mbmi->mv[0].as_int) {
1440*77c1e3ccSAndroid Build Coastguard Worker // Keep the refined MV and WM parameters.
1441*77c1e3ccSAndroid Build Coastguard Worker tmp_rate_mv = av1_mv_bit_cost(
1442*77c1e3ccSAndroid Build Coastguard Worker &mbmi->mv[0].as_mv, &ref_mv.as_mv, x->mv_costs->nmv_joint_cost,
1443*77c1e3ccSAndroid Build Coastguard Worker x->mv_costs->mv_cost_stack, MV_COST_WEIGHT);
1444*77c1e3ccSAndroid Build Coastguard Worker tmp_rate2 = rate2_nocoeff - rate_mv0 + tmp_rate_mv;
1445*77c1e3ccSAndroid Build Coastguard Worker } else {
1446*77c1e3ccSAndroid Build Coastguard Worker // Restore the old MV and WM parameters.
1447*77c1e3ccSAndroid Build Coastguard Worker mbmi->mv[0] = mv0;
1448*77c1e3ccSAndroid Build Coastguard Worker mbmi->wm_params = wm_params0;
1449*77c1e3ccSAndroid Build Coastguard Worker mbmi->num_proj_ref = num_proj_ref0;
1450*77c1e3ccSAndroid Build Coastguard Worker }
1451*77c1e3ccSAndroid Build Coastguard Worker }
1452*77c1e3ccSAndroid Build Coastguard Worker
1453*77c1e3ccSAndroid Build Coastguard Worker // Build the warped predictor
1454*77c1e3ccSAndroid Build Coastguard Worker av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, NULL, bsize, 0,
1455*77c1e3ccSAndroid Build Coastguard Worker av1_num_planes(cm) - 1);
1456*77c1e3ccSAndroid Build Coastguard Worker } else {
1457*77c1e3ccSAndroid Build Coastguard Worker continue;
1458*77c1e3ccSAndroid Build Coastguard Worker }
1459*77c1e3ccSAndroid Build Coastguard Worker #endif // !CONFIG_REALTIME_ONLY
1460*77c1e3ccSAndroid Build Coastguard Worker } else if (is_interintra_mode) {
1461*77c1e3ccSAndroid Build Coastguard Worker const int ret =
1462*77c1e3ccSAndroid Build Coastguard Worker av1_handle_inter_intra_mode(cpi, x, bsize, mbmi, args, ref_best_rd,
1463*77c1e3ccSAndroid Build Coastguard Worker &tmp_rate_mv, &tmp_rate2, orig_dst);
1464*77c1e3ccSAndroid Build Coastguard Worker if (ret < 0) continue;
1465*77c1e3ccSAndroid Build Coastguard Worker }
1466*77c1e3ccSAndroid Build Coastguard Worker
1467*77c1e3ccSAndroid Build Coastguard Worker // If we are searching newmv and the mv is the same as refmv, skip the
1468*77c1e3ccSAndroid Build Coastguard Worker // current mode
1469*77c1e3ccSAndroid Build Coastguard Worker if (!av1_check_newmv_joint_nonzero(cm, x)) continue;
1470*77c1e3ccSAndroid Build Coastguard Worker
1471*77c1e3ccSAndroid Build Coastguard Worker // Update rd_stats for the current motion mode
1472*77c1e3ccSAndroid Build Coastguard Worker txfm_info->skip_txfm = 0;
1473*77c1e3ccSAndroid Build Coastguard Worker rd_stats->dist = 0;
1474*77c1e3ccSAndroid Build Coastguard Worker rd_stats->sse = 0;
1475*77c1e3ccSAndroid Build Coastguard Worker rd_stats->skip_txfm = 1;
1476*77c1e3ccSAndroid Build Coastguard Worker rd_stats->rate = tmp_rate2;
1477*77c1e3ccSAndroid Build Coastguard Worker const ModeCosts *mode_costs = &x->mode_costs;
1478*77c1e3ccSAndroid Build Coastguard Worker if (mbmi->motion_mode != WARPED_CAUSAL) rd_stats->rate += switchable_rate;
1479*77c1e3ccSAndroid Build Coastguard Worker if (interintra_allowed) {
1480*77c1e3ccSAndroid Build Coastguard Worker rd_stats->rate +=
1481*77c1e3ccSAndroid Build Coastguard Worker mode_costs->interintra_cost[size_group_lookup[bsize]]
1482*77c1e3ccSAndroid Build Coastguard Worker [mbmi->ref_frame[1] == INTRA_FRAME];
1483*77c1e3ccSAndroid Build Coastguard Worker }
1484*77c1e3ccSAndroid Build Coastguard Worker if ((last_motion_mode_allowed > SIMPLE_TRANSLATION) &&
1485*77c1e3ccSAndroid Build Coastguard Worker (mbmi->ref_frame[1] != INTRA_FRAME)) {
1486*77c1e3ccSAndroid Build Coastguard Worker if (last_motion_mode_allowed == WARPED_CAUSAL) {
1487*77c1e3ccSAndroid Build Coastguard Worker rd_stats->rate +=
1488*77c1e3ccSAndroid Build Coastguard Worker mode_costs->motion_mode_cost[bsize][mbmi->motion_mode];
1489*77c1e3ccSAndroid Build Coastguard Worker } else {
1490*77c1e3ccSAndroid Build Coastguard Worker rd_stats->rate +=
1491*77c1e3ccSAndroid Build Coastguard Worker mode_costs->motion_mode_cost1[bsize][mbmi->motion_mode];
1492*77c1e3ccSAndroid Build Coastguard Worker }
1493*77c1e3ccSAndroid Build Coastguard Worker }
1494*77c1e3ccSAndroid Build Coastguard Worker
1495*77c1e3ccSAndroid Build Coastguard Worker int64_t this_yrd = INT64_MAX;
1496*77c1e3ccSAndroid Build Coastguard Worker
1497*77c1e3ccSAndroid Build Coastguard Worker if (!do_tx_search) {
1498*77c1e3ccSAndroid Build Coastguard Worker // Avoid doing a transform search here to speed up the overall mode
1499*77c1e3ccSAndroid Build Coastguard Worker // search. It will be done later in the mode search if the current
1500*77c1e3ccSAndroid Build Coastguard Worker // motion mode seems promising.
1501*77c1e3ccSAndroid Build Coastguard Worker int64_t curr_sse = -1;
1502*77c1e3ccSAndroid Build Coastguard Worker int64_t sse_y = -1;
1503*77c1e3ccSAndroid Build Coastguard Worker int est_residue_cost = 0;
1504*77c1e3ccSAndroid Build Coastguard Worker int64_t est_dist = 0;
1505*77c1e3ccSAndroid Build Coastguard Worker int64_t est_rd = 0;
1506*77c1e3ccSAndroid Build Coastguard Worker if (cpi->sf.inter_sf.inter_mode_rd_model_estimation == 1) {
1507*77c1e3ccSAndroid Build Coastguard Worker curr_sse = get_sse(cpi, x, &sse_y);
1508*77c1e3ccSAndroid Build Coastguard Worker const int has_est_rd = get_est_rate_dist(tile_data, bsize, curr_sse,
1509*77c1e3ccSAndroid Build Coastguard Worker &est_residue_cost, &est_dist);
1510*77c1e3ccSAndroid Build Coastguard Worker (void)has_est_rd;
1511*77c1e3ccSAndroid Build Coastguard Worker assert(has_est_rd);
1512*77c1e3ccSAndroid Build Coastguard Worker } else if (cpi->sf.inter_sf.inter_mode_rd_model_estimation == 2 ||
1513*77c1e3ccSAndroid Build Coastguard Worker cpi->sf.rt_sf.use_nonrd_pick_mode) {
1514*77c1e3ccSAndroid Build Coastguard Worker model_rd_sb_fn[MODELRD_TYPE_MOTION_MODE_RD](
1515*77c1e3ccSAndroid Build Coastguard Worker cpi, bsize, x, xd, 0, num_planes - 1, &est_residue_cost, &est_dist,
1516*77c1e3ccSAndroid Build Coastguard Worker NULL, &curr_sse, NULL, NULL, NULL);
1517*77c1e3ccSAndroid Build Coastguard Worker sse_y = x->pred_sse[xd->mi[0]->ref_frame[0]];
1518*77c1e3ccSAndroid Build Coastguard Worker }
1519*77c1e3ccSAndroid Build Coastguard Worker est_rd = RDCOST(x->rdmult, rd_stats->rate + est_residue_cost, est_dist);
1520*77c1e3ccSAndroid Build Coastguard Worker if (est_rd * 0.80 > *best_est_rd) {
1521*77c1e3ccSAndroid Build Coastguard Worker mbmi->ref_frame[1] = ref_frame_1;
1522*77c1e3ccSAndroid Build Coastguard Worker continue;
1523*77c1e3ccSAndroid Build Coastguard Worker }
1524*77c1e3ccSAndroid Build Coastguard Worker const int mode_rate = rd_stats->rate;
1525*77c1e3ccSAndroid Build Coastguard Worker rd_stats->rate += est_residue_cost;
1526*77c1e3ccSAndroid Build Coastguard Worker rd_stats->dist = est_dist;
1527*77c1e3ccSAndroid Build Coastguard Worker rd_stats->rdcost = est_rd;
1528*77c1e3ccSAndroid Build Coastguard Worker if (rd_stats->rdcost < *best_est_rd) {
1529*77c1e3ccSAndroid Build Coastguard Worker *best_est_rd = rd_stats->rdcost;
1530*77c1e3ccSAndroid Build Coastguard Worker assert(sse_y >= 0);
1531*77c1e3ccSAndroid Build Coastguard Worker ref_skip_rd[1] = txfm_rd_gate_level
1532*77c1e3ccSAndroid Build Coastguard Worker ? RDCOST(x->rdmult, mode_rate, (sse_y << 4))
1533*77c1e3ccSAndroid Build Coastguard Worker : INT64_MAX;
1534*77c1e3ccSAndroid Build Coastguard Worker }
1535*77c1e3ccSAndroid Build Coastguard Worker if (cm->current_frame.reference_mode == SINGLE_REFERENCE) {
1536*77c1e3ccSAndroid Build Coastguard Worker if (!is_comp_pred) {
1537*77c1e3ccSAndroid Build Coastguard Worker assert(curr_sse >= 0);
1538*77c1e3ccSAndroid Build Coastguard Worker inter_modes_info_push(inter_modes_info, mode_rate, curr_sse,
1539*77c1e3ccSAndroid Build Coastguard Worker rd_stats->rdcost, rd_stats, rd_stats_y,
1540*77c1e3ccSAndroid Build Coastguard Worker rd_stats_uv, mbmi);
1541*77c1e3ccSAndroid Build Coastguard Worker }
1542*77c1e3ccSAndroid Build Coastguard Worker } else {
1543*77c1e3ccSAndroid Build Coastguard Worker assert(curr_sse >= 0);
1544*77c1e3ccSAndroid Build Coastguard Worker inter_modes_info_push(inter_modes_info, mode_rate, curr_sse,
1545*77c1e3ccSAndroid Build Coastguard Worker rd_stats->rdcost, rd_stats, rd_stats_y,
1546*77c1e3ccSAndroid Build Coastguard Worker rd_stats_uv, mbmi);
1547*77c1e3ccSAndroid Build Coastguard Worker }
1548*77c1e3ccSAndroid Build Coastguard Worker mbmi->skip_txfm = 0;
1549*77c1e3ccSAndroid Build Coastguard Worker } else {
1550*77c1e3ccSAndroid Build Coastguard Worker // Perform full transform search
1551*77c1e3ccSAndroid Build Coastguard Worker int64_t skip_rd = INT64_MAX;
1552*77c1e3ccSAndroid Build Coastguard Worker int64_t skip_rdy = INT64_MAX;
1553*77c1e3ccSAndroid Build Coastguard Worker if (txfm_rd_gate_level) {
1554*77c1e3ccSAndroid Build Coastguard Worker // Check if the mode is good enough based on skip RD
1555*77c1e3ccSAndroid Build Coastguard Worker int64_t sse_y = INT64_MAX;
1556*77c1e3ccSAndroid Build Coastguard Worker int64_t curr_sse = get_sse(cpi, x, &sse_y);
1557*77c1e3ccSAndroid Build Coastguard Worker skip_rd = RDCOST(x->rdmult, rd_stats->rate, curr_sse);
1558*77c1e3ccSAndroid Build Coastguard Worker skip_rdy = RDCOST(x->rdmult, rd_stats->rate, (sse_y << 4));
1559*77c1e3ccSAndroid Build Coastguard Worker int eval_txfm = check_txfm_eval(x, bsize, ref_skip_rd[0], skip_rd,
1560*77c1e3ccSAndroid Build Coastguard Worker txfm_rd_gate_level, 0);
1561*77c1e3ccSAndroid Build Coastguard Worker if (!eval_txfm) continue;
1562*77c1e3ccSAndroid Build Coastguard Worker }
1563*77c1e3ccSAndroid Build Coastguard Worker
1564*77c1e3ccSAndroid Build Coastguard Worker // Do transform search
1565*77c1e3ccSAndroid Build Coastguard Worker const int mode_rate = rd_stats->rate;
1566*77c1e3ccSAndroid Build Coastguard Worker if (!av1_txfm_search(cpi, x, bsize, rd_stats, rd_stats_y, rd_stats_uv,
1567*77c1e3ccSAndroid Build Coastguard Worker rd_stats->rate, ref_best_rd)) {
1568*77c1e3ccSAndroid Build Coastguard Worker if (rd_stats_y->rate == INT_MAX && mode_index == 0) {
1569*77c1e3ccSAndroid Build Coastguard Worker return INT64_MAX;
1570*77c1e3ccSAndroid Build Coastguard Worker }
1571*77c1e3ccSAndroid Build Coastguard Worker continue;
1572*77c1e3ccSAndroid Build Coastguard Worker }
1573*77c1e3ccSAndroid Build Coastguard Worker const int skip_ctx = av1_get_skip_txfm_context(xd);
1574*77c1e3ccSAndroid Build Coastguard Worker const int y_rate =
1575*77c1e3ccSAndroid Build Coastguard Worker rd_stats->skip_txfm
1576*77c1e3ccSAndroid Build Coastguard Worker ? x->mode_costs.skip_txfm_cost[skip_ctx][1]
1577*77c1e3ccSAndroid Build Coastguard Worker : (rd_stats_y->rate + x->mode_costs.skip_txfm_cost[skip_ctx][0]);
1578*77c1e3ccSAndroid Build Coastguard Worker this_yrd = RDCOST(x->rdmult, y_rate + mode_rate, rd_stats_y->dist);
1579*77c1e3ccSAndroid Build Coastguard Worker
1580*77c1e3ccSAndroid Build Coastguard Worker const int64_t curr_rd = RDCOST(x->rdmult, rd_stats->rate, rd_stats->dist);
1581*77c1e3ccSAndroid Build Coastguard Worker if (curr_rd < ref_best_rd) {
1582*77c1e3ccSAndroid Build Coastguard Worker ref_best_rd = curr_rd;
1583*77c1e3ccSAndroid Build Coastguard Worker ref_skip_rd[0] = skip_rd;
1584*77c1e3ccSAndroid Build Coastguard Worker ref_skip_rd[1] = skip_rdy;
1585*77c1e3ccSAndroid Build Coastguard Worker }
1586*77c1e3ccSAndroid Build Coastguard Worker if (cpi->sf.inter_sf.inter_mode_rd_model_estimation == 1) {
1587*77c1e3ccSAndroid Build Coastguard Worker inter_mode_data_push(
1588*77c1e3ccSAndroid Build Coastguard Worker tile_data, mbmi->bsize, rd_stats->sse, rd_stats->dist,
1589*77c1e3ccSAndroid Build Coastguard Worker rd_stats_y->rate + rd_stats_uv->rate +
1590*77c1e3ccSAndroid Build Coastguard Worker mode_costs->skip_txfm_cost[skip_ctx][mbmi->skip_txfm]);
1591*77c1e3ccSAndroid Build Coastguard Worker }
1592*77c1e3ccSAndroid Build Coastguard Worker }
1593*77c1e3ccSAndroid Build Coastguard Worker
1594*77c1e3ccSAndroid Build Coastguard Worker if (this_mode == GLOBALMV || this_mode == GLOBAL_GLOBALMV) {
1595*77c1e3ccSAndroid Build Coastguard Worker if (is_nontrans_global_motion(xd, xd->mi[0])) {
1596*77c1e3ccSAndroid Build Coastguard Worker mbmi->interp_filters =
1597*77c1e3ccSAndroid Build Coastguard Worker av1_broadcast_interp_filter(av1_unswitchable_filter(interp_filter));
1598*77c1e3ccSAndroid Build Coastguard Worker }
1599*77c1e3ccSAndroid Build Coastguard Worker }
1600*77c1e3ccSAndroid Build Coastguard Worker
1601*77c1e3ccSAndroid Build Coastguard Worker const int64_t tmp_rd = RDCOST(x->rdmult, rd_stats->rate, rd_stats->dist);
1602*77c1e3ccSAndroid Build Coastguard Worker if (mode_index == 0) {
1603*77c1e3ccSAndroid Build Coastguard Worker args->simple_rd[this_mode][mbmi->ref_mv_idx][mbmi->ref_frame[0]] = tmp_rd;
1604*77c1e3ccSAndroid Build Coastguard Worker }
1605*77c1e3ccSAndroid Build Coastguard Worker if (mode_index == 0 || tmp_rd < best_rd) {
1606*77c1e3ccSAndroid Build Coastguard Worker // Update best_rd data if this is the best motion mode so far
1607*77c1e3ccSAndroid Build Coastguard Worker best_mbmi = *mbmi;
1608*77c1e3ccSAndroid Build Coastguard Worker best_rd = tmp_rd;
1609*77c1e3ccSAndroid Build Coastguard Worker best_rd_stats = *rd_stats;
1610*77c1e3ccSAndroid Build Coastguard Worker best_rd_stats_y = *rd_stats_y;
1611*77c1e3ccSAndroid Build Coastguard Worker best_rate_mv = tmp_rate_mv;
1612*77c1e3ccSAndroid Build Coastguard Worker *yrd = this_yrd;
1613*77c1e3ccSAndroid Build Coastguard Worker if (num_planes > 1) best_rd_stats_uv = *rd_stats_uv;
1614*77c1e3ccSAndroid Build Coastguard Worker memcpy(best_blk_skip, txfm_info->blk_skip,
1615*77c1e3ccSAndroid Build Coastguard Worker sizeof(txfm_info->blk_skip[0]) * xd->height * xd->width);
1616*77c1e3ccSAndroid Build Coastguard Worker av1_copy_array(best_tx_type_map, xd->tx_type_map, xd->height * xd->width);
1617*77c1e3ccSAndroid Build Coastguard Worker best_xskip_txfm = mbmi->skip_txfm;
1618*77c1e3ccSAndroid Build Coastguard Worker }
1619*77c1e3ccSAndroid Build Coastguard Worker }
1620*77c1e3ccSAndroid Build Coastguard Worker // Update RD and mbmi stats for selected motion mode
1621*77c1e3ccSAndroid Build Coastguard Worker mbmi->ref_frame[1] = ref_frame_1;
1622*77c1e3ccSAndroid Build Coastguard Worker *rate_mv = best_rate_mv;
1623*77c1e3ccSAndroid Build Coastguard Worker if (best_rd == INT64_MAX || !av1_check_newmv_joint_nonzero(cm, x)) {
1624*77c1e3ccSAndroid Build Coastguard Worker av1_invalid_rd_stats(rd_stats);
1625*77c1e3ccSAndroid Build Coastguard Worker restore_dst_buf(xd, *orig_dst, num_planes);
1626*77c1e3ccSAndroid Build Coastguard Worker return INT64_MAX;
1627*77c1e3ccSAndroid Build Coastguard Worker }
1628*77c1e3ccSAndroid Build Coastguard Worker *mbmi = best_mbmi;
1629*77c1e3ccSAndroid Build Coastguard Worker *rd_stats = best_rd_stats;
1630*77c1e3ccSAndroid Build Coastguard Worker *rd_stats_y = best_rd_stats_y;
1631*77c1e3ccSAndroid Build Coastguard Worker if (num_planes > 1) *rd_stats_uv = best_rd_stats_uv;
1632*77c1e3ccSAndroid Build Coastguard Worker memcpy(txfm_info->blk_skip, best_blk_skip,
1633*77c1e3ccSAndroid Build Coastguard Worker sizeof(txfm_info->blk_skip[0]) * xd->height * xd->width);
1634*77c1e3ccSAndroid Build Coastguard Worker av1_copy_array(xd->tx_type_map, best_tx_type_map, xd->height * xd->width);
1635*77c1e3ccSAndroid Build Coastguard Worker txfm_info->skip_txfm = best_xskip_txfm;
1636*77c1e3ccSAndroid Build Coastguard Worker
1637*77c1e3ccSAndroid Build Coastguard Worker restore_dst_buf(xd, *orig_dst, num_planes);
1638*77c1e3ccSAndroid Build Coastguard Worker return 0;
1639*77c1e3ccSAndroid Build Coastguard Worker }
1640*77c1e3ccSAndroid Build Coastguard Worker
skip_mode_rd(RD_STATS * rd_stats,const AV1_COMP * const cpi,MACROBLOCK * const x,BLOCK_SIZE bsize,const BUFFER_SET * const orig_dst,int64_t best_rd)1641*77c1e3ccSAndroid Build Coastguard Worker static int64_t skip_mode_rd(RD_STATS *rd_stats, const AV1_COMP *const cpi,
1642*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCK *const x, BLOCK_SIZE bsize,
1643*77c1e3ccSAndroid Build Coastguard Worker const BUFFER_SET *const orig_dst, int64_t best_rd) {
1644*77c1e3ccSAndroid Build Coastguard Worker assert(bsize < BLOCK_SIZES_ALL);
1645*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *cm = &cpi->common;
1646*77c1e3ccSAndroid Build Coastguard Worker const int num_planes = av1_num_planes(cm);
1647*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *const xd = &x->e_mbd;
1648*77c1e3ccSAndroid Build Coastguard Worker const int mi_row = xd->mi_row;
1649*77c1e3ccSAndroid Build Coastguard Worker const int mi_col = xd->mi_col;
1650*77c1e3ccSAndroid Build Coastguard Worker int64_t total_sse = 0;
1651*77c1e3ccSAndroid Build Coastguard Worker int64_t this_rd = INT64_MAX;
1652*77c1e3ccSAndroid Build Coastguard Worker const int skip_mode_ctx = av1_get_skip_mode_context(xd);
1653*77c1e3ccSAndroid Build Coastguard Worker rd_stats->rate = x->mode_costs.skip_mode_cost[skip_mode_ctx][1];
1654*77c1e3ccSAndroid Build Coastguard Worker
1655*77c1e3ccSAndroid Build Coastguard Worker for (int plane = 0; plane < num_planes; ++plane) {
1656*77c1e3ccSAndroid Build Coastguard Worker // Call av1_enc_build_inter_predictor() for one plane at a time.
1657*77c1e3ccSAndroid Build Coastguard Worker av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, orig_dst, bsize,
1658*77c1e3ccSAndroid Build Coastguard Worker plane, plane);
1659*77c1e3ccSAndroid Build Coastguard Worker const struct macroblockd_plane *const pd = &xd->plane[plane];
1660*77c1e3ccSAndroid Build Coastguard Worker const BLOCK_SIZE plane_bsize =
1661*77c1e3ccSAndroid Build Coastguard Worker get_plane_block_size(bsize, pd->subsampling_x, pd->subsampling_y);
1662*77c1e3ccSAndroid Build Coastguard Worker
1663*77c1e3ccSAndroid Build Coastguard Worker av1_subtract_plane(x, plane_bsize, plane);
1664*77c1e3ccSAndroid Build Coastguard Worker
1665*77c1e3ccSAndroid Build Coastguard Worker int64_t sse =
1666*77c1e3ccSAndroid Build Coastguard Worker av1_pixel_diff_dist(x, plane, 0, 0, plane_bsize, plane_bsize, NULL);
1667*77c1e3ccSAndroid Build Coastguard Worker if (is_cur_buf_hbd(xd)) sse = ROUND_POWER_OF_TWO(sse, (xd->bd - 8) * 2);
1668*77c1e3ccSAndroid Build Coastguard Worker sse <<= 4;
1669*77c1e3ccSAndroid Build Coastguard Worker total_sse += sse;
1670*77c1e3ccSAndroid Build Coastguard Worker // When current rd cost is more than the best rd, skip evaluation of
1671*77c1e3ccSAndroid Build Coastguard Worker // remaining planes.
1672*77c1e3ccSAndroid Build Coastguard Worker this_rd = RDCOST(x->rdmult, rd_stats->rate, total_sse);
1673*77c1e3ccSAndroid Build Coastguard Worker if (this_rd > best_rd) break;
1674*77c1e3ccSAndroid Build Coastguard Worker }
1675*77c1e3ccSAndroid Build Coastguard Worker
1676*77c1e3ccSAndroid Build Coastguard Worker rd_stats->dist = rd_stats->sse = total_sse;
1677*77c1e3ccSAndroid Build Coastguard Worker rd_stats->rdcost = this_rd;
1678*77c1e3ccSAndroid Build Coastguard Worker
1679*77c1e3ccSAndroid Build Coastguard Worker restore_dst_buf(xd, *orig_dst, num_planes);
1680*77c1e3ccSAndroid Build Coastguard Worker return 0;
1681*77c1e3ccSAndroid Build Coastguard Worker }
1682*77c1e3ccSAndroid Build Coastguard Worker
1683*77c1e3ccSAndroid Build Coastguard Worker // Check NEARESTMV, NEARMV, GLOBALMV ref mvs for duplicate and skip the relevant
1684*77c1e3ccSAndroid Build Coastguard Worker // mode
1685*77c1e3ccSAndroid Build Coastguard Worker // Note(rachelbarker): This speed feature currently does not interact correctly
1686*77c1e3ccSAndroid Build Coastguard Worker // with global motion. The issue is that, when global motion is used, GLOBALMV
1687*77c1e3ccSAndroid Build Coastguard Worker // produces a different prediction to NEARESTMV/NEARMV even if the motion
1688*77c1e3ccSAndroid Build Coastguard Worker // vectors are the same. Thus GLOBALMV should not be pruned in this case.
check_repeat_ref_mv(const MB_MODE_INFO_EXT * mbmi_ext,int ref_idx,const MV_REFERENCE_FRAME * ref_frame,PREDICTION_MODE single_mode)1689*77c1e3ccSAndroid Build Coastguard Worker static inline int check_repeat_ref_mv(const MB_MODE_INFO_EXT *mbmi_ext,
1690*77c1e3ccSAndroid Build Coastguard Worker int ref_idx,
1691*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME *ref_frame,
1692*77c1e3ccSAndroid Build Coastguard Worker PREDICTION_MODE single_mode) {
1693*77c1e3ccSAndroid Build Coastguard Worker const uint8_t ref_frame_type = av1_ref_frame_type(ref_frame);
1694*77c1e3ccSAndroid Build Coastguard Worker const int ref_mv_count = mbmi_ext->ref_mv_count[ref_frame_type];
1695*77c1e3ccSAndroid Build Coastguard Worker assert(single_mode != NEWMV);
1696*77c1e3ccSAndroid Build Coastguard Worker if (single_mode == NEARESTMV) {
1697*77c1e3ccSAndroid Build Coastguard Worker return 0;
1698*77c1e3ccSAndroid Build Coastguard Worker } else if (single_mode == NEARMV) {
1699*77c1e3ccSAndroid Build Coastguard Worker // when ref_mv_count = 0, NEARESTMV and NEARMV are same as GLOBALMV
1700*77c1e3ccSAndroid Build Coastguard Worker // when ref_mv_count = 1, NEARMV is same as GLOBALMV
1701*77c1e3ccSAndroid Build Coastguard Worker if (ref_mv_count < 2) return 1;
1702*77c1e3ccSAndroid Build Coastguard Worker } else if (single_mode == GLOBALMV) {
1703*77c1e3ccSAndroid Build Coastguard Worker // when ref_mv_count == 0, GLOBALMV is same as NEARESTMV
1704*77c1e3ccSAndroid Build Coastguard Worker if (ref_mv_count == 0) return 1;
1705*77c1e3ccSAndroid Build Coastguard Worker // when ref_mv_count == 1, NEARMV is same as GLOBALMV
1706*77c1e3ccSAndroid Build Coastguard Worker else if (ref_mv_count == 1)
1707*77c1e3ccSAndroid Build Coastguard Worker return 0;
1708*77c1e3ccSAndroid Build Coastguard Worker
1709*77c1e3ccSAndroid Build Coastguard Worker int stack_size = AOMMIN(USABLE_REF_MV_STACK_SIZE, ref_mv_count);
1710*77c1e3ccSAndroid Build Coastguard Worker // Check GLOBALMV is matching with any mv in ref_mv_stack
1711*77c1e3ccSAndroid Build Coastguard Worker for (int ref_mv_idx = 0; ref_mv_idx < stack_size; ref_mv_idx++) {
1712*77c1e3ccSAndroid Build Coastguard Worker int_mv this_mv;
1713*77c1e3ccSAndroid Build Coastguard Worker
1714*77c1e3ccSAndroid Build Coastguard Worker if (ref_idx == 0)
1715*77c1e3ccSAndroid Build Coastguard Worker this_mv = mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_idx].this_mv;
1716*77c1e3ccSAndroid Build Coastguard Worker else
1717*77c1e3ccSAndroid Build Coastguard Worker this_mv = mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_idx].comp_mv;
1718*77c1e3ccSAndroid Build Coastguard Worker
1719*77c1e3ccSAndroid Build Coastguard Worker if (this_mv.as_int == mbmi_ext->global_mvs[ref_frame[ref_idx]].as_int)
1720*77c1e3ccSAndroid Build Coastguard Worker return 1;
1721*77c1e3ccSAndroid Build Coastguard Worker }
1722*77c1e3ccSAndroid Build Coastguard Worker }
1723*77c1e3ccSAndroid Build Coastguard Worker return 0;
1724*77c1e3ccSAndroid Build Coastguard Worker }
1725*77c1e3ccSAndroid Build Coastguard Worker
get_this_mv(int_mv * this_mv,PREDICTION_MODE this_mode,int ref_idx,int ref_mv_idx,int skip_repeated_ref_mv,const MV_REFERENCE_FRAME * ref_frame,const MB_MODE_INFO_EXT * mbmi_ext)1726*77c1e3ccSAndroid Build Coastguard Worker static inline int get_this_mv(int_mv *this_mv, PREDICTION_MODE this_mode,
1727*77c1e3ccSAndroid Build Coastguard Worker int ref_idx, int ref_mv_idx,
1728*77c1e3ccSAndroid Build Coastguard Worker int skip_repeated_ref_mv,
1729*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME *ref_frame,
1730*77c1e3ccSAndroid Build Coastguard Worker const MB_MODE_INFO_EXT *mbmi_ext) {
1731*77c1e3ccSAndroid Build Coastguard Worker const PREDICTION_MODE single_mode = get_single_mode(this_mode, ref_idx);
1732*77c1e3ccSAndroid Build Coastguard Worker assert(is_inter_singleref_mode(single_mode));
1733*77c1e3ccSAndroid Build Coastguard Worker if (single_mode == NEWMV) {
1734*77c1e3ccSAndroid Build Coastguard Worker this_mv->as_int = INVALID_MV;
1735*77c1e3ccSAndroid Build Coastguard Worker } else if (single_mode == GLOBALMV) {
1736*77c1e3ccSAndroid Build Coastguard Worker if (skip_repeated_ref_mv &&
1737*77c1e3ccSAndroid Build Coastguard Worker check_repeat_ref_mv(mbmi_ext, ref_idx, ref_frame, single_mode))
1738*77c1e3ccSAndroid Build Coastguard Worker return 0;
1739*77c1e3ccSAndroid Build Coastguard Worker *this_mv = mbmi_ext->global_mvs[ref_frame[ref_idx]];
1740*77c1e3ccSAndroid Build Coastguard Worker } else {
1741*77c1e3ccSAndroid Build Coastguard Worker assert(single_mode == NEARMV || single_mode == NEARESTMV);
1742*77c1e3ccSAndroid Build Coastguard Worker const uint8_t ref_frame_type = av1_ref_frame_type(ref_frame);
1743*77c1e3ccSAndroid Build Coastguard Worker const int ref_mv_offset = single_mode == NEARESTMV ? 0 : ref_mv_idx + 1;
1744*77c1e3ccSAndroid Build Coastguard Worker if (ref_mv_offset < mbmi_ext->ref_mv_count[ref_frame_type]) {
1745*77c1e3ccSAndroid Build Coastguard Worker assert(ref_mv_offset >= 0);
1746*77c1e3ccSAndroid Build Coastguard Worker if (ref_idx == 0) {
1747*77c1e3ccSAndroid Build Coastguard Worker *this_mv =
1748*77c1e3ccSAndroid Build Coastguard Worker mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_offset].this_mv;
1749*77c1e3ccSAndroid Build Coastguard Worker } else {
1750*77c1e3ccSAndroid Build Coastguard Worker *this_mv =
1751*77c1e3ccSAndroid Build Coastguard Worker mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_offset].comp_mv;
1752*77c1e3ccSAndroid Build Coastguard Worker }
1753*77c1e3ccSAndroid Build Coastguard Worker } else {
1754*77c1e3ccSAndroid Build Coastguard Worker if (skip_repeated_ref_mv &&
1755*77c1e3ccSAndroid Build Coastguard Worker check_repeat_ref_mv(mbmi_ext, ref_idx, ref_frame, single_mode))
1756*77c1e3ccSAndroid Build Coastguard Worker return 0;
1757*77c1e3ccSAndroid Build Coastguard Worker *this_mv = mbmi_ext->global_mvs[ref_frame[ref_idx]];
1758*77c1e3ccSAndroid Build Coastguard Worker }
1759*77c1e3ccSAndroid Build Coastguard Worker }
1760*77c1e3ccSAndroid Build Coastguard Worker return 1;
1761*77c1e3ccSAndroid Build Coastguard Worker }
1762*77c1e3ccSAndroid Build Coastguard Worker
1763*77c1e3ccSAndroid Build Coastguard Worker // Skip NEARESTMV and NEARMV modes based on refmv weight computed in ref mv list
1764*77c1e3ccSAndroid Build Coastguard Worker // population
skip_nearest_near_mv_using_refmv_weight(const MACROBLOCK * const x,const PREDICTION_MODE this_mode,const int8_t ref_frame_type,PREDICTION_MODE best_mode)1765*77c1e3ccSAndroid Build Coastguard Worker static inline int skip_nearest_near_mv_using_refmv_weight(
1766*77c1e3ccSAndroid Build Coastguard Worker const MACROBLOCK *const x, const PREDICTION_MODE this_mode,
1767*77c1e3ccSAndroid Build Coastguard Worker const int8_t ref_frame_type, PREDICTION_MODE best_mode) {
1768*77c1e3ccSAndroid Build Coastguard Worker if (this_mode != NEARESTMV && this_mode != NEARMV) return 0;
1769*77c1e3ccSAndroid Build Coastguard Worker // Do not skip the mode if the current block has not yet obtained a valid
1770*77c1e3ccSAndroid Build Coastguard Worker // inter mode.
1771*77c1e3ccSAndroid Build Coastguard Worker if (!is_inter_mode(best_mode)) return 0;
1772*77c1e3ccSAndroid Build Coastguard Worker
1773*77c1e3ccSAndroid Build Coastguard Worker const MACROBLOCKD *xd = &x->e_mbd;
1774*77c1e3ccSAndroid Build Coastguard Worker // Do not skip the mode if both the top and left neighboring blocks are not
1775*77c1e3ccSAndroid Build Coastguard Worker // available.
1776*77c1e3ccSAndroid Build Coastguard Worker if (!xd->left_available || !xd->up_available) return 0;
1777*77c1e3ccSAndroid Build Coastguard Worker const MB_MODE_INFO_EXT *const mbmi_ext = &x->mbmi_ext;
1778*77c1e3ccSAndroid Build Coastguard Worker const uint16_t *const ref_mv_weight = mbmi_ext->weight[ref_frame_type];
1779*77c1e3ccSAndroid Build Coastguard Worker const int ref_mv_count =
1780*77c1e3ccSAndroid Build Coastguard Worker AOMMIN(MAX_REF_MV_SEARCH, mbmi_ext->ref_mv_count[ref_frame_type]);
1781*77c1e3ccSAndroid Build Coastguard Worker
1782*77c1e3ccSAndroid Build Coastguard Worker if (ref_mv_count == 0) return 0;
1783*77c1e3ccSAndroid Build Coastguard Worker // If ref mv list has at least one nearest candidate do not prune NEARESTMV
1784*77c1e3ccSAndroid Build Coastguard Worker if (this_mode == NEARESTMV && ref_mv_weight[0] >= REF_CAT_LEVEL) return 0;
1785*77c1e3ccSAndroid Build Coastguard Worker
1786*77c1e3ccSAndroid Build Coastguard Worker // Count number of ref mvs populated from nearest candidates
1787*77c1e3ccSAndroid Build Coastguard Worker int nearest_refmv_count = 0;
1788*77c1e3ccSAndroid Build Coastguard Worker for (int ref_mv_idx = 0; ref_mv_idx < ref_mv_count; ref_mv_idx++) {
1789*77c1e3ccSAndroid Build Coastguard Worker if (ref_mv_weight[ref_mv_idx] >= REF_CAT_LEVEL) nearest_refmv_count++;
1790*77c1e3ccSAndroid Build Coastguard Worker }
1791*77c1e3ccSAndroid Build Coastguard Worker
1792*77c1e3ccSAndroid Build Coastguard Worker // nearest_refmv_count indicates the closeness of block motion characteristics
1793*77c1e3ccSAndroid Build Coastguard Worker // with respect to its spatial neighbor. Smaller value of nearest_refmv_count
1794*77c1e3ccSAndroid Build Coastguard Worker // w.r.t to ref_mv_count means less correlation with its spatial neighbors.
1795*77c1e3ccSAndroid Build Coastguard Worker // Hence less possibility for NEARESTMV and NEARMV modes becoming the best
1796*77c1e3ccSAndroid Build Coastguard Worker // mode since these modes work well for blocks that shares similar motion
1797*77c1e3ccSAndroid Build Coastguard Worker // characteristics with its neighbor. Thus, NEARMV mode is pruned when
1798*77c1e3ccSAndroid Build Coastguard Worker // nearest_refmv_count is relatively smaller than ref_mv_count and NEARESTMV
1799*77c1e3ccSAndroid Build Coastguard Worker // mode is pruned if none of the ref mvs are populated from nearest candidate.
1800*77c1e3ccSAndroid Build Coastguard Worker const int prune_thresh = 1 + (ref_mv_count >= 2);
1801*77c1e3ccSAndroid Build Coastguard Worker if (nearest_refmv_count < prune_thresh) return 1;
1802*77c1e3ccSAndroid Build Coastguard Worker return 0;
1803*77c1e3ccSAndroid Build Coastguard Worker }
1804*77c1e3ccSAndroid Build Coastguard Worker
1805*77c1e3ccSAndroid Build Coastguard Worker // This function update the non-new mv for the current prediction mode
build_cur_mv(int_mv * cur_mv,PREDICTION_MODE this_mode,const AV1_COMMON * cm,const MACROBLOCK * x,int skip_repeated_ref_mv)1806*77c1e3ccSAndroid Build Coastguard Worker static inline int build_cur_mv(int_mv *cur_mv, PREDICTION_MODE this_mode,
1807*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *cm, const MACROBLOCK *x,
1808*77c1e3ccSAndroid Build Coastguard Worker int skip_repeated_ref_mv) {
1809*77c1e3ccSAndroid Build Coastguard Worker const MACROBLOCKD *xd = &x->e_mbd;
1810*77c1e3ccSAndroid Build Coastguard Worker const MB_MODE_INFO *mbmi = xd->mi[0];
1811*77c1e3ccSAndroid Build Coastguard Worker const int is_comp_pred = has_second_ref(mbmi);
1812*77c1e3ccSAndroid Build Coastguard Worker
1813*77c1e3ccSAndroid Build Coastguard Worker int ret = 1;
1814*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < is_comp_pred + 1; ++i) {
1815*77c1e3ccSAndroid Build Coastguard Worker int_mv this_mv;
1816*77c1e3ccSAndroid Build Coastguard Worker this_mv.as_int = INVALID_MV;
1817*77c1e3ccSAndroid Build Coastguard Worker ret = get_this_mv(&this_mv, this_mode, i, mbmi->ref_mv_idx,
1818*77c1e3ccSAndroid Build Coastguard Worker skip_repeated_ref_mv, mbmi->ref_frame, &x->mbmi_ext);
1819*77c1e3ccSAndroid Build Coastguard Worker if (!ret) return 0;
1820*77c1e3ccSAndroid Build Coastguard Worker const PREDICTION_MODE single_mode = get_single_mode(this_mode, i);
1821*77c1e3ccSAndroid Build Coastguard Worker if (single_mode == NEWMV) {
1822*77c1e3ccSAndroid Build Coastguard Worker const uint8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
1823*77c1e3ccSAndroid Build Coastguard Worker cur_mv[i] =
1824*77c1e3ccSAndroid Build Coastguard Worker (i == 0) ? x->mbmi_ext.ref_mv_stack[ref_frame_type][mbmi->ref_mv_idx]
1825*77c1e3ccSAndroid Build Coastguard Worker .this_mv
1826*77c1e3ccSAndroid Build Coastguard Worker : x->mbmi_ext.ref_mv_stack[ref_frame_type][mbmi->ref_mv_idx]
1827*77c1e3ccSAndroid Build Coastguard Worker .comp_mv;
1828*77c1e3ccSAndroid Build Coastguard Worker } else {
1829*77c1e3ccSAndroid Build Coastguard Worker ret &= clamp_and_check_mv(cur_mv + i, this_mv, cm, x);
1830*77c1e3ccSAndroid Build Coastguard Worker }
1831*77c1e3ccSAndroid Build Coastguard Worker }
1832*77c1e3ccSAndroid Build Coastguard Worker return ret;
1833*77c1e3ccSAndroid Build Coastguard Worker }
1834*77c1e3ccSAndroid Build Coastguard Worker
get_drl_cost(const MB_MODE_INFO * mbmi,const MB_MODE_INFO_EXT * mbmi_ext,const int (* const drl_mode_cost0)[2],int8_t ref_frame_type)1835*77c1e3ccSAndroid Build Coastguard Worker static inline int get_drl_cost(const MB_MODE_INFO *mbmi,
1836*77c1e3ccSAndroid Build Coastguard Worker const MB_MODE_INFO_EXT *mbmi_ext,
1837*77c1e3ccSAndroid Build Coastguard Worker const int (*const drl_mode_cost0)[2],
1838*77c1e3ccSAndroid Build Coastguard Worker int8_t ref_frame_type) {
1839*77c1e3ccSAndroid Build Coastguard Worker int cost = 0;
1840*77c1e3ccSAndroid Build Coastguard Worker if (mbmi->mode == NEWMV || mbmi->mode == NEW_NEWMV) {
1841*77c1e3ccSAndroid Build Coastguard Worker for (int idx = 0; idx < 2; ++idx) {
1842*77c1e3ccSAndroid Build Coastguard Worker if (mbmi_ext->ref_mv_count[ref_frame_type] > idx + 1) {
1843*77c1e3ccSAndroid Build Coastguard Worker uint8_t drl_ctx = av1_drl_ctx(mbmi_ext->weight[ref_frame_type], idx);
1844*77c1e3ccSAndroid Build Coastguard Worker cost += drl_mode_cost0[drl_ctx][mbmi->ref_mv_idx != idx];
1845*77c1e3ccSAndroid Build Coastguard Worker if (mbmi->ref_mv_idx == idx) return cost;
1846*77c1e3ccSAndroid Build Coastguard Worker }
1847*77c1e3ccSAndroid Build Coastguard Worker }
1848*77c1e3ccSAndroid Build Coastguard Worker return cost;
1849*77c1e3ccSAndroid Build Coastguard Worker }
1850*77c1e3ccSAndroid Build Coastguard Worker
1851*77c1e3ccSAndroid Build Coastguard Worker if (have_nearmv_in_inter_mode(mbmi->mode)) {
1852*77c1e3ccSAndroid Build Coastguard Worker for (int idx = 1; idx < 3; ++idx) {
1853*77c1e3ccSAndroid Build Coastguard Worker if (mbmi_ext->ref_mv_count[ref_frame_type] > idx + 1) {
1854*77c1e3ccSAndroid Build Coastguard Worker uint8_t drl_ctx = av1_drl_ctx(mbmi_ext->weight[ref_frame_type], idx);
1855*77c1e3ccSAndroid Build Coastguard Worker cost += drl_mode_cost0[drl_ctx][mbmi->ref_mv_idx != (idx - 1)];
1856*77c1e3ccSAndroid Build Coastguard Worker if (mbmi->ref_mv_idx == (idx - 1)) return cost;
1857*77c1e3ccSAndroid Build Coastguard Worker }
1858*77c1e3ccSAndroid Build Coastguard Worker }
1859*77c1e3ccSAndroid Build Coastguard Worker return cost;
1860*77c1e3ccSAndroid Build Coastguard Worker }
1861*77c1e3ccSAndroid Build Coastguard Worker return cost;
1862*77c1e3ccSAndroid Build Coastguard Worker }
1863*77c1e3ccSAndroid Build Coastguard Worker
is_single_newmv_valid(const HandleInterModeArgs * const args,const MB_MODE_INFO * const mbmi,PREDICTION_MODE this_mode)1864*77c1e3ccSAndroid Build Coastguard Worker static inline int is_single_newmv_valid(const HandleInterModeArgs *const args,
1865*77c1e3ccSAndroid Build Coastguard Worker const MB_MODE_INFO *const mbmi,
1866*77c1e3ccSAndroid Build Coastguard Worker PREDICTION_MODE this_mode) {
1867*77c1e3ccSAndroid Build Coastguard Worker for (int ref_idx = 0; ref_idx < 2; ++ref_idx) {
1868*77c1e3ccSAndroid Build Coastguard Worker const PREDICTION_MODE single_mode = get_single_mode(this_mode, ref_idx);
1869*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME ref = mbmi->ref_frame[ref_idx];
1870*77c1e3ccSAndroid Build Coastguard Worker if (single_mode == NEWMV &&
1871*77c1e3ccSAndroid Build Coastguard Worker args->single_newmv_valid[mbmi->ref_mv_idx][ref] == 0) {
1872*77c1e3ccSAndroid Build Coastguard Worker return 0;
1873*77c1e3ccSAndroid Build Coastguard Worker }
1874*77c1e3ccSAndroid Build Coastguard Worker }
1875*77c1e3ccSAndroid Build Coastguard Worker return 1;
1876*77c1e3ccSAndroid Build Coastguard Worker }
1877*77c1e3ccSAndroid Build Coastguard Worker
get_drl_refmv_count(const MACROBLOCK * const x,const MV_REFERENCE_FRAME * ref_frame,PREDICTION_MODE mode)1878*77c1e3ccSAndroid Build Coastguard Worker static int get_drl_refmv_count(const MACROBLOCK *const x,
1879*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME *ref_frame,
1880*77c1e3ccSAndroid Build Coastguard Worker PREDICTION_MODE mode) {
1881*77c1e3ccSAndroid Build Coastguard Worker const MB_MODE_INFO_EXT *const mbmi_ext = &x->mbmi_ext;
1882*77c1e3ccSAndroid Build Coastguard Worker const int8_t ref_frame_type = av1_ref_frame_type(ref_frame);
1883*77c1e3ccSAndroid Build Coastguard Worker const int has_nearmv = have_nearmv_in_inter_mode(mode) ? 1 : 0;
1884*77c1e3ccSAndroid Build Coastguard Worker const int ref_mv_count = mbmi_ext->ref_mv_count[ref_frame_type];
1885*77c1e3ccSAndroid Build Coastguard Worker const int only_newmv = (mode == NEWMV || mode == NEW_NEWMV);
1886*77c1e3ccSAndroid Build Coastguard Worker const int has_drl =
1887*77c1e3ccSAndroid Build Coastguard Worker (has_nearmv && ref_mv_count > 2) || (only_newmv && ref_mv_count > 1);
1888*77c1e3ccSAndroid Build Coastguard Worker const int ref_set =
1889*77c1e3ccSAndroid Build Coastguard Worker has_drl ? AOMMIN(MAX_REF_MV_SEARCH, ref_mv_count - has_nearmv) : 1;
1890*77c1e3ccSAndroid Build Coastguard Worker
1891*77c1e3ccSAndroid Build Coastguard Worker return ref_set;
1892*77c1e3ccSAndroid Build Coastguard Worker }
1893*77c1e3ccSAndroid Build Coastguard Worker
1894*77c1e3ccSAndroid Build Coastguard Worker // Checks if particular ref_mv_idx should be pruned.
prune_ref_mv_idx_using_qindex(const int reduce_inter_modes,const int qindex,const int ref_mv_idx)1895*77c1e3ccSAndroid Build Coastguard Worker static int prune_ref_mv_idx_using_qindex(const int reduce_inter_modes,
1896*77c1e3ccSAndroid Build Coastguard Worker const int qindex,
1897*77c1e3ccSAndroid Build Coastguard Worker const int ref_mv_idx) {
1898*77c1e3ccSAndroid Build Coastguard Worker if (reduce_inter_modes >= 3) return 1;
1899*77c1e3ccSAndroid Build Coastguard Worker // Q-index logic based pruning is enabled only for
1900*77c1e3ccSAndroid Build Coastguard Worker // reduce_inter_modes = 2.
1901*77c1e3ccSAndroid Build Coastguard Worker assert(reduce_inter_modes == 2);
1902*77c1e3ccSAndroid Build Coastguard Worker // When reduce_inter_modes=2, pruning happens as below based on q index.
1903*77c1e3ccSAndroid Build Coastguard Worker // For q index range between 0 and 85: prune if ref_mv_idx >= 1.
1904*77c1e3ccSAndroid Build Coastguard Worker // For q index range between 86 and 170: prune if ref_mv_idx == 2.
1905*77c1e3ccSAndroid Build Coastguard Worker // For q index range between 171 and 255: no pruning.
1906*77c1e3ccSAndroid Build Coastguard Worker const int min_prune_ref_mv_idx = (qindex * 3 / QINDEX_RANGE) + 1;
1907*77c1e3ccSAndroid Build Coastguard Worker return (ref_mv_idx >= min_prune_ref_mv_idx);
1908*77c1e3ccSAndroid Build Coastguard Worker }
1909*77c1e3ccSAndroid Build Coastguard Worker
1910*77c1e3ccSAndroid Build Coastguard Worker // Whether this reference motion vector can be skipped, based on initial
1911*77c1e3ccSAndroid Build Coastguard Worker // heuristics.
ref_mv_idx_early_breakout(const SPEED_FEATURES * const sf,const RefFrameDistanceInfo * const ref_frame_dist_info,MACROBLOCK * x,const HandleInterModeArgs * const args,int64_t ref_best_rd,int ref_mv_idx)1912*77c1e3ccSAndroid Build Coastguard Worker static bool ref_mv_idx_early_breakout(
1913*77c1e3ccSAndroid Build Coastguard Worker const SPEED_FEATURES *const sf,
1914*77c1e3ccSAndroid Build Coastguard Worker const RefFrameDistanceInfo *const ref_frame_dist_info, MACROBLOCK *x,
1915*77c1e3ccSAndroid Build Coastguard Worker const HandleInterModeArgs *const args, int64_t ref_best_rd,
1916*77c1e3ccSAndroid Build Coastguard Worker int ref_mv_idx) {
1917*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *xd = &x->e_mbd;
1918*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *mbmi = xd->mi[0];
1919*77c1e3ccSAndroid Build Coastguard Worker const MB_MODE_INFO_EXT *const mbmi_ext = &x->mbmi_ext;
1920*77c1e3ccSAndroid Build Coastguard Worker const int8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
1921*77c1e3ccSAndroid Build Coastguard Worker const int is_comp_pred = has_second_ref(mbmi);
1922*77c1e3ccSAndroid Build Coastguard Worker if (sf->inter_sf.reduce_inter_modes && ref_mv_idx > 0) {
1923*77c1e3ccSAndroid Build Coastguard Worker if (mbmi->ref_frame[0] == LAST2_FRAME ||
1924*77c1e3ccSAndroid Build Coastguard Worker mbmi->ref_frame[0] == LAST3_FRAME ||
1925*77c1e3ccSAndroid Build Coastguard Worker mbmi->ref_frame[1] == LAST2_FRAME ||
1926*77c1e3ccSAndroid Build Coastguard Worker mbmi->ref_frame[1] == LAST3_FRAME) {
1927*77c1e3ccSAndroid Build Coastguard Worker const int has_nearmv = have_nearmv_in_inter_mode(mbmi->mode) ? 1 : 0;
1928*77c1e3ccSAndroid Build Coastguard Worker if (mbmi_ext->weight[ref_frame_type][ref_mv_idx + has_nearmv] <
1929*77c1e3ccSAndroid Build Coastguard Worker REF_CAT_LEVEL) {
1930*77c1e3ccSAndroid Build Coastguard Worker return true;
1931*77c1e3ccSAndroid Build Coastguard Worker }
1932*77c1e3ccSAndroid Build Coastguard Worker }
1933*77c1e3ccSAndroid Build Coastguard Worker // TODO(any): Experiment with reduce_inter_modes for compound prediction
1934*77c1e3ccSAndroid Build Coastguard Worker if (sf->inter_sf.reduce_inter_modes >= 2 && !is_comp_pred &&
1935*77c1e3ccSAndroid Build Coastguard Worker have_newmv_in_inter_mode(mbmi->mode)) {
1936*77c1e3ccSAndroid Build Coastguard Worker if (mbmi->ref_frame[0] != ref_frame_dist_info->nearest_past_ref &&
1937*77c1e3ccSAndroid Build Coastguard Worker mbmi->ref_frame[0] != ref_frame_dist_info->nearest_future_ref) {
1938*77c1e3ccSAndroid Build Coastguard Worker const int has_nearmv = have_nearmv_in_inter_mode(mbmi->mode) ? 1 : 0;
1939*77c1e3ccSAndroid Build Coastguard Worker const int do_prune = prune_ref_mv_idx_using_qindex(
1940*77c1e3ccSAndroid Build Coastguard Worker sf->inter_sf.reduce_inter_modes, x->qindex, ref_mv_idx);
1941*77c1e3ccSAndroid Build Coastguard Worker if (do_prune &&
1942*77c1e3ccSAndroid Build Coastguard Worker (mbmi_ext->weight[ref_frame_type][ref_mv_idx + has_nearmv] <
1943*77c1e3ccSAndroid Build Coastguard Worker REF_CAT_LEVEL)) {
1944*77c1e3ccSAndroid Build Coastguard Worker return true;
1945*77c1e3ccSAndroid Build Coastguard Worker }
1946*77c1e3ccSAndroid Build Coastguard Worker }
1947*77c1e3ccSAndroid Build Coastguard Worker }
1948*77c1e3ccSAndroid Build Coastguard Worker }
1949*77c1e3ccSAndroid Build Coastguard Worker
1950*77c1e3ccSAndroid Build Coastguard Worker mbmi->ref_mv_idx = ref_mv_idx;
1951*77c1e3ccSAndroid Build Coastguard Worker if (is_comp_pred && (!is_single_newmv_valid(args, mbmi, mbmi->mode))) {
1952*77c1e3ccSAndroid Build Coastguard Worker return true;
1953*77c1e3ccSAndroid Build Coastguard Worker }
1954*77c1e3ccSAndroid Build Coastguard Worker size_t est_rd_rate = args->ref_frame_cost + args->single_comp_cost;
1955*77c1e3ccSAndroid Build Coastguard Worker const int drl_cost = get_drl_cost(
1956*77c1e3ccSAndroid Build Coastguard Worker mbmi, mbmi_ext, x->mode_costs.drl_mode_cost0, ref_frame_type);
1957*77c1e3ccSAndroid Build Coastguard Worker est_rd_rate += drl_cost;
1958*77c1e3ccSAndroid Build Coastguard Worker if (RDCOST(x->rdmult, est_rd_rate, 0) > ref_best_rd &&
1959*77c1e3ccSAndroid Build Coastguard Worker mbmi->mode != NEARESTMV && mbmi->mode != NEAREST_NEARESTMV) {
1960*77c1e3ccSAndroid Build Coastguard Worker return true;
1961*77c1e3ccSAndroid Build Coastguard Worker }
1962*77c1e3ccSAndroid Build Coastguard Worker return false;
1963*77c1e3ccSAndroid Build Coastguard Worker }
1964*77c1e3ccSAndroid Build Coastguard Worker
1965*77c1e3ccSAndroid Build Coastguard Worker // Compute the estimated RD cost for the motion vector with simple translation.
simple_translation_pred_rd(AV1_COMP * const cpi,MACROBLOCK * x,RD_STATS * rd_stats,HandleInterModeArgs * args,int ref_mv_idx,int64_t ref_best_rd,BLOCK_SIZE bsize)1966*77c1e3ccSAndroid Build Coastguard Worker static int64_t simple_translation_pred_rd(AV1_COMP *const cpi, MACROBLOCK *x,
1967*77c1e3ccSAndroid Build Coastguard Worker RD_STATS *rd_stats,
1968*77c1e3ccSAndroid Build Coastguard Worker HandleInterModeArgs *args,
1969*77c1e3ccSAndroid Build Coastguard Worker int ref_mv_idx, int64_t ref_best_rd,
1970*77c1e3ccSAndroid Build Coastguard Worker BLOCK_SIZE bsize) {
1971*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *xd = &x->e_mbd;
1972*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *mbmi = xd->mi[0];
1973*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO_EXT *const mbmi_ext = &x->mbmi_ext;
1974*77c1e3ccSAndroid Build Coastguard Worker const int8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
1975*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *cm = &cpi->common;
1976*77c1e3ccSAndroid Build Coastguard Worker const int is_comp_pred = has_second_ref(mbmi);
1977*77c1e3ccSAndroid Build Coastguard Worker const ModeCosts *mode_costs = &x->mode_costs;
1978*77c1e3ccSAndroid Build Coastguard Worker
1979*77c1e3ccSAndroid Build Coastguard Worker struct macroblockd_plane *p = xd->plane;
1980*77c1e3ccSAndroid Build Coastguard Worker const BUFFER_SET orig_dst = {
1981*77c1e3ccSAndroid Build Coastguard Worker { p[0].dst.buf, p[1].dst.buf, p[2].dst.buf },
1982*77c1e3ccSAndroid Build Coastguard Worker { p[0].dst.stride, p[1].dst.stride, p[2].dst.stride },
1983*77c1e3ccSAndroid Build Coastguard Worker };
1984*77c1e3ccSAndroid Build Coastguard Worker av1_init_rd_stats(rd_stats);
1985*77c1e3ccSAndroid Build Coastguard Worker
1986*77c1e3ccSAndroid Build Coastguard Worker mbmi->interinter_comp.type = COMPOUND_AVERAGE;
1987*77c1e3ccSAndroid Build Coastguard Worker mbmi->comp_group_idx = 0;
1988*77c1e3ccSAndroid Build Coastguard Worker mbmi->compound_idx = 1;
1989*77c1e3ccSAndroid Build Coastguard Worker if (mbmi->ref_frame[1] == INTRA_FRAME) {
1990*77c1e3ccSAndroid Build Coastguard Worker mbmi->ref_frame[1] = NONE_FRAME;
1991*77c1e3ccSAndroid Build Coastguard Worker }
1992*77c1e3ccSAndroid Build Coastguard Worker int16_t mode_ctx =
1993*77c1e3ccSAndroid Build Coastguard Worker av1_mode_context_analyzer(mbmi_ext->mode_context, mbmi->ref_frame);
1994*77c1e3ccSAndroid Build Coastguard Worker
1995*77c1e3ccSAndroid Build Coastguard Worker mbmi->num_proj_ref = 0;
1996*77c1e3ccSAndroid Build Coastguard Worker mbmi->motion_mode = SIMPLE_TRANSLATION;
1997*77c1e3ccSAndroid Build Coastguard Worker mbmi->ref_mv_idx = ref_mv_idx;
1998*77c1e3ccSAndroid Build Coastguard Worker
1999*77c1e3ccSAndroid Build Coastguard Worker rd_stats->rate += args->ref_frame_cost + args->single_comp_cost;
2000*77c1e3ccSAndroid Build Coastguard Worker const int drl_cost =
2001*77c1e3ccSAndroid Build Coastguard Worker get_drl_cost(mbmi, mbmi_ext, mode_costs->drl_mode_cost0, ref_frame_type);
2002*77c1e3ccSAndroid Build Coastguard Worker rd_stats->rate += drl_cost;
2003*77c1e3ccSAndroid Build Coastguard Worker
2004*77c1e3ccSAndroid Build Coastguard Worker int_mv cur_mv[2];
2005*77c1e3ccSAndroid Build Coastguard Worker if (!build_cur_mv(cur_mv, mbmi->mode, cm, x, 0)) {
2006*77c1e3ccSAndroid Build Coastguard Worker return INT64_MAX;
2007*77c1e3ccSAndroid Build Coastguard Worker }
2008*77c1e3ccSAndroid Build Coastguard Worker assert(have_nearmv_in_inter_mode(mbmi->mode));
2009*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < is_comp_pred + 1; ++i) {
2010*77c1e3ccSAndroid Build Coastguard Worker mbmi->mv[i].as_int = cur_mv[i].as_int;
2011*77c1e3ccSAndroid Build Coastguard Worker }
2012*77c1e3ccSAndroid Build Coastguard Worker const int ref_mv_cost = cost_mv_ref(mode_costs, mbmi->mode, mode_ctx);
2013*77c1e3ccSAndroid Build Coastguard Worker rd_stats->rate += ref_mv_cost;
2014*77c1e3ccSAndroid Build Coastguard Worker
2015*77c1e3ccSAndroid Build Coastguard Worker if (RDCOST(x->rdmult, rd_stats->rate, 0) > ref_best_rd) {
2016*77c1e3ccSAndroid Build Coastguard Worker return INT64_MAX;
2017*77c1e3ccSAndroid Build Coastguard Worker }
2018*77c1e3ccSAndroid Build Coastguard Worker
2019*77c1e3ccSAndroid Build Coastguard Worker mbmi->motion_mode = SIMPLE_TRANSLATION;
2020*77c1e3ccSAndroid Build Coastguard Worker mbmi->num_proj_ref = 0;
2021*77c1e3ccSAndroid Build Coastguard Worker if (is_comp_pred) {
2022*77c1e3ccSAndroid Build Coastguard Worker // Only compound_average
2023*77c1e3ccSAndroid Build Coastguard Worker mbmi->interinter_comp.type = COMPOUND_AVERAGE;
2024*77c1e3ccSAndroid Build Coastguard Worker mbmi->comp_group_idx = 0;
2025*77c1e3ccSAndroid Build Coastguard Worker mbmi->compound_idx = 1;
2026*77c1e3ccSAndroid Build Coastguard Worker }
2027*77c1e3ccSAndroid Build Coastguard Worker set_default_interp_filters(mbmi, cm->features.interp_filter);
2028*77c1e3ccSAndroid Build Coastguard Worker
2029*77c1e3ccSAndroid Build Coastguard Worker const int mi_row = xd->mi_row;
2030*77c1e3ccSAndroid Build Coastguard Worker const int mi_col = xd->mi_col;
2031*77c1e3ccSAndroid Build Coastguard Worker av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, &orig_dst, bsize,
2032*77c1e3ccSAndroid Build Coastguard Worker AOM_PLANE_Y, AOM_PLANE_Y);
2033*77c1e3ccSAndroid Build Coastguard Worker int est_rate;
2034*77c1e3ccSAndroid Build Coastguard Worker int64_t est_dist;
2035*77c1e3ccSAndroid Build Coastguard Worker model_rd_sb_fn[MODELRD_CURVFIT](cpi, bsize, x, xd, 0, 0, &est_rate, &est_dist,
2036*77c1e3ccSAndroid Build Coastguard Worker NULL, NULL, NULL, NULL, NULL);
2037*77c1e3ccSAndroid Build Coastguard Worker return RDCOST(x->rdmult, rd_stats->rate + est_rate, est_dist);
2038*77c1e3ccSAndroid Build Coastguard Worker }
2039*77c1e3ccSAndroid Build Coastguard Worker
2040*77c1e3ccSAndroid Build Coastguard Worker // Represents a set of integers, from 0 to sizeof(int) * 8, as bits in
2041*77c1e3ccSAndroid Build Coastguard Worker // an integer. 0 for the i-th bit means that integer is excluded, 1 means
2042*77c1e3ccSAndroid Build Coastguard Worker // it is included.
mask_set_bit(int * mask,int index)2043*77c1e3ccSAndroid Build Coastguard Worker static inline void mask_set_bit(int *mask, int index) { *mask |= (1 << index); }
2044*77c1e3ccSAndroid Build Coastguard Worker
mask_check_bit(int mask,int index)2045*77c1e3ccSAndroid Build Coastguard Worker static inline bool mask_check_bit(int mask, int index) {
2046*77c1e3ccSAndroid Build Coastguard Worker return (mask >> index) & 0x1;
2047*77c1e3ccSAndroid Build Coastguard Worker }
2048*77c1e3ccSAndroid Build Coastguard Worker
2049*77c1e3ccSAndroid Build Coastguard Worker // Before performing the full MV search in handle_inter_mode, do a simple
2050*77c1e3ccSAndroid Build Coastguard Worker // translation search and see if we can eliminate any motion vectors.
2051*77c1e3ccSAndroid Build Coastguard Worker // Returns an integer where, if the i-th bit is set, it means that the i-th
2052*77c1e3ccSAndroid Build Coastguard Worker // motion vector should be searched. This is only set for NEAR_MV.
ref_mv_idx_to_search(AV1_COMP * const cpi,MACROBLOCK * x,RD_STATS * rd_stats,HandleInterModeArgs * const args,int64_t ref_best_rd,BLOCK_SIZE bsize,const int ref_set)2053*77c1e3ccSAndroid Build Coastguard Worker static int ref_mv_idx_to_search(AV1_COMP *const cpi, MACROBLOCK *x,
2054*77c1e3ccSAndroid Build Coastguard Worker RD_STATS *rd_stats,
2055*77c1e3ccSAndroid Build Coastguard Worker HandleInterModeArgs *const args,
2056*77c1e3ccSAndroid Build Coastguard Worker int64_t ref_best_rd, BLOCK_SIZE bsize,
2057*77c1e3ccSAndroid Build Coastguard Worker const int ref_set) {
2058*77c1e3ccSAndroid Build Coastguard Worker // If the number of ref mv count is equal to 1, do not prune the same. It
2059*77c1e3ccSAndroid Build Coastguard Worker // is better to evaluate the same than to prune it.
2060*77c1e3ccSAndroid Build Coastguard Worker if (ref_set == 1) return 1;
2061*77c1e3ccSAndroid Build Coastguard Worker AV1_COMMON *const cm = &cpi->common;
2062*77c1e3ccSAndroid Build Coastguard Worker const MACROBLOCKD *const xd = &x->e_mbd;
2063*77c1e3ccSAndroid Build Coastguard Worker const MB_MODE_INFO *const mbmi = xd->mi[0];
2064*77c1e3ccSAndroid Build Coastguard Worker const PREDICTION_MODE this_mode = mbmi->mode;
2065*77c1e3ccSAndroid Build Coastguard Worker
2066*77c1e3ccSAndroid Build Coastguard Worker // Only search indices if they have some chance of being good.
2067*77c1e3ccSAndroid Build Coastguard Worker int good_indices = 0;
2068*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < ref_set; ++i) {
2069*77c1e3ccSAndroid Build Coastguard Worker if (ref_mv_idx_early_breakout(&cpi->sf, &cpi->ref_frame_dist_info, x, args,
2070*77c1e3ccSAndroid Build Coastguard Worker ref_best_rd, i)) {
2071*77c1e3ccSAndroid Build Coastguard Worker continue;
2072*77c1e3ccSAndroid Build Coastguard Worker }
2073*77c1e3ccSAndroid Build Coastguard Worker mask_set_bit(&good_indices, i);
2074*77c1e3ccSAndroid Build Coastguard Worker }
2075*77c1e3ccSAndroid Build Coastguard Worker
2076*77c1e3ccSAndroid Build Coastguard Worker // Only prune in NEARMV mode, if the speed feature is set, and the block size
2077*77c1e3ccSAndroid Build Coastguard Worker // is large enough. If these conditions are not met, return all good indices
2078*77c1e3ccSAndroid Build Coastguard Worker // found so far.
2079*77c1e3ccSAndroid Build Coastguard Worker if (!cpi->sf.inter_sf.prune_mode_search_simple_translation)
2080*77c1e3ccSAndroid Build Coastguard Worker return good_indices;
2081*77c1e3ccSAndroid Build Coastguard Worker if (!have_nearmv_in_inter_mode(this_mode)) return good_indices;
2082*77c1e3ccSAndroid Build Coastguard Worker if (num_pels_log2_lookup[bsize] <= 6) return good_indices;
2083*77c1e3ccSAndroid Build Coastguard Worker // Do not prune when there is internal resizing. TODO(elliottk) fix this
2084*77c1e3ccSAndroid Build Coastguard Worker // so b/2384 can be resolved.
2085*77c1e3ccSAndroid Build Coastguard Worker if (av1_is_scaled(get_ref_scale_factors(cm, mbmi->ref_frame[0])) ||
2086*77c1e3ccSAndroid Build Coastguard Worker (mbmi->ref_frame[1] > 0 &&
2087*77c1e3ccSAndroid Build Coastguard Worker av1_is_scaled(get_ref_scale_factors(cm, mbmi->ref_frame[1])))) {
2088*77c1e3ccSAndroid Build Coastguard Worker return good_indices;
2089*77c1e3ccSAndroid Build Coastguard Worker }
2090*77c1e3ccSAndroid Build Coastguard Worker
2091*77c1e3ccSAndroid Build Coastguard Worker // Calculate the RD cost for the motion vectors using simple translation.
2092*77c1e3ccSAndroid Build Coastguard Worker int64_t idx_rdcost[] = { INT64_MAX, INT64_MAX, INT64_MAX };
2093*77c1e3ccSAndroid Build Coastguard Worker for (int ref_mv_idx = 0; ref_mv_idx < ref_set; ++ref_mv_idx) {
2094*77c1e3ccSAndroid Build Coastguard Worker // If this index is bad, ignore it.
2095*77c1e3ccSAndroid Build Coastguard Worker if (!mask_check_bit(good_indices, ref_mv_idx)) {
2096*77c1e3ccSAndroid Build Coastguard Worker continue;
2097*77c1e3ccSAndroid Build Coastguard Worker }
2098*77c1e3ccSAndroid Build Coastguard Worker idx_rdcost[ref_mv_idx] = simple_translation_pred_rd(
2099*77c1e3ccSAndroid Build Coastguard Worker cpi, x, rd_stats, args, ref_mv_idx, ref_best_rd, bsize);
2100*77c1e3ccSAndroid Build Coastguard Worker }
2101*77c1e3ccSAndroid Build Coastguard Worker // Find the index with the best RD cost.
2102*77c1e3ccSAndroid Build Coastguard Worker int best_idx = 0;
2103*77c1e3ccSAndroid Build Coastguard Worker for (int i = 1; i < MAX_REF_MV_SEARCH; ++i) {
2104*77c1e3ccSAndroid Build Coastguard Worker if (idx_rdcost[i] < idx_rdcost[best_idx]) {
2105*77c1e3ccSAndroid Build Coastguard Worker best_idx = i;
2106*77c1e3ccSAndroid Build Coastguard Worker }
2107*77c1e3ccSAndroid Build Coastguard Worker }
2108*77c1e3ccSAndroid Build Coastguard Worker // Only include indices that are good and within a % of the best.
2109*77c1e3ccSAndroid Build Coastguard Worker const double dth = has_second_ref(mbmi) ? 1.05 : 1.001;
2110*77c1e3ccSAndroid Build Coastguard Worker // If the simple translation cost is not within this multiple of the
2111*77c1e3ccSAndroid Build Coastguard Worker // best RD, skip it. Note that the cutoff is derived experimentally.
2112*77c1e3ccSAndroid Build Coastguard Worker const double ref_dth = 5;
2113*77c1e3ccSAndroid Build Coastguard Worker int result = 0;
2114*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < ref_set; ++i) {
2115*77c1e3ccSAndroid Build Coastguard Worker if (mask_check_bit(good_indices, i) &&
2116*77c1e3ccSAndroid Build Coastguard Worker (1.0 * idx_rdcost[i]) / idx_rdcost[best_idx] < dth &&
2117*77c1e3ccSAndroid Build Coastguard Worker (1.0 * idx_rdcost[i]) / ref_best_rd < ref_dth) {
2118*77c1e3ccSAndroid Build Coastguard Worker mask_set_bit(&result, i);
2119*77c1e3ccSAndroid Build Coastguard Worker }
2120*77c1e3ccSAndroid Build Coastguard Worker }
2121*77c1e3ccSAndroid Build Coastguard Worker return result;
2122*77c1e3ccSAndroid Build Coastguard Worker }
2123*77c1e3ccSAndroid Build Coastguard Worker
2124*77c1e3ccSAndroid Build Coastguard Worker /*!\brief Motion mode information for inter mode search speedup.
2125*77c1e3ccSAndroid Build Coastguard Worker *
2126*77c1e3ccSAndroid Build Coastguard Worker * Used in a speed feature to search motion modes other than
2127*77c1e3ccSAndroid Build Coastguard Worker * SIMPLE_TRANSLATION only on winning candidates.
2128*77c1e3ccSAndroid Build Coastguard Worker */
2129*77c1e3ccSAndroid Build Coastguard Worker typedef struct motion_mode_candidate {
2130*77c1e3ccSAndroid Build Coastguard Worker /*!
2131*77c1e3ccSAndroid Build Coastguard Worker * Mode info for the motion mode candidate.
2132*77c1e3ccSAndroid Build Coastguard Worker */
2133*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO mbmi;
2134*77c1e3ccSAndroid Build Coastguard Worker /*!
2135*77c1e3ccSAndroid Build Coastguard Worker * Rate describing the cost of the motion vectors for this candidate.
2136*77c1e3ccSAndroid Build Coastguard Worker */
2137*77c1e3ccSAndroid Build Coastguard Worker int rate_mv;
2138*77c1e3ccSAndroid Build Coastguard Worker /*!
2139*77c1e3ccSAndroid Build Coastguard Worker * Rate before motion mode search and transform coding is applied.
2140*77c1e3ccSAndroid Build Coastguard Worker */
2141*77c1e3ccSAndroid Build Coastguard Worker int rate2_nocoeff;
2142*77c1e3ccSAndroid Build Coastguard Worker /*!
2143*77c1e3ccSAndroid Build Coastguard Worker * An integer value 0 or 1 which indicates whether or not to skip the motion
2144*77c1e3ccSAndroid Build Coastguard Worker * mode search and default to SIMPLE_TRANSLATION as a speed feature for this
2145*77c1e3ccSAndroid Build Coastguard Worker * candidate.
2146*77c1e3ccSAndroid Build Coastguard Worker */
2147*77c1e3ccSAndroid Build Coastguard Worker int skip_motion_mode;
2148*77c1e3ccSAndroid Build Coastguard Worker /*!
2149*77c1e3ccSAndroid Build Coastguard Worker * Total RD cost for this candidate.
2150*77c1e3ccSAndroid Build Coastguard Worker */
2151*77c1e3ccSAndroid Build Coastguard Worker int64_t rd_cost;
2152*77c1e3ccSAndroid Build Coastguard Worker } motion_mode_candidate;
2153*77c1e3ccSAndroid Build Coastguard Worker
2154*77c1e3ccSAndroid Build Coastguard Worker /*!\cond */
2155*77c1e3ccSAndroid Build Coastguard Worker typedef struct motion_mode_best_st_candidate {
2156*77c1e3ccSAndroid Build Coastguard Worker motion_mode_candidate motion_mode_cand[MAX_WINNER_MOTION_MODES];
2157*77c1e3ccSAndroid Build Coastguard Worker int num_motion_mode_cand;
2158*77c1e3ccSAndroid Build Coastguard Worker } motion_mode_best_st_candidate;
2159*77c1e3ccSAndroid Build Coastguard Worker
2160*77c1e3ccSAndroid Build Coastguard Worker // Checks if the current reference frame matches with neighbouring block's
2161*77c1e3ccSAndroid Build Coastguard Worker // (top/left) reference frames
ref_match_found_in_nb_blocks(MB_MODE_INFO * cur_mbmi,MB_MODE_INFO * nb_mbmi)2162*77c1e3ccSAndroid Build Coastguard Worker static inline int ref_match_found_in_nb_blocks(MB_MODE_INFO *cur_mbmi,
2163*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *nb_mbmi) {
2164*77c1e3ccSAndroid Build Coastguard Worker MV_REFERENCE_FRAME nb_ref_frames[2] = { nb_mbmi->ref_frame[0],
2165*77c1e3ccSAndroid Build Coastguard Worker nb_mbmi->ref_frame[1] };
2166*77c1e3ccSAndroid Build Coastguard Worker MV_REFERENCE_FRAME cur_ref_frames[2] = { cur_mbmi->ref_frame[0],
2167*77c1e3ccSAndroid Build Coastguard Worker cur_mbmi->ref_frame[1] };
2168*77c1e3ccSAndroid Build Coastguard Worker const int is_cur_comp_pred = has_second_ref(cur_mbmi);
2169*77c1e3ccSAndroid Build Coastguard Worker int match_found = 0;
2170*77c1e3ccSAndroid Build Coastguard Worker
2171*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < (is_cur_comp_pred + 1); i++) {
2172*77c1e3ccSAndroid Build Coastguard Worker if ((cur_ref_frames[i] == nb_ref_frames[0]) ||
2173*77c1e3ccSAndroid Build Coastguard Worker (cur_ref_frames[i] == nb_ref_frames[1]))
2174*77c1e3ccSAndroid Build Coastguard Worker match_found = 1;
2175*77c1e3ccSAndroid Build Coastguard Worker }
2176*77c1e3ccSAndroid Build Coastguard Worker return match_found;
2177*77c1e3ccSAndroid Build Coastguard Worker }
2178*77c1e3ccSAndroid Build Coastguard Worker
find_ref_match_in_above_nbs(const int total_mi_cols,MACROBLOCKD * xd)2179*77c1e3ccSAndroid Build Coastguard Worker static inline int find_ref_match_in_above_nbs(const int total_mi_cols,
2180*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *xd) {
2181*77c1e3ccSAndroid Build Coastguard Worker if (!xd->up_available) return 1;
2182*77c1e3ccSAndroid Build Coastguard Worker const int mi_col = xd->mi_col;
2183*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO **cur_mbmi = xd->mi;
2184*77c1e3ccSAndroid Build Coastguard Worker // prev_row_mi points into the mi array, starting at the beginning of the
2185*77c1e3ccSAndroid Build Coastguard Worker // previous row.
2186*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO **prev_row_mi = xd->mi - mi_col - 1 * xd->mi_stride;
2187*77c1e3ccSAndroid Build Coastguard Worker const int end_col = AOMMIN(mi_col + xd->width, total_mi_cols);
2188*77c1e3ccSAndroid Build Coastguard Worker uint8_t mi_step;
2189*77c1e3ccSAndroid Build Coastguard Worker for (int above_mi_col = mi_col; above_mi_col < end_col;
2190*77c1e3ccSAndroid Build Coastguard Worker above_mi_col += mi_step) {
2191*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO **above_mi = prev_row_mi + above_mi_col;
2192*77c1e3ccSAndroid Build Coastguard Worker mi_step = mi_size_wide[above_mi[0]->bsize];
2193*77c1e3ccSAndroid Build Coastguard Worker int match_found = 0;
2194*77c1e3ccSAndroid Build Coastguard Worker if (is_inter_block(*above_mi))
2195*77c1e3ccSAndroid Build Coastguard Worker match_found = ref_match_found_in_nb_blocks(*cur_mbmi, *above_mi);
2196*77c1e3ccSAndroid Build Coastguard Worker if (match_found) return 1;
2197*77c1e3ccSAndroid Build Coastguard Worker }
2198*77c1e3ccSAndroid Build Coastguard Worker return 0;
2199*77c1e3ccSAndroid Build Coastguard Worker }
2200*77c1e3ccSAndroid Build Coastguard Worker
find_ref_match_in_left_nbs(const int total_mi_rows,MACROBLOCKD * xd)2201*77c1e3ccSAndroid Build Coastguard Worker static inline int find_ref_match_in_left_nbs(const int total_mi_rows,
2202*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *xd) {
2203*77c1e3ccSAndroid Build Coastguard Worker if (!xd->left_available) return 1;
2204*77c1e3ccSAndroid Build Coastguard Worker const int mi_row = xd->mi_row;
2205*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO **cur_mbmi = xd->mi;
2206*77c1e3ccSAndroid Build Coastguard Worker // prev_col_mi points into the mi array, starting at the top of the
2207*77c1e3ccSAndroid Build Coastguard Worker // previous column
2208*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO **prev_col_mi = xd->mi - 1 - mi_row * xd->mi_stride;
2209*77c1e3ccSAndroid Build Coastguard Worker const int end_row = AOMMIN(mi_row + xd->height, total_mi_rows);
2210*77c1e3ccSAndroid Build Coastguard Worker uint8_t mi_step;
2211*77c1e3ccSAndroid Build Coastguard Worker for (int left_mi_row = mi_row; left_mi_row < end_row;
2212*77c1e3ccSAndroid Build Coastguard Worker left_mi_row += mi_step) {
2213*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO **left_mi = prev_col_mi + left_mi_row * xd->mi_stride;
2214*77c1e3ccSAndroid Build Coastguard Worker mi_step = mi_size_high[left_mi[0]->bsize];
2215*77c1e3ccSAndroid Build Coastguard Worker int match_found = 0;
2216*77c1e3ccSAndroid Build Coastguard Worker if (is_inter_block(*left_mi))
2217*77c1e3ccSAndroid Build Coastguard Worker match_found = ref_match_found_in_nb_blocks(*cur_mbmi, *left_mi);
2218*77c1e3ccSAndroid Build Coastguard Worker if (match_found) return 1;
2219*77c1e3ccSAndroid Build Coastguard Worker }
2220*77c1e3ccSAndroid Build Coastguard Worker return 0;
2221*77c1e3ccSAndroid Build Coastguard Worker }
2222*77c1e3ccSAndroid Build Coastguard Worker /*!\endcond */
2223*77c1e3ccSAndroid Build Coastguard Worker
2224*77c1e3ccSAndroid Build Coastguard Worker /*! \brief Struct used to hold TPL data to
2225*77c1e3ccSAndroid Build Coastguard Worker * narrow down parts of the inter mode search.
2226*77c1e3ccSAndroid Build Coastguard Worker */
2227*77c1e3ccSAndroid Build Coastguard Worker typedef struct {
2228*77c1e3ccSAndroid Build Coastguard Worker /*!
2229*77c1e3ccSAndroid Build Coastguard Worker * The best inter cost out of all of the reference frames.
2230*77c1e3ccSAndroid Build Coastguard Worker */
2231*77c1e3ccSAndroid Build Coastguard Worker int64_t best_inter_cost;
2232*77c1e3ccSAndroid Build Coastguard Worker /*!
2233*77c1e3ccSAndroid Build Coastguard Worker * The inter cost for each reference frame.
2234*77c1e3ccSAndroid Build Coastguard Worker */
2235*77c1e3ccSAndroid Build Coastguard Worker int64_t ref_inter_cost[INTER_REFS_PER_FRAME];
2236*77c1e3ccSAndroid Build Coastguard Worker } PruneInfoFromTpl;
2237*77c1e3ccSAndroid Build Coastguard Worker
2238*77c1e3ccSAndroid Build Coastguard Worker #if !CONFIG_REALTIME_ONLY
2239*77c1e3ccSAndroid Build Coastguard Worker // TODO(Remya): Check if get_tpl_stats_b() can be reused
get_block_level_tpl_stats(AV1_COMP * cpi,BLOCK_SIZE bsize,int mi_row,int mi_col,int * valid_refs,PruneInfoFromTpl * inter_cost_info_from_tpl)2240*77c1e3ccSAndroid Build Coastguard Worker static inline void get_block_level_tpl_stats(
2241*77c1e3ccSAndroid Build Coastguard Worker AV1_COMP *cpi, BLOCK_SIZE bsize, int mi_row, int mi_col, int *valid_refs,
2242*77c1e3ccSAndroid Build Coastguard Worker PruneInfoFromTpl *inter_cost_info_from_tpl) {
2243*77c1e3ccSAndroid Build Coastguard Worker AV1_COMMON *const cm = &cpi->common;
2244*77c1e3ccSAndroid Build Coastguard Worker
2245*77c1e3ccSAndroid Build Coastguard Worker assert(IMPLIES(cpi->ppi->gf_group.size > 0,
2246*77c1e3ccSAndroid Build Coastguard Worker cpi->gf_frame_index < cpi->ppi->gf_group.size));
2247*77c1e3ccSAndroid Build Coastguard Worker const int tpl_idx = cpi->gf_frame_index;
2248*77c1e3ccSAndroid Build Coastguard Worker TplParams *const tpl_data = &cpi->ppi->tpl_data;
2249*77c1e3ccSAndroid Build Coastguard Worker if (!av1_tpl_stats_ready(tpl_data, tpl_idx)) return;
2250*77c1e3ccSAndroid Build Coastguard Worker const TplDepFrame *tpl_frame = &tpl_data->tpl_frame[tpl_idx];
2251*77c1e3ccSAndroid Build Coastguard Worker const TplDepStats *tpl_stats = tpl_frame->tpl_stats_ptr;
2252*77c1e3ccSAndroid Build Coastguard Worker const int mi_wide = mi_size_wide[bsize];
2253*77c1e3ccSAndroid Build Coastguard Worker const int mi_high = mi_size_high[bsize];
2254*77c1e3ccSAndroid Build Coastguard Worker const int tpl_stride = tpl_frame->stride;
2255*77c1e3ccSAndroid Build Coastguard Worker const int step = 1 << tpl_data->tpl_stats_block_mis_log2;
2256*77c1e3ccSAndroid Build Coastguard Worker const int mi_col_sr =
2257*77c1e3ccSAndroid Build Coastguard Worker coded_to_superres_mi(mi_col, cm->superres_scale_denominator);
2258*77c1e3ccSAndroid Build Coastguard Worker const int mi_col_end_sr =
2259*77c1e3ccSAndroid Build Coastguard Worker coded_to_superres_mi(mi_col + mi_wide, cm->superres_scale_denominator);
2260*77c1e3ccSAndroid Build Coastguard Worker const int mi_cols_sr = av1_pixels_to_mi(cm->superres_upscaled_width);
2261*77c1e3ccSAndroid Build Coastguard Worker
2262*77c1e3ccSAndroid Build Coastguard Worker const int row_step = step;
2263*77c1e3ccSAndroid Build Coastguard Worker const int col_step_sr =
2264*77c1e3ccSAndroid Build Coastguard Worker coded_to_superres_mi(step, cm->superres_scale_denominator);
2265*77c1e3ccSAndroid Build Coastguard Worker for (int row = mi_row; row < AOMMIN(mi_row + mi_high, cm->mi_params.mi_rows);
2266*77c1e3ccSAndroid Build Coastguard Worker row += row_step) {
2267*77c1e3ccSAndroid Build Coastguard Worker for (int col = mi_col_sr; col < AOMMIN(mi_col_end_sr, mi_cols_sr);
2268*77c1e3ccSAndroid Build Coastguard Worker col += col_step_sr) {
2269*77c1e3ccSAndroid Build Coastguard Worker const TplDepStats *this_stats = &tpl_stats[av1_tpl_ptr_pos(
2270*77c1e3ccSAndroid Build Coastguard Worker row, col, tpl_stride, tpl_data->tpl_stats_block_mis_log2)];
2271*77c1e3ccSAndroid Build Coastguard Worker
2272*77c1e3ccSAndroid Build Coastguard Worker // Sums up the inter cost of corresponding ref frames
2273*77c1e3ccSAndroid Build Coastguard Worker for (int ref_idx = 0; ref_idx < INTER_REFS_PER_FRAME; ref_idx++) {
2274*77c1e3ccSAndroid Build Coastguard Worker inter_cost_info_from_tpl->ref_inter_cost[ref_idx] +=
2275*77c1e3ccSAndroid Build Coastguard Worker this_stats->pred_error[ref_idx];
2276*77c1e3ccSAndroid Build Coastguard Worker }
2277*77c1e3ccSAndroid Build Coastguard Worker }
2278*77c1e3ccSAndroid Build Coastguard Worker }
2279*77c1e3ccSAndroid Build Coastguard Worker
2280*77c1e3ccSAndroid Build Coastguard Worker // Computes the best inter cost (minimum inter_cost)
2281*77c1e3ccSAndroid Build Coastguard Worker int64_t best_inter_cost = INT64_MAX;
2282*77c1e3ccSAndroid Build Coastguard Worker for (int ref_idx = 0; ref_idx < INTER_REFS_PER_FRAME; ref_idx++) {
2283*77c1e3ccSAndroid Build Coastguard Worker const int64_t cur_inter_cost =
2284*77c1e3ccSAndroid Build Coastguard Worker inter_cost_info_from_tpl->ref_inter_cost[ref_idx];
2285*77c1e3ccSAndroid Build Coastguard Worker // For invalid ref frames, cur_inter_cost = 0 and has to be handled while
2286*77c1e3ccSAndroid Build Coastguard Worker // calculating the minimum inter_cost
2287*77c1e3ccSAndroid Build Coastguard Worker if (cur_inter_cost != 0 && (cur_inter_cost < best_inter_cost) &&
2288*77c1e3ccSAndroid Build Coastguard Worker valid_refs[ref_idx])
2289*77c1e3ccSAndroid Build Coastguard Worker best_inter_cost = cur_inter_cost;
2290*77c1e3ccSAndroid Build Coastguard Worker }
2291*77c1e3ccSAndroid Build Coastguard Worker inter_cost_info_from_tpl->best_inter_cost = best_inter_cost;
2292*77c1e3ccSAndroid Build Coastguard Worker }
2293*77c1e3ccSAndroid Build Coastguard Worker #endif
2294*77c1e3ccSAndroid Build Coastguard Worker
prune_modes_based_on_tpl_stats(PruneInfoFromTpl * inter_cost_info_from_tpl,const int * refs,int ref_mv_idx,const PREDICTION_MODE this_mode,int prune_mode_level)2295*77c1e3ccSAndroid Build Coastguard Worker static inline int prune_modes_based_on_tpl_stats(
2296*77c1e3ccSAndroid Build Coastguard Worker PruneInfoFromTpl *inter_cost_info_from_tpl, const int *refs, int ref_mv_idx,
2297*77c1e3ccSAndroid Build Coastguard Worker const PREDICTION_MODE this_mode, int prune_mode_level) {
2298*77c1e3ccSAndroid Build Coastguard Worker const int have_newmv = have_newmv_in_inter_mode(this_mode);
2299*77c1e3ccSAndroid Build Coastguard Worker if ((prune_mode_level < 2) && have_newmv) return 0;
2300*77c1e3ccSAndroid Build Coastguard Worker
2301*77c1e3ccSAndroid Build Coastguard Worker const int64_t best_inter_cost = inter_cost_info_from_tpl->best_inter_cost;
2302*77c1e3ccSAndroid Build Coastguard Worker if (best_inter_cost == INT64_MAX) return 0;
2303*77c1e3ccSAndroid Build Coastguard Worker
2304*77c1e3ccSAndroid Build Coastguard Worker const int prune_level = prune_mode_level - 1;
2305*77c1e3ccSAndroid Build Coastguard Worker int64_t cur_inter_cost;
2306*77c1e3ccSAndroid Build Coastguard Worker
2307*77c1e3ccSAndroid Build Coastguard Worker const int is_globalmv =
2308*77c1e3ccSAndroid Build Coastguard Worker (this_mode == GLOBALMV) || (this_mode == GLOBAL_GLOBALMV);
2309*77c1e3ccSAndroid Build Coastguard Worker const int prune_index = is_globalmv ? MAX_REF_MV_SEARCH : ref_mv_idx;
2310*77c1e3ccSAndroid Build Coastguard Worker
2311*77c1e3ccSAndroid Build Coastguard Worker // Thresholds used for pruning:
2312*77c1e3ccSAndroid Build Coastguard Worker // Lower value indicates aggressive pruning and higher value indicates
2313*77c1e3ccSAndroid Build Coastguard Worker // conservative pruning which is set based on ref_mv_idx and speed feature.
2314*77c1e3ccSAndroid Build Coastguard Worker // 'prune_index' 0, 1, 2 corresponds to ref_mv indices 0, 1 and 2. prune_index
2315*77c1e3ccSAndroid Build Coastguard Worker // 3 corresponds to GLOBALMV/GLOBAL_GLOBALMV
2316*77c1e3ccSAndroid Build Coastguard Worker static const int tpl_inter_mode_prune_mul_factor[3][MAX_REF_MV_SEARCH + 1] = {
2317*77c1e3ccSAndroid Build Coastguard Worker { 6, 6, 6, 4 }, { 6, 4, 4, 4 }, { 5, 4, 4, 4 }
2318*77c1e3ccSAndroid Build Coastguard Worker };
2319*77c1e3ccSAndroid Build Coastguard Worker
2320*77c1e3ccSAndroid Build Coastguard Worker const int is_comp_pred = (refs[1] > INTRA_FRAME);
2321*77c1e3ccSAndroid Build Coastguard Worker if (!is_comp_pred) {
2322*77c1e3ccSAndroid Build Coastguard Worker cur_inter_cost = inter_cost_info_from_tpl->ref_inter_cost[refs[0] - 1];
2323*77c1e3ccSAndroid Build Coastguard Worker } else {
2324*77c1e3ccSAndroid Build Coastguard Worker const int64_t inter_cost_ref0 =
2325*77c1e3ccSAndroid Build Coastguard Worker inter_cost_info_from_tpl->ref_inter_cost[refs[0] - 1];
2326*77c1e3ccSAndroid Build Coastguard Worker const int64_t inter_cost_ref1 =
2327*77c1e3ccSAndroid Build Coastguard Worker inter_cost_info_from_tpl->ref_inter_cost[refs[1] - 1];
2328*77c1e3ccSAndroid Build Coastguard Worker // Choose maximum inter_cost among inter_cost_ref0 and inter_cost_ref1 for
2329*77c1e3ccSAndroid Build Coastguard Worker // more aggressive pruning
2330*77c1e3ccSAndroid Build Coastguard Worker cur_inter_cost = AOMMAX(inter_cost_ref0, inter_cost_ref1);
2331*77c1e3ccSAndroid Build Coastguard Worker }
2332*77c1e3ccSAndroid Build Coastguard Worker
2333*77c1e3ccSAndroid Build Coastguard Worker // Prune the mode if cur_inter_cost is greater than threshold times
2334*77c1e3ccSAndroid Build Coastguard Worker // best_inter_cost
2335*77c1e3ccSAndroid Build Coastguard Worker if (cur_inter_cost >
2336*77c1e3ccSAndroid Build Coastguard Worker ((tpl_inter_mode_prune_mul_factor[prune_level][prune_index] *
2337*77c1e3ccSAndroid Build Coastguard Worker best_inter_cost) >>
2338*77c1e3ccSAndroid Build Coastguard Worker 2))
2339*77c1e3ccSAndroid Build Coastguard Worker return 1;
2340*77c1e3ccSAndroid Build Coastguard Worker return 0;
2341*77c1e3ccSAndroid Build Coastguard Worker }
2342*77c1e3ccSAndroid Build Coastguard Worker
2343*77c1e3ccSAndroid Build Coastguard Worker /*!\brief High level function to select parameters for compound mode.
2344*77c1e3ccSAndroid Build Coastguard Worker *
2345*77c1e3ccSAndroid Build Coastguard Worker * \ingroup inter_mode_search
2346*77c1e3ccSAndroid Build Coastguard Worker * The main search functionality is done in the call to av1_compound_type_rd().
2347*77c1e3ccSAndroid Build Coastguard Worker *
2348*77c1e3ccSAndroid Build Coastguard Worker * \param[in] cpi Top-level encoder structure.
2349*77c1e3ccSAndroid Build Coastguard Worker * \param[in] x Pointer to struct holding all the data for
2350*77c1e3ccSAndroid Build Coastguard Worker * the current macroblock.
2351*77c1e3ccSAndroid Build Coastguard Worker * \param[in] args HandleInterModeArgs struct holding
2352*77c1e3ccSAndroid Build Coastguard Worker * miscellaneous arguments for inter mode
2353*77c1e3ccSAndroid Build Coastguard Worker * search. See the documentation for this
2354*77c1e3ccSAndroid Build Coastguard Worker * struct for a description of each member.
2355*77c1e3ccSAndroid Build Coastguard Worker * \param[in] ref_best_rd Best RD found so far for this block.
2356*77c1e3ccSAndroid Build Coastguard Worker * It is used for early termination of this
2357*77c1e3ccSAndroid Build Coastguard Worker * search if the RD exceeds this value.
2358*77c1e3ccSAndroid Build Coastguard Worker * \param[in,out] cur_mv Current motion vector.
2359*77c1e3ccSAndroid Build Coastguard Worker * \param[in] bsize Current block size.
2360*77c1e3ccSAndroid Build Coastguard Worker * \param[in,out] compmode_interinter_cost RD of the selected interinter
2361*77c1e3ccSAndroid Build Coastguard Worker compound mode.
2362*77c1e3ccSAndroid Build Coastguard Worker * \param[in,out] rd_buffers CompoundTypeRdBuffers struct to hold all
2363*77c1e3ccSAndroid Build Coastguard Worker * allocated buffers for the compound
2364*77c1e3ccSAndroid Build Coastguard Worker * predictors and masks in the compound type
2365*77c1e3ccSAndroid Build Coastguard Worker * search.
2366*77c1e3ccSAndroid Build Coastguard Worker * \param[in,out] orig_dst A prediction buffer to hold a computed
2367*77c1e3ccSAndroid Build Coastguard Worker * prediction. This will eventually hold the
2368*77c1e3ccSAndroid Build Coastguard Worker * final prediction, and the tmp_dst info will
2369*77c1e3ccSAndroid Build Coastguard Worker * be copied here.
2370*77c1e3ccSAndroid Build Coastguard Worker * \param[in] tmp_dst A temporary prediction buffer to hold a
2371*77c1e3ccSAndroid Build Coastguard Worker * computed prediction.
2372*77c1e3ccSAndroid Build Coastguard Worker * \param[in,out] rate_mv The rate associated with the motion vectors.
2373*77c1e3ccSAndroid Build Coastguard Worker * This will be modified if a motion search is
2374*77c1e3ccSAndroid Build Coastguard Worker * done in the motion mode search.
2375*77c1e3ccSAndroid Build Coastguard Worker * \param[in,out] rd_stats Struct to keep track of the overall RD
2376*77c1e3ccSAndroid Build Coastguard Worker * information.
2377*77c1e3ccSAndroid Build Coastguard Worker * \param[in,out] skip_rd An array of length 2 where skip_rd[0] is the
2378*77c1e3ccSAndroid Build Coastguard Worker * best total RD for a skip mode so far, and
2379*77c1e3ccSAndroid Build Coastguard Worker * skip_rd[1] is the best RD for a skip mode so
2380*77c1e3ccSAndroid Build Coastguard Worker * far in luma. This is used as a speed feature
2381*77c1e3ccSAndroid Build Coastguard Worker * to skip the transform search if the computed
2382*77c1e3ccSAndroid Build Coastguard Worker * skip RD for the current mode is not better
2383*77c1e3ccSAndroid Build Coastguard Worker * than the best skip_rd so far.
2384*77c1e3ccSAndroid Build Coastguard Worker * \param[in,out] skip_build_pred Indicates whether or not to build the inter
2385*77c1e3ccSAndroid Build Coastguard Worker * predictor. If this is 0, the inter predictor
2386*77c1e3ccSAndroid Build Coastguard Worker * has already been built and thus we can avoid
2387*77c1e3ccSAndroid Build Coastguard Worker * repeating computation.
2388*77c1e3ccSAndroid Build Coastguard Worker * \return Returns 1 if this mode is worse than one already seen and 0 if it is
2389*77c1e3ccSAndroid Build Coastguard Worker * a viable candidate.
2390*77c1e3ccSAndroid Build Coastguard Worker */
process_compound_inter_mode(AV1_COMP * const cpi,MACROBLOCK * x,HandleInterModeArgs * args,int64_t ref_best_rd,int_mv * cur_mv,BLOCK_SIZE bsize,int * compmode_interinter_cost,const CompoundTypeRdBuffers * rd_buffers,const BUFFER_SET * orig_dst,const BUFFER_SET * tmp_dst,int * rate_mv,RD_STATS * rd_stats,int64_t * skip_rd,int * skip_build_pred)2391*77c1e3ccSAndroid Build Coastguard Worker static int process_compound_inter_mode(
2392*77c1e3ccSAndroid Build Coastguard Worker AV1_COMP *const cpi, MACROBLOCK *x, HandleInterModeArgs *args,
2393*77c1e3ccSAndroid Build Coastguard Worker int64_t ref_best_rd, int_mv *cur_mv, BLOCK_SIZE bsize,
2394*77c1e3ccSAndroid Build Coastguard Worker int *compmode_interinter_cost, const CompoundTypeRdBuffers *rd_buffers,
2395*77c1e3ccSAndroid Build Coastguard Worker const BUFFER_SET *orig_dst, const BUFFER_SET *tmp_dst, int *rate_mv,
2396*77c1e3ccSAndroid Build Coastguard Worker RD_STATS *rd_stats, int64_t *skip_rd, int *skip_build_pred) {
2397*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *xd = &x->e_mbd;
2398*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *mbmi = xd->mi[0];
2399*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *cm = &cpi->common;
2400*77c1e3ccSAndroid Build Coastguard Worker const int masked_compound_used = is_any_masked_compound_used(bsize) &&
2401*77c1e3ccSAndroid Build Coastguard Worker cm->seq_params->enable_masked_compound;
2402*77c1e3ccSAndroid Build Coastguard Worker int mode_search_mask = (1 << COMPOUND_AVERAGE) | (1 << COMPOUND_DISTWTD) |
2403*77c1e3ccSAndroid Build Coastguard Worker (1 << COMPOUND_WEDGE) | (1 << COMPOUND_DIFFWTD);
2404*77c1e3ccSAndroid Build Coastguard Worker
2405*77c1e3ccSAndroid Build Coastguard Worker const int num_planes = av1_num_planes(cm);
2406*77c1e3ccSAndroid Build Coastguard Worker const int mi_row = xd->mi_row;
2407*77c1e3ccSAndroid Build Coastguard Worker const int mi_col = xd->mi_col;
2408*77c1e3ccSAndroid Build Coastguard Worker int is_luma_interp_done = 0;
2409*77c1e3ccSAndroid Build Coastguard Worker set_default_interp_filters(mbmi, cm->features.interp_filter);
2410*77c1e3ccSAndroid Build Coastguard Worker
2411*77c1e3ccSAndroid Build Coastguard Worker int64_t best_rd_compound;
2412*77c1e3ccSAndroid Build Coastguard Worker int64_t rd_thresh;
2413*77c1e3ccSAndroid Build Coastguard Worker const int comp_type_rd_shift = COMP_TYPE_RD_THRESH_SHIFT;
2414*77c1e3ccSAndroid Build Coastguard Worker const int comp_type_rd_scale = COMP_TYPE_RD_THRESH_SCALE;
2415*77c1e3ccSAndroid Build Coastguard Worker rd_thresh = get_rd_thresh_from_best_rd(ref_best_rd, (1 << comp_type_rd_shift),
2416*77c1e3ccSAndroid Build Coastguard Worker comp_type_rd_scale);
2417*77c1e3ccSAndroid Build Coastguard Worker // Select compound type and any parameters related to that type
2418*77c1e3ccSAndroid Build Coastguard Worker // (for example, the mask parameters if it is a masked mode) and compute
2419*77c1e3ccSAndroid Build Coastguard Worker // the RD
2420*77c1e3ccSAndroid Build Coastguard Worker *compmode_interinter_cost = av1_compound_type_rd(
2421*77c1e3ccSAndroid Build Coastguard Worker cpi, x, args, bsize, cur_mv, mode_search_mask, masked_compound_used,
2422*77c1e3ccSAndroid Build Coastguard Worker orig_dst, tmp_dst, rd_buffers, rate_mv, &best_rd_compound, rd_stats,
2423*77c1e3ccSAndroid Build Coastguard Worker ref_best_rd, skip_rd[1], &is_luma_interp_done, rd_thresh);
2424*77c1e3ccSAndroid Build Coastguard Worker if (ref_best_rd < INT64_MAX &&
2425*77c1e3ccSAndroid Build Coastguard Worker (best_rd_compound >> comp_type_rd_shift) * comp_type_rd_scale >
2426*77c1e3ccSAndroid Build Coastguard Worker ref_best_rd) {
2427*77c1e3ccSAndroid Build Coastguard Worker restore_dst_buf(xd, *orig_dst, num_planes);
2428*77c1e3ccSAndroid Build Coastguard Worker return 1;
2429*77c1e3ccSAndroid Build Coastguard Worker }
2430*77c1e3ccSAndroid Build Coastguard Worker
2431*77c1e3ccSAndroid Build Coastguard Worker // Build only uv predictor for COMPOUND_AVERAGE.
2432*77c1e3ccSAndroid Build Coastguard Worker // Note there is no need to call av1_enc_build_inter_predictor
2433*77c1e3ccSAndroid Build Coastguard Worker // for luma if COMPOUND_AVERAGE is selected because it is the first
2434*77c1e3ccSAndroid Build Coastguard Worker // candidate in av1_compound_type_rd, which means it used the dst_buf
2435*77c1e3ccSAndroid Build Coastguard Worker // rather than the tmp_buf.
2436*77c1e3ccSAndroid Build Coastguard Worker if (mbmi->interinter_comp.type == COMPOUND_AVERAGE && is_luma_interp_done) {
2437*77c1e3ccSAndroid Build Coastguard Worker if (num_planes > 1) {
2438*77c1e3ccSAndroid Build Coastguard Worker av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, orig_dst, bsize,
2439*77c1e3ccSAndroid Build Coastguard Worker AOM_PLANE_U, num_planes - 1);
2440*77c1e3ccSAndroid Build Coastguard Worker }
2441*77c1e3ccSAndroid Build Coastguard Worker *skip_build_pred = 1;
2442*77c1e3ccSAndroid Build Coastguard Worker }
2443*77c1e3ccSAndroid Build Coastguard Worker return 0;
2444*77c1e3ccSAndroid Build Coastguard Worker }
2445*77c1e3ccSAndroid Build Coastguard Worker
2446*77c1e3ccSAndroid Build Coastguard Worker // Speed feature to prune out MVs that are similar to previous MVs if they
2447*77c1e3ccSAndroid Build Coastguard Worker // don't achieve the best RD advantage.
prune_ref_mv_idx_search(int ref_mv_idx,int best_ref_mv_idx,int_mv save_mv[MAX_REF_MV_SEARCH-1][2],MB_MODE_INFO * mbmi,int pruning_factor)2448*77c1e3ccSAndroid Build Coastguard Worker static int prune_ref_mv_idx_search(int ref_mv_idx, int best_ref_mv_idx,
2449*77c1e3ccSAndroid Build Coastguard Worker int_mv save_mv[MAX_REF_MV_SEARCH - 1][2],
2450*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *mbmi, int pruning_factor) {
2451*77c1e3ccSAndroid Build Coastguard Worker int i;
2452*77c1e3ccSAndroid Build Coastguard Worker const int is_comp_pred = has_second_ref(mbmi);
2453*77c1e3ccSAndroid Build Coastguard Worker const int thr = (1 + is_comp_pred) << (pruning_factor + 1);
2454*77c1e3ccSAndroid Build Coastguard Worker
2455*77c1e3ccSAndroid Build Coastguard Worker // Skip the evaluation if an MV match is found.
2456*77c1e3ccSAndroid Build Coastguard Worker if (ref_mv_idx > 0) {
2457*77c1e3ccSAndroid Build Coastguard Worker for (int idx = 0; idx < ref_mv_idx; ++idx) {
2458*77c1e3ccSAndroid Build Coastguard Worker if (save_mv[idx][0].as_int == INVALID_MV) continue;
2459*77c1e3ccSAndroid Build Coastguard Worker
2460*77c1e3ccSAndroid Build Coastguard Worker int mv_diff = 0;
2461*77c1e3ccSAndroid Build Coastguard Worker for (i = 0; i < 1 + is_comp_pred; ++i) {
2462*77c1e3ccSAndroid Build Coastguard Worker mv_diff += abs(save_mv[idx][i].as_mv.row - mbmi->mv[i].as_mv.row) +
2463*77c1e3ccSAndroid Build Coastguard Worker abs(save_mv[idx][i].as_mv.col - mbmi->mv[i].as_mv.col);
2464*77c1e3ccSAndroid Build Coastguard Worker }
2465*77c1e3ccSAndroid Build Coastguard Worker
2466*77c1e3ccSAndroid Build Coastguard Worker // If this mode is not the best one, and current MV is similar to
2467*77c1e3ccSAndroid Build Coastguard Worker // previous stored MV, terminate this ref_mv_idx evaluation.
2468*77c1e3ccSAndroid Build Coastguard Worker if (best_ref_mv_idx == -1 && mv_diff <= thr) return 1;
2469*77c1e3ccSAndroid Build Coastguard Worker }
2470*77c1e3ccSAndroid Build Coastguard Worker }
2471*77c1e3ccSAndroid Build Coastguard Worker
2472*77c1e3ccSAndroid Build Coastguard Worker if (ref_mv_idx < MAX_REF_MV_SEARCH - 1) {
2473*77c1e3ccSAndroid Build Coastguard Worker for (i = 0; i < is_comp_pred + 1; ++i)
2474*77c1e3ccSAndroid Build Coastguard Worker save_mv[ref_mv_idx][i].as_int = mbmi->mv[i].as_int;
2475*77c1e3ccSAndroid Build Coastguard Worker }
2476*77c1e3ccSAndroid Build Coastguard Worker
2477*77c1e3ccSAndroid Build Coastguard Worker return 0;
2478*77c1e3ccSAndroid Build Coastguard Worker }
2479*77c1e3ccSAndroid Build Coastguard Worker
2480*77c1e3ccSAndroid Build Coastguard Worker /*!\brief Prunes ZeroMV Search Using Best NEWMV's SSE
2481*77c1e3ccSAndroid Build Coastguard Worker *
2482*77c1e3ccSAndroid Build Coastguard Worker * \ingroup inter_mode_search
2483*77c1e3ccSAndroid Build Coastguard Worker *
2484*77c1e3ccSAndroid Build Coastguard Worker * Compares the sse of zero mv and the best sse found in single new_mv. If the
2485*77c1e3ccSAndroid Build Coastguard Worker * sse of the zero_mv is higher, returns 1 to signal zero_mv can be skipped.
2486*77c1e3ccSAndroid Build Coastguard Worker * Else returns 0.
2487*77c1e3ccSAndroid Build Coastguard Worker *
2488*77c1e3ccSAndroid Build Coastguard Worker * Note that the sse of here comes from single_motion_search. So it is
2489*77c1e3ccSAndroid Build Coastguard Worker * interpolated with the filter in motion search, not the actual interpolation
2490*77c1e3ccSAndroid Build Coastguard Worker * filter used in encoding.
2491*77c1e3ccSAndroid Build Coastguard Worker *
2492*77c1e3ccSAndroid Build Coastguard Worker * \param[in] fn_ptr A table of function pointers to compute SSE.
2493*77c1e3ccSAndroid Build Coastguard Worker * \param[in] x Pointer to struct holding all the data for
2494*77c1e3ccSAndroid Build Coastguard Worker * the current macroblock.
2495*77c1e3ccSAndroid Build Coastguard Worker * \param[in] bsize The current block_size.
2496*77c1e3ccSAndroid Build Coastguard Worker * \param[in] args The args to handle_inter_mode, used to track
2497*77c1e3ccSAndroid Build Coastguard Worker * the best SSE.
2498*77c1e3ccSAndroid Build Coastguard Worker * \param[in] prune_zero_mv_with_sse The argument holds speed feature
2499*77c1e3ccSAndroid Build Coastguard Worker * prune_zero_mv_with_sse value
2500*77c1e3ccSAndroid Build Coastguard Worker * \return Returns 1 if zero_mv is pruned, 0 otherwise.
2501*77c1e3ccSAndroid Build Coastguard Worker */
prune_zero_mv_with_sse(const aom_variance_fn_ptr_t * fn_ptr,const MACROBLOCK * x,BLOCK_SIZE bsize,const HandleInterModeArgs * args,int prune_zero_mv_with_sse)2502*77c1e3ccSAndroid Build Coastguard Worker static inline int prune_zero_mv_with_sse(const aom_variance_fn_ptr_t *fn_ptr,
2503*77c1e3ccSAndroid Build Coastguard Worker const MACROBLOCK *x, BLOCK_SIZE bsize,
2504*77c1e3ccSAndroid Build Coastguard Worker const HandleInterModeArgs *args,
2505*77c1e3ccSAndroid Build Coastguard Worker int prune_zero_mv_with_sse) {
2506*77c1e3ccSAndroid Build Coastguard Worker const MACROBLOCKD *xd = &x->e_mbd;
2507*77c1e3ccSAndroid Build Coastguard Worker const MB_MODE_INFO *mbmi = xd->mi[0];
2508*77c1e3ccSAndroid Build Coastguard Worker
2509*77c1e3ccSAndroid Build Coastguard Worker const int is_comp_pred = has_second_ref(mbmi);
2510*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME *refs = mbmi->ref_frame;
2511*77c1e3ccSAndroid Build Coastguard Worker
2512*77c1e3ccSAndroid Build Coastguard Worker for (int idx = 0; idx < 1 + is_comp_pred; idx++) {
2513*77c1e3ccSAndroid Build Coastguard Worker if (xd->global_motion[refs[idx]].wmtype != IDENTITY) {
2514*77c1e3ccSAndroid Build Coastguard Worker // Pruning logic only works for IDENTITY type models
2515*77c1e3ccSAndroid Build Coastguard Worker // Note: In theory we could apply similar logic for TRANSLATION
2516*77c1e3ccSAndroid Build Coastguard Worker // type models, but we do not code these due to a spec bug
2517*77c1e3ccSAndroid Build Coastguard Worker // (see comments in gm_get_motion_vector() in av1/common/mv.h)
2518*77c1e3ccSAndroid Build Coastguard Worker assert(xd->global_motion[refs[idx]].wmtype != TRANSLATION);
2519*77c1e3ccSAndroid Build Coastguard Worker return 0;
2520*77c1e3ccSAndroid Build Coastguard Worker }
2521*77c1e3ccSAndroid Build Coastguard Worker
2522*77c1e3ccSAndroid Build Coastguard Worker // Don't prune if we have invalid data
2523*77c1e3ccSAndroid Build Coastguard Worker assert(mbmi->mv[idx].as_int == 0);
2524*77c1e3ccSAndroid Build Coastguard Worker if (args->best_single_sse_in_refs[refs[idx]] == INT32_MAX) {
2525*77c1e3ccSAndroid Build Coastguard Worker return 0;
2526*77c1e3ccSAndroid Build Coastguard Worker }
2527*77c1e3ccSAndroid Build Coastguard Worker }
2528*77c1e3ccSAndroid Build Coastguard Worker
2529*77c1e3ccSAndroid Build Coastguard Worker // Sum up the sse of ZEROMV and best NEWMV
2530*77c1e3ccSAndroid Build Coastguard Worker unsigned int this_sse_sum = 0;
2531*77c1e3ccSAndroid Build Coastguard Worker unsigned int best_sse_sum = 0;
2532*77c1e3ccSAndroid Build Coastguard Worker for (int idx = 0; idx < 1 + is_comp_pred; idx++) {
2533*77c1e3ccSAndroid Build Coastguard Worker const struct macroblock_plane *const p = &x->plane[AOM_PLANE_Y];
2534*77c1e3ccSAndroid Build Coastguard Worker const struct macroblockd_plane *pd = xd->plane;
2535*77c1e3ccSAndroid Build Coastguard Worker const struct buf_2d *src_buf = &p->src;
2536*77c1e3ccSAndroid Build Coastguard Worker const struct buf_2d *ref_buf = &pd->pre[idx];
2537*77c1e3ccSAndroid Build Coastguard Worker const uint8_t *src = src_buf->buf;
2538*77c1e3ccSAndroid Build Coastguard Worker const uint8_t *ref = ref_buf->buf;
2539*77c1e3ccSAndroid Build Coastguard Worker const int src_stride = src_buf->stride;
2540*77c1e3ccSAndroid Build Coastguard Worker const int ref_stride = ref_buf->stride;
2541*77c1e3ccSAndroid Build Coastguard Worker
2542*77c1e3ccSAndroid Build Coastguard Worker unsigned int this_sse;
2543*77c1e3ccSAndroid Build Coastguard Worker fn_ptr[bsize].vf(ref, ref_stride, src, src_stride, &this_sse);
2544*77c1e3ccSAndroid Build Coastguard Worker this_sse_sum += this_sse;
2545*77c1e3ccSAndroid Build Coastguard Worker
2546*77c1e3ccSAndroid Build Coastguard Worker const unsigned int best_sse = args->best_single_sse_in_refs[refs[idx]];
2547*77c1e3ccSAndroid Build Coastguard Worker best_sse_sum += best_sse;
2548*77c1e3ccSAndroid Build Coastguard Worker }
2549*77c1e3ccSAndroid Build Coastguard Worker
2550*77c1e3ccSAndroid Build Coastguard Worker const double mul = prune_zero_mv_with_sse > 1 ? 1.00 : 1.25;
2551*77c1e3ccSAndroid Build Coastguard Worker if ((double)this_sse_sum > (mul * (double)best_sse_sum)) {
2552*77c1e3ccSAndroid Build Coastguard Worker return 1;
2553*77c1e3ccSAndroid Build Coastguard Worker }
2554*77c1e3ccSAndroid Build Coastguard Worker
2555*77c1e3ccSAndroid Build Coastguard Worker return 0;
2556*77c1e3ccSAndroid Build Coastguard Worker }
2557*77c1e3ccSAndroid Build Coastguard Worker
2558*77c1e3ccSAndroid Build Coastguard Worker /*!\brief Searches for interpolation filter in realtime mode during winner eval
2559*77c1e3ccSAndroid Build Coastguard Worker *
2560*77c1e3ccSAndroid Build Coastguard Worker * \ingroup inter_mode_search
2561*77c1e3ccSAndroid Build Coastguard Worker *
2562*77c1e3ccSAndroid Build Coastguard Worker * Does a simple interpolation filter search during winner mode evaluation. This
2563*77c1e3ccSAndroid Build Coastguard Worker * is currently only used by realtime mode as \ref
2564*77c1e3ccSAndroid Build Coastguard Worker * av1_interpolation_filter_search is not called during realtime encoding.
2565*77c1e3ccSAndroid Build Coastguard Worker *
2566*77c1e3ccSAndroid Build Coastguard Worker * This function only searches over two possible filters. EIGHTTAP_REGULAR is
2567*77c1e3ccSAndroid Build Coastguard Worker * always search. For lowres clips (<= 240p), MULTITAP_SHARP is also search. For
2568*77c1e3ccSAndroid Build Coastguard Worker * higher res slips (>240p), EIGHTTAP_SMOOTH is also searched.
2569*77c1e3ccSAndroid Build Coastguard Worker * *
2570*77c1e3ccSAndroid Build Coastguard Worker * \param[in] cpi Pointer to the compressor. Used for feature
2571*77c1e3ccSAndroid Build Coastguard Worker * flags.
2572*77c1e3ccSAndroid Build Coastguard Worker * \param[in,out] x Pointer to macroblock. This is primarily
2573*77c1e3ccSAndroid Build Coastguard Worker * used to access the buffers.
2574*77c1e3ccSAndroid Build Coastguard Worker * \param[in] mi_row The current row in mi unit (4X4 pixels).
2575*77c1e3ccSAndroid Build Coastguard Worker * \param[in] mi_col The current col in mi unit (4X4 pixels).
2576*77c1e3ccSAndroid Build Coastguard Worker * \param[in] bsize The current block_size.
2577*77c1e3ccSAndroid Build Coastguard Worker * \return Returns true if a predictor is built in xd->dst, false otherwise.
2578*77c1e3ccSAndroid Build Coastguard Worker */
fast_interp_search(const AV1_COMP * cpi,MACROBLOCK * x,int mi_row,int mi_col,BLOCK_SIZE bsize)2579*77c1e3ccSAndroid Build Coastguard Worker static inline bool fast_interp_search(const AV1_COMP *cpi, MACROBLOCK *x,
2580*77c1e3ccSAndroid Build Coastguard Worker int mi_row, int mi_col,
2581*77c1e3ccSAndroid Build Coastguard Worker BLOCK_SIZE bsize) {
2582*77c1e3ccSAndroid Build Coastguard Worker static const InterpFilters filters_ref_set[3] = {
2583*77c1e3ccSAndroid Build Coastguard Worker { EIGHTTAP_REGULAR, EIGHTTAP_REGULAR },
2584*77c1e3ccSAndroid Build Coastguard Worker { EIGHTTAP_SMOOTH, EIGHTTAP_SMOOTH },
2585*77c1e3ccSAndroid Build Coastguard Worker { MULTITAP_SHARP, MULTITAP_SHARP }
2586*77c1e3ccSAndroid Build Coastguard Worker };
2587*77c1e3ccSAndroid Build Coastguard Worker
2588*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *const cm = &cpi->common;
2589*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *const xd = &x->e_mbd;
2590*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *const mi = xd->mi[0];
2591*77c1e3ccSAndroid Build Coastguard Worker int64_t best_cost = INT64_MAX;
2592*77c1e3ccSAndroid Build Coastguard Worker int best_filter_index = -1;
2593*77c1e3ccSAndroid Build Coastguard Worker // dst_bufs[0] sores the new predictor, and dist_bifs[1] stores the best
2594*77c1e3ccSAndroid Build Coastguard Worker const int num_planes = av1_num_planes(cm);
2595*77c1e3ccSAndroid Build Coastguard Worker const int is_240p_or_lesser = AOMMIN(cm->width, cm->height) <= 240;
2596*77c1e3ccSAndroid Build Coastguard Worker assert(is_inter_mode(mi->mode));
2597*77c1e3ccSAndroid Build Coastguard Worker assert(mi->motion_mode == SIMPLE_TRANSLATION);
2598*77c1e3ccSAndroid Build Coastguard Worker assert(!is_inter_compound_mode(mi->mode));
2599*77c1e3ccSAndroid Build Coastguard Worker
2600*77c1e3ccSAndroid Build Coastguard Worker if (!av1_is_interp_needed(xd)) {
2601*77c1e3ccSAndroid Build Coastguard Worker return false;
2602*77c1e3ccSAndroid Build Coastguard Worker }
2603*77c1e3ccSAndroid Build Coastguard Worker
2604*77c1e3ccSAndroid Build Coastguard Worker struct macroblockd_plane *pd = xd->plane;
2605*77c1e3ccSAndroid Build Coastguard Worker const BUFFER_SET orig_dst = {
2606*77c1e3ccSAndroid Build Coastguard Worker { pd[0].dst.buf, pd[1].dst.buf, pd[2].dst.buf },
2607*77c1e3ccSAndroid Build Coastguard Worker { pd[0].dst.stride, pd[1].dst.stride, pd[2].dst.stride },
2608*77c1e3ccSAndroid Build Coastguard Worker };
2609*77c1e3ccSAndroid Build Coastguard Worker uint8_t *const tmp_buf = get_buf_by_bd(xd, x->tmp_pred_bufs[0]);
2610*77c1e3ccSAndroid Build Coastguard Worker const BUFFER_SET tmp_dst = { { tmp_buf, tmp_buf + 1 * MAX_SB_SQUARE,
2611*77c1e3ccSAndroid Build Coastguard Worker tmp_buf + 2 * MAX_SB_SQUARE },
2612*77c1e3ccSAndroid Build Coastguard Worker { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE } };
2613*77c1e3ccSAndroid Build Coastguard Worker const BUFFER_SET *dst_bufs[2] = { &orig_dst, &tmp_dst };
2614*77c1e3ccSAndroid Build Coastguard Worker
2615*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < 3; ++i) {
2616*77c1e3ccSAndroid Build Coastguard Worker if (is_240p_or_lesser) {
2617*77c1e3ccSAndroid Build Coastguard Worker if (filters_ref_set[i].x_filter == EIGHTTAP_SMOOTH) {
2618*77c1e3ccSAndroid Build Coastguard Worker continue;
2619*77c1e3ccSAndroid Build Coastguard Worker }
2620*77c1e3ccSAndroid Build Coastguard Worker } else {
2621*77c1e3ccSAndroid Build Coastguard Worker if (filters_ref_set[i].x_filter == MULTITAP_SHARP) {
2622*77c1e3ccSAndroid Build Coastguard Worker continue;
2623*77c1e3ccSAndroid Build Coastguard Worker }
2624*77c1e3ccSAndroid Build Coastguard Worker }
2625*77c1e3ccSAndroid Build Coastguard Worker int64_t cost;
2626*77c1e3ccSAndroid Build Coastguard Worker RD_STATS tmp_rd = { 0 };
2627*77c1e3ccSAndroid Build Coastguard Worker
2628*77c1e3ccSAndroid Build Coastguard Worker mi->interp_filters.as_filters = filters_ref_set[i];
2629*77c1e3ccSAndroid Build Coastguard Worker av1_enc_build_inter_predictor_y(xd, mi_row, mi_col);
2630*77c1e3ccSAndroid Build Coastguard Worker
2631*77c1e3ccSAndroid Build Coastguard Worker model_rd_sb_fn[cpi->sf.rt_sf.use_simple_rd_model
2632*77c1e3ccSAndroid Build Coastguard Worker ? MODELRD_LEGACY
2633*77c1e3ccSAndroid Build Coastguard Worker : MODELRD_TYPE_INTERP_FILTER](
2634*77c1e3ccSAndroid Build Coastguard Worker cpi, bsize, x, xd, AOM_PLANE_Y, AOM_PLANE_Y, &tmp_rd.rate, &tmp_rd.dist,
2635*77c1e3ccSAndroid Build Coastguard Worker &tmp_rd.skip_txfm, &tmp_rd.sse, NULL, NULL, NULL);
2636*77c1e3ccSAndroid Build Coastguard Worker
2637*77c1e3ccSAndroid Build Coastguard Worker tmp_rd.rate += av1_get_switchable_rate(x, xd, cm->features.interp_filter,
2638*77c1e3ccSAndroid Build Coastguard Worker cm->seq_params->enable_dual_filter);
2639*77c1e3ccSAndroid Build Coastguard Worker cost = RDCOST(x->rdmult, tmp_rd.rate, tmp_rd.dist);
2640*77c1e3ccSAndroid Build Coastguard Worker if (cost < best_cost) {
2641*77c1e3ccSAndroid Build Coastguard Worker best_filter_index = i;
2642*77c1e3ccSAndroid Build Coastguard Worker best_cost = cost;
2643*77c1e3ccSAndroid Build Coastguard Worker swap_dst_buf(xd, dst_bufs, num_planes);
2644*77c1e3ccSAndroid Build Coastguard Worker }
2645*77c1e3ccSAndroid Build Coastguard Worker }
2646*77c1e3ccSAndroid Build Coastguard Worker assert(best_filter_index >= 0);
2647*77c1e3ccSAndroid Build Coastguard Worker
2648*77c1e3ccSAndroid Build Coastguard Worker mi->interp_filters.as_filters = filters_ref_set[best_filter_index];
2649*77c1e3ccSAndroid Build Coastguard Worker
2650*77c1e3ccSAndroid Build Coastguard Worker const bool is_best_pred_in_orig = &orig_dst == dst_bufs[1];
2651*77c1e3ccSAndroid Build Coastguard Worker
2652*77c1e3ccSAndroid Build Coastguard Worker if (is_best_pred_in_orig) {
2653*77c1e3ccSAndroid Build Coastguard Worker swap_dst_buf(xd, dst_bufs, num_planes);
2654*77c1e3ccSAndroid Build Coastguard Worker } else {
2655*77c1e3ccSAndroid Build Coastguard Worker // Note that xd->pd's bufers are kept in sync with dst_bufs[0]. So if
2656*77c1e3ccSAndroid Build Coastguard Worker // is_best_pred_in_orig is false, that means the current buffer is the
2657*77c1e3ccSAndroid Build Coastguard Worker // original one.
2658*77c1e3ccSAndroid Build Coastguard Worker assert(&orig_dst == dst_bufs[0]);
2659*77c1e3ccSAndroid Build Coastguard Worker assert(xd->plane[AOM_PLANE_Y].dst.buf == orig_dst.plane[AOM_PLANE_Y]);
2660*77c1e3ccSAndroid Build Coastguard Worker const int width = block_size_wide[bsize];
2661*77c1e3ccSAndroid Build Coastguard Worker const int height = block_size_high[bsize];
2662*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_AV1_HIGHBITDEPTH
2663*77c1e3ccSAndroid Build Coastguard Worker const bool is_hbd = is_cur_buf_hbd(xd);
2664*77c1e3ccSAndroid Build Coastguard Worker if (is_hbd) {
2665*77c1e3ccSAndroid Build Coastguard Worker aom_highbd_convolve_copy(CONVERT_TO_SHORTPTR(tmp_dst.plane[AOM_PLANE_Y]),
2666*77c1e3ccSAndroid Build Coastguard Worker tmp_dst.stride[AOM_PLANE_Y],
2667*77c1e3ccSAndroid Build Coastguard Worker CONVERT_TO_SHORTPTR(orig_dst.plane[AOM_PLANE_Y]),
2668*77c1e3ccSAndroid Build Coastguard Worker orig_dst.stride[AOM_PLANE_Y], width, height);
2669*77c1e3ccSAndroid Build Coastguard Worker } else {
2670*77c1e3ccSAndroid Build Coastguard Worker aom_convolve_copy(tmp_dst.plane[AOM_PLANE_Y], tmp_dst.stride[AOM_PLANE_Y],
2671*77c1e3ccSAndroid Build Coastguard Worker orig_dst.plane[AOM_PLANE_Y],
2672*77c1e3ccSAndroid Build Coastguard Worker orig_dst.stride[AOM_PLANE_Y], width, height);
2673*77c1e3ccSAndroid Build Coastguard Worker }
2674*77c1e3ccSAndroid Build Coastguard Worker #else
2675*77c1e3ccSAndroid Build Coastguard Worker aom_convolve_copy(tmp_dst.plane[AOM_PLANE_Y], tmp_dst.stride[AOM_PLANE_Y],
2676*77c1e3ccSAndroid Build Coastguard Worker orig_dst.plane[AOM_PLANE_Y], orig_dst.stride[AOM_PLANE_Y],
2677*77c1e3ccSAndroid Build Coastguard Worker width, height);
2678*77c1e3ccSAndroid Build Coastguard Worker #endif
2679*77c1e3ccSAndroid Build Coastguard Worker }
2680*77c1e3ccSAndroid Build Coastguard Worker
2681*77c1e3ccSAndroid Build Coastguard Worker // Build the YUV predictor.
2682*77c1e3ccSAndroid Build Coastguard Worker if (num_planes > 1) {
2683*77c1e3ccSAndroid Build Coastguard Worker av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, NULL, bsize,
2684*77c1e3ccSAndroid Build Coastguard Worker AOM_PLANE_U, AOM_PLANE_V);
2685*77c1e3ccSAndroid Build Coastguard Worker }
2686*77c1e3ccSAndroid Build Coastguard Worker
2687*77c1e3ccSAndroid Build Coastguard Worker return true;
2688*77c1e3ccSAndroid Build Coastguard Worker }
2689*77c1e3ccSAndroid Build Coastguard Worker
2690*77c1e3ccSAndroid Build Coastguard Worker /*!\brief AV1 inter mode RD computation
2691*77c1e3ccSAndroid Build Coastguard Worker *
2692*77c1e3ccSAndroid Build Coastguard Worker * \ingroup inter_mode_search
2693*77c1e3ccSAndroid Build Coastguard Worker * Do the RD search for a given inter mode and compute all information relevant
2694*77c1e3ccSAndroid Build Coastguard Worker * to the input mode. It will compute the best MV,
2695*77c1e3ccSAndroid Build Coastguard Worker * compound parameters (if the mode is a compound mode) and interpolation filter
2696*77c1e3ccSAndroid Build Coastguard Worker * parameters.
2697*77c1e3ccSAndroid Build Coastguard Worker *
2698*77c1e3ccSAndroid Build Coastguard Worker * \param[in] cpi Top-level encoder structure.
2699*77c1e3ccSAndroid Build Coastguard Worker * \param[in] tile_data Pointer to struct holding adaptive
2700*77c1e3ccSAndroid Build Coastguard Worker * data/contexts/models for the tile during
2701*77c1e3ccSAndroid Build Coastguard Worker * encoding.
2702*77c1e3ccSAndroid Build Coastguard Worker * \param[in] x Pointer to structure holding all the data
2703*77c1e3ccSAndroid Build Coastguard Worker * for the current macroblock.
2704*77c1e3ccSAndroid Build Coastguard Worker * \param[in] bsize Current block size.
2705*77c1e3ccSAndroid Build Coastguard Worker * \param[in,out] rd_stats Struct to keep track of the overall RD
2706*77c1e3ccSAndroid Build Coastguard Worker * information.
2707*77c1e3ccSAndroid Build Coastguard Worker * \param[in,out] rd_stats_y Struct to keep track of the RD information
2708*77c1e3ccSAndroid Build Coastguard Worker * for only the Y plane.
2709*77c1e3ccSAndroid Build Coastguard Worker * \param[in,out] rd_stats_uv Struct to keep track of the RD information
2710*77c1e3ccSAndroid Build Coastguard Worker * for only the UV planes.
2711*77c1e3ccSAndroid Build Coastguard Worker * \param[in] args HandleInterModeArgs struct holding
2712*77c1e3ccSAndroid Build Coastguard Worker * miscellaneous arguments for inter mode
2713*77c1e3ccSAndroid Build Coastguard Worker * search. See the documentation for this
2714*77c1e3ccSAndroid Build Coastguard Worker * struct for a description of each member.
2715*77c1e3ccSAndroid Build Coastguard Worker * \param[in] ref_best_rd Best RD found so far for this block.
2716*77c1e3ccSAndroid Build Coastguard Worker * It is used for early termination of this
2717*77c1e3ccSAndroid Build Coastguard Worker * search if the RD exceeds this value.
2718*77c1e3ccSAndroid Build Coastguard Worker * \param[in] tmp_buf Temporary buffer used to hold predictors
2719*77c1e3ccSAndroid Build Coastguard Worker * built in this search.
2720*77c1e3ccSAndroid Build Coastguard Worker * \param[in,out] rd_buffers CompoundTypeRdBuffers struct to hold all
2721*77c1e3ccSAndroid Build Coastguard Worker * allocated buffers for the compound
2722*77c1e3ccSAndroid Build Coastguard Worker * predictors and masks in the compound type
2723*77c1e3ccSAndroid Build Coastguard Worker * search.
2724*77c1e3ccSAndroid Build Coastguard Worker * \param[in,out] best_est_rd Estimated RD for motion mode search if
2725*77c1e3ccSAndroid Build Coastguard Worker * do_tx_search (see below) is 0.
2726*77c1e3ccSAndroid Build Coastguard Worker * \param[in] do_tx_search Parameter to indicate whether or not to do
2727*77c1e3ccSAndroid Build Coastguard Worker * a full transform search. This will compute
2728*77c1e3ccSAndroid Build Coastguard Worker * an estimated RD for the modes without the
2729*77c1e3ccSAndroid Build Coastguard Worker * transform search and later perform the full
2730*77c1e3ccSAndroid Build Coastguard Worker * transform search on the best candidates.
2731*77c1e3ccSAndroid Build Coastguard Worker * \param[in,out] inter_modes_info InterModesInfo struct to hold inter mode
2732*77c1e3ccSAndroid Build Coastguard Worker * information to perform a full transform
2733*77c1e3ccSAndroid Build Coastguard Worker * search only on winning candidates searched
2734*77c1e3ccSAndroid Build Coastguard Worker * with an estimate for transform coding RD.
2735*77c1e3ccSAndroid Build Coastguard Worker * \param[in,out] motion_mode_cand A motion_mode_candidate struct to store
2736*77c1e3ccSAndroid Build Coastguard Worker * motion mode information used in a speed
2737*77c1e3ccSAndroid Build Coastguard Worker * feature to search motion modes other than
2738*77c1e3ccSAndroid Build Coastguard Worker * SIMPLE_TRANSLATION only on winning
2739*77c1e3ccSAndroid Build Coastguard Worker * candidates.
2740*77c1e3ccSAndroid Build Coastguard Worker * \param[in,out] skip_rd A length 2 array, where skip_rd[0] is the
2741*77c1e3ccSAndroid Build Coastguard Worker * best total RD for a skip mode so far, and
2742*77c1e3ccSAndroid Build Coastguard Worker * skip_rd[1] is the best RD for a skip mode so
2743*77c1e3ccSAndroid Build Coastguard Worker * far in luma. This is used as a speed feature
2744*77c1e3ccSAndroid Build Coastguard Worker * to skip the transform search if the computed
2745*77c1e3ccSAndroid Build Coastguard Worker * skip RD for the current mode is not better
2746*77c1e3ccSAndroid Build Coastguard Worker * than the best skip_rd so far.
2747*77c1e3ccSAndroid Build Coastguard Worker * \param[in] inter_cost_info_from_tpl A PruneInfoFromTpl struct used to
2748*77c1e3ccSAndroid Build Coastguard Worker * narrow down the search based on data
2749*77c1e3ccSAndroid Build Coastguard Worker * collected in the TPL model.
2750*77c1e3ccSAndroid Build Coastguard Worker * \param[out] yrd Stores the rdcost corresponding to encoding
2751*77c1e3ccSAndroid Build Coastguard Worker * the luma plane.
2752*77c1e3ccSAndroid Build Coastguard Worker *
2753*77c1e3ccSAndroid Build Coastguard Worker * \return The RD cost for the mode being searched.
2754*77c1e3ccSAndroid Build Coastguard Worker */
handle_inter_mode(AV1_COMP * const cpi,TileDataEnc * tile_data,MACROBLOCK * x,BLOCK_SIZE bsize,RD_STATS * rd_stats,RD_STATS * rd_stats_y,RD_STATS * rd_stats_uv,HandleInterModeArgs * args,int64_t ref_best_rd,uint8_t * const tmp_buf,const CompoundTypeRdBuffers * rd_buffers,int64_t * best_est_rd,const int do_tx_search,InterModesInfo * inter_modes_info,motion_mode_candidate * motion_mode_cand,int64_t * skip_rd,PruneInfoFromTpl * inter_cost_info_from_tpl,int64_t * yrd)2755*77c1e3ccSAndroid Build Coastguard Worker static int64_t handle_inter_mode(
2756*77c1e3ccSAndroid Build Coastguard Worker AV1_COMP *const cpi, TileDataEnc *tile_data, MACROBLOCK *x,
2757*77c1e3ccSAndroid Build Coastguard Worker BLOCK_SIZE bsize, RD_STATS *rd_stats, RD_STATS *rd_stats_y,
2758*77c1e3ccSAndroid Build Coastguard Worker RD_STATS *rd_stats_uv, HandleInterModeArgs *args, int64_t ref_best_rd,
2759*77c1e3ccSAndroid Build Coastguard Worker uint8_t *const tmp_buf, const CompoundTypeRdBuffers *rd_buffers,
2760*77c1e3ccSAndroid Build Coastguard Worker int64_t *best_est_rd, const int do_tx_search,
2761*77c1e3ccSAndroid Build Coastguard Worker InterModesInfo *inter_modes_info, motion_mode_candidate *motion_mode_cand,
2762*77c1e3ccSAndroid Build Coastguard Worker int64_t *skip_rd, PruneInfoFromTpl *inter_cost_info_from_tpl,
2763*77c1e3ccSAndroid Build Coastguard Worker int64_t *yrd) {
2764*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *cm = &cpi->common;
2765*77c1e3ccSAndroid Build Coastguard Worker const int num_planes = av1_num_planes(cm);
2766*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *xd = &x->e_mbd;
2767*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *mbmi = xd->mi[0];
2768*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO_EXT *const mbmi_ext = &x->mbmi_ext;
2769*77c1e3ccSAndroid Build Coastguard Worker TxfmSearchInfo *txfm_info = &x->txfm_search_info;
2770*77c1e3ccSAndroid Build Coastguard Worker const int is_comp_pred = has_second_ref(mbmi);
2771*77c1e3ccSAndroid Build Coastguard Worker const PREDICTION_MODE this_mode = mbmi->mode;
2772*77c1e3ccSAndroid Build Coastguard Worker
2773*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_REALTIME_ONLY
2774*77c1e3ccSAndroid Build Coastguard Worker const int prune_modes_based_on_tpl = 0;
2775*77c1e3ccSAndroid Build Coastguard Worker #else // CONFIG_REALTIME_ONLY
2776*77c1e3ccSAndroid Build Coastguard Worker const TplParams *const tpl_data = &cpi->ppi->tpl_data;
2777*77c1e3ccSAndroid Build Coastguard Worker const int prune_modes_based_on_tpl =
2778*77c1e3ccSAndroid Build Coastguard Worker cpi->sf.inter_sf.prune_inter_modes_based_on_tpl &&
2779*77c1e3ccSAndroid Build Coastguard Worker av1_tpl_stats_ready(tpl_data, cpi->gf_frame_index);
2780*77c1e3ccSAndroid Build Coastguard Worker #endif // CONFIG_REALTIME_ONLY
2781*77c1e3ccSAndroid Build Coastguard Worker int i;
2782*77c1e3ccSAndroid Build Coastguard Worker // Reference frames for this mode
2783*77c1e3ccSAndroid Build Coastguard Worker const int refs[2] = { mbmi->ref_frame[0],
2784*77c1e3ccSAndroid Build Coastguard Worker (mbmi->ref_frame[1] < 0 ? 0 : mbmi->ref_frame[1]) };
2785*77c1e3ccSAndroid Build Coastguard Worker int rate_mv = 0;
2786*77c1e3ccSAndroid Build Coastguard Worker int64_t rd = INT64_MAX;
2787*77c1e3ccSAndroid Build Coastguard Worker // Do first prediction into the destination buffer. Do the next
2788*77c1e3ccSAndroid Build Coastguard Worker // prediction into a temporary buffer. Then keep track of which one
2789*77c1e3ccSAndroid Build Coastguard Worker // of these currently holds the best predictor, and use the other
2790*77c1e3ccSAndroid Build Coastguard Worker // one for future predictions. In the end, copy from tmp_buf to
2791*77c1e3ccSAndroid Build Coastguard Worker // dst if necessary.
2792*77c1e3ccSAndroid Build Coastguard Worker struct macroblockd_plane *pd = xd->plane;
2793*77c1e3ccSAndroid Build Coastguard Worker const BUFFER_SET orig_dst = {
2794*77c1e3ccSAndroid Build Coastguard Worker { pd[0].dst.buf, pd[1].dst.buf, pd[2].dst.buf },
2795*77c1e3ccSAndroid Build Coastguard Worker { pd[0].dst.stride, pd[1].dst.stride, pd[2].dst.stride },
2796*77c1e3ccSAndroid Build Coastguard Worker };
2797*77c1e3ccSAndroid Build Coastguard Worker const BUFFER_SET tmp_dst = { { tmp_buf, tmp_buf + 1 * MAX_SB_SQUARE,
2798*77c1e3ccSAndroid Build Coastguard Worker tmp_buf + 2 * MAX_SB_SQUARE },
2799*77c1e3ccSAndroid Build Coastguard Worker { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE } };
2800*77c1e3ccSAndroid Build Coastguard Worker
2801*77c1e3ccSAndroid Build Coastguard Worker int64_t ret_val = INT64_MAX;
2802*77c1e3ccSAndroid Build Coastguard Worker const int8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
2803*77c1e3ccSAndroid Build Coastguard Worker RD_STATS best_rd_stats, best_rd_stats_y, best_rd_stats_uv;
2804*77c1e3ccSAndroid Build Coastguard Worker int64_t best_rd = INT64_MAX;
2805*77c1e3ccSAndroid Build Coastguard Worker uint8_t best_blk_skip[MAX_MIB_SIZE * MAX_MIB_SIZE];
2806*77c1e3ccSAndroid Build Coastguard Worker uint8_t best_tx_type_map[MAX_MIB_SIZE * MAX_MIB_SIZE];
2807*77c1e3ccSAndroid Build Coastguard Worker int64_t best_yrd = INT64_MAX;
2808*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO best_mbmi = *mbmi;
2809*77c1e3ccSAndroid Build Coastguard Worker int best_xskip_txfm = 0;
2810*77c1e3ccSAndroid Build Coastguard Worker int64_t newmv_ret_val = INT64_MAX;
2811*77c1e3ccSAndroid Build Coastguard Worker inter_mode_info mode_info[MAX_REF_MV_SEARCH];
2812*77c1e3ccSAndroid Build Coastguard Worker
2813*77c1e3ccSAndroid Build Coastguard Worker // Do not prune the mode based on inter cost from tpl if the current ref frame
2814*77c1e3ccSAndroid Build Coastguard Worker // is the winner ref in neighbouring blocks.
2815*77c1e3ccSAndroid Build Coastguard Worker int ref_match_found_in_above_nb = 0;
2816*77c1e3ccSAndroid Build Coastguard Worker int ref_match_found_in_left_nb = 0;
2817*77c1e3ccSAndroid Build Coastguard Worker if (prune_modes_based_on_tpl) {
2818*77c1e3ccSAndroid Build Coastguard Worker ref_match_found_in_above_nb =
2819*77c1e3ccSAndroid Build Coastguard Worker find_ref_match_in_above_nbs(cm->mi_params.mi_cols, xd);
2820*77c1e3ccSAndroid Build Coastguard Worker ref_match_found_in_left_nb =
2821*77c1e3ccSAndroid Build Coastguard Worker find_ref_match_in_left_nbs(cm->mi_params.mi_rows, xd);
2822*77c1e3ccSAndroid Build Coastguard Worker }
2823*77c1e3ccSAndroid Build Coastguard Worker
2824*77c1e3ccSAndroid Build Coastguard Worker // First, perform a simple translation search for each of the indices. If
2825*77c1e3ccSAndroid Build Coastguard Worker // an index performs well, it will be fully searched in the main loop
2826*77c1e3ccSAndroid Build Coastguard Worker // of this function.
2827*77c1e3ccSAndroid Build Coastguard Worker const int ref_set = get_drl_refmv_count(x, mbmi->ref_frame, this_mode);
2828*77c1e3ccSAndroid Build Coastguard Worker // Save MV results from first 2 ref_mv_idx.
2829*77c1e3ccSAndroid Build Coastguard Worker int_mv save_mv[MAX_REF_MV_SEARCH - 1][2];
2830*77c1e3ccSAndroid Build Coastguard Worker int best_ref_mv_idx = -1;
2831*77c1e3ccSAndroid Build Coastguard Worker const int idx_mask =
2832*77c1e3ccSAndroid Build Coastguard Worker ref_mv_idx_to_search(cpi, x, rd_stats, args, ref_best_rd, bsize, ref_set);
2833*77c1e3ccSAndroid Build Coastguard Worker const int16_t mode_ctx =
2834*77c1e3ccSAndroid Build Coastguard Worker av1_mode_context_analyzer(mbmi_ext->mode_context, mbmi->ref_frame);
2835*77c1e3ccSAndroid Build Coastguard Worker const ModeCosts *mode_costs = &x->mode_costs;
2836*77c1e3ccSAndroid Build Coastguard Worker const int ref_mv_cost = cost_mv_ref(mode_costs, this_mode, mode_ctx);
2837*77c1e3ccSAndroid Build Coastguard Worker const int base_rate =
2838*77c1e3ccSAndroid Build Coastguard Worker args->ref_frame_cost + args->single_comp_cost + ref_mv_cost;
2839*77c1e3ccSAndroid Build Coastguard Worker
2840*77c1e3ccSAndroid Build Coastguard Worker for (i = 0; i < MAX_REF_MV_SEARCH - 1; ++i) {
2841*77c1e3ccSAndroid Build Coastguard Worker save_mv[i][0].as_int = INVALID_MV;
2842*77c1e3ccSAndroid Build Coastguard Worker save_mv[i][1].as_int = INVALID_MV;
2843*77c1e3ccSAndroid Build Coastguard Worker }
2844*77c1e3ccSAndroid Build Coastguard Worker args->start_mv_cnt = 0;
2845*77c1e3ccSAndroid Build Coastguard Worker
2846*77c1e3ccSAndroid Build Coastguard Worker // Main loop of this function. This will iterate over all of the ref mvs
2847*77c1e3ccSAndroid Build Coastguard Worker // in the dynamic reference list and do the following:
2848*77c1e3ccSAndroid Build Coastguard Worker // 1.) Get the current MV. Create newmv MV if necessary
2849*77c1e3ccSAndroid Build Coastguard Worker // 2.) Search compound type and parameters if applicable
2850*77c1e3ccSAndroid Build Coastguard Worker // 3.) Do interpolation filter search
2851*77c1e3ccSAndroid Build Coastguard Worker // 4.) Build the inter predictor
2852*77c1e3ccSAndroid Build Coastguard Worker // 5.) Pick the motion mode (SIMPLE_TRANSLATION, OBMC_CAUSAL,
2853*77c1e3ccSAndroid Build Coastguard Worker // WARPED_CAUSAL)
2854*77c1e3ccSAndroid Build Coastguard Worker // 6.) Update stats if best so far
2855*77c1e3ccSAndroid Build Coastguard Worker for (int ref_mv_idx = 0; ref_mv_idx < ref_set; ++ref_mv_idx) {
2856*77c1e3ccSAndroid Build Coastguard Worker mbmi->ref_mv_idx = ref_mv_idx;
2857*77c1e3ccSAndroid Build Coastguard Worker
2858*77c1e3ccSAndroid Build Coastguard Worker mode_info[ref_mv_idx].full_search_mv.as_int = INVALID_MV;
2859*77c1e3ccSAndroid Build Coastguard Worker mode_info[ref_mv_idx].full_mv_bestsme = INT_MAX;
2860*77c1e3ccSAndroid Build Coastguard Worker const int drl_cost = get_drl_cost(
2861*77c1e3ccSAndroid Build Coastguard Worker mbmi, mbmi_ext, mode_costs->drl_mode_cost0, ref_frame_type);
2862*77c1e3ccSAndroid Build Coastguard Worker mode_info[ref_mv_idx].drl_cost = drl_cost;
2863*77c1e3ccSAndroid Build Coastguard Worker mode_info[ref_mv_idx].skip = 0;
2864*77c1e3ccSAndroid Build Coastguard Worker
2865*77c1e3ccSAndroid Build Coastguard Worker if (!mask_check_bit(idx_mask, ref_mv_idx)) {
2866*77c1e3ccSAndroid Build Coastguard Worker // MV did not perform well in simple translation search. Skip it.
2867*77c1e3ccSAndroid Build Coastguard Worker continue;
2868*77c1e3ccSAndroid Build Coastguard Worker }
2869*77c1e3ccSAndroid Build Coastguard Worker if (prune_modes_based_on_tpl && !ref_match_found_in_above_nb &&
2870*77c1e3ccSAndroid Build Coastguard Worker !ref_match_found_in_left_nb && (ref_best_rd != INT64_MAX)) {
2871*77c1e3ccSAndroid Build Coastguard Worker // Skip mode if TPL model indicates it will not be beneficial.
2872*77c1e3ccSAndroid Build Coastguard Worker if (prune_modes_based_on_tpl_stats(
2873*77c1e3ccSAndroid Build Coastguard Worker inter_cost_info_from_tpl, refs, ref_mv_idx, this_mode,
2874*77c1e3ccSAndroid Build Coastguard Worker cpi->sf.inter_sf.prune_inter_modes_based_on_tpl))
2875*77c1e3ccSAndroid Build Coastguard Worker continue;
2876*77c1e3ccSAndroid Build Coastguard Worker }
2877*77c1e3ccSAndroid Build Coastguard Worker av1_init_rd_stats(rd_stats);
2878*77c1e3ccSAndroid Build Coastguard Worker
2879*77c1e3ccSAndroid Build Coastguard Worker // Initialize compound mode data
2880*77c1e3ccSAndroid Build Coastguard Worker mbmi->interinter_comp.type = COMPOUND_AVERAGE;
2881*77c1e3ccSAndroid Build Coastguard Worker mbmi->comp_group_idx = 0;
2882*77c1e3ccSAndroid Build Coastguard Worker mbmi->compound_idx = 1;
2883*77c1e3ccSAndroid Build Coastguard Worker if (mbmi->ref_frame[1] == INTRA_FRAME) mbmi->ref_frame[1] = NONE_FRAME;
2884*77c1e3ccSAndroid Build Coastguard Worker
2885*77c1e3ccSAndroid Build Coastguard Worker mbmi->num_proj_ref = 0;
2886*77c1e3ccSAndroid Build Coastguard Worker mbmi->motion_mode = SIMPLE_TRANSLATION;
2887*77c1e3ccSAndroid Build Coastguard Worker
2888*77c1e3ccSAndroid Build Coastguard Worker // Compute cost for signalling this DRL index
2889*77c1e3ccSAndroid Build Coastguard Worker rd_stats->rate = base_rate;
2890*77c1e3ccSAndroid Build Coastguard Worker rd_stats->rate += drl_cost;
2891*77c1e3ccSAndroid Build Coastguard Worker
2892*77c1e3ccSAndroid Build Coastguard Worker int rs = 0;
2893*77c1e3ccSAndroid Build Coastguard Worker int compmode_interinter_cost = 0;
2894*77c1e3ccSAndroid Build Coastguard Worker
2895*77c1e3ccSAndroid Build Coastguard Worker int_mv cur_mv[2];
2896*77c1e3ccSAndroid Build Coastguard Worker
2897*77c1e3ccSAndroid Build Coastguard Worker // TODO(Cherma): Extend this speed feature to support compound mode
2898*77c1e3ccSAndroid Build Coastguard Worker int skip_repeated_ref_mv =
2899*77c1e3ccSAndroid Build Coastguard Worker is_comp_pred ? 0 : cpi->sf.inter_sf.skip_repeated_ref_mv;
2900*77c1e3ccSAndroid Build Coastguard Worker // Generate the current mv according to the prediction mode
2901*77c1e3ccSAndroid Build Coastguard Worker if (!build_cur_mv(cur_mv, this_mode, cm, x, skip_repeated_ref_mv)) {
2902*77c1e3ccSAndroid Build Coastguard Worker continue;
2903*77c1e3ccSAndroid Build Coastguard Worker }
2904*77c1e3ccSAndroid Build Coastguard Worker
2905*77c1e3ccSAndroid Build Coastguard Worker // The above call to build_cur_mv does not handle NEWMV modes. Build
2906*77c1e3ccSAndroid Build Coastguard Worker // the mv here if we have NEWMV for any predictors.
2907*77c1e3ccSAndroid Build Coastguard Worker if (have_newmv_in_inter_mode(this_mode)) {
2908*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_COLLECT_COMPONENT_TIMING
2909*77c1e3ccSAndroid Build Coastguard Worker start_timing(cpi, handle_newmv_time);
2910*77c1e3ccSAndroid Build Coastguard Worker #endif
2911*77c1e3ccSAndroid Build Coastguard Worker newmv_ret_val =
2912*77c1e3ccSAndroid Build Coastguard Worker handle_newmv(cpi, x, bsize, cur_mv, &rate_mv, args, mode_info);
2913*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_COLLECT_COMPONENT_TIMING
2914*77c1e3ccSAndroid Build Coastguard Worker end_timing(cpi, handle_newmv_time);
2915*77c1e3ccSAndroid Build Coastguard Worker #endif
2916*77c1e3ccSAndroid Build Coastguard Worker
2917*77c1e3ccSAndroid Build Coastguard Worker if (newmv_ret_val != 0) continue;
2918*77c1e3ccSAndroid Build Coastguard Worker
2919*77c1e3ccSAndroid Build Coastguard Worker if (is_inter_singleref_mode(this_mode) &&
2920*77c1e3ccSAndroid Build Coastguard Worker cur_mv[0].as_int != INVALID_MV) {
2921*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME ref = refs[0];
2922*77c1e3ccSAndroid Build Coastguard Worker const unsigned int this_sse = x->pred_sse[ref];
2923*77c1e3ccSAndroid Build Coastguard Worker if (this_sse < args->best_single_sse_in_refs[ref]) {
2924*77c1e3ccSAndroid Build Coastguard Worker args->best_single_sse_in_refs[ref] = this_sse;
2925*77c1e3ccSAndroid Build Coastguard Worker }
2926*77c1e3ccSAndroid Build Coastguard Worker
2927*77c1e3ccSAndroid Build Coastguard Worker if (cpi->sf.rt_sf.skip_newmv_mode_based_on_sse) {
2928*77c1e3ccSAndroid Build Coastguard Worker const int th_idx = cpi->sf.rt_sf.skip_newmv_mode_based_on_sse - 1;
2929*77c1e3ccSAndroid Build Coastguard Worker const int pix_idx = num_pels_log2_lookup[bsize] - 4;
2930*77c1e3ccSAndroid Build Coastguard Worker const double scale_factor[3][11] = {
2931*77c1e3ccSAndroid Build Coastguard Worker { 0.7, 0.7, 0.7, 0.7, 0.7, 0.8, 0.8, 0.9, 0.9, 0.9, 0.9 },
2932*77c1e3ccSAndroid Build Coastguard Worker { 0.7, 0.7, 0.7, 0.7, 0.8, 0.8, 1, 1, 1, 1, 1 },
2933*77c1e3ccSAndroid Build Coastguard Worker { 0.7, 0.7, 0.7, 0.7, 1, 1, 1, 1, 1, 1, 1 }
2934*77c1e3ccSAndroid Build Coastguard Worker };
2935*77c1e3ccSAndroid Build Coastguard Worker assert(pix_idx >= 0);
2936*77c1e3ccSAndroid Build Coastguard Worker assert(th_idx <= 2);
2937*77c1e3ccSAndroid Build Coastguard Worker if (args->best_pred_sse < scale_factor[th_idx][pix_idx] * this_sse)
2938*77c1e3ccSAndroid Build Coastguard Worker continue;
2939*77c1e3ccSAndroid Build Coastguard Worker }
2940*77c1e3ccSAndroid Build Coastguard Worker }
2941*77c1e3ccSAndroid Build Coastguard Worker
2942*77c1e3ccSAndroid Build Coastguard Worker rd_stats->rate += rate_mv;
2943*77c1e3ccSAndroid Build Coastguard Worker }
2944*77c1e3ccSAndroid Build Coastguard Worker // Copy the motion vector for this mode into mbmi struct
2945*77c1e3ccSAndroid Build Coastguard Worker for (i = 0; i < is_comp_pred + 1; ++i) {
2946*77c1e3ccSAndroid Build Coastguard Worker mbmi->mv[i].as_int = cur_mv[i].as_int;
2947*77c1e3ccSAndroid Build Coastguard Worker }
2948*77c1e3ccSAndroid Build Coastguard Worker
2949*77c1e3ccSAndroid Build Coastguard Worker if (RDCOST(x->rdmult, rd_stats->rate, 0) > ref_best_rd &&
2950*77c1e3ccSAndroid Build Coastguard Worker mbmi->mode != NEARESTMV && mbmi->mode != NEAREST_NEARESTMV) {
2951*77c1e3ccSAndroid Build Coastguard Worker continue;
2952*77c1e3ccSAndroid Build Coastguard Worker }
2953*77c1e3ccSAndroid Build Coastguard Worker
2954*77c1e3ccSAndroid Build Coastguard Worker // Skip the rest of the search if prune_ref_mv_idx_search speed feature
2955*77c1e3ccSAndroid Build Coastguard Worker // is enabled, and the current MV is similar to a previous one.
2956*77c1e3ccSAndroid Build Coastguard Worker if (cpi->sf.inter_sf.prune_ref_mv_idx_search && is_comp_pred &&
2957*77c1e3ccSAndroid Build Coastguard Worker prune_ref_mv_idx_search(ref_mv_idx, best_ref_mv_idx, save_mv, mbmi,
2958*77c1e3ccSAndroid Build Coastguard Worker cpi->sf.inter_sf.prune_ref_mv_idx_search))
2959*77c1e3ccSAndroid Build Coastguard Worker continue;
2960*77c1e3ccSAndroid Build Coastguard Worker
2961*77c1e3ccSAndroid Build Coastguard Worker if (cpi->sf.gm_sf.prune_zero_mv_with_sse &&
2962*77c1e3ccSAndroid Build Coastguard Worker (this_mode == GLOBALMV || this_mode == GLOBAL_GLOBALMV)) {
2963*77c1e3ccSAndroid Build Coastguard Worker if (prune_zero_mv_with_sse(cpi->ppi->fn_ptr, x, bsize, args,
2964*77c1e3ccSAndroid Build Coastguard Worker cpi->sf.gm_sf.prune_zero_mv_with_sse)) {
2965*77c1e3ccSAndroid Build Coastguard Worker continue;
2966*77c1e3ccSAndroid Build Coastguard Worker }
2967*77c1e3ccSAndroid Build Coastguard Worker }
2968*77c1e3ccSAndroid Build Coastguard Worker
2969*77c1e3ccSAndroid Build Coastguard Worker int skip_build_pred = 0;
2970*77c1e3ccSAndroid Build Coastguard Worker const int mi_row = xd->mi_row;
2971*77c1e3ccSAndroid Build Coastguard Worker const int mi_col = xd->mi_col;
2972*77c1e3ccSAndroid Build Coastguard Worker
2973*77c1e3ccSAndroid Build Coastguard Worker // Handle a compound predictor, continue if it is determined this
2974*77c1e3ccSAndroid Build Coastguard Worker // cannot be the best compound mode
2975*77c1e3ccSAndroid Build Coastguard Worker if (is_comp_pred) {
2976*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_COLLECT_COMPONENT_TIMING
2977*77c1e3ccSAndroid Build Coastguard Worker start_timing(cpi, compound_type_rd_time);
2978*77c1e3ccSAndroid Build Coastguard Worker #endif
2979*77c1e3ccSAndroid Build Coastguard Worker const int not_best_mode = process_compound_inter_mode(
2980*77c1e3ccSAndroid Build Coastguard Worker cpi, x, args, ref_best_rd, cur_mv, bsize, &compmode_interinter_cost,
2981*77c1e3ccSAndroid Build Coastguard Worker rd_buffers, &orig_dst, &tmp_dst, &rate_mv, rd_stats, skip_rd,
2982*77c1e3ccSAndroid Build Coastguard Worker &skip_build_pred);
2983*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_COLLECT_COMPONENT_TIMING
2984*77c1e3ccSAndroid Build Coastguard Worker end_timing(cpi, compound_type_rd_time);
2985*77c1e3ccSAndroid Build Coastguard Worker #endif
2986*77c1e3ccSAndroid Build Coastguard Worker if (not_best_mode) continue;
2987*77c1e3ccSAndroid Build Coastguard Worker }
2988*77c1e3ccSAndroid Build Coastguard Worker
2989*77c1e3ccSAndroid Build Coastguard Worker if (!args->skip_ifs) {
2990*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_COLLECT_COMPONENT_TIMING
2991*77c1e3ccSAndroid Build Coastguard Worker start_timing(cpi, interpolation_filter_search_time);
2992*77c1e3ccSAndroid Build Coastguard Worker #endif
2993*77c1e3ccSAndroid Build Coastguard Worker // Determine the interpolation filter for this mode
2994*77c1e3ccSAndroid Build Coastguard Worker ret_val = av1_interpolation_filter_search(
2995*77c1e3ccSAndroid Build Coastguard Worker x, cpi, tile_data, bsize, &tmp_dst, &orig_dst, &rd, &rs,
2996*77c1e3ccSAndroid Build Coastguard Worker &skip_build_pred, args, ref_best_rd);
2997*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_COLLECT_COMPONENT_TIMING
2998*77c1e3ccSAndroid Build Coastguard Worker end_timing(cpi, interpolation_filter_search_time);
2999*77c1e3ccSAndroid Build Coastguard Worker #endif
3000*77c1e3ccSAndroid Build Coastguard Worker if (args->modelled_rd != NULL && !is_comp_pred) {
3001*77c1e3ccSAndroid Build Coastguard Worker args->modelled_rd[this_mode][ref_mv_idx][refs[0]] = rd;
3002*77c1e3ccSAndroid Build Coastguard Worker }
3003*77c1e3ccSAndroid Build Coastguard Worker if (ret_val != 0) {
3004*77c1e3ccSAndroid Build Coastguard Worker restore_dst_buf(xd, orig_dst, num_planes);
3005*77c1e3ccSAndroid Build Coastguard Worker continue;
3006*77c1e3ccSAndroid Build Coastguard Worker } else if (cpi->sf.inter_sf.model_based_post_interp_filter_breakout &&
3007*77c1e3ccSAndroid Build Coastguard Worker ref_best_rd != INT64_MAX && (rd >> 3) * 3 > ref_best_rd) {
3008*77c1e3ccSAndroid Build Coastguard Worker restore_dst_buf(xd, orig_dst, num_planes);
3009*77c1e3ccSAndroid Build Coastguard Worker continue;
3010*77c1e3ccSAndroid Build Coastguard Worker }
3011*77c1e3ccSAndroid Build Coastguard Worker
3012*77c1e3ccSAndroid Build Coastguard Worker // Compute modelled RD if enabled
3013*77c1e3ccSAndroid Build Coastguard Worker if (args->modelled_rd != NULL) {
3014*77c1e3ccSAndroid Build Coastguard Worker if (is_comp_pred) {
3015*77c1e3ccSAndroid Build Coastguard Worker const int mode0 = compound_ref0_mode(this_mode);
3016*77c1e3ccSAndroid Build Coastguard Worker const int mode1 = compound_ref1_mode(this_mode);
3017*77c1e3ccSAndroid Build Coastguard Worker const int64_t mrd =
3018*77c1e3ccSAndroid Build Coastguard Worker AOMMIN(args->modelled_rd[mode0][ref_mv_idx][refs[0]],
3019*77c1e3ccSAndroid Build Coastguard Worker args->modelled_rd[mode1][ref_mv_idx][refs[1]]);
3020*77c1e3ccSAndroid Build Coastguard Worker if ((rd >> 3) * 6 > mrd && ref_best_rd < INT64_MAX) {
3021*77c1e3ccSAndroid Build Coastguard Worker restore_dst_buf(xd, orig_dst, num_planes);
3022*77c1e3ccSAndroid Build Coastguard Worker continue;
3023*77c1e3ccSAndroid Build Coastguard Worker }
3024*77c1e3ccSAndroid Build Coastguard Worker }
3025*77c1e3ccSAndroid Build Coastguard Worker }
3026*77c1e3ccSAndroid Build Coastguard Worker }
3027*77c1e3ccSAndroid Build Coastguard Worker
3028*77c1e3ccSAndroid Build Coastguard Worker rd_stats->rate += compmode_interinter_cost;
3029*77c1e3ccSAndroid Build Coastguard Worker if (skip_build_pred != 1) {
3030*77c1e3ccSAndroid Build Coastguard Worker // Build this inter predictor if it has not been previously built
3031*77c1e3ccSAndroid Build Coastguard Worker av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, &orig_dst, bsize, 0,
3032*77c1e3ccSAndroid Build Coastguard Worker av1_num_planes(cm) - 1);
3033*77c1e3ccSAndroid Build Coastguard Worker }
3034*77c1e3ccSAndroid Build Coastguard Worker
3035*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_COLLECT_COMPONENT_TIMING
3036*77c1e3ccSAndroid Build Coastguard Worker start_timing(cpi, motion_mode_rd_time);
3037*77c1e3ccSAndroid Build Coastguard Worker #endif
3038*77c1e3ccSAndroid Build Coastguard Worker int rate2_nocoeff = rd_stats->rate;
3039*77c1e3ccSAndroid Build Coastguard Worker // Determine the motion mode. This will be one of SIMPLE_TRANSLATION,
3040*77c1e3ccSAndroid Build Coastguard Worker // OBMC_CAUSAL or WARPED_CAUSAL
3041*77c1e3ccSAndroid Build Coastguard Worker int64_t this_yrd;
3042*77c1e3ccSAndroid Build Coastguard Worker ret_val = motion_mode_rd(cpi, tile_data, x, bsize, rd_stats, rd_stats_y,
3043*77c1e3ccSAndroid Build Coastguard Worker rd_stats_uv, args, ref_best_rd, skip_rd, &rate_mv,
3044*77c1e3ccSAndroid Build Coastguard Worker &orig_dst, best_est_rd, do_tx_search,
3045*77c1e3ccSAndroid Build Coastguard Worker inter_modes_info, 0, &this_yrd);
3046*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_COLLECT_COMPONENT_TIMING
3047*77c1e3ccSAndroid Build Coastguard Worker end_timing(cpi, motion_mode_rd_time);
3048*77c1e3ccSAndroid Build Coastguard Worker #endif
3049*77c1e3ccSAndroid Build Coastguard Worker assert(
3050*77c1e3ccSAndroid Build Coastguard Worker IMPLIES(!av1_check_newmv_joint_nonzero(cm, x), ret_val == INT64_MAX));
3051*77c1e3ccSAndroid Build Coastguard Worker
3052*77c1e3ccSAndroid Build Coastguard Worker if (ret_val != INT64_MAX) {
3053*77c1e3ccSAndroid Build Coastguard Worker int64_t tmp_rd = RDCOST(x->rdmult, rd_stats->rate, rd_stats->dist);
3054*77c1e3ccSAndroid Build Coastguard Worker const THR_MODES mode_enum = get_prediction_mode_idx(
3055*77c1e3ccSAndroid Build Coastguard Worker mbmi->mode, mbmi->ref_frame[0], mbmi->ref_frame[1]);
3056*77c1e3ccSAndroid Build Coastguard Worker // Collect mode stats for multiwinner mode processing
3057*77c1e3ccSAndroid Build Coastguard Worker store_winner_mode_stats(&cpi->common, x, mbmi, rd_stats, rd_stats_y,
3058*77c1e3ccSAndroid Build Coastguard Worker rd_stats_uv, mode_enum, NULL, bsize, tmp_rd,
3059*77c1e3ccSAndroid Build Coastguard Worker cpi->sf.winner_mode_sf.multi_winner_mode_type,
3060*77c1e3ccSAndroid Build Coastguard Worker do_tx_search);
3061*77c1e3ccSAndroid Build Coastguard Worker if (tmp_rd < best_rd) {
3062*77c1e3ccSAndroid Build Coastguard Worker best_yrd = this_yrd;
3063*77c1e3ccSAndroid Build Coastguard Worker // Update the best rd stats if we found the best mode so far
3064*77c1e3ccSAndroid Build Coastguard Worker best_rd_stats = *rd_stats;
3065*77c1e3ccSAndroid Build Coastguard Worker best_rd_stats_y = *rd_stats_y;
3066*77c1e3ccSAndroid Build Coastguard Worker best_rd_stats_uv = *rd_stats_uv;
3067*77c1e3ccSAndroid Build Coastguard Worker best_rd = tmp_rd;
3068*77c1e3ccSAndroid Build Coastguard Worker best_mbmi = *mbmi;
3069*77c1e3ccSAndroid Build Coastguard Worker best_xskip_txfm = txfm_info->skip_txfm;
3070*77c1e3ccSAndroid Build Coastguard Worker memcpy(best_blk_skip, txfm_info->blk_skip,
3071*77c1e3ccSAndroid Build Coastguard Worker sizeof(best_blk_skip[0]) * xd->height * xd->width);
3072*77c1e3ccSAndroid Build Coastguard Worker av1_copy_array(best_tx_type_map, xd->tx_type_map,
3073*77c1e3ccSAndroid Build Coastguard Worker xd->height * xd->width);
3074*77c1e3ccSAndroid Build Coastguard Worker motion_mode_cand->rate_mv = rate_mv;
3075*77c1e3ccSAndroid Build Coastguard Worker motion_mode_cand->rate2_nocoeff = rate2_nocoeff;
3076*77c1e3ccSAndroid Build Coastguard Worker }
3077*77c1e3ccSAndroid Build Coastguard Worker
3078*77c1e3ccSAndroid Build Coastguard Worker if (tmp_rd < ref_best_rd) {
3079*77c1e3ccSAndroid Build Coastguard Worker ref_best_rd = tmp_rd;
3080*77c1e3ccSAndroid Build Coastguard Worker best_ref_mv_idx = ref_mv_idx;
3081*77c1e3ccSAndroid Build Coastguard Worker }
3082*77c1e3ccSAndroid Build Coastguard Worker }
3083*77c1e3ccSAndroid Build Coastguard Worker restore_dst_buf(xd, orig_dst, num_planes);
3084*77c1e3ccSAndroid Build Coastguard Worker }
3085*77c1e3ccSAndroid Build Coastguard Worker
3086*77c1e3ccSAndroid Build Coastguard Worker if (best_rd == INT64_MAX) return INT64_MAX;
3087*77c1e3ccSAndroid Build Coastguard Worker
3088*77c1e3ccSAndroid Build Coastguard Worker // re-instate status of the best choice
3089*77c1e3ccSAndroid Build Coastguard Worker *rd_stats = best_rd_stats;
3090*77c1e3ccSAndroid Build Coastguard Worker *rd_stats_y = best_rd_stats_y;
3091*77c1e3ccSAndroid Build Coastguard Worker *rd_stats_uv = best_rd_stats_uv;
3092*77c1e3ccSAndroid Build Coastguard Worker *yrd = best_yrd;
3093*77c1e3ccSAndroid Build Coastguard Worker *mbmi = best_mbmi;
3094*77c1e3ccSAndroid Build Coastguard Worker txfm_info->skip_txfm = best_xskip_txfm;
3095*77c1e3ccSAndroid Build Coastguard Worker assert(IMPLIES(mbmi->comp_group_idx == 1,
3096*77c1e3ccSAndroid Build Coastguard Worker mbmi->interinter_comp.type != COMPOUND_AVERAGE));
3097*77c1e3ccSAndroid Build Coastguard Worker memcpy(txfm_info->blk_skip, best_blk_skip,
3098*77c1e3ccSAndroid Build Coastguard Worker sizeof(best_blk_skip[0]) * xd->height * xd->width);
3099*77c1e3ccSAndroid Build Coastguard Worker av1_copy_array(xd->tx_type_map, best_tx_type_map, xd->height * xd->width);
3100*77c1e3ccSAndroid Build Coastguard Worker
3101*77c1e3ccSAndroid Build Coastguard Worker rd_stats->rdcost = RDCOST(x->rdmult, rd_stats->rate, rd_stats->dist);
3102*77c1e3ccSAndroid Build Coastguard Worker
3103*77c1e3ccSAndroid Build Coastguard Worker return rd_stats->rdcost;
3104*77c1e3ccSAndroid Build Coastguard Worker }
3105*77c1e3ccSAndroid Build Coastguard Worker
3106*77c1e3ccSAndroid Build Coastguard Worker /*!\brief Search for the best intrabc predictor
3107*77c1e3ccSAndroid Build Coastguard Worker *
3108*77c1e3ccSAndroid Build Coastguard Worker * \ingroup intra_mode_search
3109*77c1e3ccSAndroid Build Coastguard Worker * \callergraph
3110*77c1e3ccSAndroid Build Coastguard Worker * This function performs a motion search to find the best intrabc predictor.
3111*77c1e3ccSAndroid Build Coastguard Worker *
3112*77c1e3ccSAndroid Build Coastguard Worker * \returns Returns the best overall rdcost (including the non-intrabc modes
3113*77c1e3ccSAndroid Build Coastguard Worker * search before this function).
3114*77c1e3ccSAndroid Build Coastguard Worker */
rd_pick_intrabc_mode_sb(const AV1_COMP * cpi,MACROBLOCK * x,PICK_MODE_CONTEXT * ctx,RD_STATS * rd_stats,BLOCK_SIZE bsize,int64_t best_rd)3115*77c1e3ccSAndroid Build Coastguard Worker static int64_t rd_pick_intrabc_mode_sb(const AV1_COMP *cpi, MACROBLOCK *x,
3116*77c1e3ccSAndroid Build Coastguard Worker PICK_MODE_CONTEXT *ctx,
3117*77c1e3ccSAndroid Build Coastguard Worker RD_STATS *rd_stats, BLOCK_SIZE bsize,
3118*77c1e3ccSAndroid Build Coastguard Worker int64_t best_rd) {
3119*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *const cm = &cpi->common;
3120*77c1e3ccSAndroid Build Coastguard Worker if (!av1_allow_intrabc(cm) || !cpi->oxcf.kf_cfg.enable_intrabc ||
3121*77c1e3ccSAndroid Build Coastguard Worker !cpi->sf.mv_sf.use_intrabc || cpi->sf.rt_sf.use_nonrd_pick_mode)
3122*77c1e3ccSAndroid Build Coastguard Worker return INT64_MAX;
3123*77c1e3ccSAndroid Build Coastguard Worker const int num_planes = av1_num_planes(cm);
3124*77c1e3ccSAndroid Build Coastguard Worker
3125*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *const xd = &x->e_mbd;
3126*77c1e3ccSAndroid Build Coastguard Worker const TileInfo *tile = &xd->tile;
3127*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *mbmi = xd->mi[0];
3128*77c1e3ccSAndroid Build Coastguard Worker TxfmSearchInfo *txfm_info = &x->txfm_search_info;
3129*77c1e3ccSAndroid Build Coastguard Worker
3130*77c1e3ccSAndroid Build Coastguard Worker const int mi_row = xd->mi_row;
3131*77c1e3ccSAndroid Build Coastguard Worker const int mi_col = xd->mi_col;
3132*77c1e3ccSAndroid Build Coastguard Worker const int w = block_size_wide[bsize];
3133*77c1e3ccSAndroid Build Coastguard Worker const int h = block_size_high[bsize];
3134*77c1e3ccSAndroid Build Coastguard Worker const int sb_row = mi_row >> cm->seq_params->mib_size_log2;
3135*77c1e3ccSAndroid Build Coastguard Worker const int sb_col = mi_col >> cm->seq_params->mib_size_log2;
3136*77c1e3ccSAndroid Build Coastguard Worker
3137*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO_EXT *const mbmi_ext = &x->mbmi_ext;
3138*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME ref_frame = INTRA_FRAME;
3139*77c1e3ccSAndroid Build Coastguard Worker av1_find_mv_refs(cm, xd, mbmi, ref_frame, mbmi_ext->ref_mv_count,
3140*77c1e3ccSAndroid Build Coastguard Worker xd->ref_mv_stack, xd->weight, NULL, mbmi_ext->global_mvs,
3141*77c1e3ccSAndroid Build Coastguard Worker mbmi_ext->mode_context);
3142*77c1e3ccSAndroid Build Coastguard Worker // TODO(Ravi): Populate mbmi_ext->ref_mv_stack[ref_frame][4] and
3143*77c1e3ccSAndroid Build Coastguard Worker // mbmi_ext->weight[ref_frame][4] inside av1_find_mv_refs.
3144*77c1e3ccSAndroid Build Coastguard Worker av1_copy_usable_ref_mv_stack_and_weight(xd, mbmi_ext, ref_frame);
3145*77c1e3ccSAndroid Build Coastguard Worker int_mv nearestmv, nearmv;
3146*77c1e3ccSAndroid Build Coastguard Worker av1_find_best_ref_mvs_from_stack(0, mbmi_ext, ref_frame, &nearestmv, &nearmv,
3147*77c1e3ccSAndroid Build Coastguard Worker 0);
3148*77c1e3ccSAndroid Build Coastguard Worker
3149*77c1e3ccSAndroid Build Coastguard Worker if (nearestmv.as_int == INVALID_MV) {
3150*77c1e3ccSAndroid Build Coastguard Worker nearestmv.as_int = 0;
3151*77c1e3ccSAndroid Build Coastguard Worker }
3152*77c1e3ccSAndroid Build Coastguard Worker if (nearmv.as_int == INVALID_MV) {
3153*77c1e3ccSAndroid Build Coastguard Worker nearmv.as_int = 0;
3154*77c1e3ccSAndroid Build Coastguard Worker }
3155*77c1e3ccSAndroid Build Coastguard Worker
3156*77c1e3ccSAndroid Build Coastguard Worker int_mv dv_ref = nearestmv.as_int == 0 ? nearmv : nearestmv;
3157*77c1e3ccSAndroid Build Coastguard Worker if (dv_ref.as_int == 0) {
3158*77c1e3ccSAndroid Build Coastguard Worker av1_find_ref_dv(&dv_ref, tile, cm->seq_params->mib_size, mi_row);
3159*77c1e3ccSAndroid Build Coastguard Worker }
3160*77c1e3ccSAndroid Build Coastguard Worker // Ref DV should not have sub-pel.
3161*77c1e3ccSAndroid Build Coastguard Worker assert((dv_ref.as_mv.col & 7) == 0);
3162*77c1e3ccSAndroid Build Coastguard Worker assert((dv_ref.as_mv.row & 7) == 0);
3163*77c1e3ccSAndroid Build Coastguard Worker mbmi_ext->ref_mv_stack[INTRA_FRAME][0].this_mv = dv_ref;
3164*77c1e3ccSAndroid Build Coastguard Worker
3165*77c1e3ccSAndroid Build Coastguard Worker struct buf_2d yv12_mb[MAX_MB_PLANE];
3166*77c1e3ccSAndroid Build Coastguard Worker av1_setup_pred_block(xd, yv12_mb, xd->cur_buf, NULL, NULL, num_planes);
3167*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < num_planes; ++i) {
3168*77c1e3ccSAndroid Build Coastguard Worker xd->plane[i].pre[0] = yv12_mb[i];
3169*77c1e3ccSAndroid Build Coastguard Worker }
3170*77c1e3ccSAndroid Build Coastguard Worker
3171*77c1e3ccSAndroid Build Coastguard Worker enum IntrabcMotionDirection {
3172*77c1e3ccSAndroid Build Coastguard Worker IBC_MOTION_ABOVE,
3173*77c1e3ccSAndroid Build Coastguard Worker IBC_MOTION_LEFT,
3174*77c1e3ccSAndroid Build Coastguard Worker IBC_MOTION_DIRECTIONS
3175*77c1e3ccSAndroid Build Coastguard Worker };
3176*77c1e3ccSAndroid Build Coastguard Worker
3177*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO best_mbmi = *mbmi;
3178*77c1e3ccSAndroid Build Coastguard Worker RD_STATS best_rdstats = *rd_stats;
3179*77c1e3ccSAndroid Build Coastguard Worker uint8_t best_blk_skip[MAX_MIB_SIZE * MAX_MIB_SIZE] = { 0 };
3180*77c1e3ccSAndroid Build Coastguard Worker uint8_t best_tx_type_map[MAX_MIB_SIZE * MAX_MIB_SIZE];
3181*77c1e3ccSAndroid Build Coastguard Worker av1_copy_array(best_tx_type_map, xd->tx_type_map, ctx->num_4x4_blk);
3182*77c1e3ccSAndroid Build Coastguard Worker
3183*77c1e3ccSAndroid Build Coastguard Worker FULLPEL_MOTION_SEARCH_PARAMS fullms_params;
3184*77c1e3ccSAndroid Build Coastguard Worker const SEARCH_METHODS search_method =
3185*77c1e3ccSAndroid Build Coastguard Worker av1_get_default_mv_search_method(x, &cpi->sf.mv_sf, bsize);
3186*77c1e3ccSAndroid Build Coastguard Worker const search_site_config *lookahead_search_sites =
3187*77c1e3ccSAndroid Build Coastguard Worker cpi->mv_search_params.search_site_cfg[SS_CFG_LOOKAHEAD];
3188*77c1e3ccSAndroid Build Coastguard Worker const FULLPEL_MV start_mv = get_fullmv_from_mv(&dv_ref.as_mv);
3189*77c1e3ccSAndroid Build Coastguard Worker av1_make_default_fullpel_ms_params(&fullms_params, cpi, x, bsize,
3190*77c1e3ccSAndroid Build Coastguard Worker &dv_ref.as_mv, start_mv,
3191*77c1e3ccSAndroid Build Coastguard Worker lookahead_search_sites, search_method,
3192*77c1e3ccSAndroid Build Coastguard Worker /*fine_search_interval=*/0);
3193*77c1e3ccSAndroid Build Coastguard Worker const IntraBCMVCosts *const dv_costs = x->dv_costs;
3194*77c1e3ccSAndroid Build Coastguard Worker av1_set_ms_to_intra_mode(&fullms_params, dv_costs);
3195*77c1e3ccSAndroid Build Coastguard Worker
3196*77c1e3ccSAndroid Build Coastguard Worker for (enum IntrabcMotionDirection dir = IBC_MOTION_ABOVE;
3197*77c1e3ccSAndroid Build Coastguard Worker dir < IBC_MOTION_DIRECTIONS; ++dir) {
3198*77c1e3ccSAndroid Build Coastguard Worker switch (dir) {
3199*77c1e3ccSAndroid Build Coastguard Worker case IBC_MOTION_ABOVE:
3200*77c1e3ccSAndroid Build Coastguard Worker fullms_params.mv_limits.col_min =
3201*77c1e3ccSAndroid Build Coastguard Worker (tile->mi_col_start - mi_col) * MI_SIZE;
3202*77c1e3ccSAndroid Build Coastguard Worker fullms_params.mv_limits.col_max =
3203*77c1e3ccSAndroid Build Coastguard Worker (tile->mi_col_end - mi_col) * MI_SIZE - w;
3204*77c1e3ccSAndroid Build Coastguard Worker fullms_params.mv_limits.row_min =
3205*77c1e3ccSAndroid Build Coastguard Worker (tile->mi_row_start - mi_row) * MI_SIZE;
3206*77c1e3ccSAndroid Build Coastguard Worker fullms_params.mv_limits.row_max =
3207*77c1e3ccSAndroid Build Coastguard Worker (sb_row * cm->seq_params->mib_size - mi_row) * MI_SIZE - h;
3208*77c1e3ccSAndroid Build Coastguard Worker break;
3209*77c1e3ccSAndroid Build Coastguard Worker case IBC_MOTION_LEFT:
3210*77c1e3ccSAndroid Build Coastguard Worker fullms_params.mv_limits.col_min =
3211*77c1e3ccSAndroid Build Coastguard Worker (tile->mi_col_start - mi_col) * MI_SIZE;
3212*77c1e3ccSAndroid Build Coastguard Worker fullms_params.mv_limits.col_max =
3213*77c1e3ccSAndroid Build Coastguard Worker (sb_col * cm->seq_params->mib_size - mi_col) * MI_SIZE - w;
3214*77c1e3ccSAndroid Build Coastguard Worker // TODO([email protected]): Minimize the overlap between above and
3215*77c1e3ccSAndroid Build Coastguard Worker // left areas.
3216*77c1e3ccSAndroid Build Coastguard Worker fullms_params.mv_limits.row_min =
3217*77c1e3ccSAndroid Build Coastguard Worker (tile->mi_row_start - mi_row) * MI_SIZE;
3218*77c1e3ccSAndroid Build Coastguard Worker int bottom_coded_mi_edge =
3219*77c1e3ccSAndroid Build Coastguard Worker AOMMIN((sb_row + 1) * cm->seq_params->mib_size, tile->mi_row_end);
3220*77c1e3ccSAndroid Build Coastguard Worker fullms_params.mv_limits.row_max =
3221*77c1e3ccSAndroid Build Coastguard Worker (bottom_coded_mi_edge - mi_row) * MI_SIZE - h;
3222*77c1e3ccSAndroid Build Coastguard Worker break;
3223*77c1e3ccSAndroid Build Coastguard Worker default: assert(0);
3224*77c1e3ccSAndroid Build Coastguard Worker }
3225*77c1e3ccSAndroid Build Coastguard Worker assert(fullms_params.mv_limits.col_min >= fullms_params.mv_limits.col_min);
3226*77c1e3ccSAndroid Build Coastguard Worker assert(fullms_params.mv_limits.col_max <= fullms_params.mv_limits.col_max);
3227*77c1e3ccSAndroid Build Coastguard Worker assert(fullms_params.mv_limits.row_min >= fullms_params.mv_limits.row_min);
3228*77c1e3ccSAndroid Build Coastguard Worker assert(fullms_params.mv_limits.row_max <= fullms_params.mv_limits.row_max);
3229*77c1e3ccSAndroid Build Coastguard Worker
3230*77c1e3ccSAndroid Build Coastguard Worker av1_set_mv_search_range(&fullms_params.mv_limits, &dv_ref.as_mv);
3231*77c1e3ccSAndroid Build Coastguard Worker
3232*77c1e3ccSAndroid Build Coastguard Worker if (fullms_params.mv_limits.col_max < fullms_params.mv_limits.col_min ||
3233*77c1e3ccSAndroid Build Coastguard Worker fullms_params.mv_limits.row_max < fullms_params.mv_limits.row_min) {
3234*77c1e3ccSAndroid Build Coastguard Worker continue;
3235*77c1e3ccSAndroid Build Coastguard Worker }
3236*77c1e3ccSAndroid Build Coastguard Worker
3237*77c1e3ccSAndroid Build Coastguard Worker const int step_param = cpi->mv_search_params.mv_step_param;
3238*77c1e3ccSAndroid Build Coastguard Worker IntraBCHashInfo *intrabc_hash_info = &x->intrabc_hash_info;
3239*77c1e3ccSAndroid Build Coastguard Worker int_mv best_mv, best_hash_mv;
3240*77c1e3ccSAndroid Build Coastguard Worker FULLPEL_MV_STATS best_mv_stats;
3241*77c1e3ccSAndroid Build Coastguard Worker
3242*77c1e3ccSAndroid Build Coastguard Worker int bestsme =
3243*77c1e3ccSAndroid Build Coastguard Worker av1_full_pixel_search(start_mv, &fullms_params, step_param, NULL,
3244*77c1e3ccSAndroid Build Coastguard Worker &best_mv.as_fullmv, &best_mv_stats, NULL);
3245*77c1e3ccSAndroid Build Coastguard Worker const int hashsme = av1_intrabc_hash_search(
3246*77c1e3ccSAndroid Build Coastguard Worker cpi, xd, &fullms_params, intrabc_hash_info, &best_hash_mv.as_fullmv);
3247*77c1e3ccSAndroid Build Coastguard Worker if (hashsme < bestsme) {
3248*77c1e3ccSAndroid Build Coastguard Worker best_mv = best_hash_mv;
3249*77c1e3ccSAndroid Build Coastguard Worker bestsme = hashsme;
3250*77c1e3ccSAndroid Build Coastguard Worker }
3251*77c1e3ccSAndroid Build Coastguard Worker
3252*77c1e3ccSAndroid Build Coastguard Worker if (bestsme == INT_MAX) continue;
3253*77c1e3ccSAndroid Build Coastguard Worker const MV dv = get_mv_from_fullmv(&best_mv.as_fullmv);
3254*77c1e3ccSAndroid Build Coastguard Worker if (!av1_is_fullmv_in_range(&fullms_params.mv_limits,
3255*77c1e3ccSAndroid Build Coastguard Worker get_fullmv_from_mv(&dv)))
3256*77c1e3ccSAndroid Build Coastguard Worker continue;
3257*77c1e3ccSAndroid Build Coastguard Worker if (!av1_is_dv_valid(dv, cm, xd, mi_row, mi_col, bsize,
3258*77c1e3ccSAndroid Build Coastguard Worker cm->seq_params->mib_size_log2))
3259*77c1e3ccSAndroid Build Coastguard Worker continue;
3260*77c1e3ccSAndroid Build Coastguard Worker
3261*77c1e3ccSAndroid Build Coastguard Worker // DV should not have sub-pel.
3262*77c1e3ccSAndroid Build Coastguard Worker assert((dv.col & 7) == 0);
3263*77c1e3ccSAndroid Build Coastguard Worker assert((dv.row & 7) == 0);
3264*77c1e3ccSAndroid Build Coastguard Worker memset(&mbmi->palette_mode_info, 0, sizeof(mbmi->palette_mode_info));
3265*77c1e3ccSAndroid Build Coastguard Worker mbmi->filter_intra_mode_info.use_filter_intra = 0;
3266*77c1e3ccSAndroid Build Coastguard Worker mbmi->use_intrabc = 1;
3267*77c1e3ccSAndroid Build Coastguard Worker mbmi->mode = DC_PRED;
3268*77c1e3ccSAndroid Build Coastguard Worker mbmi->uv_mode = UV_DC_PRED;
3269*77c1e3ccSAndroid Build Coastguard Worker mbmi->motion_mode = SIMPLE_TRANSLATION;
3270*77c1e3ccSAndroid Build Coastguard Worker mbmi->mv[0].as_mv = dv;
3271*77c1e3ccSAndroid Build Coastguard Worker mbmi->interp_filters = av1_broadcast_interp_filter(BILINEAR);
3272*77c1e3ccSAndroid Build Coastguard Worker mbmi->skip_txfm = 0;
3273*77c1e3ccSAndroid Build Coastguard Worker av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, NULL, bsize, 0,
3274*77c1e3ccSAndroid Build Coastguard Worker av1_num_planes(cm) - 1);
3275*77c1e3ccSAndroid Build Coastguard Worker
3276*77c1e3ccSAndroid Build Coastguard Worker // TODO([email protected]): The full motion field defining discount
3277*77c1e3ccSAndroid Build Coastguard Worker // in MV_COST_WEIGHT is too large. Explore other values.
3278*77c1e3ccSAndroid Build Coastguard Worker const int rate_mv = av1_mv_bit_cost(&dv, &dv_ref.as_mv, dv_costs->joint_mv,
3279*77c1e3ccSAndroid Build Coastguard Worker dv_costs->dv_costs, MV_COST_WEIGHT_SUB);
3280*77c1e3ccSAndroid Build Coastguard Worker const int rate_mode = x->mode_costs.intrabc_cost[1];
3281*77c1e3ccSAndroid Build Coastguard Worker RD_STATS rd_stats_yuv, rd_stats_y, rd_stats_uv;
3282*77c1e3ccSAndroid Build Coastguard Worker if (!av1_txfm_search(cpi, x, bsize, &rd_stats_yuv, &rd_stats_y,
3283*77c1e3ccSAndroid Build Coastguard Worker &rd_stats_uv, rate_mode + rate_mv, INT64_MAX))
3284*77c1e3ccSAndroid Build Coastguard Worker continue;
3285*77c1e3ccSAndroid Build Coastguard Worker rd_stats_yuv.rdcost =
3286*77c1e3ccSAndroid Build Coastguard Worker RDCOST(x->rdmult, rd_stats_yuv.rate, rd_stats_yuv.dist);
3287*77c1e3ccSAndroid Build Coastguard Worker if (rd_stats_yuv.rdcost < best_rd) {
3288*77c1e3ccSAndroid Build Coastguard Worker best_rd = rd_stats_yuv.rdcost;
3289*77c1e3ccSAndroid Build Coastguard Worker best_mbmi = *mbmi;
3290*77c1e3ccSAndroid Build Coastguard Worker best_rdstats = rd_stats_yuv;
3291*77c1e3ccSAndroid Build Coastguard Worker memcpy(best_blk_skip, txfm_info->blk_skip,
3292*77c1e3ccSAndroid Build Coastguard Worker sizeof(txfm_info->blk_skip[0]) * xd->height * xd->width);
3293*77c1e3ccSAndroid Build Coastguard Worker av1_copy_array(best_tx_type_map, xd->tx_type_map, xd->height * xd->width);
3294*77c1e3ccSAndroid Build Coastguard Worker }
3295*77c1e3ccSAndroid Build Coastguard Worker }
3296*77c1e3ccSAndroid Build Coastguard Worker *mbmi = best_mbmi;
3297*77c1e3ccSAndroid Build Coastguard Worker *rd_stats = best_rdstats;
3298*77c1e3ccSAndroid Build Coastguard Worker memcpy(txfm_info->blk_skip, best_blk_skip,
3299*77c1e3ccSAndroid Build Coastguard Worker sizeof(txfm_info->blk_skip[0]) * xd->height * xd->width);
3300*77c1e3ccSAndroid Build Coastguard Worker av1_copy_array(xd->tx_type_map, best_tx_type_map, ctx->num_4x4_blk);
3301*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_RD_DEBUG
3302*77c1e3ccSAndroid Build Coastguard Worker mbmi->rd_stats = *rd_stats;
3303*77c1e3ccSAndroid Build Coastguard Worker #endif
3304*77c1e3ccSAndroid Build Coastguard Worker return best_rd;
3305*77c1e3ccSAndroid Build Coastguard Worker }
3306*77c1e3ccSAndroid Build Coastguard Worker
3307*77c1e3ccSAndroid Build Coastguard Worker // TODO([email protected]): We are using struct $struct_name instead of their
3308*77c1e3ccSAndroid Build Coastguard Worker // typedef here because Doxygen doesn't know about the typedefs yet. So using
3309*77c1e3ccSAndroid Build Coastguard Worker // the typedef will prevent doxygen from finding this function and generating
3310*77c1e3ccSAndroid Build Coastguard Worker // the callgraph. Once documents for AV1_COMP and MACROBLOCK are added to
3311*77c1e3ccSAndroid Build Coastguard Worker // doxygen, we can revert back to using the typedefs.
av1_rd_pick_intra_mode_sb(const struct AV1_COMP * cpi,struct macroblock * x,struct RD_STATS * rd_cost,BLOCK_SIZE bsize,PICK_MODE_CONTEXT * ctx,int64_t best_rd)3312*77c1e3ccSAndroid Build Coastguard Worker void av1_rd_pick_intra_mode_sb(const struct AV1_COMP *cpi, struct macroblock *x,
3313*77c1e3ccSAndroid Build Coastguard Worker struct RD_STATS *rd_cost, BLOCK_SIZE bsize,
3314*77c1e3ccSAndroid Build Coastguard Worker PICK_MODE_CONTEXT *ctx, int64_t best_rd) {
3315*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *const cm = &cpi->common;
3316*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *const xd = &x->e_mbd;
3317*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *const mbmi = xd->mi[0];
3318*77c1e3ccSAndroid Build Coastguard Worker const int num_planes = av1_num_planes(cm);
3319*77c1e3ccSAndroid Build Coastguard Worker TxfmSearchInfo *txfm_info = &x->txfm_search_info;
3320*77c1e3ccSAndroid Build Coastguard Worker int rate_y = 0, rate_uv = 0, rate_y_tokenonly = 0, rate_uv_tokenonly = 0;
3321*77c1e3ccSAndroid Build Coastguard Worker uint8_t y_skip_txfm = 0, uv_skip_txfm = 0;
3322*77c1e3ccSAndroid Build Coastguard Worker int64_t dist_y = 0, dist_uv = 0;
3323*77c1e3ccSAndroid Build Coastguard Worker
3324*77c1e3ccSAndroid Build Coastguard Worker ctx->rd_stats.skip_txfm = 0;
3325*77c1e3ccSAndroid Build Coastguard Worker mbmi->ref_frame[0] = INTRA_FRAME;
3326*77c1e3ccSAndroid Build Coastguard Worker mbmi->ref_frame[1] = NONE_FRAME;
3327*77c1e3ccSAndroid Build Coastguard Worker mbmi->use_intrabc = 0;
3328*77c1e3ccSAndroid Build Coastguard Worker mbmi->mv[0].as_int = 0;
3329*77c1e3ccSAndroid Build Coastguard Worker mbmi->skip_mode = 0;
3330*77c1e3ccSAndroid Build Coastguard Worker
3331*77c1e3ccSAndroid Build Coastguard Worker const int64_t intra_yrd =
3332*77c1e3ccSAndroid Build Coastguard Worker av1_rd_pick_intra_sby_mode(cpi, x, &rate_y, &rate_y_tokenonly, &dist_y,
3333*77c1e3ccSAndroid Build Coastguard Worker &y_skip_txfm, bsize, best_rd, ctx);
3334*77c1e3ccSAndroid Build Coastguard Worker
3335*77c1e3ccSAndroid Build Coastguard Worker // Initialize default mode evaluation params
3336*77c1e3ccSAndroid Build Coastguard Worker set_mode_eval_params(cpi, x, DEFAULT_EVAL);
3337*77c1e3ccSAndroid Build Coastguard Worker
3338*77c1e3ccSAndroid Build Coastguard Worker if (intra_yrd < best_rd) {
3339*77c1e3ccSAndroid Build Coastguard Worker // Search intra modes for uv planes if needed
3340*77c1e3ccSAndroid Build Coastguard Worker if (num_planes > 1) {
3341*77c1e3ccSAndroid Build Coastguard Worker // Set up the tx variables for reproducing the y predictions in case we
3342*77c1e3ccSAndroid Build Coastguard Worker // need it for chroma-from-luma.
3343*77c1e3ccSAndroid Build Coastguard Worker if (xd->is_chroma_ref && store_cfl_required_rdo(cm, x)) {
3344*77c1e3ccSAndroid Build Coastguard Worker memcpy(txfm_info->blk_skip, ctx->blk_skip,
3345*77c1e3ccSAndroid Build Coastguard Worker sizeof(txfm_info->blk_skip[0]) * ctx->num_4x4_blk);
3346*77c1e3ccSAndroid Build Coastguard Worker av1_copy_array(xd->tx_type_map, ctx->tx_type_map, ctx->num_4x4_blk);
3347*77c1e3ccSAndroid Build Coastguard Worker }
3348*77c1e3ccSAndroid Build Coastguard Worker const TX_SIZE max_uv_tx_size = av1_get_tx_size(AOM_PLANE_U, xd);
3349*77c1e3ccSAndroid Build Coastguard Worker av1_rd_pick_intra_sbuv_mode(cpi, x, &rate_uv, &rate_uv_tokenonly,
3350*77c1e3ccSAndroid Build Coastguard Worker &dist_uv, &uv_skip_txfm, bsize,
3351*77c1e3ccSAndroid Build Coastguard Worker max_uv_tx_size);
3352*77c1e3ccSAndroid Build Coastguard Worker }
3353*77c1e3ccSAndroid Build Coastguard Worker
3354*77c1e3ccSAndroid Build Coastguard Worker // Intra block is always coded as non-skip
3355*77c1e3ccSAndroid Build Coastguard Worker rd_cost->rate =
3356*77c1e3ccSAndroid Build Coastguard Worker rate_y + rate_uv +
3357*77c1e3ccSAndroid Build Coastguard Worker x->mode_costs.skip_txfm_cost[av1_get_skip_txfm_context(xd)][0];
3358*77c1e3ccSAndroid Build Coastguard Worker rd_cost->dist = dist_y + dist_uv;
3359*77c1e3ccSAndroid Build Coastguard Worker rd_cost->rdcost = RDCOST(x->rdmult, rd_cost->rate, rd_cost->dist);
3360*77c1e3ccSAndroid Build Coastguard Worker rd_cost->skip_txfm = 0;
3361*77c1e3ccSAndroid Build Coastguard Worker } else {
3362*77c1e3ccSAndroid Build Coastguard Worker rd_cost->rate = INT_MAX;
3363*77c1e3ccSAndroid Build Coastguard Worker }
3364*77c1e3ccSAndroid Build Coastguard Worker
3365*77c1e3ccSAndroid Build Coastguard Worker if (rd_cost->rate != INT_MAX && rd_cost->rdcost < best_rd)
3366*77c1e3ccSAndroid Build Coastguard Worker best_rd = rd_cost->rdcost;
3367*77c1e3ccSAndroid Build Coastguard Worker if (rd_pick_intrabc_mode_sb(cpi, x, ctx, rd_cost, bsize, best_rd) < best_rd) {
3368*77c1e3ccSAndroid Build Coastguard Worker ctx->rd_stats.skip_txfm = mbmi->skip_txfm;
3369*77c1e3ccSAndroid Build Coastguard Worker memcpy(ctx->blk_skip, txfm_info->blk_skip,
3370*77c1e3ccSAndroid Build Coastguard Worker sizeof(txfm_info->blk_skip[0]) * ctx->num_4x4_blk);
3371*77c1e3ccSAndroid Build Coastguard Worker assert(rd_cost->rate != INT_MAX);
3372*77c1e3ccSAndroid Build Coastguard Worker }
3373*77c1e3ccSAndroid Build Coastguard Worker if (rd_cost->rate == INT_MAX) return;
3374*77c1e3ccSAndroid Build Coastguard Worker
3375*77c1e3ccSAndroid Build Coastguard Worker ctx->mic = *xd->mi[0];
3376*77c1e3ccSAndroid Build Coastguard Worker av1_copy_mbmi_ext_to_mbmi_ext_frame(&ctx->mbmi_ext_best, &x->mbmi_ext,
3377*77c1e3ccSAndroid Build Coastguard Worker av1_ref_frame_type(xd->mi[0]->ref_frame));
3378*77c1e3ccSAndroid Build Coastguard Worker av1_copy_array(ctx->tx_type_map, xd->tx_type_map, ctx->num_4x4_blk);
3379*77c1e3ccSAndroid Build Coastguard Worker }
3380*77c1e3ccSAndroid Build Coastguard Worker
3381*77c1e3ccSAndroid Build Coastguard Worker static inline void calc_target_weighted_pred(
3382*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *cm, const MACROBLOCK *x, const MACROBLOCKD *xd,
3383*77c1e3ccSAndroid Build Coastguard Worker const uint8_t *above, int above_stride, const uint8_t *left,
3384*77c1e3ccSAndroid Build Coastguard Worker int left_stride);
3385*77c1e3ccSAndroid Build Coastguard Worker
rd_pick_skip_mode(RD_STATS * rd_cost,InterModeSearchState * search_state,const AV1_COMP * const cpi,MACROBLOCK * const x,BLOCK_SIZE bsize,struct buf_2d yv12_mb[REF_FRAMES][MAX_MB_PLANE])3386*77c1e3ccSAndroid Build Coastguard Worker static inline void rd_pick_skip_mode(
3387*77c1e3ccSAndroid Build Coastguard Worker RD_STATS *rd_cost, InterModeSearchState *search_state,
3388*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMP *const cpi, MACROBLOCK *const x, BLOCK_SIZE bsize,
3389*77c1e3ccSAndroid Build Coastguard Worker struct buf_2d yv12_mb[REF_FRAMES][MAX_MB_PLANE]) {
3390*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *const cm = &cpi->common;
3391*77c1e3ccSAndroid Build Coastguard Worker const SkipModeInfo *const skip_mode_info = &cm->current_frame.skip_mode_info;
3392*77c1e3ccSAndroid Build Coastguard Worker const int num_planes = av1_num_planes(cm);
3393*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *const xd = &x->e_mbd;
3394*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *const mbmi = xd->mi[0];
3395*77c1e3ccSAndroid Build Coastguard Worker
3396*77c1e3ccSAndroid Build Coastguard Worker x->compound_idx = 1; // COMPOUND_AVERAGE
3397*77c1e3ccSAndroid Build Coastguard Worker RD_STATS skip_mode_rd_stats;
3398*77c1e3ccSAndroid Build Coastguard Worker av1_invalid_rd_stats(&skip_mode_rd_stats);
3399*77c1e3ccSAndroid Build Coastguard Worker
3400*77c1e3ccSAndroid Build Coastguard Worker if (skip_mode_info->ref_frame_idx_0 == INVALID_IDX ||
3401*77c1e3ccSAndroid Build Coastguard Worker skip_mode_info->ref_frame_idx_1 == INVALID_IDX) {
3402*77c1e3ccSAndroid Build Coastguard Worker return;
3403*77c1e3ccSAndroid Build Coastguard Worker }
3404*77c1e3ccSAndroid Build Coastguard Worker
3405*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME ref_frame =
3406*77c1e3ccSAndroid Build Coastguard Worker LAST_FRAME + skip_mode_info->ref_frame_idx_0;
3407*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME second_ref_frame =
3408*77c1e3ccSAndroid Build Coastguard Worker LAST_FRAME + skip_mode_info->ref_frame_idx_1;
3409*77c1e3ccSAndroid Build Coastguard Worker const PREDICTION_MODE this_mode = NEAREST_NEARESTMV;
3410*77c1e3ccSAndroid Build Coastguard Worker const THR_MODES mode_index =
3411*77c1e3ccSAndroid Build Coastguard Worker get_prediction_mode_idx(this_mode, ref_frame, second_ref_frame);
3412*77c1e3ccSAndroid Build Coastguard Worker
3413*77c1e3ccSAndroid Build Coastguard Worker if (mode_index == THR_INVALID) {
3414*77c1e3ccSAndroid Build Coastguard Worker return;
3415*77c1e3ccSAndroid Build Coastguard Worker }
3416*77c1e3ccSAndroid Build Coastguard Worker
3417*77c1e3ccSAndroid Build Coastguard Worker if ((!cpi->oxcf.ref_frm_cfg.enable_onesided_comp ||
3418*77c1e3ccSAndroid Build Coastguard Worker cpi->sf.inter_sf.disable_onesided_comp) &&
3419*77c1e3ccSAndroid Build Coastguard Worker cpi->all_one_sided_refs) {
3420*77c1e3ccSAndroid Build Coastguard Worker return;
3421*77c1e3ccSAndroid Build Coastguard Worker }
3422*77c1e3ccSAndroid Build Coastguard Worker
3423*77c1e3ccSAndroid Build Coastguard Worker mbmi->mode = this_mode;
3424*77c1e3ccSAndroid Build Coastguard Worker mbmi->uv_mode = UV_DC_PRED;
3425*77c1e3ccSAndroid Build Coastguard Worker mbmi->ref_frame[0] = ref_frame;
3426*77c1e3ccSAndroid Build Coastguard Worker mbmi->ref_frame[1] = second_ref_frame;
3427*77c1e3ccSAndroid Build Coastguard Worker const uint8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
3428*77c1e3ccSAndroid Build Coastguard Worker if (x->mbmi_ext.ref_mv_count[ref_frame_type] == UINT8_MAX) {
3429*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO_EXT *mbmi_ext = &x->mbmi_ext;
3430*77c1e3ccSAndroid Build Coastguard Worker if (mbmi_ext->ref_mv_count[ref_frame] == UINT8_MAX ||
3431*77c1e3ccSAndroid Build Coastguard Worker mbmi_ext->ref_mv_count[second_ref_frame] == UINT8_MAX) {
3432*77c1e3ccSAndroid Build Coastguard Worker return;
3433*77c1e3ccSAndroid Build Coastguard Worker }
3434*77c1e3ccSAndroid Build Coastguard Worker av1_find_mv_refs(cm, xd, mbmi, ref_frame_type, mbmi_ext->ref_mv_count,
3435*77c1e3ccSAndroid Build Coastguard Worker xd->ref_mv_stack, xd->weight, NULL, mbmi_ext->global_mvs,
3436*77c1e3ccSAndroid Build Coastguard Worker mbmi_ext->mode_context);
3437*77c1e3ccSAndroid Build Coastguard Worker // TODO(Ravi): Populate mbmi_ext->ref_mv_stack[ref_frame][4] and
3438*77c1e3ccSAndroid Build Coastguard Worker // mbmi_ext->weight[ref_frame][4] inside av1_find_mv_refs.
3439*77c1e3ccSAndroid Build Coastguard Worker av1_copy_usable_ref_mv_stack_and_weight(xd, mbmi_ext, ref_frame_type);
3440*77c1e3ccSAndroid Build Coastguard Worker }
3441*77c1e3ccSAndroid Build Coastguard Worker
3442*77c1e3ccSAndroid Build Coastguard Worker assert(this_mode == NEAREST_NEARESTMV);
3443*77c1e3ccSAndroid Build Coastguard Worker if (!build_cur_mv(mbmi->mv, this_mode, cm, x, 0)) {
3444*77c1e3ccSAndroid Build Coastguard Worker return;
3445*77c1e3ccSAndroid Build Coastguard Worker }
3446*77c1e3ccSAndroid Build Coastguard Worker
3447*77c1e3ccSAndroid Build Coastguard Worker mbmi->filter_intra_mode_info.use_filter_intra = 0;
3448*77c1e3ccSAndroid Build Coastguard Worker mbmi->interintra_mode = (INTERINTRA_MODE)(II_DC_PRED - 1);
3449*77c1e3ccSAndroid Build Coastguard Worker mbmi->comp_group_idx = 0;
3450*77c1e3ccSAndroid Build Coastguard Worker mbmi->compound_idx = x->compound_idx;
3451*77c1e3ccSAndroid Build Coastguard Worker mbmi->interinter_comp.type = COMPOUND_AVERAGE;
3452*77c1e3ccSAndroid Build Coastguard Worker mbmi->motion_mode = SIMPLE_TRANSLATION;
3453*77c1e3ccSAndroid Build Coastguard Worker mbmi->ref_mv_idx = 0;
3454*77c1e3ccSAndroid Build Coastguard Worker mbmi->skip_mode = mbmi->skip_txfm = 1;
3455*77c1e3ccSAndroid Build Coastguard Worker mbmi->palette_mode_info.palette_size[0] = 0;
3456*77c1e3ccSAndroid Build Coastguard Worker mbmi->palette_mode_info.palette_size[1] = 0;
3457*77c1e3ccSAndroid Build Coastguard Worker
3458*77c1e3ccSAndroid Build Coastguard Worker set_default_interp_filters(mbmi, cm->features.interp_filter);
3459*77c1e3ccSAndroid Build Coastguard Worker
3460*77c1e3ccSAndroid Build Coastguard Worker set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
3461*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < num_planes; i++) {
3462*77c1e3ccSAndroid Build Coastguard Worker xd->plane[i].pre[0] = yv12_mb[mbmi->ref_frame[0]][i];
3463*77c1e3ccSAndroid Build Coastguard Worker xd->plane[i].pre[1] = yv12_mb[mbmi->ref_frame[1]][i];
3464*77c1e3ccSAndroid Build Coastguard Worker }
3465*77c1e3ccSAndroid Build Coastguard Worker
3466*77c1e3ccSAndroid Build Coastguard Worker BUFFER_SET orig_dst;
3467*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < num_planes; i++) {
3468*77c1e3ccSAndroid Build Coastguard Worker orig_dst.plane[i] = xd->plane[i].dst.buf;
3469*77c1e3ccSAndroid Build Coastguard Worker orig_dst.stride[i] = xd->plane[i].dst.stride;
3470*77c1e3ccSAndroid Build Coastguard Worker }
3471*77c1e3ccSAndroid Build Coastguard Worker
3472*77c1e3ccSAndroid Build Coastguard Worker // Compare the use of skip_mode with the best intra/inter mode obtained.
3473*77c1e3ccSAndroid Build Coastguard Worker const int skip_mode_ctx = av1_get_skip_mode_context(xd);
3474*77c1e3ccSAndroid Build Coastguard Worker int64_t best_intra_inter_mode_cost = INT64_MAX;
3475*77c1e3ccSAndroid Build Coastguard Worker if (rd_cost->dist < INT64_MAX && rd_cost->rate < INT32_MAX) {
3476*77c1e3ccSAndroid Build Coastguard Worker const ModeCosts *mode_costs = &x->mode_costs;
3477*77c1e3ccSAndroid Build Coastguard Worker best_intra_inter_mode_cost = RDCOST(
3478*77c1e3ccSAndroid Build Coastguard Worker x->rdmult, rd_cost->rate + mode_costs->skip_mode_cost[skip_mode_ctx][0],
3479*77c1e3ccSAndroid Build Coastguard Worker rd_cost->dist);
3480*77c1e3ccSAndroid Build Coastguard Worker // Account for non-skip mode rate in total rd stats
3481*77c1e3ccSAndroid Build Coastguard Worker rd_cost->rate += mode_costs->skip_mode_cost[skip_mode_ctx][0];
3482*77c1e3ccSAndroid Build Coastguard Worker av1_rd_cost_update(x->rdmult, rd_cost);
3483*77c1e3ccSAndroid Build Coastguard Worker }
3484*77c1e3ccSAndroid Build Coastguard Worker
3485*77c1e3ccSAndroid Build Coastguard Worker // Obtain the rdcost for skip_mode.
3486*77c1e3ccSAndroid Build Coastguard Worker skip_mode_rd(&skip_mode_rd_stats, cpi, x, bsize, &orig_dst,
3487*77c1e3ccSAndroid Build Coastguard Worker best_intra_inter_mode_cost);
3488*77c1e3ccSAndroid Build Coastguard Worker
3489*77c1e3ccSAndroid Build Coastguard Worker if (skip_mode_rd_stats.rdcost <= best_intra_inter_mode_cost &&
3490*77c1e3ccSAndroid Build Coastguard Worker (!xd->lossless[mbmi->segment_id] || skip_mode_rd_stats.dist == 0)) {
3491*77c1e3ccSAndroid Build Coastguard Worker assert(mode_index != THR_INVALID);
3492*77c1e3ccSAndroid Build Coastguard Worker search_state->best_mbmode.skip_mode = 1;
3493*77c1e3ccSAndroid Build Coastguard Worker search_state->best_mbmode = *mbmi;
3494*77c1e3ccSAndroid Build Coastguard Worker memset(search_state->best_mbmode.inter_tx_size,
3495*77c1e3ccSAndroid Build Coastguard Worker search_state->best_mbmode.tx_size,
3496*77c1e3ccSAndroid Build Coastguard Worker sizeof(search_state->best_mbmode.inter_tx_size));
3497*77c1e3ccSAndroid Build Coastguard Worker set_txfm_ctxs(search_state->best_mbmode.tx_size, xd->width, xd->height,
3498*77c1e3ccSAndroid Build Coastguard Worker search_state->best_mbmode.skip_txfm && is_inter_block(mbmi),
3499*77c1e3ccSAndroid Build Coastguard Worker xd);
3500*77c1e3ccSAndroid Build Coastguard Worker search_state->best_mode_index = mode_index;
3501*77c1e3ccSAndroid Build Coastguard Worker
3502*77c1e3ccSAndroid Build Coastguard Worker // Update rd_cost
3503*77c1e3ccSAndroid Build Coastguard Worker rd_cost->rate = skip_mode_rd_stats.rate;
3504*77c1e3ccSAndroid Build Coastguard Worker rd_cost->dist = rd_cost->sse = skip_mode_rd_stats.dist;
3505*77c1e3ccSAndroid Build Coastguard Worker rd_cost->rdcost = skip_mode_rd_stats.rdcost;
3506*77c1e3ccSAndroid Build Coastguard Worker
3507*77c1e3ccSAndroid Build Coastguard Worker search_state->best_rd = rd_cost->rdcost;
3508*77c1e3ccSAndroid Build Coastguard Worker search_state->best_skip2 = 1;
3509*77c1e3ccSAndroid Build Coastguard Worker search_state->best_mode_skippable = 1;
3510*77c1e3ccSAndroid Build Coastguard Worker
3511*77c1e3ccSAndroid Build Coastguard Worker x->txfm_search_info.skip_txfm = 1;
3512*77c1e3ccSAndroid Build Coastguard Worker }
3513*77c1e3ccSAndroid Build Coastguard Worker }
3514*77c1e3ccSAndroid Build Coastguard Worker
3515*77c1e3ccSAndroid Build Coastguard Worker // Get winner mode stats of given mode index
get_winner_mode_stats(MACROBLOCK * x,MB_MODE_INFO * best_mbmode,RD_STATS * best_rd_cost,int best_rate_y,int best_rate_uv,THR_MODES * best_mode_index,RD_STATS ** winner_rd_cost,int * winner_rate_y,int * winner_rate_uv,THR_MODES * winner_mode_index,MULTI_WINNER_MODE_TYPE multi_winner_mode_type,int mode_idx)3516*77c1e3ccSAndroid Build Coastguard Worker static inline MB_MODE_INFO *get_winner_mode_stats(
3517*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCK *x, MB_MODE_INFO *best_mbmode, RD_STATS *best_rd_cost,
3518*77c1e3ccSAndroid Build Coastguard Worker int best_rate_y, int best_rate_uv, THR_MODES *best_mode_index,
3519*77c1e3ccSAndroid Build Coastguard Worker RD_STATS **winner_rd_cost, int *winner_rate_y, int *winner_rate_uv,
3520*77c1e3ccSAndroid Build Coastguard Worker THR_MODES *winner_mode_index, MULTI_WINNER_MODE_TYPE multi_winner_mode_type,
3521*77c1e3ccSAndroid Build Coastguard Worker int mode_idx) {
3522*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *winner_mbmi;
3523*77c1e3ccSAndroid Build Coastguard Worker if (multi_winner_mode_type) {
3524*77c1e3ccSAndroid Build Coastguard Worker assert(mode_idx >= 0 && mode_idx < x->winner_mode_count);
3525*77c1e3ccSAndroid Build Coastguard Worker WinnerModeStats *winner_mode_stat = &x->winner_mode_stats[mode_idx];
3526*77c1e3ccSAndroid Build Coastguard Worker winner_mbmi = &winner_mode_stat->mbmi;
3527*77c1e3ccSAndroid Build Coastguard Worker
3528*77c1e3ccSAndroid Build Coastguard Worker *winner_rd_cost = &winner_mode_stat->rd_cost;
3529*77c1e3ccSAndroid Build Coastguard Worker *winner_rate_y = winner_mode_stat->rate_y;
3530*77c1e3ccSAndroid Build Coastguard Worker *winner_rate_uv = winner_mode_stat->rate_uv;
3531*77c1e3ccSAndroid Build Coastguard Worker *winner_mode_index = winner_mode_stat->mode_index;
3532*77c1e3ccSAndroid Build Coastguard Worker } else {
3533*77c1e3ccSAndroid Build Coastguard Worker winner_mbmi = best_mbmode;
3534*77c1e3ccSAndroid Build Coastguard Worker *winner_rd_cost = best_rd_cost;
3535*77c1e3ccSAndroid Build Coastguard Worker *winner_rate_y = best_rate_y;
3536*77c1e3ccSAndroid Build Coastguard Worker *winner_rate_uv = best_rate_uv;
3537*77c1e3ccSAndroid Build Coastguard Worker *winner_mode_index = *best_mode_index;
3538*77c1e3ccSAndroid Build Coastguard Worker }
3539*77c1e3ccSAndroid Build Coastguard Worker return winner_mbmi;
3540*77c1e3ccSAndroid Build Coastguard Worker }
3541*77c1e3ccSAndroid Build Coastguard Worker
3542*77c1e3ccSAndroid Build Coastguard Worker // speed feature: fast intra/inter transform type search
3543*77c1e3ccSAndroid Build Coastguard Worker // Used for speed >= 2
3544*77c1e3ccSAndroid Build Coastguard Worker // When this speed feature is on, in rd mode search, only DCT is used.
3545*77c1e3ccSAndroid Build Coastguard Worker // After the mode is determined, this function is called, to select
3546*77c1e3ccSAndroid Build Coastguard Worker // transform types and get accurate rdcost.
refine_winner_mode_tx(const AV1_COMP * cpi,MACROBLOCK * x,RD_STATS * rd_cost,BLOCK_SIZE bsize,PICK_MODE_CONTEXT * ctx,THR_MODES * best_mode_index,MB_MODE_INFO * best_mbmode,struct buf_2d yv12_mb[REF_FRAMES][MAX_MB_PLANE],int best_rate_y,int best_rate_uv,int * best_skip2,int winner_mode_count)3547*77c1e3ccSAndroid Build Coastguard Worker static inline void refine_winner_mode_tx(
3548*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMP *cpi, MACROBLOCK *x, RD_STATS *rd_cost, BLOCK_SIZE bsize,
3549*77c1e3ccSAndroid Build Coastguard Worker PICK_MODE_CONTEXT *ctx, THR_MODES *best_mode_index,
3550*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *best_mbmode, struct buf_2d yv12_mb[REF_FRAMES][MAX_MB_PLANE],
3551*77c1e3ccSAndroid Build Coastguard Worker int best_rate_y, int best_rate_uv, int *best_skip2, int winner_mode_count) {
3552*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *const cm = &cpi->common;
3553*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *const xd = &x->e_mbd;
3554*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *const mbmi = xd->mi[0];
3555*77c1e3ccSAndroid Build Coastguard Worker TxfmSearchParams *txfm_params = &x->txfm_search_params;
3556*77c1e3ccSAndroid Build Coastguard Worker TxfmSearchInfo *txfm_info = &x->txfm_search_info;
3557*77c1e3ccSAndroid Build Coastguard Worker int64_t best_rd;
3558*77c1e3ccSAndroid Build Coastguard Worker const int num_planes = av1_num_planes(cm);
3559*77c1e3ccSAndroid Build Coastguard Worker
3560*77c1e3ccSAndroid Build Coastguard Worker if (!is_winner_mode_processing_enabled(cpi, x, best_mbmode,
3561*77c1e3ccSAndroid Build Coastguard Worker rd_cost->skip_txfm))
3562*77c1e3ccSAndroid Build Coastguard Worker return;
3563*77c1e3ccSAndroid Build Coastguard Worker
3564*77c1e3ccSAndroid Build Coastguard Worker // Set params for winner mode evaluation
3565*77c1e3ccSAndroid Build Coastguard Worker set_mode_eval_params(cpi, x, WINNER_MODE_EVAL);
3566*77c1e3ccSAndroid Build Coastguard Worker
3567*77c1e3ccSAndroid Build Coastguard Worker // No best mode identified so far
3568*77c1e3ccSAndroid Build Coastguard Worker if (*best_mode_index == THR_INVALID) return;
3569*77c1e3ccSAndroid Build Coastguard Worker
3570*77c1e3ccSAndroid Build Coastguard Worker best_rd = RDCOST(x->rdmult, rd_cost->rate, rd_cost->dist);
3571*77c1e3ccSAndroid Build Coastguard Worker for (int mode_idx = 0; mode_idx < winner_mode_count; mode_idx++) {
3572*77c1e3ccSAndroid Build Coastguard Worker RD_STATS *winner_rd_stats = NULL;
3573*77c1e3ccSAndroid Build Coastguard Worker int winner_rate_y = 0, winner_rate_uv = 0;
3574*77c1e3ccSAndroid Build Coastguard Worker THR_MODES winner_mode_index = 0;
3575*77c1e3ccSAndroid Build Coastguard Worker
3576*77c1e3ccSAndroid Build Coastguard Worker // TODO(any): Combine best mode and multi-winner mode processing paths
3577*77c1e3ccSAndroid Build Coastguard Worker // Get winner mode stats for current mode index
3578*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *winner_mbmi = get_winner_mode_stats(
3579*77c1e3ccSAndroid Build Coastguard Worker x, best_mbmode, rd_cost, best_rate_y, best_rate_uv, best_mode_index,
3580*77c1e3ccSAndroid Build Coastguard Worker &winner_rd_stats, &winner_rate_y, &winner_rate_uv, &winner_mode_index,
3581*77c1e3ccSAndroid Build Coastguard Worker cpi->sf.winner_mode_sf.multi_winner_mode_type, mode_idx);
3582*77c1e3ccSAndroid Build Coastguard Worker
3583*77c1e3ccSAndroid Build Coastguard Worker if (xd->lossless[winner_mbmi->segment_id] == 0 &&
3584*77c1e3ccSAndroid Build Coastguard Worker winner_mode_index != THR_INVALID &&
3585*77c1e3ccSAndroid Build Coastguard Worker is_winner_mode_processing_enabled(cpi, x, winner_mbmi,
3586*77c1e3ccSAndroid Build Coastguard Worker rd_cost->skip_txfm)) {
3587*77c1e3ccSAndroid Build Coastguard Worker RD_STATS rd_stats = *winner_rd_stats;
3588*77c1e3ccSAndroid Build Coastguard Worker int skip_blk = 0;
3589*77c1e3ccSAndroid Build Coastguard Worker RD_STATS rd_stats_y, rd_stats_uv;
3590*77c1e3ccSAndroid Build Coastguard Worker const int skip_ctx = av1_get_skip_txfm_context(xd);
3591*77c1e3ccSAndroid Build Coastguard Worker
3592*77c1e3ccSAndroid Build Coastguard Worker *mbmi = *winner_mbmi;
3593*77c1e3ccSAndroid Build Coastguard Worker
3594*77c1e3ccSAndroid Build Coastguard Worker set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
3595*77c1e3ccSAndroid Build Coastguard Worker
3596*77c1e3ccSAndroid Build Coastguard Worker // Select prediction reference frames.
3597*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < num_planes; i++) {
3598*77c1e3ccSAndroid Build Coastguard Worker xd->plane[i].pre[0] = yv12_mb[mbmi->ref_frame[0]][i];
3599*77c1e3ccSAndroid Build Coastguard Worker if (has_second_ref(mbmi))
3600*77c1e3ccSAndroid Build Coastguard Worker xd->plane[i].pre[1] = yv12_mb[mbmi->ref_frame[1]][i];
3601*77c1e3ccSAndroid Build Coastguard Worker }
3602*77c1e3ccSAndroid Build Coastguard Worker
3603*77c1e3ccSAndroid Build Coastguard Worker if (is_inter_mode(mbmi->mode)) {
3604*77c1e3ccSAndroid Build Coastguard Worker const int mi_row = xd->mi_row;
3605*77c1e3ccSAndroid Build Coastguard Worker const int mi_col = xd->mi_col;
3606*77c1e3ccSAndroid Build Coastguard Worker bool is_predictor_built = false;
3607*77c1e3ccSAndroid Build Coastguard Worker const PREDICTION_MODE prediction_mode = mbmi->mode;
3608*77c1e3ccSAndroid Build Coastguard Worker // Do interpolation filter search for realtime mode if applicable.
3609*77c1e3ccSAndroid Build Coastguard Worker if (cpi->sf.winner_mode_sf.winner_mode_ifs &&
3610*77c1e3ccSAndroid Build Coastguard Worker cpi->oxcf.mode == REALTIME &&
3611*77c1e3ccSAndroid Build Coastguard Worker cm->current_frame.reference_mode == SINGLE_REFERENCE &&
3612*77c1e3ccSAndroid Build Coastguard Worker is_inter_mode(prediction_mode) &&
3613*77c1e3ccSAndroid Build Coastguard Worker mbmi->motion_mode == SIMPLE_TRANSLATION &&
3614*77c1e3ccSAndroid Build Coastguard Worker !is_inter_compound_mode(prediction_mode)) {
3615*77c1e3ccSAndroid Build Coastguard Worker is_predictor_built =
3616*77c1e3ccSAndroid Build Coastguard Worker fast_interp_search(cpi, x, mi_row, mi_col, bsize);
3617*77c1e3ccSAndroid Build Coastguard Worker }
3618*77c1e3ccSAndroid Build Coastguard Worker if (!is_predictor_built) {
3619*77c1e3ccSAndroid Build Coastguard Worker av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, NULL, bsize, 0,
3620*77c1e3ccSAndroid Build Coastguard Worker av1_num_planes(cm) - 1);
3621*77c1e3ccSAndroid Build Coastguard Worker }
3622*77c1e3ccSAndroid Build Coastguard Worker if (mbmi->motion_mode == OBMC_CAUSAL)
3623*77c1e3ccSAndroid Build Coastguard Worker av1_build_obmc_inter_predictors_sb(cm, xd);
3624*77c1e3ccSAndroid Build Coastguard Worker
3625*77c1e3ccSAndroid Build Coastguard Worker av1_subtract_plane(x, bsize, 0);
3626*77c1e3ccSAndroid Build Coastguard Worker if (txfm_params->tx_mode_search_type == TX_MODE_SELECT &&
3627*77c1e3ccSAndroid Build Coastguard Worker !xd->lossless[mbmi->segment_id]) {
3628*77c1e3ccSAndroid Build Coastguard Worker av1_pick_recursive_tx_size_type_yrd(cpi, x, &rd_stats_y, bsize,
3629*77c1e3ccSAndroid Build Coastguard Worker INT64_MAX);
3630*77c1e3ccSAndroid Build Coastguard Worker assert(rd_stats_y.rate != INT_MAX);
3631*77c1e3ccSAndroid Build Coastguard Worker } else {
3632*77c1e3ccSAndroid Build Coastguard Worker av1_pick_uniform_tx_size_type_yrd(cpi, x, &rd_stats_y, bsize,
3633*77c1e3ccSAndroid Build Coastguard Worker INT64_MAX);
3634*77c1e3ccSAndroid Build Coastguard Worker memset(mbmi->inter_tx_size, mbmi->tx_size,
3635*77c1e3ccSAndroid Build Coastguard Worker sizeof(mbmi->inter_tx_size));
3636*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < xd->height * xd->width; ++i)
3637*77c1e3ccSAndroid Build Coastguard Worker set_blk_skip(txfm_info->blk_skip, 0, i, rd_stats_y.skip_txfm);
3638*77c1e3ccSAndroid Build Coastguard Worker }
3639*77c1e3ccSAndroid Build Coastguard Worker } else {
3640*77c1e3ccSAndroid Build Coastguard Worker av1_pick_uniform_tx_size_type_yrd(cpi, x, &rd_stats_y, bsize,
3641*77c1e3ccSAndroid Build Coastguard Worker INT64_MAX);
3642*77c1e3ccSAndroid Build Coastguard Worker }
3643*77c1e3ccSAndroid Build Coastguard Worker
3644*77c1e3ccSAndroid Build Coastguard Worker if (num_planes > 1) {
3645*77c1e3ccSAndroid Build Coastguard Worker av1_txfm_uvrd(cpi, x, &rd_stats_uv, bsize, INT64_MAX);
3646*77c1e3ccSAndroid Build Coastguard Worker } else {
3647*77c1e3ccSAndroid Build Coastguard Worker av1_init_rd_stats(&rd_stats_uv);
3648*77c1e3ccSAndroid Build Coastguard Worker }
3649*77c1e3ccSAndroid Build Coastguard Worker
3650*77c1e3ccSAndroid Build Coastguard Worker const ModeCosts *mode_costs = &x->mode_costs;
3651*77c1e3ccSAndroid Build Coastguard Worker if (is_inter_mode(mbmi->mode) &&
3652*77c1e3ccSAndroid Build Coastguard Worker RDCOST(x->rdmult,
3653*77c1e3ccSAndroid Build Coastguard Worker mode_costs->skip_txfm_cost[skip_ctx][0] + rd_stats_y.rate +
3654*77c1e3ccSAndroid Build Coastguard Worker rd_stats_uv.rate,
3655*77c1e3ccSAndroid Build Coastguard Worker (rd_stats_y.dist + rd_stats_uv.dist)) >
3656*77c1e3ccSAndroid Build Coastguard Worker RDCOST(x->rdmult, mode_costs->skip_txfm_cost[skip_ctx][1],
3657*77c1e3ccSAndroid Build Coastguard Worker (rd_stats_y.sse + rd_stats_uv.sse))) {
3658*77c1e3ccSAndroid Build Coastguard Worker skip_blk = 1;
3659*77c1e3ccSAndroid Build Coastguard Worker rd_stats_y.rate = mode_costs->skip_txfm_cost[skip_ctx][1];
3660*77c1e3ccSAndroid Build Coastguard Worker rd_stats_uv.rate = 0;
3661*77c1e3ccSAndroid Build Coastguard Worker rd_stats_y.dist = rd_stats_y.sse;
3662*77c1e3ccSAndroid Build Coastguard Worker rd_stats_uv.dist = rd_stats_uv.sse;
3663*77c1e3ccSAndroid Build Coastguard Worker } else {
3664*77c1e3ccSAndroid Build Coastguard Worker skip_blk = 0;
3665*77c1e3ccSAndroid Build Coastguard Worker rd_stats_y.rate += mode_costs->skip_txfm_cost[skip_ctx][0];
3666*77c1e3ccSAndroid Build Coastguard Worker }
3667*77c1e3ccSAndroid Build Coastguard Worker int this_rate = rd_stats.rate + rd_stats_y.rate + rd_stats_uv.rate -
3668*77c1e3ccSAndroid Build Coastguard Worker winner_rate_y - winner_rate_uv;
3669*77c1e3ccSAndroid Build Coastguard Worker int64_t this_rd =
3670*77c1e3ccSAndroid Build Coastguard Worker RDCOST(x->rdmult, this_rate, (rd_stats_y.dist + rd_stats_uv.dist));
3671*77c1e3ccSAndroid Build Coastguard Worker if (best_rd > this_rd) {
3672*77c1e3ccSAndroid Build Coastguard Worker *best_mbmode = *mbmi;
3673*77c1e3ccSAndroid Build Coastguard Worker *best_mode_index = winner_mode_index;
3674*77c1e3ccSAndroid Build Coastguard Worker av1_copy_array(ctx->blk_skip, txfm_info->blk_skip, ctx->num_4x4_blk);
3675*77c1e3ccSAndroid Build Coastguard Worker av1_copy_array(ctx->tx_type_map, xd->tx_type_map, ctx->num_4x4_blk);
3676*77c1e3ccSAndroid Build Coastguard Worker rd_cost->rate = this_rate;
3677*77c1e3ccSAndroid Build Coastguard Worker rd_cost->dist = rd_stats_y.dist + rd_stats_uv.dist;
3678*77c1e3ccSAndroid Build Coastguard Worker rd_cost->sse = rd_stats_y.sse + rd_stats_uv.sse;
3679*77c1e3ccSAndroid Build Coastguard Worker rd_cost->rdcost = this_rd;
3680*77c1e3ccSAndroid Build Coastguard Worker best_rd = this_rd;
3681*77c1e3ccSAndroid Build Coastguard Worker *best_skip2 = skip_blk;
3682*77c1e3ccSAndroid Build Coastguard Worker }
3683*77c1e3ccSAndroid Build Coastguard Worker }
3684*77c1e3ccSAndroid Build Coastguard Worker }
3685*77c1e3ccSAndroid Build Coastguard Worker }
3686*77c1e3ccSAndroid Build Coastguard Worker
3687*77c1e3ccSAndroid Build Coastguard Worker /*!\cond */
3688*77c1e3ccSAndroid Build Coastguard Worker typedef struct {
3689*77c1e3ccSAndroid Build Coastguard Worker // Mask for each reference frame, specifying which prediction modes to NOT try
3690*77c1e3ccSAndroid Build Coastguard Worker // during search.
3691*77c1e3ccSAndroid Build Coastguard Worker uint32_t pred_modes[REF_FRAMES];
3692*77c1e3ccSAndroid Build Coastguard Worker // If ref_combo[i][j + 1] is true, do NOT try prediction using combination of
3693*77c1e3ccSAndroid Build Coastguard Worker // reference frames (i, j).
3694*77c1e3ccSAndroid Build Coastguard Worker // Note: indexing with 'j + 1' is due to the fact that 2nd reference can be -1
3695*77c1e3ccSAndroid Build Coastguard Worker // (NONE_FRAME).
3696*77c1e3ccSAndroid Build Coastguard Worker bool ref_combo[REF_FRAMES][REF_FRAMES + 1];
3697*77c1e3ccSAndroid Build Coastguard Worker } mode_skip_mask_t;
3698*77c1e3ccSAndroid Build Coastguard Worker /*!\endcond */
3699*77c1e3ccSAndroid Build Coastguard Worker
3700*77c1e3ccSAndroid Build Coastguard Worker // Update 'ref_combo' mask to disable given 'ref' in single and compound modes.
disable_reference(MV_REFERENCE_FRAME ref,bool ref_combo[REF_FRAMES][REF_FRAMES+1])3701*77c1e3ccSAndroid Build Coastguard Worker static inline void disable_reference(
3702*77c1e3ccSAndroid Build Coastguard Worker MV_REFERENCE_FRAME ref, bool ref_combo[REF_FRAMES][REF_FRAMES + 1]) {
3703*77c1e3ccSAndroid Build Coastguard Worker for (MV_REFERENCE_FRAME ref2 = NONE_FRAME; ref2 < REF_FRAMES; ++ref2) {
3704*77c1e3ccSAndroid Build Coastguard Worker ref_combo[ref][ref2 + 1] = true;
3705*77c1e3ccSAndroid Build Coastguard Worker }
3706*77c1e3ccSAndroid Build Coastguard Worker }
3707*77c1e3ccSAndroid Build Coastguard Worker
3708*77c1e3ccSAndroid Build Coastguard Worker // Update 'ref_combo' mask to disable all inter references except ALTREF.
disable_inter_references_except_altref(bool ref_combo[REF_FRAMES][REF_FRAMES+1])3709*77c1e3ccSAndroid Build Coastguard Worker static inline void disable_inter_references_except_altref(
3710*77c1e3ccSAndroid Build Coastguard Worker bool ref_combo[REF_FRAMES][REF_FRAMES + 1]) {
3711*77c1e3ccSAndroid Build Coastguard Worker disable_reference(LAST_FRAME, ref_combo);
3712*77c1e3ccSAndroid Build Coastguard Worker disable_reference(LAST2_FRAME, ref_combo);
3713*77c1e3ccSAndroid Build Coastguard Worker disable_reference(LAST3_FRAME, ref_combo);
3714*77c1e3ccSAndroid Build Coastguard Worker disable_reference(GOLDEN_FRAME, ref_combo);
3715*77c1e3ccSAndroid Build Coastguard Worker disable_reference(BWDREF_FRAME, ref_combo);
3716*77c1e3ccSAndroid Build Coastguard Worker disable_reference(ALTREF2_FRAME, ref_combo);
3717*77c1e3ccSAndroid Build Coastguard Worker }
3718*77c1e3ccSAndroid Build Coastguard Worker
3719*77c1e3ccSAndroid Build Coastguard Worker static const MV_REFERENCE_FRAME reduced_ref_combos[][2] = {
3720*77c1e3ccSAndroid Build Coastguard Worker { LAST_FRAME, NONE_FRAME }, { ALTREF_FRAME, NONE_FRAME },
3721*77c1e3ccSAndroid Build Coastguard Worker { LAST_FRAME, ALTREF_FRAME }, { GOLDEN_FRAME, NONE_FRAME },
3722*77c1e3ccSAndroid Build Coastguard Worker { INTRA_FRAME, NONE_FRAME }, { GOLDEN_FRAME, ALTREF_FRAME },
3723*77c1e3ccSAndroid Build Coastguard Worker { LAST_FRAME, GOLDEN_FRAME }, { LAST_FRAME, INTRA_FRAME },
3724*77c1e3ccSAndroid Build Coastguard Worker { LAST_FRAME, BWDREF_FRAME }, { LAST_FRAME, LAST3_FRAME },
3725*77c1e3ccSAndroid Build Coastguard Worker { GOLDEN_FRAME, BWDREF_FRAME }, { GOLDEN_FRAME, INTRA_FRAME },
3726*77c1e3ccSAndroid Build Coastguard Worker { BWDREF_FRAME, NONE_FRAME }, { BWDREF_FRAME, ALTREF_FRAME },
3727*77c1e3ccSAndroid Build Coastguard Worker { ALTREF_FRAME, INTRA_FRAME }, { BWDREF_FRAME, INTRA_FRAME },
3728*77c1e3ccSAndroid Build Coastguard Worker };
3729*77c1e3ccSAndroid Build Coastguard Worker
3730*77c1e3ccSAndroid Build Coastguard Worker typedef enum { REF_SET_FULL, REF_SET_REDUCED, REF_SET_REALTIME } REF_SET;
3731*77c1e3ccSAndroid Build Coastguard Worker
default_skip_mask(mode_skip_mask_t * mask,REF_SET ref_set)3732*77c1e3ccSAndroid Build Coastguard Worker static inline void default_skip_mask(mode_skip_mask_t *mask, REF_SET ref_set) {
3733*77c1e3ccSAndroid Build Coastguard Worker if (ref_set == REF_SET_FULL) {
3734*77c1e3ccSAndroid Build Coastguard Worker // Everything available by default.
3735*77c1e3ccSAndroid Build Coastguard Worker memset(mask, 0, sizeof(*mask));
3736*77c1e3ccSAndroid Build Coastguard Worker } else {
3737*77c1e3ccSAndroid Build Coastguard Worker // All modes available by default.
3738*77c1e3ccSAndroid Build Coastguard Worker memset(mask->pred_modes, 0, sizeof(mask->pred_modes));
3739*77c1e3ccSAndroid Build Coastguard Worker // All references disabled first.
3740*77c1e3ccSAndroid Build Coastguard Worker for (MV_REFERENCE_FRAME ref1 = INTRA_FRAME; ref1 < REF_FRAMES; ++ref1) {
3741*77c1e3ccSAndroid Build Coastguard Worker for (MV_REFERENCE_FRAME ref2 = NONE_FRAME; ref2 < REF_FRAMES; ++ref2) {
3742*77c1e3ccSAndroid Build Coastguard Worker mask->ref_combo[ref1][ref2 + 1] = true;
3743*77c1e3ccSAndroid Build Coastguard Worker }
3744*77c1e3ccSAndroid Build Coastguard Worker }
3745*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME(*ref_set_combos)[2];
3746*77c1e3ccSAndroid Build Coastguard Worker int num_ref_combos;
3747*77c1e3ccSAndroid Build Coastguard Worker
3748*77c1e3ccSAndroid Build Coastguard Worker // Then enable reduced set of references explicitly.
3749*77c1e3ccSAndroid Build Coastguard Worker switch (ref_set) {
3750*77c1e3ccSAndroid Build Coastguard Worker case REF_SET_REDUCED:
3751*77c1e3ccSAndroid Build Coastguard Worker ref_set_combos = reduced_ref_combos;
3752*77c1e3ccSAndroid Build Coastguard Worker num_ref_combos =
3753*77c1e3ccSAndroid Build Coastguard Worker (int)sizeof(reduced_ref_combos) / sizeof(reduced_ref_combos[0]);
3754*77c1e3ccSAndroid Build Coastguard Worker break;
3755*77c1e3ccSAndroid Build Coastguard Worker case REF_SET_REALTIME:
3756*77c1e3ccSAndroid Build Coastguard Worker ref_set_combos = real_time_ref_combos;
3757*77c1e3ccSAndroid Build Coastguard Worker num_ref_combos =
3758*77c1e3ccSAndroid Build Coastguard Worker (int)sizeof(real_time_ref_combos) / sizeof(real_time_ref_combos[0]);
3759*77c1e3ccSAndroid Build Coastguard Worker break;
3760*77c1e3ccSAndroid Build Coastguard Worker default: assert(0); num_ref_combos = 0;
3761*77c1e3ccSAndroid Build Coastguard Worker }
3762*77c1e3ccSAndroid Build Coastguard Worker
3763*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < num_ref_combos; ++i) {
3764*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME *const this_combo = ref_set_combos[i];
3765*77c1e3ccSAndroid Build Coastguard Worker mask->ref_combo[this_combo[0]][this_combo[1] + 1] = false;
3766*77c1e3ccSAndroid Build Coastguard Worker }
3767*77c1e3ccSAndroid Build Coastguard Worker }
3768*77c1e3ccSAndroid Build Coastguard Worker }
3769*77c1e3ccSAndroid Build Coastguard Worker
init_mode_skip_mask(mode_skip_mask_t * mask,const AV1_COMP * cpi,MACROBLOCK * x,BLOCK_SIZE bsize)3770*77c1e3ccSAndroid Build Coastguard Worker static inline void init_mode_skip_mask(mode_skip_mask_t *mask,
3771*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMP *cpi, MACROBLOCK *x,
3772*77c1e3ccSAndroid Build Coastguard Worker BLOCK_SIZE bsize) {
3773*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *const cm = &cpi->common;
3774*77c1e3ccSAndroid Build Coastguard Worker const struct segmentation *const seg = &cm->seg;
3775*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *const xd = &x->e_mbd;
3776*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *const mbmi = xd->mi[0];
3777*77c1e3ccSAndroid Build Coastguard Worker unsigned char segment_id = mbmi->segment_id;
3778*77c1e3ccSAndroid Build Coastguard Worker const SPEED_FEATURES *const sf = &cpi->sf;
3779*77c1e3ccSAndroid Build Coastguard Worker const INTER_MODE_SPEED_FEATURES *const inter_sf = &sf->inter_sf;
3780*77c1e3ccSAndroid Build Coastguard Worker REF_SET ref_set = REF_SET_FULL;
3781*77c1e3ccSAndroid Build Coastguard Worker
3782*77c1e3ccSAndroid Build Coastguard Worker if (sf->rt_sf.use_real_time_ref_set)
3783*77c1e3ccSAndroid Build Coastguard Worker ref_set = REF_SET_REALTIME;
3784*77c1e3ccSAndroid Build Coastguard Worker else if (cpi->oxcf.ref_frm_cfg.enable_reduced_reference_set)
3785*77c1e3ccSAndroid Build Coastguard Worker ref_set = REF_SET_REDUCED;
3786*77c1e3ccSAndroid Build Coastguard Worker
3787*77c1e3ccSAndroid Build Coastguard Worker default_skip_mask(mask, ref_set);
3788*77c1e3ccSAndroid Build Coastguard Worker
3789*77c1e3ccSAndroid Build Coastguard Worker int min_pred_mv_sad = INT_MAX;
3790*77c1e3ccSAndroid Build Coastguard Worker MV_REFERENCE_FRAME ref_frame;
3791*77c1e3ccSAndroid Build Coastguard Worker if (ref_set == REF_SET_REALTIME) {
3792*77c1e3ccSAndroid Build Coastguard Worker // For real-time encoding, we only look at a subset of ref frames. So the
3793*77c1e3ccSAndroid Build Coastguard Worker // threshold for pruning should be computed from this subset as well.
3794*77c1e3ccSAndroid Build Coastguard Worker const int num_rt_refs =
3795*77c1e3ccSAndroid Build Coastguard Worker sizeof(real_time_ref_combos) / sizeof(*real_time_ref_combos);
3796*77c1e3ccSAndroid Build Coastguard Worker for (int r_idx = 0; r_idx < num_rt_refs; r_idx++) {
3797*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME ref = real_time_ref_combos[r_idx][0];
3798*77c1e3ccSAndroid Build Coastguard Worker if (ref != INTRA_FRAME) {
3799*77c1e3ccSAndroid Build Coastguard Worker min_pred_mv_sad = AOMMIN(min_pred_mv_sad, x->pred_mv_sad[ref]);
3800*77c1e3ccSAndroid Build Coastguard Worker }
3801*77c1e3ccSAndroid Build Coastguard Worker }
3802*77c1e3ccSAndroid Build Coastguard Worker } else {
3803*77c1e3ccSAndroid Build Coastguard Worker for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame)
3804*77c1e3ccSAndroid Build Coastguard Worker min_pred_mv_sad = AOMMIN(min_pred_mv_sad, x->pred_mv_sad[ref_frame]);
3805*77c1e3ccSAndroid Build Coastguard Worker }
3806*77c1e3ccSAndroid Build Coastguard Worker
3807*77c1e3ccSAndroid Build Coastguard Worker for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
3808*77c1e3ccSAndroid Build Coastguard Worker if (!(cpi->ref_frame_flags & av1_ref_frame_flag_list[ref_frame])) {
3809*77c1e3ccSAndroid Build Coastguard Worker // Skip checking missing reference in both single and compound reference
3810*77c1e3ccSAndroid Build Coastguard Worker // modes.
3811*77c1e3ccSAndroid Build Coastguard Worker disable_reference(ref_frame, mask->ref_combo);
3812*77c1e3ccSAndroid Build Coastguard Worker } else {
3813*77c1e3ccSAndroid Build Coastguard Worker // Skip fixed mv modes for poor references
3814*77c1e3ccSAndroid Build Coastguard Worker if ((x->pred_mv_sad[ref_frame] >> 2) > min_pred_mv_sad) {
3815*77c1e3ccSAndroid Build Coastguard Worker mask->pred_modes[ref_frame] |= INTER_NEAREST_NEAR_ZERO;
3816*77c1e3ccSAndroid Build Coastguard Worker }
3817*77c1e3ccSAndroid Build Coastguard Worker }
3818*77c1e3ccSAndroid Build Coastguard Worker if (segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME) &&
3819*77c1e3ccSAndroid Build Coastguard Worker get_segdata(seg, segment_id, SEG_LVL_REF_FRAME) != (int)ref_frame) {
3820*77c1e3ccSAndroid Build Coastguard Worker // Reference not used for the segment.
3821*77c1e3ccSAndroid Build Coastguard Worker disable_reference(ref_frame, mask->ref_combo);
3822*77c1e3ccSAndroid Build Coastguard Worker }
3823*77c1e3ccSAndroid Build Coastguard Worker }
3824*77c1e3ccSAndroid Build Coastguard Worker // Note: We use the following drop-out only if the SEG_LVL_REF_FRAME feature
3825*77c1e3ccSAndroid Build Coastguard Worker // is disabled for this segment. This is to prevent the possibility that we
3826*77c1e3ccSAndroid Build Coastguard Worker // end up unable to pick any mode.
3827*77c1e3ccSAndroid Build Coastguard Worker if (!segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME)) {
3828*77c1e3ccSAndroid Build Coastguard Worker // Only consider GLOBALMV/ALTREF_FRAME for alt ref frame,
3829*77c1e3ccSAndroid Build Coastguard Worker // unless ARNR filtering is enabled in which case we want
3830*77c1e3ccSAndroid Build Coastguard Worker // an unfiltered alternative. We allow near/nearest as well
3831*77c1e3ccSAndroid Build Coastguard Worker // because they may result in zero-zero MVs but be cheaper.
3832*77c1e3ccSAndroid Build Coastguard Worker if (cpi->rc.is_src_frame_alt_ref &&
3833*77c1e3ccSAndroid Build Coastguard Worker (cpi->oxcf.algo_cfg.arnr_max_frames == 0)) {
3834*77c1e3ccSAndroid Build Coastguard Worker disable_inter_references_except_altref(mask->ref_combo);
3835*77c1e3ccSAndroid Build Coastguard Worker
3836*77c1e3ccSAndroid Build Coastguard Worker mask->pred_modes[ALTREF_FRAME] = ~INTER_NEAREST_NEAR_ZERO;
3837*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME tmp_ref_frames[2] = { ALTREF_FRAME, NONE_FRAME };
3838*77c1e3ccSAndroid Build Coastguard Worker int_mv near_mv, nearest_mv, global_mv;
3839*77c1e3ccSAndroid Build Coastguard Worker get_this_mv(&nearest_mv, NEARESTMV, 0, 0, 0, tmp_ref_frames,
3840*77c1e3ccSAndroid Build Coastguard Worker &x->mbmi_ext);
3841*77c1e3ccSAndroid Build Coastguard Worker get_this_mv(&near_mv, NEARMV, 0, 0, 0, tmp_ref_frames, &x->mbmi_ext);
3842*77c1e3ccSAndroid Build Coastguard Worker get_this_mv(&global_mv, GLOBALMV, 0, 0, 0, tmp_ref_frames, &x->mbmi_ext);
3843*77c1e3ccSAndroid Build Coastguard Worker
3844*77c1e3ccSAndroid Build Coastguard Worker if (near_mv.as_int != global_mv.as_int)
3845*77c1e3ccSAndroid Build Coastguard Worker mask->pred_modes[ALTREF_FRAME] |= (1 << NEARMV);
3846*77c1e3ccSAndroid Build Coastguard Worker if (nearest_mv.as_int != global_mv.as_int)
3847*77c1e3ccSAndroid Build Coastguard Worker mask->pred_modes[ALTREF_FRAME] |= (1 << NEARESTMV);
3848*77c1e3ccSAndroid Build Coastguard Worker }
3849*77c1e3ccSAndroid Build Coastguard Worker }
3850*77c1e3ccSAndroid Build Coastguard Worker
3851*77c1e3ccSAndroid Build Coastguard Worker if (cpi->rc.is_src_frame_alt_ref) {
3852*77c1e3ccSAndroid Build Coastguard Worker if (inter_sf->alt_ref_search_fp &&
3853*77c1e3ccSAndroid Build Coastguard Worker (cpi->ref_frame_flags & av1_ref_frame_flag_list[ALTREF_FRAME])) {
3854*77c1e3ccSAndroid Build Coastguard Worker mask->pred_modes[ALTREF_FRAME] = 0;
3855*77c1e3ccSAndroid Build Coastguard Worker disable_inter_references_except_altref(mask->ref_combo);
3856*77c1e3ccSAndroid Build Coastguard Worker disable_reference(INTRA_FRAME, mask->ref_combo);
3857*77c1e3ccSAndroid Build Coastguard Worker }
3858*77c1e3ccSAndroid Build Coastguard Worker }
3859*77c1e3ccSAndroid Build Coastguard Worker
3860*77c1e3ccSAndroid Build Coastguard Worker if (inter_sf->alt_ref_search_fp) {
3861*77c1e3ccSAndroid Build Coastguard Worker if (!cm->show_frame && x->best_pred_mv_sad[0] < INT_MAX) {
3862*77c1e3ccSAndroid Build Coastguard Worker int sad_thresh = x->best_pred_mv_sad[0] + (x->best_pred_mv_sad[0] >> 3);
3863*77c1e3ccSAndroid Build Coastguard Worker // Conservatively skip the modes w.r.t. BWDREF, ALTREF2 and ALTREF, if
3864*77c1e3ccSAndroid Build Coastguard Worker // those are past frames
3865*77c1e3ccSAndroid Build Coastguard Worker MV_REFERENCE_FRAME start_frame =
3866*77c1e3ccSAndroid Build Coastguard Worker inter_sf->alt_ref_search_fp == 1 ? ALTREF2_FRAME : BWDREF_FRAME;
3867*77c1e3ccSAndroid Build Coastguard Worker for (ref_frame = start_frame; ref_frame <= ALTREF_FRAME; ref_frame++) {
3868*77c1e3ccSAndroid Build Coastguard Worker if (cpi->ref_frame_dist_info.ref_relative_dist[ref_frame - LAST_FRAME] <
3869*77c1e3ccSAndroid Build Coastguard Worker 0) {
3870*77c1e3ccSAndroid Build Coastguard Worker // Prune inter modes when relative dist of ALTREF2 and ALTREF is close
3871*77c1e3ccSAndroid Build Coastguard Worker // to the relative dist of LAST_FRAME.
3872*77c1e3ccSAndroid Build Coastguard Worker if (inter_sf->alt_ref_search_fp == 1 &&
3873*77c1e3ccSAndroid Build Coastguard Worker (abs(cpi->ref_frame_dist_info
3874*77c1e3ccSAndroid Build Coastguard Worker .ref_relative_dist[ref_frame - LAST_FRAME]) >
3875*77c1e3ccSAndroid Build Coastguard Worker 1.5 * abs(cpi->ref_frame_dist_info
3876*77c1e3ccSAndroid Build Coastguard Worker .ref_relative_dist[LAST_FRAME - LAST_FRAME]))) {
3877*77c1e3ccSAndroid Build Coastguard Worker continue;
3878*77c1e3ccSAndroid Build Coastguard Worker }
3879*77c1e3ccSAndroid Build Coastguard Worker if (x->pred_mv_sad[ref_frame] > sad_thresh)
3880*77c1e3ccSAndroid Build Coastguard Worker mask->pred_modes[ref_frame] |= INTER_ALL;
3881*77c1e3ccSAndroid Build Coastguard Worker }
3882*77c1e3ccSAndroid Build Coastguard Worker }
3883*77c1e3ccSAndroid Build Coastguard Worker }
3884*77c1e3ccSAndroid Build Coastguard Worker }
3885*77c1e3ccSAndroid Build Coastguard Worker
3886*77c1e3ccSAndroid Build Coastguard Worker if (sf->rt_sf.prune_inter_modes_wrt_gf_arf_based_on_sad) {
3887*77c1e3ccSAndroid Build Coastguard Worker if (x->best_pred_mv_sad[0] < INT_MAX) {
3888*77c1e3ccSAndroid Build Coastguard Worker int sad_thresh = x->best_pred_mv_sad[0] + (x->best_pred_mv_sad[0] >> 1);
3889*77c1e3ccSAndroid Build Coastguard Worker const int prune_ref_list[2] = { GOLDEN_FRAME, ALTREF_FRAME };
3890*77c1e3ccSAndroid Build Coastguard Worker
3891*77c1e3ccSAndroid Build Coastguard Worker // Conservatively skip the modes w.r.t. GOLDEN and ALTREF references
3892*77c1e3ccSAndroid Build Coastguard Worker for (int ref_idx = 0; ref_idx < 2; ref_idx++) {
3893*77c1e3ccSAndroid Build Coastguard Worker ref_frame = prune_ref_list[ref_idx];
3894*77c1e3ccSAndroid Build Coastguard Worker if (x->pred_mv_sad[ref_frame] > sad_thresh)
3895*77c1e3ccSAndroid Build Coastguard Worker mask->pred_modes[ref_frame] |= INTER_NEAREST_NEAR_ZERO;
3896*77c1e3ccSAndroid Build Coastguard Worker }
3897*77c1e3ccSAndroid Build Coastguard Worker }
3898*77c1e3ccSAndroid Build Coastguard Worker }
3899*77c1e3ccSAndroid Build Coastguard Worker
3900*77c1e3ccSAndroid Build Coastguard Worker if (bsize > sf->part_sf.max_intra_bsize) {
3901*77c1e3ccSAndroid Build Coastguard Worker disable_reference(INTRA_FRAME, mask->ref_combo);
3902*77c1e3ccSAndroid Build Coastguard Worker }
3903*77c1e3ccSAndroid Build Coastguard Worker
3904*77c1e3ccSAndroid Build Coastguard Worker if (!cpi->oxcf.tool_cfg.enable_global_motion) {
3905*77c1e3ccSAndroid Build Coastguard Worker for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
3906*77c1e3ccSAndroid Build Coastguard Worker mask->pred_modes[ref_frame] |= (1 << GLOBALMV);
3907*77c1e3ccSAndroid Build Coastguard Worker mask->pred_modes[ref_frame] |= (1 << GLOBAL_GLOBALMV);
3908*77c1e3ccSAndroid Build Coastguard Worker }
3909*77c1e3ccSAndroid Build Coastguard Worker }
3910*77c1e3ccSAndroid Build Coastguard Worker
3911*77c1e3ccSAndroid Build Coastguard Worker mask->pred_modes[INTRA_FRAME] |=
3912*77c1e3ccSAndroid Build Coastguard Worker ~(uint32_t)sf->intra_sf.intra_y_mode_mask[max_txsize_lookup[bsize]];
3913*77c1e3ccSAndroid Build Coastguard Worker
3914*77c1e3ccSAndroid Build Coastguard Worker // Prune reference frames which are not the closest to the current
3915*77c1e3ccSAndroid Build Coastguard Worker // frame and with large pred_mv_sad.
3916*77c1e3ccSAndroid Build Coastguard Worker if (inter_sf->prune_single_ref) {
3917*77c1e3ccSAndroid Build Coastguard Worker assert(inter_sf->prune_single_ref > 0 && inter_sf->prune_single_ref < 3);
3918*77c1e3ccSAndroid Build Coastguard Worker const double prune_threshes[2] = { 1.20, 1.05 };
3919*77c1e3ccSAndroid Build Coastguard Worker
3920*77c1e3ccSAndroid Build Coastguard Worker for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
3921*77c1e3ccSAndroid Build Coastguard Worker const RefFrameDistanceInfo *const ref_frame_dist_info =
3922*77c1e3ccSAndroid Build Coastguard Worker &cpi->ref_frame_dist_info;
3923*77c1e3ccSAndroid Build Coastguard Worker const int is_closest_ref =
3924*77c1e3ccSAndroid Build Coastguard Worker (ref_frame == ref_frame_dist_info->nearest_past_ref) ||
3925*77c1e3ccSAndroid Build Coastguard Worker (ref_frame == ref_frame_dist_info->nearest_future_ref);
3926*77c1e3ccSAndroid Build Coastguard Worker
3927*77c1e3ccSAndroid Build Coastguard Worker if (!is_closest_ref) {
3928*77c1e3ccSAndroid Build Coastguard Worker const int dir =
3929*77c1e3ccSAndroid Build Coastguard Worker (ref_frame_dist_info->ref_relative_dist[ref_frame - LAST_FRAME] < 0)
3930*77c1e3ccSAndroid Build Coastguard Worker ? 0
3931*77c1e3ccSAndroid Build Coastguard Worker : 1;
3932*77c1e3ccSAndroid Build Coastguard Worker if (x->best_pred_mv_sad[dir] < INT_MAX &&
3933*77c1e3ccSAndroid Build Coastguard Worker x->pred_mv_sad[ref_frame] >
3934*77c1e3ccSAndroid Build Coastguard Worker prune_threshes[inter_sf->prune_single_ref - 1] *
3935*77c1e3ccSAndroid Build Coastguard Worker x->best_pred_mv_sad[dir])
3936*77c1e3ccSAndroid Build Coastguard Worker mask->pred_modes[ref_frame] |= INTER_SINGLE_ALL;
3937*77c1e3ccSAndroid Build Coastguard Worker }
3938*77c1e3ccSAndroid Build Coastguard Worker }
3939*77c1e3ccSAndroid Build Coastguard Worker }
3940*77c1e3ccSAndroid Build Coastguard Worker }
3941*77c1e3ccSAndroid Build Coastguard Worker
init_neighbor_pred_buf(const OBMCBuffer * const obmc_buffer,HandleInterModeArgs * const args,int is_hbd)3942*77c1e3ccSAndroid Build Coastguard Worker static inline void init_neighbor_pred_buf(const OBMCBuffer *const obmc_buffer,
3943*77c1e3ccSAndroid Build Coastguard Worker HandleInterModeArgs *const args,
3944*77c1e3ccSAndroid Build Coastguard Worker int is_hbd) {
3945*77c1e3ccSAndroid Build Coastguard Worker if (is_hbd) {
3946*77c1e3ccSAndroid Build Coastguard Worker const int len = sizeof(uint16_t);
3947*77c1e3ccSAndroid Build Coastguard Worker args->above_pred_buf[0] = CONVERT_TO_BYTEPTR(obmc_buffer->above_pred);
3948*77c1e3ccSAndroid Build Coastguard Worker args->above_pred_buf[1] = CONVERT_TO_BYTEPTR(obmc_buffer->above_pred +
3949*77c1e3ccSAndroid Build Coastguard Worker (MAX_SB_SQUARE >> 1) * len);
3950*77c1e3ccSAndroid Build Coastguard Worker args->above_pred_buf[2] =
3951*77c1e3ccSAndroid Build Coastguard Worker CONVERT_TO_BYTEPTR(obmc_buffer->above_pred + MAX_SB_SQUARE * len);
3952*77c1e3ccSAndroid Build Coastguard Worker args->left_pred_buf[0] = CONVERT_TO_BYTEPTR(obmc_buffer->left_pred);
3953*77c1e3ccSAndroid Build Coastguard Worker args->left_pred_buf[1] =
3954*77c1e3ccSAndroid Build Coastguard Worker CONVERT_TO_BYTEPTR(obmc_buffer->left_pred + (MAX_SB_SQUARE >> 1) * len);
3955*77c1e3ccSAndroid Build Coastguard Worker args->left_pred_buf[2] =
3956*77c1e3ccSAndroid Build Coastguard Worker CONVERT_TO_BYTEPTR(obmc_buffer->left_pred + MAX_SB_SQUARE * len);
3957*77c1e3ccSAndroid Build Coastguard Worker } else {
3958*77c1e3ccSAndroid Build Coastguard Worker args->above_pred_buf[0] = obmc_buffer->above_pred;
3959*77c1e3ccSAndroid Build Coastguard Worker args->above_pred_buf[1] = obmc_buffer->above_pred + (MAX_SB_SQUARE >> 1);
3960*77c1e3ccSAndroid Build Coastguard Worker args->above_pred_buf[2] = obmc_buffer->above_pred + MAX_SB_SQUARE;
3961*77c1e3ccSAndroid Build Coastguard Worker args->left_pred_buf[0] = obmc_buffer->left_pred;
3962*77c1e3ccSAndroid Build Coastguard Worker args->left_pred_buf[1] = obmc_buffer->left_pred + (MAX_SB_SQUARE >> 1);
3963*77c1e3ccSAndroid Build Coastguard Worker args->left_pred_buf[2] = obmc_buffer->left_pred + MAX_SB_SQUARE;
3964*77c1e3ccSAndroid Build Coastguard Worker }
3965*77c1e3ccSAndroid Build Coastguard Worker }
3966*77c1e3ccSAndroid Build Coastguard Worker
prune_ref_frame(const AV1_COMP * cpi,const MACROBLOCK * x,MV_REFERENCE_FRAME ref_frame)3967*77c1e3ccSAndroid Build Coastguard Worker static inline int prune_ref_frame(const AV1_COMP *cpi, const MACROBLOCK *x,
3968*77c1e3ccSAndroid Build Coastguard Worker MV_REFERENCE_FRAME ref_frame) {
3969*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *const cm = &cpi->common;
3970*77c1e3ccSAndroid Build Coastguard Worker MV_REFERENCE_FRAME rf[2];
3971*77c1e3ccSAndroid Build Coastguard Worker av1_set_ref_frame(rf, ref_frame);
3972*77c1e3ccSAndroid Build Coastguard Worker
3973*77c1e3ccSAndroid Build Coastguard Worker if ((cpi->prune_ref_frame_mask >> ref_frame) & 1) return 1;
3974*77c1e3ccSAndroid Build Coastguard Worker
3975*77c1e3ccSAndroid Build Coastguard Worker if (prune_ref_by_selective_ref_frame(cpi, x, rf,
3976*77c1e3ccSAndroid Build Coastguard Worker cm->cur_frame->ref_display_order_hint)) {
3977*77c1e3ccSAndroid Build Coastguard Worker return 1;
3978*77c1e3ccSAndroid Build Coastguard Worker }
3979*77c1e3ccSAndroid Build Coastguard Worker
3980*77c1e3ccSAndroid Build Coastguard Worker return 0;
3981*77c1e3ccSAndroid Build Coastguard Worker }
3982*77c1e3ccSAndroid Build Coastguard Worker
is_ref_frame_used_by_compound_ref(int ref_frame,int skip_ref_frame_mask)3983*77c1e3ccSAndroid Build Coastguard Worker static inline int is_ref_frame_used_by_compound_ref(int ref_frame,
3984*77c1e3ccSAndroid Build Coastguard Worker int skip_ref_frame_mask) {
3985*77c1e3ccSAndroid Build Coastguard Worker for (int r = ALTREF_FRAME + 1; r < MODE_CTX_REF_FRAMES; ++r) {
3986*77c1e3ccSAndroid Build Coastguard Worker if (!(skip_ref_frame_mask & (1 << r))) {
3987*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME *rf = ref_frame_map[r - REF_FRAMES];
3988*77c1e3ccSAndroid Build Coastguard Worker if (rf[0] == ref_frame || rf[1] == ref_frame) {
3989*77c1e3ccSAndroid Build Coastguard Worker return 1;
3990*77c1e3ccSAndroid Build Coastguard Worker }
3991*77c1e3ccSAndroid Build Coastguard Worker }
3992*77c1e3ccSAndroid Build Coastguard Worker }
3993*77c1e3ccSAndroid Build Coastguard Worker return 0;
3994*77c1e3ccSAndroid Build Coastguard Worker }
3995*77c1e3ccSAndroid Build Coastguard Worker
is_ref_frame_used_in_cache(MV_REFERENCE_FRAME ref_frame,const MB_MODE_INFO * mi_cache)3996*77c1e3ccSAndroid Build Coastguard Worker static inline int is_ref_frame_used_in_cache(MV_REFERENCE_FRAME ref_frame,
3997*77c1e3ccSAndroid Build Coastguard Worker const MB_MODE_INFO *mi_cache) {
3998*77c1e3ccSAndroid Build Coastguard Worker if (!mi_cache) {
3999*77c1e3ccSAndroid Build Coastguard Worker return 0;
4000*77c1e3ccSAndroid Build Coastguard Worker }
4001*77c1e3ccSAndroid Build Coastguard Worker
4002*77c1e3ccSAndroid Build Coastguard Worker if (ref_frame < REF_FRAMES) {
4003*77c1e3ccSAndroid Build Coastguard Worker return (ref_frame == mi_cache->ref_frame[0] ||
4004*77c1e3ccSAndroid Build Coastguard Worker ref_frame == mi_cache->ref_frame[1]);
4005*77c1e3ccSAndroid Build Coastguard Worker }
4006*77c1e3ccSAndroid Build Coastguard Worker
4007*77c1e3ccSAndroid Build Coastguard Worker // if we are here, then the current mode is compound.
4008*77c1e3ccSAndroid Build Coastguard Worker MV_REFERENCE_FRAME cached_ref_type = av1_ref_frame_type(mi_cache->ref_frame);
4009*77c1e3ccSAndroid Build Coastguard Worker return ref_frame == cached_ref_type;
4010*77c1e3ccSAndroid Build Coastguard Worker }
4011*77c1e3ccSAndroid Build Coastguard Worker
4012*77c1e3ccSAndroid Build Coastguard Worker // Please add/modify parameter setting in this function, making it consistent
4013*77c1e3ccSAndroid Build Coastguard Worker // and easy to read and maintain.
set_params_rd_pick_inter_mode(const AV1_COMP * cpi,MACROBLOCK * x,HandleInterModeArgs * args,BLOCK_SIZE bsize,mode_skip_mask_t * mode_skip_mask,int skip_ref_frame_mask,unsigned int * ref_costs_single,unsigned int (* ref_costs_comp)[REF_FRAMES],struct buf_2d (* yv12_mb)[MAX_MB_PLANE])4014*77c1e3ccSAndroid Build Coastguard Worker static inline void set_params_rd_pick_inter_mode(
4015*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMP *cpi, MACROBLOCK *x, HandleInterModeArgs *args,
4016*77c1e3ccSAndroid Build Coastguard Worker BLOCK_SIZE bsize, mode_skip_mask_t *mode_skip_mask, int skip_ref_frame_mask,
4017*77c1e3ccSAndroid Build Coastguard Worker unsigned int *ref_costs_single, unsigned int (*ref_costs_comp)[REF_FRAMES],
4018*77c1e3ccSAndroid Build Coastguard Worker struct buf_2d (*yv12_mb)[MAX_MB_PLANE]) {
4019*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *const cm = &cpi->common;
4020*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *const xd = &x->e_mbd;
4021*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *const mbmi = xd->mi[0];
4022*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO_EXT *const mbmi_ext = &x->mbmi_ext;
4023*77c1e3ccSAndroid Build Coastguard Worker unsigned char segment_id = mbmi->segment_id;
4024*77c1e3ccSAndroid Build Coastguard Worker
4025*77c1e3ccSAndroid Build Coastguard Worker init_neighbor_pred_buf(&x->obmc_buffer, args, is_cur_buf_hbd(&x->e_mbd));
4026*77c1e3ccSAndroid Build Coastguard Worker av1_collect_neighbors_ref_counts(xd);
4027*77c1e3ccSAndroid Build Coastguard Worker estimate_ref_frame_costs(cm, xd, &x->mode_costs, segment_id, ref_costs_single,
4028*77c1e3ccSAndroid Build Coastguard Worker ref_costs_comp);
4029*77c1e3ccSAndroid Build Coastguard Worker
4030*77c1e3ccSAndroid Build Coastguard Worker const int mi_row = xd->mi_row;
4031*77c1e3ccSAndroid Build Coastguard Worker const int mi_col = xd->mi_col;
4032*77c1e3ccSAndroid Build Coastguard Worker x->best_pred_mv_sad[0] = INT_MAX;
4033*77c1e3ccSAndroid Build Coastguard Worker x->best_pred_mv_sad[1] = INT_MAX;
4034*77c1e3ccSAndroid Build Coastguard Worker
4035*77c1e3ccSAndroid Build Coastguard Worker for (MV_REFERENCE_FRAME ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME;
4036*77c1e3ccSAndroid Build Coastguard Worker ++ref_frame) {
4037*77c1e3ccSAndroid Build Coastguard Worker x->pred_mv_sad[ref_frame] = INT_MAX;
4038*77c1e3ccSAndroid Build Coastguard Worker mbmi_ext->mode_context[ref_frame] = 0;
4039*77c1e3ccSAndroid Build Coastguard Worker mbmi_ext->ref_mv_count[ref_frame] = UINT8_MAX;
4040*77c1e3ccSAndroid Build Coastguard Worker if (cpi->ref_frame_flags & av1_ref_frame_flag_list[ref_frame]) {
4041*77c1e3ccSAndroid Build Coastguard Worker // Skip the ref frame if the mask says skip and the ref is not used by
4042*77c1e3ccSAndroid Build Coastguard Worker // compound ref.
4043*77c1e3ccSAndroid Build Coastguard Worker if (skip_ref_frame_mask & (1 << ref_frame) &&
4044*77c1e3ccSAndroid Build Coastguard Worker !is_ref_frame_used_by_compound_ref(ref_frame, skip_ref_frame_mask) &&
4045*77c1e3ccSAndroid Build Coastguard Worker !is_ref_frame_used_in_cache(ref_frame, x->mb_mode_cache)) {
4046*77c1e3ccSAndroid Build Coastguard Worker continue;
4047*77c1e3ccSAndroid Build Coastguard Worker }
4048*77c1e3ccSAndroid Build Coastguard Worker assert(get_ref_frame_yv12_buf(cm, ref_frame) != NULL);
4049*77c1e3ccSAndroid Build Coastguard Worker setup_buffer_ref_mvs_inter(cpi, x, ref_frame, bsize, yv12_mb);
4050*77c1e3ccSAndroid Build Coastguard Worker }
4051*77c1e3ccSAndroid Build Coastguard Worker if (cpi->sf.inter_sf.alt_ref_search_fp ||
4052*77c1e3ccSAndroid Build Coastguard Worker cpi->sf.inter_sf.prune_single_ref ||
4053*77c1e3ccSAndroid Build Coastguard Worker cpi->sf.rt_sf.prune_inter_modes_wrt_gf_arf_based_on_sad) {
4054*77c1e3ccSAndroid Build Coastguard Worker // Store the best pred_mv_sad across all past frames
4055*77c1e3ccSAndroid Build Coastguard Worker if (cpi->ref_frame_dist_info.ref_relative_dist[ref_frame - LAST_FRAME] <
4056*77c1e3ccSAndroid Build Coastguard Worker 0)
4057*77c1e3ccSAndroid Build Coastguard Worker x->best_pred_mv_sad[0] =
4058*77c1e3ccSAndroid Build Coastguard Worker AOMMIN(x->best_pred_mv_sad[0], x->pred_mv_sad[ref_frame]);
4059*77c1e3ccSAndroid Build Coastguard Worker else
4060*77c1e3ccSAndroid Build Coastguard Worker // Store the best pred_mv_sad across all future frames
4061*77c1e3ccSAndroid Build Coastguard Worker x->best_pred_mv_sad[1] =
4062*77c1e3ccSAndroid Build Coastguard Worker AOMMIN(x->best_pred_mv_sad[1], x->pred_mv_sad[ref_frame]);
4063*77c1e3ccSAndroid Build Coastguard Worker }
4064*77c1e3ccSAndroid Build Coastguard Worker }
4065*77c1e3ccSAndroid Build Coastguard Worker
4066*77c1e3ccSAndroid Build Coastguard Worker if (!cpi->sf.rt_sf.use_real_time_ref_set && is_comp_ref_allowed(bsize)) {
4067*77c1e3ccSAndroid Build Coastguard Worker // No second reference on RT ref set, so no need to initialize
4068*77c1e3ccSAndroid Build Coastguard Worker for (MV_REFERENCE_FRAME ref_frame = EXTREF_FRAME;
4069*77c1e3ccSAndroid Build Coastguard Worker ref_frame < MODE_CTX_REF_FRAMES; ++ref_frame) {
4070*77c1e3ccSAndroid Build Coastguard Worker mbmi_ext->mode_context[ref_frame] = 0;
4071*77c1e3ccSAndroid Build Coastguard Worker mbmi_ext->ref_mv_count[ref_frame] = UINT8_MAX;
4072*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME *rf = ref_frame_map[ref_frame - REF_FRAMES];
4073*77c1e3ccSAndroid Build Coastguard Worker if (!((cpi->ref_frame_flags & av1_ref_frame_flag_list[rf[0]]) &&
4074*77c1e3ccSAndroid Build Coastguard Worker (cpi->ref_frame_flags & av1_ref_frame_flag_list[rf[1]]))) {
4075*77c1e3ccSAndroid Build Coastguard Worker continue;
4076*77c1e3ccSAndroid Build Coastguard Worker }
4077*77c1e3ccSAndroid Build Coastguard Worker
4078*77c1e3ccSAndroid Build Coastguard Worker if (skip_ref_frame_mask & (1 << ref_frame) &&
4079*77c1e3ccSAndroid Build Coastguard Worker !is_ref_frame_used_in_cache(ref_frame, x->mb_mode_cache)) {
4080*77c1e3ccSAndroid Build Coastguard Worker continue;
4081*77c1e3ccSAndroid Build Coastguard Worker }
4082*77c1e3ccSAndroid Build Coastguard Worker // Ref mv list population is not required, when compound references are
4083*77c1e3ccSAndroid Build Coastguard Worker // pruned.
4084*77c1e3ccSAndroid Build Coastguard Worker if (prune_ref_frame(cpi, x, ref_frame)) continue;
4085*77c1e3ccSAndroid Build Coastguard Worker
4086*77c1e3ccSAndroid Build Coastguard Worker av1_find_mv_refs(cm, xd, mbmi, ref_frame, mbmi_ext->ref_mv_count,
4087*77c1e3ccSAndroid Build Coastguard Worker xd->ref_mv_stack, xd->weight, NULL, mbmi_ext->global_mvs,
4088*77c1e3ccSAndroid Build Coastguard Worker mbmi_ext->mode_context);
4089*77c1e3ccSAndroid Build Coastguard Worker // TODO(Ravi): Populate mbmi_ext->ref_mv_stack[ref_frame][4] and
4090*77c1e3ccSAndroid Build Coastguard Worker // mbmi_ext->weight[ref_frame][4] inside av1_find_mv_refs.
4091*77c1e3ccSAndroid Build Coastguard Worker av1_copy_usable_ref_mv_stack_and_weight(xd, mbmi_ext, ref_frame);
4092*77c1e3ccSAndroid Build Coastguard Worker }
4093*77c1e3ccSAndroid Build Coastguard Worker }
4094*77c1e3ccSAndroid Build Coastguard Worker
4095*77c1e3ccSAndroid Build Coastguard Worker av1_count_overlappable_neighbors(cm, xd);
4096*77c1e3ccSAndroid Build Coastguard Worker const FRAME_UPDATE_TYPE update_type =
4097*77c1e3ccSAndroid Build Coastguard Worker get_frame_update_type(&cpi->ppi->gf_group, cpi->gf_frame_index);
4098*77c1e3ccSAndroid Build Coastguard Worker int use_actual_frame_probs = 1;
4099*77c1e3ccSAndroid Build Coastguard Worker int prune_obmc;
4100*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_FPMT_TEST
4101*77c1e3ccSAndroid Build Coastguard Worker use_actual_frame_probs =
4102*77c1e3ccSAndroid Build Coastguard Worker (cpi->ppi->fpmt_unit_test_cfg == PARALLEL_SIMULATION_ENCODE) ? 0 : 1;
4103*77c1e3ccSAndroid Build Coastguard Worker if (!use_actual_frame_probs) {
4104*77c1e3ccSAndroid Build Coastguard Worker prune_obmc = cpi->ppi->temp_frame_probs.obmc_probs[update_type][bsize] <
4105*77c1e3ccSAndroid Build Coastguard Worker cpi->sf.inter_sf.prune_obmc_prob_thresh;
4106*77c1e3ccSAndroid Build Coastguard Worker }
4107*77c1e3ccSAndroid Build Coastguard Worker #endif
4108*77c1e3ccSAndroid Build Coastguard Worker if (use_actual_frame_probs) {
4109*77c1e3ccSAndroid Build Coastguard Worker prune_obmc = cpi->ppi->frame_probs.obmc_probs[update_type][bsize] <
4110*77c1e3ccSAndroid Build Coastguard Worker cpi->sf.inter_sf.prune_obmc_prob_thresh;
4111*77c1e3ccSAndroid Build Coastguard Worker }
4112*77c1e3ccSAndroid Build Coastguard Worker if (cpi->oxcf.motion_mode_cfg.enable_obmc && !prune_obmc) {
4113*77c1e3ccSAndroid Build Coastguard Worker if (check_num_overlappable_neighbors(mbmi) &&
4114*77c1e3ccSAndroid Build Coastguard Worker is_motion_variation_allowed_bsize(bsize)) {
4115*77c1e3ccSAndroid Build Coastguard Worker int dst_width1[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE };
4116*77c1e3ccSAndroid Build Coastguard Worker int dst_width2[MAX_MB_PLANE] = { MAX_SB_SIZE >> 1, MAX_SB_SIZE >> 1,
4117*77c1e3ccSAndroid Build Coastguard Worker MAX_SB_SIZE >> 1 };
4118*77c1e3ccSAndroid Build Coastguard Worker int dst_height1[MAX_MB_PLANE] = { MAX_SB_SIZE >> 1, MAX_SB_SIZE >> 1,
4119*77c1e3ccSAndroid Build Coastguard Worker MAX_SB_SIZE >> 1 };
4120*77c1e3ccSAndroid Build Coastguard Worker int dst_height2[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE };
4121*77c1e3ccSAndroid Build Coastguard Worker av1_build_prediction_by_above_preds(cm, xd, args->above_pred_buf,
4122*77c1e3ccSAndroid Build Coastguard Worker dst_width1, dst_height1,
4123*77c1e3ccSAndroid Build Coastguard Worker args->above_pred_stride);
4124*77c1e3ccSAndroid Build Coastguard Worker av1_build_prediction_by_left_preds(cm, xd, args->left_pred_buf,
4125*77c1e3ccSAndroid Build Coastguard Worker dst_width2, dst_height2,
4126*77c1e3ccSAndroid Build Coastguard Worker args->left_pred_stride);
4127*77c1e3ccSAndroid Build Coastguard Worker const int num_planes = av1_num_planes(cm);
4128*77c1e3ccSAndroid Build Coastguard Worker av1_setup_dst_planes(xd->plane, bsize, &cm->cur_frame->buf, mi_row,
4129*77c1e3ccSAndroid Build Coastguard Worker mi_col, 0, num_planes);
4130*77c1e3ccSAndroid Build Coastguard Worker calc_target_weighted_pred(
4131*77c1e3ccSAndroid Build Coastguard Worker cm, x, xd, args->above_pred_buf[0], args->above_pred_stride[0],
4132*77c1e3ccSAndroid Build Coastguard Worker args->left_pred_buf[0], args->left_pred_stride[0]);
4133*77c1e3ccSAndroid Build Coastguard Worker }
4134*77c1e3ccSAndroid Build Coastguard Worker }
4135*77c1e3ccSAndroid Build Coastguard Worker
4136*77c1e3ccSAndroid Build Coastguard Worker init_mode_skip_mask(mode_skip_mask, cpi, x, bsize);
4137*77c1e3ccSAndroid Build Coastguard Worker
4138*77c1e3ccSAndroid Build Coastguard Worker // Set params for mode evaluation
4139*77c1e3ccSAndroid Build Coastguard Worker set_mode_eval_params(cpi, x, MODE_EVAL);
4140*77c1e3ccSAndroid Build Coastguard Worker
4141*77c1e3ccSAndroid Build Coastguard Worker x->comp_rd_stats_idx = 0;
4142*77c1e3ccSAndroid Build Coastguard Worker
4143*77c1e3ccSAndroid Build Coastguard Worker for (int idx = 0; idx < REF_FRAMES; idx++) {
4144*77c1e3ccSAndroid Build Coastguard Worker args->best_single_sse_in_refs[idx] = INT32_MAX;
4145*77c1e3ccSAndroid Build Coastguard Worker }
4146*77c1e3ccSAndroid Build Coastguard Worker }
4147*77c1e3ccSAndroid Build Coastguard Worker
init_single_inter_mode_search_state(InterModeSearchState * search_state)4148*77c1e3ccSAndroid Build Coastguard Worker static inline void init_single_inter_mode_search_state(
4149*77c1e3ccSAndroid Build Coastguard Worker InterModeSearchState *search_state) {
4150*77c1e3ccSAndroid Build Coastguard Worker for (int dir = 0; dir < 2; ++dir) {
4151*77c1e3ccSAndroid Build Coastguard Worker for (int mode = 0; mode < SINGLE_INTER_MODE_NUM; ++mode) {
4152*77c1e3ccSAndroid Build Coastguard Worker for (int ref_frame = 0; ref_frame < FWD_REFS; ++ref_frame) {
4153*77c1e3ccSAndroid Build Coastguard Worker SingleInterModeState *state;
4154*77c1e3ccSAndroid Build Coastguard Worker
4155*77c1e3ccSAndroid Build Coastguard Worker state = &search_state->single_state[dir][mode][ref_frame];
4156*77c1e3ccSAndroid Build Coastguard Worker state->ref_frame = NONE_FRAME;
4157*77c1e3ccSAndroid Build Coastguard Worker state->rd = INT64_MAX;
4158*77c1e3ccSAndroid Build Coastguard Worker
4159*77c1e3ccSAndroid Build Coastguard Worker state = &search_state->single_state_modelled[dir][mode][ref_frame];
4160*77c1e3ccSAndroid Build Coastguard Worker state->ref_frame = NONE_FRAME;
4161*77c1e3ccSAndroid Build Coastguard Worker state->rd = INT64_MAX;
4162*77c1e3ccSAndroid Build Coastguard Worker
4163*77c1e3ccSAndroid Build Coastguard Worker search_state->single_rd_order[dir][mode][ref_frame] = NONE_FRAME;
4164*77c1e3ccSAndroid Build Coastguard Worker }
4165*77c1e3ccSAndroid Build Coastguard Worker }
4166*77c1e3ccSAndroid Build Coastguard Worker }
4167*77c1e3ccSAndroid Build Coastguard Worker
4168*77c1e3ccSAndroid Build Coastguard Worker for (int ref_frame = 0; ref_frame < REF_FRAMES; ++ref_frame) {
4169*77c1e3ccSAndroid Build Coastguard Worker search_state->best_single_rd[ref_frame] = INT64_MAX;
4170*77c1e3ccSAndroid Build Coastguard Worker search_state->best_single_mode[ref_frame] = PRED_MODE_INVALID;
4171*77c1e3ccSAndroid Build Coastguard Worker }
4172*77c1e3ccSAndroid Build Coastguard Worker av1_zero(search_state->single_state_cnt);
4173*77c1e3ccSAndroid Build Coastguard Worker av1_zero(search_state->single_state_modelled_cnt);
4174*77c1e3ccSAndroid Build Coastguard Worker }
4175*77c1e3ccSAndroid Build Coastguard Worker
init_inter_mode_search_state(InterModeSearchState * search_state,const AV1_COMP * cpi,const MACROBLOCK * x,BLOCK_SIZE bsize,int64_t best_rd_so_far)4176*77c1e3ccSAndroid Build Coastguard Worker static inline void init_inter_mode_search_state(
4177*77c1e3ccSAndroid Build Coastguard Worker InterModeSearchState *search_state, const AV1_COMP *cpi,
4178*77c1e3ccSAndroid Build Coastguard Worker const MACROBLOCK *x, BLOCK_SIZE bsize, int64_t best_rd_so_far) {
4179*77c1e3ccSAndroid Build Coastguard Worker init_intra_mode_search_state(&search_state->intra_search_state);
4180*77c1e3ccSAndroid Build Coastguard Worker av1_invalid_rd_stats(&search_state->best_y_rdcost);
4181*77c1e3ccSAndroid Build Coastguard Worker
4182*77c1e3ccSAndroid Build Coastguard Worker search_state->best_rd = best_rd_so_far;
4183*77c1e3ccSAndroid Build Coastguard Worker search_state->best_skip_rd[0] = INT64_MAX;
4184*77c1e3ccSAndroid Build Coastguard Worker search_state->best_skip_rd[1] = INT64_MAX;
4185*77c1e3ccSAndroid Build Coastguard Worker
4186*77c1e3ccSAndroid Build Coastguard Worker av1_zero(search_state->best_mbmode);
4187*77c1e3ccSAndroid Build Coastguard Worker
4188*77c1e3ccSAndroid Build Coastguard Worker search_state->best_rate_y = INT_MAX;
4189*77c1e3ccSAndroid Build Coastguard Worker
4190*77c1e3ccSAndroid Build Coastguard Worker search_state->best_rate_uv = INT_MAX;
4191*77c1e3ccSAndroid Build Coastguard Worker
4192*77c1e3ccSAndroid Build Coastguard Worker search_state->best_mode_skippable = 0;
4193*77c1e3ccSAndroid Build Coastguard Worker
4194*77c1e3ccSAndroid Build Coastguard Worker search_state->best_skip2 = 0;
4195*77c1e3ccSAndroid Build Coastguard Worker
4196*77c1e3ccSAndroid Build Coastguard Worker search_state->best_mode_index = THR_INVALID;
4197*77c1e3ccSAndroid Build Coastguard Worker
4198*77c1e3ccSAndroid Build Coastguard Worker const MACROBLOCKD *const xd = &x->e_mbd;
4199*77c1e3ccSAndroid Build Coastguard Worker const MB_MODE_INFO *const mbmi = xd->mi[0];
4200*77c1e3ccSAndroid Build Coastguard Worker const unsigned char segment_id = mbmi->segment_id;
4201*77c1e3ccSAndroid Build Coastguard Worker
4202*77c1e3ccSAndroid Build Coastguard Worker search_state->num_available_refs = 0;
4203*77c1e3ccSAndroid Build Coastguard Worker memset(search_state->dist_refs, -1, sizeof(search_state->dist_refs));
4204*77c1e3ccSAndroid Build Coastguard Worker memset(search_state->dist_order_refs, -1,
4205*77c1e3ccSAndroid Build Coastguard Worker sizeof(search_state->dist_order_refs));
4206*77c1e3ccSAndroid Build Coastguard Worker
4207*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i <= LAST_NEW_MV_INDEX; ++i)
4208*77c1e3ccSAndroid Build Coastguard Worker search_state->mode_threshold[i] = 0;
4209*77c1e3ccSAndroid Build Coastguard Worker const int *const rd_threshes = cpi->rd.threshes[segment_id][bsize];
4210*77c1e3ccSAndroid Build Coastguard Worker for (int i = LAST_NEW_MV_INDEX + 1; i < SINGLE_REF_MODE_END; ++i)
4211*77c1e3ccSAndroid Build Coastguard Worker search_state->mode_threshold[i] =
4212*77c1e3ccSAndroid Build Coastguard Worker ((int64_t)rd_threshes[i] * x->thresh_freq_fact[bsize][i]) >>
4213*77c1e3ccSAndroid Build Coastguard Worker RD_THRESH_FAC_FRAC_BITS;
4214*77c1e3ccSAndroid Build Coastguard Worker
4215*77c1e3ccSAndroid Build Coastguard Worker search_state->best_intra_rd = INT64_MAX;
4216*77c1e3ccSAndroid Build Coastguard Worker
4217*77c1e3ccSAndroid Build Coastguard Worker search_state->best_pred_sse = UINT_MAX;
4218*77c1e3ccSAndroid Build Coastguard Worker
4219*77c1e3ccSAndroid Build Coastguard Worker av1_zero(search_state->single_newmv);
4220*77c1e3ccSAndroid Build Coastguard Worker av1_zero(search_state->single_newmv_rate);
4221*77c1e3ccSAndroid Build Coastguard Worker av1_zero(search_state->single_newmv_valid);
4222*77c1e3ccSAndroid Build Coastguard Worker for (int i = SINGLE_INTER_MODE_START; i < SINGLE_INTER_MODE_END; ++i) {
4223*77c1e3ccSAndroid Build Coastguard Worker for (int j = 0; j < MAX_REF_MV_SEARCH; ++j) {
4224*77c1e3ccSAndroid Build Coastguard Worker for (int ref_frame = 0; ref_frame < REF_FRAMES; ++ref_frame) {
4225*77c1e3ccSAndroid Build Coastguard Worker search_state->modelled_rd[i][j][ref_frame] = INT64_MAX;
4226*77c1e3ccSAndroid Build Coastguard Worker search_state->simple_rd[i][j][ref_frame] = INT64_MAX;
4227*77c1e3ccSAndroid Build Coastguard Worker }
4228*77c1e3ccSAndroid Build Coastguard Worker }
4229*77c1e3ccSAndroid Build Coastguard Worker }
4230*77c1e3ccSAndroid Build Coastguard Worker
4231*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < REFERENCE_MODES; ++i) {
4232*77c1e3ccSAndroid Build Coastguard Worker search_state->best_pred_rd[i] = INT64_MAX;
4233*77c1e3ccSAndroid Build Coastguard Worker }
4234*77c1e3ccSAndroid Build Coastguard Worker
4235*77c1e3ccSAndroid Build Coastguard Worker if (cpi->common.current_frame.reference_mode != SINGLE_REFERENCE) {
4236*77c1e3ccSAndroid Build Coastguard Worker for (int i = SINGLE_REF_MODE_END; i < THR_INTER_MODE_END; ++i)
4237*77c1e3ccSAndroid Build Coastguard Worker search_state->mode_threshold[i] =
4238*77c1e3ccSAndroid Build Coastguard Worker ((int64_t)rd_threshes[i] * x->thresh_freq_fact[bsize][i]) >>
4239*77c1e3ccSAndroid Build Coastguard Worker RD_THRESH_FAC_FRAC_BITS;
4240*77c1e3ccSAndroid Build Coastguard Worker
4241*77c1e3ccSAndroid Build Coastguard Worker for (int i = COMP_INTER_MODE_START; i < COMP_INTER_MODE_END; ++i) {
4242*77c1e3ccSAndroid Build Coastguard Worker for (int j = 0; j < MAX_REF_MV_SEARCH; ++j) {
4243*77c1e3ccSAndroid Build Coastguard Worker for (int ref_frame = 0; ref_frame < REF_FRAMES; ++ref_frame) {
4244*77c1e3ccSAndroid Build Coastguard Worker search_state->modelled_rd[i][j][ref_frame] = INT64_MAX;
4245*77c1e3ccSAndroid Build Coastguard Worker search_state->simple_rd[i][j][ref_frame] = INT64_MAX;
4246*77c1e3ccSAndroid Build Coastguard Worker }
4247*77c1e3ccSAndroid Build Coastguard Worker }
4248*77c1e3ccSAndroid Build Coastguard Worker }
4249*77c1e3ccSAndroid Build Coastguard Worker
4250*77c1e3ccSAndroid Build Coastguard Worker init_single_inter_mode_search_state(search_state);
4251*77c1e3ccSAndroid Build Coastguard Worker }
4252*77c1e3ccSAndroid Build Coastguard Worker }
4253*77c1e3ccSAndroid Build Coastguard Worker
mask_says_skip(const mode_skip_mask_t * mode_skip_mask,const MV_REFERENCE_FRAME * ref_frame,const PREDICTION_MODE this_mode)4254*77c1e3ccSAndroid Build Coastguard Worker static bool mask_says_skip(const mode_skip_mask_t *mode_skip_mask,
4255*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME *ref_frame,
4256*77c1e3ccSAndroid Build Coastguard Worker const PREDICTION_MODE this_mode) {
4257*77c1e3ccSAndroid Build Coastguard Worker if (mode_skip_mask->pred_modes[ref_frame[0]] & (1 << this_mode)) {
4258*77c1e3ccSAndroid Build Coastguard Worker return true;
4259*77c1e3ccSAndroid Build Coastguard Worker }
4260*77c1e3ccSAndroid Build Coastguard Worker
4261*77c1e3ccSAndroid Build Coastguard Worker return mode_skip_mask->ref_combo[ref_frame[0]][ref_frame[1] + 1];
4262*77c1e3ccSAndroid Build Coastguard Worker }
4263*77c1e3ccSAndroid Build Coastguard Worker
inter_mode_compatible_skip(const AV1_COMP * cpi,const MACROBLOCK * x,BLOCK_SIZE bsize,PREDICTION_MODE curr_mode,const MV_REFERENCE_FRAME * ref_frames)4264*77c1e3ccSAndroid Build Coastguard Worker static int inter_mode_compatible_skip(const AV1_COMP *cpi, const MACROBLOCK *x,
4265*77c1e3ccSAndroid Build Coastguard Worker BLOCK_SIZE bsize,
4266*77c1e3ccSAndroid Build Coastguard Worker PREDICTION_MODE curr_mode,
4267*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME *ref_frames) {
4268*77c1e3ccSAndroid Build Coastguard Worker const int comp_pred = ref_frames[1] > INTRA_FRAME;
4269*77c1e3ccSAndroid Build Coastguard Worker if (comp_pred) {
4270*77c1e3ccSAndroid Build Coastguard Worker if (!is_comp_ref_allowed(bsize)) return 1;
4271*77c1e3ccSAndroid Build Coastguard Worker if (!(cpi->ref_frame_flags & av1_ref_frame_flag_list[ref_frames[1]])) {
4272*77c1e3ccSAndroid Build Coastguard Worker return 1;
4273*77c1e3ccSAndroid Build Coastguard Worker }
4274*77c1e3ccSAndroid Build Coastguard Worker
4275*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *const cm = &cpi->common;
4276*77c1e3ccSAndroid Build Coastguard Worker if (frame_is_intra_only(cm)) return 1;
4277*77c1e3ccSAndroid Build Coastguard Worker
4278*77c1e3ccSAndroid Build Coastguard Worker const CurrentFrame *const current_frame = &cm->current_frame;
4279*77c1e3ccSAndroid Build Coastguard Worker if (current_frame->reference_mode == SINGLE_REFERENCE) return 1;
4280*77c1e3ccSAndroid Build Coastguard Worker
4281*77c1e3ccSAndroid Build Coastguard Worker const struct segmentation *const seg = &cm->seg;
4282*77c1e3ccSAndroid Build Coastguard Worker const unsigned char segment_id = x->e_mbd.mi[0]->segment_id;
4283*77c1e3ccSAndroid Build Coastguard Worker // Do not allow compound prediction if the segment level reference frame
4284*77c1e3ccSAndroid Build Coastguard Worker // feature is in use as in this case there can only be one reference.
4285*77c1e3ccSAndroid Build Coastguard Worker if (segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME)) return 1;
4286*77c1e3ccSAndroid Build Coastguard Worker }
4287*77c1e3ccSAndroid Build Coastguard Worker
4288*77c1e3ccSAndroid Build Coastguard Worker if (ref_frames[0] > INTRA_FRAME && ref_frames[1] == INTRA_FRAME) {
4289*77c1e3ccSAndroid Build Coastguard Worker // Mode must be compatible
4290*77c1e3ccSAndroid Build Coastguard Worker if (!is_interintra_allowed_bsize(bsize)) return 1;
4291*77c1e3ccSAndroid Build Coastguard Worker if (!is_interintra_allowed_mode(curr_mode)) return 1;
4292*77c1e3ccSAndroid Build Coastguard Worker }
4293*77c1e3ccSAndroid Build Coastguard Worker
4294*77c1e3ccSAndroid Build Coastguard Worker return 0;
4295*77c1e3ccSAndroid Build Coastguard Worker }
4296*77c1e3ccSAndroid Build Coastguard Worker
fetch_picked_ref_frames_mask(const MACROBLOCK * const x,BLOCK_SIZE bsize,int mib_size)4297*77c1e3ccSAndroid Build Coastguard Worker static int fetch_picked_ref_frames_mask(const MACROBLOCK *const x,
4298*77c1e3ccSAndroid Build Coastguard Worker BLOCK_SIZE bsize, int mib_size) {
4299*77c1e3ccSAndroid Build Coastguard Worker const int sb_size_mask = mib_size - 1;
4300*77c1e3ccSAndroid Build Coastguard Worker const MACROBLOCKD *const xd = &x->e_mbd;
4301*77c1e3ccSAndroid Build Coastguard Worker const int mi_row = xd->mi_row;
4302*77c1e3ccSAndroid Build Coastguard Worker const int mi_col = xd->mi_col;
4303*77c1e3ccSAndroid Build Coastguard Worker const int mi_row_in_sb = mi_row & sb_size_mask;
4304*77c1e3ccSAndroid Build Coastguard Worker const int mi_col_in_sb = mi_col & sb_size_mask;
4305*77c1e3ccSAndroid Build Coastguard Worker const int mi_w = mi_size_wide[bsize];
4306*77c1e3ccSAndroid Build Coastguard Worker const int mi_h = mi_size_high[bsize];
4307*77c1e3ccSAndroid Build Coastguard Worker int picked_ref_frames_mask = 0;
4308*77c1e3ccSAndroid Build Coastguard Worker for (int i = mi_row_in_sb; i < mi_row_in_sb + mi_h; ++i) {
4309*77c1e3ccSAndroid Build Coastguard Worker for (int j = mi_col_in_sb; j < mi_col_in_sb + mi_w; ++j) {
4310*77c1e3ccSAndroid Build Coastguard Worker picked_ref_frames_mask |= x->picked_ref_frames_mask[i * 32 + j];
4311*77c1e3ccSAndroid Build Coastguard Worker }
4312*77c1e3ccSAndroid Build Coastguard Worker }
4313*77c1e3ccSAndroid Build Coastguard Worker return picked_ref_frames_mask;
4314*77c1e3ccSAndroid Build Coastguard Worker }
4315*77c1e3ccSAndroid Build Coastguard Worker
4316*77c1e3ccSAndroid Build Coastguard Worker // Check if reference frame pair of the current block matches with the given
4317*77c1e3ccSAndroid Build Coastguard Worker // block.
match_ref_frame_pair(const MB_MODE_INFO * mbmi,const MV_REFERENCE_FRAME * ref_frames)4318*77c1e3ccSAndroid Build Coastguard Worker static inline int match_ref_frame_pair(const MB_MODE_INFO *mbmi,
4319*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME *ref_frames) {
4320*77c1e3ccSAndroid Build Coastguard Worker return ((ref_frames[0] == mbmi->ref_frame[0]) &&
4321*77c1e3ccSAndroid Build Coastguard Worker (ref_frames[1] == mbmi->ref_frame[1]));
4322*77c1e3ccSAndroid Build Coastguard Worker }
4323*77c1e3ccSAndroid Build Coastguard Worker
4324*77c1e3ccSAndroid Build Coastguard Worker // Case 1: return 0, means don't skip this mode
4325*77c1e3ccSAndroid Build Coastguard Worker // Case 2: return 1, means skip this mode completely
4326*77c1e3ccSAndroid Build Coastguard Worker // Case 3: return 2, means skip compound only, but still try single motion modes
inter_mode_search_order_independent_skip(const AV1_COMP * cpi,const MACROBLOCK * x,mode_skip_mask_t * mode_skip_mask,InterModeSearchState * search_state,int skip_ref_frame_mask,PREDICTION_MODE mode,const MV_REFERENCE_FRAME * ref_frame)4327*77c1e3ccSAndroid Build Coastguard Worker static int inter_mode_search_order_independent_skip(
4328*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMP *cpi, const MACROBLOCK *x, mode_skip_mask_t *mode_skip_mask,
4329*77c1e3ccSAndroid Build Coastguard Worker InterModeSearchState *search_state, int skip_ref_frame_mask,
4330*77c1e3ccSAndroid Build Coastguard Worker PREDICTION_MODE mode, const MV_REFERENCE_FRAME *ref_frame) {
4331*77c1e3ccSAndroid Build Coastguard Worker if (mask_says_skip(mode_skip_mask, ref_frame, mode)) {
4332*77c1e3ccSAndroid Build Coastguard Worker return 1;
4333*77c1e3ccSAndroid Build Coastguard Worker }
4334*77c1e3ccSAndroid Build Coastguard Worker
4335*77c1e3ccSAndroid Build Coastguard Worker const int ref_type = av1_ref_frame_type(ref_frame);
4336*77c1e3ccSAndroid Build Coastguard Worker if (!cpi->sf.rt_sf.use_real_time_ref_set)
4337*77c1e3ccSAndroid Build Coastguard Worker if (prune_ref_frame(cpi, x, ref_type)) return 1;
4338*77c1e3ccSAndroid Build Coastguard Worker
4339*77c1e3ccSAndroid Build Coastguard Worker // This is only used in motion vector unit test.
4340*77c1e3ccSAndroid Build Coastguard Worker if (cpi->oxcf.unit_test_cfg.motion_vector_unit_test &&
4341*77c1e3ccSAndroid Build Coastguard Worker ref_frame[0] == INTRA_FRAME)
4342*77c1e3ccSAndroid Build Coastguard Worker return 1;
4343*77c1e3ccSAndroid Build Coastguard Worker
4344*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *const cm = &cpi->common;
4345*77c1e3ccSAndroid Build Coastguard Worker if (skip_repeated_mv(cm, x, mode, ref_frame, search_state)) {
4346*77c1e3ccSAndroid Build Coastguard Worker return 1;
4347*77c1e3ccSAndroid Build Coastguard Worker }
4348*77c1e3ccSAndroid Build Coastguard Worker
4349*77c1e3ccSAndroid Build Coastguard Worker // Reuse the prediction mode in cache
4350*77c1e3ccSAndroid Build Coastguard Worker if (x->use_mb_mode_cache) {
4351*77c1e3ccSAndroid Build Coastguard Worker const MB_MODE_INFO *cached_mi = x->mb_mode_cache;
4352*77c1e3ccSAndroid Build Coastguard Worker const PREDICTION_MODE cached_mode = cached_mi->mode;
4353*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME *cached_frame = cached_mi->ref_frame;
4354*77c1e3ccSAndroid Build Coastguard Worker const int cached_mode_is_single = cached_frame[1] <= INTRA_FRAME;
4355*77c1e3ccSAndroid Build Coastguard Worker
4356*77c1e3ccSAndroid Build Coastguard Worker // If the cached mode is intra, then we just need to match the mode.
4357*77c1e3ccSAndroid Build Coastguard Worker if (is_mode_intra(cached_mode) && mode != cached_mode) {
4358*77c1e3ccSAndroid Build Coastguard Worker return 1;
4359*77c1e3ccSAndroid Build Coastguard Worker }
4360*77c1e3ccSAndroid Build Coastguard Worker
4361*77c1e3ccSAndroid Build Coastguard Worker // If the cached mode is single inter mode, then we match the mode and
4362*77c1e3ccSAndroid Build Coastguard Worker // reference frame.
4363*77c1e3ccSAndroid Build Coastguard Worker if (cached_mode_is_single) {
4364*77c1e3ccSAndroid Build Coastguard Worker if (mode != cached_mode || ref_frame[0] != cached_frame[0]) {
4365*77c1e3ccSAndroid Build Coastguard Worker return 1;
4366*77c1e3ccSAndroid Build Coastguard Worker }
4367*77c1e3ccSAndroid Build Coastguard Worker } else {
4368*77c1e3ccSAndroid Build Coastguard Worker // If the cached mode is compound, then we need to consider several cases.
4369*77c1e3ccSAndroid Build Coastguard Worker const int mode_is_single = ref_frame[1] <= INTRA_FRAME;
4370*77c1e3ccSAndroid Build Coastguard Worker if (mode_is_single) {
4371*77c1e3ccSAndroid Build Coastguard Worker // If the mode is single, we know the modes can't match. But we might
4372*77c1e3ccSAndroid Build Coastguard Worker // still want to search it if compound mode depends on the current mode.
4373*77c1e3ccSAndroid Build Coastguard Worker int skip_motion_mode_only = 0;
4374*77c1e3ccSAndroid Build Coastguard Worker if (cached_mode == NEW_NEARMV || cached_mode == NEW_NEARESTMV) {
4375*77c1e3ccSAndroid Build Coastguard Worker skip_motion_mode_only = (ref_frame[0] == cached_frame[0]);
4376*77c1e3ccSAndroid Build Coastguard Worker } else if (cached_mode == NEAR_NEWMV || cached_mode == NEAREST_NEWMV) {
4377*77c1e3ccSAndroid Build Coastguard Worker skip_motion_mode_only = (ref_frame[0] == cached_frame[1]);
4378*77c1e3ccSAndroid Build Coastguard Worker } else if (cached_mode == NEW_NEWMV) {
4379*77c1e3ccSAndroid Build Coastguard Worker skip_motion_mode_only = (ref_frame[0] == cached_frame[0] ||
4380*77c1e3ccSAndroid Build Coastguard Worker ref_frame[0] == cached_frame[1]);
4381*77c1e3ccSAndroid Build Coastguard Worker }
4382*77c1e3ccSAndroid Build Coastguard Worker
4383*77c1e3ccSAndroid Build Coastguard Worker return 1 + skip_motion_mode_only;
4384*77c1e3ccSAndroid Build Coastguard Worker } else {
4385*77c1e3ccSAndroid Build Coastguard Worker // If both modes are compound, then everything must match.
4386*77c1e3ccSAndroid Build Coastguard Worker if (mode != cached_mode || ref_frame[0] != cached_frame[0] ||
4387*77c1e3ccSAndroid Build Coastguard Worker ref_frame[1] != cached_frame[1]) {
4388*77c1e3ccSAndroid Build Coastguard Worker return 1;
4389*77c1e3ccSAndroid Build Coastguard Worker }
4390*77c1e3ccSAndroid Build Coastguard Worker }
4391*77c1e3ccSAndroid Build Coastguard Worker }
4392*77c1e3ccSAndroid Build Coastguard Worker }
4393*77c1e3ccSAndroid Build Coastguard Worker
4394*77c1e3ccSAndroid Build Coastguard Worker const MB_MODE_INFO *const mbmi = x->e_mbd.mi[0];
4395*77c1e3ccSAndroid Build Coastguard Worker // If no valid mode has been found so far in PARTITION_NONE when finding a
4396*77c1e3ccSAndroid Build Coastguard Worker // valid partition is required, do not skip mode.
4397*77c1e3ccSAndroid Build Coastguard Worker if (search_state->best_rd == INT64_MAX && mbmi->partition == PARTITION_NONE &&
4398*77c1e3ccSAndroid Build Coastguard Worker x->must_find_valid_partition)
4399*77c1e3ccSAndroid Build Coastguard Worker return 0;
4400*77c1e3ccSAndroid Build Coastguard Worker
4401*77c1e3ccSAndroid Build Coastguard Worker const SPEED_FEATURES *const sf = &cpi->sf;
4402*77c1e3ccSAndroid Build Coastguard Worker // Prune NEARMV and NEAR_NEARMV based on q index and neighbor's reference
4403*77c1e3ccSAndroid Build Coastguard Worker // frames
4404*77c1e3ccSAndroid Build Coastguard Worker if (sf->inter_sf.prune_nearmv_using_neighbors &&
4405*77c1e3ccSAndroid Build Coastguard Worker (mode == NEAR_NEARMV || mode == NEARMV)) {
4406*77c1e3ccSAndroid Build Coastguard Worker const MACROBLOCKD *const xd = &x->e_mbd;
4407*77c1e3ccSAndroid Build Coastguard Worker if (search_state->best_rd != INT64_MAX && xd->left_available &&
4408*77c1e3ccSAndroid Build Coastguard Worker xd->up_available) {
4409*77c1e3ccSAndroid Build Coastguard Worker const int thresholds[PRUNE_NEARMV_MAX][3] = { { 1, 0, 0 },
4410*77c1e3ccSAndroid Build Coastguard Worker { 1, 1, 0 },
4411*77c1e3ccSAndroid Build Coastguard Worker { 2, 1, 0 } };
4412*77c1e3ccSAndroid Build Coastguard Worker const int qindex_sub_range = x->qindex * 3 / QINDEX_RANGE;
4413*77c1e3ccSAndroid Build Coastguard Worker
4414*77c1e3ccSAndroid Build Coastguard Worker assert(sf->inter_sf.prune_nearmv_using_neighbors <= PRUNE_NEARMV_MAX &&
4415*77c1e3ccSAndroid Build Coastguard Worker qindex_sub_range < 3);
4416*77c1e3ccSAndroid Build Coastguard Worker const int num_ref_frame_pair_match_thresh =
4417*77c1e3ccSAndroid Build Coastguard Worker thresholds[sf->inter_sf.prune_nearmv_using_neighbors - 1]
4418*77c1e3ccSAndroid Build Coastguard Worker [qindex_sub_range];
4419*77c1e3ccSAndroid Build Coastguard Worker
4420*77c1e3ccSAndroid Build Coastguard Worker assert(num_ref_frame_pair_match_thresh <= 2 &&
4421*77c1e3ccSAndroid Build Coastguard Worker num_ref_frame_pair_match_thresh >= 0);
4422*77c1e3ccSAndroid Build Coastguard Worker int num_ref_frame_pair_match = 0;
4423*77c1e3ccSAndroid Build Coastguard Worker
4424*77c1e3ccSAndroid Build Coastguard Worker num_ref_frame_pair_match = match_ref_frame_pair(xd->left_mbmi, ref_frame);
4425*77c1e3ccSAndroid Build Coastguard Worker num_ref_frame_pair_match +=
4426*77c1e3ccSAndroid Build Coastguard Worker match_ref_frame_pair(xd->above_mbmi, ref_frame);
4427*77c1e3ccSAndroid Build Coastguard Worker
4428*77c1e3ccSAndroid Build Coastguard Worker // Pruning based on ref frame pair match with neighbors.
4429*77c1e3ccSAndroid Build Coastguard Worker if (num_ref_frame_pair_match < num_ref_frame_pair_match_thresh) return 1;
4430*77c1e3ccSAndroid Build Coastguard Worker }
4431*77c1e3ccSAndroid Build Coastguard Worker }
4432*77c1e3ccSAndroid Build Coastguard Worker
4433*77c1e3ccSAndroid Build Coastguard Worker int skip_motion_mode = 0;
4434*77c1e3ccSAndroid Build Coastguard Worker if (mbmi->partition != PARTITION_NONE) {
4435*77c1e3ccSAndroid Build Coastguard Worker int skip_ref = skip_ref_frame_mask & (1 << ref_type);
4436*77c1e3ccSAndroid Build Coastguard Worker if (ref_type <= ALTREF_FRAME && skip_ref) {
4437*77c1e3ccSAndroid Build Coastguard Worker // Since the compound ref modes depends on the motion estimation result of
4438*77c1e3ccSAndroid Build Coastguard Worker // two single ref modes (best mv of single ref modes as the start point),
4439*77c1e3ccSAndroid Build Coastguard Worker // if current single ref mode is marked skip, we need to check if it will
4440*77c1e3ccSAndroid Build Coastguard Worker // be used in compound ref modes.
4441*77c1e3ccSAndroid Build Coastguard Worker if (is_ref_frame_used_by_compound_ref(ref_type, skip_ref_frame_mask)) {
4442*77c1e3ccSAndroid Build Coastguard Worker // Found a not skipped compound ref mode which contains current
4443*77c1e3ccSAndroid Build Coastguard Worker // single ref. So this single ref can't be skipped completely
4444*77c1e3ccSAndroid Build Coastguard Worker // Just skip its motion mode search, still try its simple
4445*77c1e3ccSAndroid Build Coastguard Worker // transition mode.
4446*77c1e3ccSAndroid Build Coastguard Worker skip_motion_mode = 1;
4447*77c1e3ccSAndroid Build Coastguard Worker skip_ref = 0;
4448*77c1e3ccSAndroid Build Coastguard Worker }
4449*77c1e3ccSAndroid Build Coastguard Worker }
4450*77c1e3ccSAndroid Build Coastguard Worker // If we are reusing the prediction from cache, and the current frame is
4451*77c1e3ccSAndroid Build Coastguard Worker // required by the cache, then we cannot prune it.
4452*77c1e3ccSAndroid Build Coastguard Worker if (is_ref_frame_used_in_cache(ref_type, x->mb_mode_cache)) {
4453*77c1e3ccSAndroid Build Coastguard Worker skip_ref = 0;
4454*77c1e3ccSAndroid Build Coastguard Worker // If the cache only needs the current reference type for compound
4455*77c1e3ccSAndroid Build Coastguard Worker // prediction, then we can skip motion mode search.
4456*77c1e3ccSAndroid Build Coastguard Worker skip_motion_mode = (ref_type <= ALTREF_FRAME &&
4457*77c1e3ccSAndroid Build Coastguard Worker x->mb_mode_cache->ref_frame[1] > INTRA_FRAME);
4458*77c1e3ccSAndroid Build Coastguard Worker }
4459*77c1e3ccSAndroid Build Coastguard Worker if (skip_ref) return 1;
4460*77c1e3ccSAndroid Build Coastguard Worker }
4461*77c1e3ccSAndroid Build Coastguard Worker
4462*77c1e3ccSAndroid Build Coastguard Worker if (ref_frame[0] == INTRA_FRAME) {
4463*77c1e3ccSAndroid Build Coastguard Worker if (mode != DC_PRED) {
4464*77c1e3ccSAndroid Build Coastguard Worker // Disable intra modes other than DC_PRED for blocks with low variance
4465*77c1e3ccSAndroid Build Coastguard Worker // Threshold for intra skipping based on source variance
4466*77c1e3ccSAndroid Build Coastguard Worker // TODO(debargha): Specialize the threshold for super block sizes
4467*77c1e3ccSAndroid Build Coastguard Worker const unsigned int skip_intra_var_thresh = 64;
4468*77c1e3ccSAndroid Build Coastguard Worker if ((sf->rt_sf.mode_search_skip_flags & FLAG_SKIP_INTRA_LOWVAR) &&
4469*77c1e3ccSAndroid Build Coastguard Worker x->source_variance < skip_intra_var_thresh)
4470*77c1e3ccSAndroid Build Coastguard Worker return 1;
4471*77c1e3ccSAndroid Build Coastguard Worker }
4472*77c1e3ccSAndroid Build Coastguard Worker }
4473*77c1e3ccSAndroid Build Coastguard Worker
4474*77c1e3ccSAndroid Build Coastguard Worker if (skip_motion_mode) return 2;
4475*77c1e3ccSAndroid Build Coastguard Worker
4476*77c1e3ccSAndroid Build Coastguard Worker return 0;
4477*77c1e3ccSAndroid Build Coastguard Worker }
4478*77c1e3ccSAndroid Build Coastguard Worker
init_mbmi(MB_MODE_INFO * mbmi,PREDICTION_MODE curr_mode,const MV_REFERENCE_FRAME * ref_frames,const AV1_COMMON * cm)4479*77c1e3ccSAndroid Build Coastguard Worker static inline void init_mbmi(MB_MODE_INFO *mbmi, PREDICTION_MODE curr_mode,
4480*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME *ref_frames,
4481*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *cm) {
4482*77c1e3ccSAndroid Build Coastguard Worker PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
4483*77c1e3ccSAndroid Build Coastguard Worker mbmi->ref_mv_idx = 0;
4484*77c1e3ccSAndroid Build Coastguard Worker mbmi->mode = curr_mode;
4485*77c1e3ccSAndroid Build Coastguard Worker mbmi->uv_mode = UV_DC_PRED;
4486*77c1e3ccSAndroid Build Coastguard Worker mbmi->ref_frame[0] = ref_frames[0];
4487*77c1e3ccSAndroid Build Coastguard Worker mbmi->ref_frame[1] = ref_frames[1];
4488*77c1e3ccSAndroid Build Coastguard Worker pmi->palette_size[0] = 0;
4489*77c1e3ccSAndroid Build Coastguard Worker pmi->palette_size[1] = 0;
4490*77c1e3ccSAndroid Build Coastguard Worker mbmi->filter_intra_mode_info.use_filter_intra = 0;
4491*77c1e3ccSAndroid Build Coastguard Worker mbmi->mv[0].as_int = mbmi->mv[1].as_int = 0;
4492*77c1e3ccSAndroid Build Coastguard Worker mbmi->motion_mode = SIMPLE_TRANSLATION;
4493*77c1e3ccSAndroid Build Coastguard Worker mbmi->interintra_mode = (INTERINTRA_MODE)(II_DC_PRED - 1);
4494*77c1e3ccSAndroid Build Coastguard Worker set_default_interp_filters(mbmi, cm->features.interp_filter);
4495*77c1e3ccSAndroid Build Coastguard Worker }
4496*77c1e3ccSAndroid Build Coastguard Worker
collect_single_states(MACROBLOCK * x,InterModeSearchState * search_state,const MB_MODE_INFO * const mbmi)4497*77c1e3ccSAndroid Build Coastguard Worker static inline void collect_single_states(MACROBLOCK *x,
4498*77c1e3ccSAndroid Build Coastguard Worker InterModeSearchState *search_state,
4499*77c1e3ccSAndroid Build Coastguard Worker const MB_MODE_INFO *const mbmi) {
4500*77c1e3ccSAndroid Build Coastguard Worker int i, j;
4501*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME ref_frame = mbmi->ref_frame[0];
4502*77c1e3ccSAndroid Build Coastguard Worker const PREDICTION_MODE this_mode = mbmi->mode;
4503*77c1e3ccSAndroid Build Coastguard Worker const int dir = ref_frame <= GOLDEN_FRAME ? 0 : 1;
4504*77c1e3ccSAndroid Build Coastguard Worker const int mode_offset = INTER_OFFSET(this_mode);
4505*77c1e3ccSAndroid Build Coastguard Worker const int ref_set = get_drl_refmv_count(x, mbmi->ref_frame, this_mode);
4506*77c1e3ccSAndroid Build Coastguard Worker
4507*77c1e3ccSAndroid Build Coastguard Worker // Simple rd
4508*77c1e3ccSAndroid Build Coastguard Worker int64_t simple_rd = search_state->simple_rd[this_mode][0][ref_frame];
4509*77c1e3ccSAndroid Build Coastguard Worker for (int ref_mv_idx = 1; ref_mv_idx < ref_set; ++ref_mv_idx) {
4510*77c1e3ccSAndroid Build Coastguard Worker const int64_t rd =
4511*77c1e3ccSAndroid Build Coastguard Worker search_state->simple_rd[this_mode][ref_mv_idx][ref_frame];
4512*77c1e3ccSAndroid Build Coastguard Worker if (rd < simple_rd) simple_rd = rd;
4513*77c1e3ccSAndroid Build Coastguard Worker }
4514*77c1e3ccSAndroid Build Coastguard Worker
4515*77c1e3ccSAndroid Build Coastguard Worker // Insertion sort of single_state
4516*77c1e3ccSAndroid Build Coastguard Worker const SingleInterModeState this_state_s = { simple_rd, ref_frame, 1 };
4517*77c1e3ccSAndroid Build Coastguard Worker SingleInterModeState *state_s = search_state->single_state[dir][mode_offset];
4518*77c1e3ccSAndroid Build Coastguard Worker i = search_state->single_state_cnt[dir][mode_offset];
4519*77c1e3ccSAndroid Build Coastguard Worker for (j = i; j > 0 && state_s[j - 1].rd > this_state_s.rd; --j)
4520*77c1e3ccSAndroid Build Coastguard Worker state_s[j] = state_s[j - 1];
4521*77c1e3ccSAndroid Build Coastguard Worker state_s[j] = this_state_s;
4522*77c1e3ccSAndroid Build Coastguard Worker search_state->single_state_cnt[dir][mode_offset]++;
4523*77c1e3ccSAndroid Build Coastguard Worker
4524*77c1e3ccSAndroid Build Coastguard Worker // Modelled rd
4525*77c1e3ccSAndroid Build Coastguard Worker int64_t modelled_rd = search_state->modelled_rd[this_mode][0][ref_frame];
4526*77c1e3ccSAndroid Build Coastguard Worker for (int ref_mv_idx = 1; ref_mv_idx < ref_set; ++ref_mv_idx) {
4527*77c1e3ccSAndroid Build Coastguard Worker const int64_t rd =
4528*77c1e3ccSAndroid Build Coastguard Worker search_state->modelled_rd[this_mode][ref_mv_idx][ref_frame];
4529*77c1e3ccSAndroid Build Coastguard Worker if (rd < modelled_rd) modelled_rd = rd;
4530*77c1e3ccSAndroid Build Coastguard Worker }
4531*77c1e3ccSAndroid Build Coastguard Worker
4532*77c1e3ccSAndroid Build Coastguard Worker // Insertion sort of single_state_modelled
4533*77c1e3ccSAndroid Build Coastguard Worker const SingleInterModeState this_state_m = { modelled_rd, ref_frame, 1 };
4534*77c1e3ccSAndroid Build Coastguard Worker SingleInterModeState *state_m =
4535*77c1e3ccSAndroid Build Coastguard Worker search_state->single_state_modelled[dir][mode_offset];
4536*77c1e3ccSAndroid Build Coastguard Worker i = search_state->single_state_modelled_cnt[dir][mode_offset];
4537*77c1e3ccSAndroid Build Coastguard Worker for (j = i; j > 0 && state_m[j - 1].rd > this_state_m.rd; --j)
4538*77c1e3ccSAndroid Build Coastguard Worker state_m[j] = state_m[j - 1];
4539*77c1e3ccSAndroid Build Coastguard Worker state_m[j] = this_state_m;
4540*77c1e3ccSAndroid Build Coastguard Worker search_state->single_state_modelled_cnt[dir][mode_offset]++;
4541*77c1e3ccSAndroid Build Coastguard Worker }
4542*77c1e3ccSAndroid Build Coastguard Worker
analyze_single_states(const AV1_COMP * cpi,InterModeSearchState * search_state)4543*77c1e3ccSAndroid Build Coastguard Worker static inline void analyze_single_states(const AV1_COMP *cpi,
4544*77c1e3ccSAndroid Build Coastguard Worker InterModeSearchState *search_state) {
4545*77c1e3ccSAndroid Build Coastguard Worker const int prune_level = cpi->sf.inter_sf.prune_comp_search_by_single_result;
4546*77c1e3ccSAndroid Build Coastguard Worker assert(prune_level >= 1);
4547*77c1e3ccSAndroid Build Coastguard Worker int i, j, dir, mode;
4548*77c1e3ccSAndroid Build Coastguard Worker
4549*77c1e3ccSAndroid Build Coastguard Worker for (dir = 0; dir < 2; ++dir) {
4550*77c1e3ccSAndroid Build Coastguard Worker int64_t best_rd;
4551*77c1e3ccSAndroid Build Coastguard Worker SingleInterModeState(*state)[FWD_REFS];
4552*77c1e3ccSAndroid Build Coastguard Worker const int prune_factor = prune_level >= 2 ? 6 : 5;
4553*77c1e3ccSAndroid Build Coastguard Worker
4554*77c1e3ccSAndroid Build Coastguard Worker // Use the best rd of GLOBALMV or NEWMV to prune the unlikely
4555*77c1e3ccSAndroid Build Coastguard Worker // reference frames for all the modes (NEARESTMV and NEARMV may not
4556*77c1e3ccSAndroid Build Coastguard Worker // have same motion vectors). Always keep the best of each mode
4557*77c1e3ccSAndroid Build Coastguard Worker // because it might form the best possible combination with other mode.
4558*77c1e3ccSAndroid Build Coastguard Worker state = search_state->single_state[dir];
4559*77c1e3ccSAndroid Build Coastguard Worker best_rd = AOMMIN(state[INTER_OFFSET(NEWMV)][0].rd,
4560*77c1e3ccSAndroid Build Coastguard Worker state[INTER_OFFSET(GLOBALMV)][0].rd);
4561*77c1e3ccSAndroid Build Coastguard Worker for (mode = 0; mode < SINGLE_INTER_MODE_NUM; ++mode) {
4562*77c1e3ccSAndroid Build Coastguard Worker for (i = 1; i < search_state->single_state_cnt[dir][mode]; ++i) {
4563*77c1e3ccSAndroid Build Coastguard Worker if (state[mode][i].rd != INT64_MAX &&
4564*77c1e3ccSAndroid Build Coastguard Worker (state[mode][i].rd >> 3) * prune_factor > best_rd) {
4565*77c1e3ccSAndroid Build Coastguard Worker state[mode][i].valid = 0;
4566*77c1e3ccSAndroid Build Coastguard Worker }
4567*77c1e3ccSAndroid Build Coastguard Worker }
4568*77c1e3ccSAndroid Build Coastguard Worker }
4569*77c1e3ccSAndroid Build Coastguard Worker
4570*77c1e3ccSAndroid Build Coastguard Worker state = search_state->single_state_modelled[dir];
4571*77c1e3ccSAndroid Build Coastguard Worker best_rd = AOMMIN(state[INTER_OFFSET(NEWMV)][0].rd,
4572*77c1e3ccSAndroid Build Coastguard Worker state[INTER_OFFSET(GLOBALMV)][0].rd);
4573*77c1e3ccSAndroid Build Coastguard Worker for (mode = 0; mode < SINGLE_INTER_MODE_NUM; ++mode) {
4574*77c1e3ccSAndroid Build Coastguard Worker for (i = 1; i < search_state->single_state_modelled_cnt[dir][mode]; ++i) {
4575*77c1e3ccSAndroid Build Coastguard Worker if (state[mode][i].rd != INT64_MAX &&
4576*77c1e3ccSAndroid Build Coastguard Worker (state[mode][i].rd >> 3) * prune_factor > best_rd) {
4577*77c1e3ccSAndroid Build Coastguard Worker state[mode][i].valid = 0;
4578*77c1e3ccSAndroid Build Coastguard Worker }
4579*77c1e3ccSAndroid Build Coastguard Worker }
4580*77c1e3ccSAndroid Build Coastguard Worker }
4581*77c1e3ccSAndroid Build Coastguard Worker }
4582*77c1e3ccSAndroid Build Coastguard Worker
4583*77c1e3ccSAndroid Build Coastguard Worker // Ordering by simple rd first, then by modelled rd
4584*77c1e3ccSAndroid Build Coastguard Worker for (dir = 0; dir < 2; ++dir) {
4585*77c1e3ccSAndroid Build Coastguard Worker for (mode = 0; mode < SINGLE_INTER_MODE_NUM; ++mode) {
4586*77c1e3ccSAndroid Build Coastguard Worker const int state_cnt_s = search_state->single_state_cnt[dir][mode];
4587*77c1e3ccSAndroid Build Coastguard Worker const int state_cnt_m =
4588*77c1e3ccSAndroid Build Coastguard Worker search_state->single_state_modelled_cnt[dir][mode];
4589*77c1e3ccSAndroid Build Coastguard Worker SingleInterModeState *state_s = search_state->single_state[dir][mode];
4590*77c1e3ccSAndroid Build Coastguard Worker SingleInterModeState *state_m =
4591*77c1e3ccSAndroid Build Coastguard Worker search_state->single_state_modelled[dir][mode];
4592*77c1e3ccSAndroid Build Coastguard Worker int count = 0;
4593*77c1e3ccSAndroid Build Coastguard Worker const int max_candidates = AOMMAX(state_cnt_s, state_cnt_m);
4594*77c1e3ccSAndroid Build Coastguard Worker for (i = 0; i < state_cnt_s; ++i) {
4595*77c1e3ccSAndroid Build Coastguard Worker if (state_s[i].rd == INT64_MAX) break;
4596*77c1e3ccSAndroid Build Coastguard Worker if (state_s[i].valid) {
4597*77c1e3ccSAndroid Build Coastguard Worker search_state->single_rd_order[dir][mode][count++] =
4598*77c1e3ccSAndroid Build Coastguard Worker state_s[i].ref_frame;
4599*77c1e3ccSAndroid Build Coastguard Worker }
4600*77c1e3ccSAndroid Build Coastguard Worker }
4601*77c1e3ccSAndroid Build Coastguard Worker if (count >= max_candidates) continue;
4602*77c1e3ccSAndroid Build Coastguard Worker
4603*77c1e3ccSAndroid Build Coastguard Worker for (i = 0; i < state_cnt_m && count < max_candidates; ++i) {
4604*77c1e3ccSAndroid Build Coastguard Worker if (state_m[i].rd == INT64_MAX) break;
4605*77c1e3ccSAndroid Build Coastguard Worker if (!state_m[i].valid) continue;
4606*77c1e3ccSAndroid Build Coastguard Worker const int ref_frame = state_m[i].ref_frame;
4607*77c1e3ccSAndroid Build Coastguard Worker int match = 0;
4608*77c1e3ccSAndroid Build Coastguard Worker // Check if existing already
4609*77c1e3ccSAndroid Build Coastguard Worker for (j = 0; j < count; ++j) {
4610*77c1e3ccSAndroid Build Coastguard Worker if (search_state->single_rd_order[dir][mode][j] == ref_frame) {
4611*77c1e3ccSAndroid Build Coastguard Worker match = 1;
4612*77c1e3ccSAndroid Build Coastguard Worker break;
4613*77c1e3ccSAndroid Build Coastguard Worker }
4614*77c1e3ccSAndroid Build Coastguard Worker }
4615*77c1e3ccSAndroid Build Coastguard Worker if (match) continue;
4616*77c1e3ccSAndroid Build Coastguard Worker // Check if this ref_frame is removed in simple rd
4617*77c1e3ccSAndroid Build Coastguard Worker int valid = 1;
4618*77c1e3ccSAndroid Build Coastguard Worker for (j = 0; j < state_cnt_s; ++j) {
4619*77c1e3ccSAndroid Build Coastguard Worker if (ref_frame == state_s[j].ref_frame) {
4620*77c1e3ccSAndroid Build Coastguard Worker valid = state_s[j].valid;
4621*77c1e3ccSAndroid Build Coastguard Worker break;
4622*77c1e3ccSAndroid Build Coastguard Worker }
4623*77c1e3ccSAndroid Build Coastguard Worker }
4624*77c1e3ccSAndroid Build Coastguard Worker if (valid) {
4625*77c1e3ccSAndroid Build Coastguard Worker search_state->single_rd_order[dir][mode][count++] = ref_frame;
4626*77c1e3ccSAndroid Build Coastguard Worker }
4627*77c1e3ccSAndroid Build Coastguard Worker }
4628*77c1e3ccSAndroid Build Coastguard Worker }
4629*77c1e3ccSAndroid Build Coastguard Worker }
4630*77c1e3ccSAndroid Build Coastguard Worker }
4631*77c1e3ccSAndroid Build Coastguard Worker
compound_skip_get_candidates(const AV1_COMP * cpi,const InterModeSearchState * search_state,const int dir,const PREDICTION_MODE mode)4632*77c1e3ccSAndroid Build Coastguard Worker static int compound_skip_get_candidates(
4633*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMP *cpi, const InterModeSearchState *search_state,
4634*77c1e3ccSAndroid Build Coastguard Worker const int dir, const PREDICTION_MODE mode) {
4635*77c1e3ccSAndroid Build Coastguard Worker const int mode_offset = INTER_OFFSET(mode);
4636*77c1e3ccSAndroid Build Coastguard Worker const SingleInterModeState *state =
4637*77c1e3ccSAndroid Build Coastguard Worker search_state->single_state[dir][mode_offset];
4638*77c1e3ccSAndroid Build Coastguard Worker const SingleInterModeState *state_modelled =
4639*77c1e3ccSAndroid Build Coastguard Worker search_state->single_state_modelled[dir][mode_offset];
4640*77c1e3ccSAndroid Build Coastguard Worker
4641*77c1e3ccSAndroid Build Coastguard Worker int max_candidates = 0;
4642*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < FWD_REFS; ++i) {
4643*77c1e3ccSAndroid Build Coastguard Worker if (search_state->single_rd_order[dir][mode_offset][i] == NONE_FRAME) break;
4644*77c1e3ccSAndroid Build Coastguard Worker max_candidates++;
4645*77c1e3ccSAndroid Build Coastguard Worker }
4646*77c1e3ccSAndroid Build Coastguard Worker
4647*77c1e3ccSAndroid Build Coastguard Worker int candidates = max_candidates;
4648*77c1e3ccSAndroid Build Coastguard Worker if (cpi->sf.inter_sf.prune_comp_search_by_single_result >= 2) {
4649*77c1e3ccSAndroid Build Coastguard Worker candidates = AOMMIN(2, max_candidates);
4650*77c1e3ccSAndroid Build Coastguard Worker }
4651*77c1e3ccSAndroid Build Coastguard Worker if (cpi->sf.inter_sf.prune_comp_search_by_single_result >= 3) {
4652*77c1e3ccSAndroid Build Coastguard Worker if (state[0].rd != INT64_MAX && state_modelled[0].rd != INT64_MAX &&
4653*77c1e3ccSAndroid Build Coastguard Worker state[0].ref_frame == state_modelled[0].ref_frame)
4654*77c1e3ccSAndroid Build Coastguard Worker candidates = 1;
4655*77c1e3ccSAndroid Build Coastguard Worker if (mode == NEARMV || mode == GLOBALMV) candidates = 1;
4656*77c1e3ccSAndroid Build Coastguard Worker }
4657*77c1e3ccSAndroid Build Coastguard Worker
4658*77c1e3ccSAndroid Build Coastguard Worker if (cpi->sf.inter_sf.prune_comp_search_by_single_result >= 4) {
4659*77c1e3ccSAndroid Build Coastguard Worker // Limit the number of candidates to 1 in each direction for compound
4660*77c1e3ccSAndroid Build Coastguard Worker // prediction
4661*77c1e3ccSAndroid Build Coastguard Worker candidates = AOMMIN(1, candidates);
4662*77c1e3ccSAndroid Build Coastguard Worker }
4663*77c1e3ccSAndroid Build Coastguard Worker return candidates;
4664*77c1e3ccSAndroid Build Coastguard Worker }
4665*77c1e3ccSAndroid Build Coastguard Worker
compound_skip_by_single_states(const AV1_COMP * cpi,const InterModeSearchState * search_state,const PREDICTION_MODE this_mode,const MV_REFERENCE_FRAME ref_frame,const MV_REFERENCE_FRAME second_ref_frame,const MACROBLOCK * x)4666*77c1e3ccSAndroid Build Coastguard Worker static int compound_skip_by_single_states(
4667*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMP *cpi, const InterModeSearchState *search_state,
4668*77c1e3ccSAndroid Build Coastguard Worker const PREDICTION_MODE this_mode, const MV_REFERENCE_FRAME ref_frame,
4669*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME second_ref_frame, const MACROBLOCK *x) {
4670*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME refs[2] = { ref_frame, second_ref_frame };
4671*77c1e3ccSAndroid Build Coastguard Worker const int mode[2] = { compound_ref0_mode(this_mode),
4672*77c1e3ccSAndroid Build Coastguard Worker compound_ref1_mode(this_mode) };
4673*77c1e3ccSAndroid Build Coastguard Worker const int mode_offset[2] = { INTER_OFFSET(mode[0]), INTER_OFFSET(mode[1]) };
4674*77c1e3ccSAndroid Build Coastguard Worker const int mode_dir[2] = { refs[0] <= GOLDEN_FRAME ? 0 : 1,
4675*77c1e3ccSAndroid Build Coastguard Worker refs[1] <= GOLDEN_FRAME ? 0 : 1 };
4676*77c1e3ccSAndroid Build Coastguard Worker int ref_searched[2] = { 0, 0 };
4677*77c1e3ccSAndroid Build Coastguard Worker int ref_mv_match[2] = { 1, 1 };
4678*77c1e3ccSAndroid Build Coastguard Worker int i, j;
4679*77c1e3ccSAndroid Build Coastguard Worker
4680*77c1e3ccSAndroid Build Coastguard Worker for (i = 0; i < 2; ++i) {
4681*77c1e3ccSAndroid Build Coastguard Worker const SingleInterModeState *state =
4682*77c1e3ccSAndroid Build Coastguard Worker search_state->single_state[mode_dir[i]][mode_offset[i]];
4683*77c1e3ccSAndroid Build Coastguard Worker const int state_cnt =
4684*77c1e3ccSAndroid Build Coastguard Worker search_state->single_state_cnt[mode_dir[i]][mode_offset[i]];
4685*77c1e3ccSAndroid Build Coastguard Worker for (j = 0; j < state_cnt; ++j) {
4686*77c1e3ccSAndroid Build Coastguard Worker if (state[j].ref_frame == refs[i]) {
4687*77c1e3ccSAndroid Build Coastguard Worker ref_searched[i] = 1;
4688*77c1e3ccSAndroid Build Coastguard Worker break;
4689*77c1e3ccSAndroid Build Coastguard Worker }
4690*77c1e3ccSAndroid Build Coastguard Worker }
4691*77c1e3ccSAndroid Build Coastguard Worker }
4692*77c1e3ccSAndroid Build Coastguard Worker
4693*77c1e3ccSAndroid Build Coastguard Worker const int ref_set = get_drl_refmv_count(x, refs, this_mode);
4694*77c1e3ccSAndroid Build Coastguard Worker for (i = 0; i < 2; ++i) {
4695*77c1e3ccSAndroid Build Coastguard Worker if (!ref_searched[i] || (mode[i] != NEARESTMV && mode[i] != NEARMV)) {
4696*77c1e3ccSAndroid Build Coastguard Worker continue;
4697*77c1e3ccSAndroid Build Coastguard Worker }
4698*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME single_refs[2] = { refs[i], NONE_FRAME };
4699*77c1e3ccSAndroid Build Coastguard Worker for (int ref_mv_idx = 0; ref_mv_idx < ref_set; ref_mv_idx++) {
4700*77c1e3ccSAndroid Build Coastguard Worker int_mv single_mv;
4701*77c1e3ccSAndroid Build Coastguard Worker int_mv comp_mv;
4702*77c1e3ccSAndroid Build Coastguard Worker get_this_mv(&single_mv, mode[i], 0, ref_mv_idx, 0, single_refs,
4703*77c1e3ccSAndroid Build Coastguard Worker &x->mbmi_ext);
4704*77c1e3ccSAndroid Build Coastguard Worker get_this_mv(&comp_mv, this_mode, i, ref_mv_idx, 0, refs, &x->mbmi_ext);
4705*77c1e3ccSAndroid Build Coastguard Worker if (single_mv.as_int != comp_mv.as_int) {
4706*77c1e3ccSAndroid Build Coastguard Worker ref_mv_match[i] = 0;
4707*77c1e3ccSAndroid Build Coastguard Worker break;
4708*77c1e3ccSAndroid Build Coastguard Worker }
4709*77c1e3ccSAndroid Build Coastguard Worker }
4710*77c1e3ccSAndroid Build Coastguard Worker }
4711*77c1e3ccSAndroid Build Coastguard Worker
4712*77c1e3ccSAndroid Build Coastguard Worker for (i = 0; i < 2; ++i) {
4713*77c1e3ccSAndroid Build Coastguard Worker if (!ref_searched[i] || !ref_mv_match[i]) continue;
4714*77c1e3ccSAndroid Build Coastguard Worker const int candidates =
4715*77c1e3ccSAndroid Build Coastguard Worker compound_skip_get_candidates(cpi, search_state, mode_dir[i], mode[i]);
4716*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME *ref_order =
4717*77c1e3ccSAndroid Build Coastguard Worker search_state->single_rd_order[mode_dir[i]][mode_offset[i]];
4718*77c1e3ccSAndroid Build Coastguard Worker int match = 0;
4719*77c1e3ccSAndroid Build Coastguard Worker for (j = 0; j < candidates; ++j) {
4720*77c1e3ccSAndroid Build Coastguard Worker if (refs[i] == ref_order[j]) {
4721*77c1e3ccSAndroid Build Coastguard Worker match = 1;
4722*77c1e3ccSAndroid Build Coastguard Worker break;
4723*77c1e3ccSAndroid Build Coastguard Worker }
4724*77c1e3ccSAndroid Build Coastguard Worker }
4725*77c1e3ccSAndroid Build Coastguard Worker if (!match) return 1;
4726*77c1e3ccSAndroid Build Coastguard Worker }
4727*77c1e3ccSAndroid Build Coastguard Worker
4728*77c1e3ccSAndroid Build Coastguard Worker return 0;
4729*77c1e3ccSAndroid Build Coastguard Worker }
4730*77c1e3ccSAndroid Build Coastguard Worker
4731*77c1e3ccSAndroid Build Coastguard Worker // Check if ref frames of current block matches with given block.
match_ref_frame(const MB_MODE_INFO * const mbmi,const MV_REFERENCE_FRAME * ref_frames,int * const is_ref_match)4732*77c1e3ccSAndroid Build Coastguard Worker static inline void match_ref_frame(const MB_MODE_INFO *const mbmi,
4733*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME *ref_frames,
4734*77c1e3ccSAndroid Build Coastguard Worker int *const is_ref_match) {
4735*77c1e3ccSAndroid Build Coastguard Worker if (is_inter_block(mbmi)) {
4736*77c1e3ccSAndroid Build Coastguard Worker is_ref_match[0] |= ref_frames[0] == mbmi->ref_frame[0];
4737*77c1e3ccSAndroid Build Coastguard Worker is_ref_match[1] |= ref_frames[1] == mbmi->ref_frame[0];
4738*77c1e3ccSAndroid Build Coastguard Worker if (has_second_ref(mbmi)) {
4739*77c1e3ccSAndroid Build Coastguard Worker is_ref_match[0] |= ref_frames[0] == mbmi->ref_frame[1];
4740*77c1e3ccSAndroid Build Coastguard Worker is_ref_match[1] |= ref_frames[1] == mbmi->ref_frame[1];
4741*77c1e3ccSAndroid Build Coastguard Worker }
4742*77c1e3ccSAndroid Build Coastguard Worker }
4743*77c1e3ccSAndroid Build Coastguard Worker }
4744*77c1e3ccSAndroid Build Coastguard Worker
4745*77c1e3ccSAndroid Build Coastguard Worker // Prune compound mode using ref frames of neighbor blocks.
compound_skip_using_neighbor_refs(MACROBLOCKD * const xd,const PREDICTION_MODE this_mode,const MV_REFERENCE_FRAME * ref_frames,int prune_ext_comp_using_neighbors)4746*77c1e3ccSAndroid Build Coastguard Worker static inline int compound_skip_using_neighbor_refs(
4747*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *const xd, const PREDICTION_MODE this_mode,
4748*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME *ref_frames, int prune_ext_comp_using_neighbors) {
4749*77c1e3ccSAndroid Build Coastguard Worker // Exclude non-extended compound modes from pruning
4750*77c1e3ccSAndroid Build Coastguard Worker if (this_mode == NEAREST_NEARESTMV || this_mode == NEAR_NEARMV ||
4751*77c1e3ccSAndroid Build Coastguard Worker this_mode == NEW_NEWMV || this_mode == GLOBAL_GLOBALMV)
4752*77c1e3ccSAndroid Build Coastguard Worker return 0;
4753*77c1e3ccSAndroid Build Coastguard Worker
4754*77c1e3ccSAndroid Build Coastguard Worker if (prune_ext_comp_using_neighbors >= 3) return 1;
4755*77c1e3ccSAndroid Build Coastguard Worker
4756*77c1e3ccSAndroid Build Coastguard Worker int is_ref_match[2] = { 0 }; // 0 - match for forward refs
4757*77c1e3ccSAndroid Build Coastguard Worker // 1 - match for backward refs
4758*77c1e3ccSAndroid Build Coastguard Worker // Check if ref frames of this block matches with left neighbor.
4759*77c1e3ccSAndroid Build Coastguard Worker if (xd->left_available)
4760*77c1e3ccSAndroid Build Coastguard Worker match_ref_frame(xd->left_mbmi, ref_frames, is_ref_match);
4761*77c1e3ccSAndroid Build Coastguard Worker
4762*77c1e3ccSAndroid Build Coastguard Worker // Check if ref frames of this block matches with above neighbor.
4763*77c1e3ccSAndroid Build Coastguard Worker if (xd->up_available)
4764*77c1e3ccSAndroid Build Coastguard Worker match_ref_frame(xd->above_mbmi, ref_frames, is_ref_match);
4765*77c1e3ccSAndroid Build Coastguard Worker
4766*77c1e3ccSAndroid Build Coastguard Worker // Combine ref frame match with neighbors in forward and backward refs.
4767*77c1e3ccSAndroid Build Coastguard Worker const int track_ref_match = is_ref_match[0] + is_ref_match[1];
4768*77c1e3ccSAndroid Build Coastguard Worker
4769*77c1e3ccSAndroid Build Coastguard Worker // Pruning based on ref frame match with neighbors.
4770*77c1e3ccSAndroid Build Coastguard Worker if (track_ref_match >= prune_ext_comp_using_neighbors) return 0;
4771*77c1e3ccSAndroid Build Coastguard Worker return 1;
4772*77c1e3ccSAndroid Build Coastguard Worker }
4773*77c1e3ccSAndroid Build Coastguard Worker
4774*77c1e3ccSAndroid Build Coastguard Worker // Update best single mode for the given reference frame based on simple rd.
update_best_single_mode(InterModeSearchState * search_state,const PREDICTION_MODE this_mode,const MV_REFERENCE_FRAME ref_frame,int64_t this_rd)4775*77c1e3ccSAndroid Build Coastguard Worker static inline void update_best_single_mode(InterModeSearchState *search_state,
4776*77c1e3ccSAndroid Build Coastguard Worker const PREDICTION_MODE this_mode,
4777*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME ref_frame,
4778*77c1e3ccSAndroid Build Coastguard Worker int64_t this_rd) {
4779*77c1e3ccSAndroid Build Coastguard Worker if (this_rd < search_state->best_single_rd[ref_frame]) {
4780*77c1e3ccSAndroid Build Coastguard Worker search_state->best_single_rd[ref_frame] = this_rd;
4781*77c1e3ccSAndroid Build Coastguard Worker search_state->best_single_mode[ref_frame] = this_mode;
4782*77c1e3ccSAndroid Build Coastguard Worker }
4783*77c1e3ccSAndroid Build Coastguard Worker }
4784*77c1e3ccSAndroid Build Coastguard Worker
4785*77c1e3ccSAndroid Build Coastguard Worker // Prune compound mode using best single mode for the same reference.
skip_compound_using_best_single_mode_ref(const PREDICTION_MODE this_mode,const MV_REFERENCE_FRAME * ref_frames,const PREDICTION_MODE * best_single_mode,int prune_comp_using_best_single_mode_ref)4786*77c1e3ccSAndroid Build Coastguard Worker static inline int skip_compound_using_best_single_mode_ref(
4787*77c1e3ccSAndroid Build Coastguard Worker const PREDICTION_MODE this_mode, const MV_REFERENCE_FRAME *ref_frames,
4788*77c1e3ccSAndroid Build Coastguard Worker const PREDICTION_MODE *best_single_mode,
4789*77c1e3ccSAndroid Build Coastguard Worker int prune_comp_using_best_single_mode_ref) {
4790*77c1e3ccSAndroid Build Coastguard Worker // Exclude non-extended compound modes from pruning
4791*77c1e3ccSAndroid Build Coastguard Worker if (this_mode == NEAREST_NEARESTMV || this_mode == NEAR_NEARMV ||
4792*77c1e3ccSAndroid Build Coastguard Worker this_mode == NEW_NEWMV || this_mode == GLOBAL_GLOBALMV)
4793*77c1e3ccSAndroid Build Coastguard Worker return 0;
4794*77c1e3ccSAndroid Build Coastguard Worker
4795*77c1e3ccSAndroid Build Coastguard Worker assert(this_mode >= NEAREST_NEWMV && this_mode <= NEW_NEARMV);
4796*77c1e3ccSAndroid Build Coastguard Worker const PREDICTION_MODE comp_mode_ref0 = compound_ref0_mode(this_mode);
4797*77c1e3ccSAndroid Build Coastguard Worker // Get ref frame direction corresponding to NEWMV
4798*77c1e3ccSAndroid Build Coastguard Worker // 0 - NEWMV corresponding to forward direction
4799*77c1e3ccSAndroid Build Coastguard Worker // 1 - NEWMV corresponding to backward direction
4800*77c1e3ccSAndroid Build Coastguard Worker const int newmv_dir = comp_mode_ref0 != NEWMV;
4801*77c1e3ccSAndroid Build Coastguard Worker
4802*77c1e3ccSAndroid Build Coastguard Worker // Avoid pruning the compound mode when ref frame corresponding to NEWMV
4803*77c1e3ccSAndroid Build Coastguard Worker // have NEWMV as single mode winner.
4804*77c1e3ccSAndroid Build Coastguard Worker // Example: For an extended-compound mode,
4805*77c1e3ccSAndroid Build Coastguard Worker // {mode, {fwd_frame, bwd_frame}} = {NEAR_NEWMV, {LAST_FRAME, ALTREF_FRAME}}
4806*77c1e3ccSAndroid Build Coastguard Worker // - Ref frame corresponding to NEWMV is ALTREF_FRAME
4807*77c1e3ccSAndroid Build Coastguard Worker // - Avoid pruning this mode, if best single mode corresponding to ref frame
4808*77c1e3ccSAndroid Build Coastguard Worker // ALTREF_FRAME is NEWMV
4809*77c1e3ccSAndroid Build Coastguard Worker const PREDICTION_MODE single_mode = best_single_mode[ref_frames[newmv_dir]];
4810*77c1e3ccSAndroid Build Coastguard Worker if (single_mode == NEWMV) return 0;
4811*77c1e3ccSAndroid Build Coastguard Worker
4812*77c1e3ccSAndroid Build Coastguard Worker // Avoid pruning the compound mode when best single mode is not available
4813*77c1e3ccSAndroid Build Coastguard Worker if (prune_comp_using_best_single_mode_ref == 1)
4814*77c1e3ccSAndroid Build Coastguard Worker if (single_mode == MB_MODE_COUNT) return 0;
4815*77c1e3ccSAndroid Build Coastguard Worker return 1;
4816*77c1e3ccSAndroid Build Coastguard Worker }
4817*77c1e3ccSAndroid Build Coastguard Worker
compare_int64(const void * a,const void * b)4818*77c1e3ccSAndroid Build Coastguard Worker static int compare_int64(const void *a, const void *b) {
4819*77c1e3ccSAndroid Build Coastguard Worker int64_t a64 = *((int64_t *)a);
4820*77c1e3ccSAndroid Build Coastguard Worker int64_t b64 = *((int64_t *)b);
4821*77c1e3ccSAndroid Build Coastguard Worker if (a64 < b64) {
4822*77c1e3ccSAndroid Build Coastguard Worker return -1;
4823*77c1e3ccSAndroid Build Coastguard Worker } else if (a64 == b64) {
4824*77c1e3ccSAndroid Build Coastguard Worker return 0;
4825*77c1e3ccSAndroid Build Coastguard Worker } else {
4826*77c1e3ccSAndroid Build Coastguard Worker return 1;
4827*77c1e3ccSAndroid Build Coastguard Worker }
4828*77c1e3ccSAndroid Build Coastguard Worker }
4829*77c1e3ccSAndroid Build Coastguard Worker
update_search_state(InterModeSearchState * search_state,RD_STATS * best_rd_stats_dst,PICK_MODE_CONTEXT * ctx,const RD_STATS * new_best_rd_stats,const RD_STATS * new_best_rd_stats_y,const RD_STATS * new_best_rd_stats_uv,THR_MODES new_best_mode,const MACROBLOCK * x,int txfm_search_done)4830*77c1e3ccSAndroid Build Coastguard Worker static inline void update_search_state(
4831*77c1e3ccSAndroid Build Coastguard Worker InterModeSearchState *search_state, RD_STATS *best_rd_stats_dst,
4832*77c1e3ccSAndroid Build Coastguard Worker PICK_MODE_CONTEXT *ctx, const RD_STATS *new_best_rd_stats,
4833*77c1e3ccSAndroid Build Coastguard Worker const RD_STATS *new_best_rd_stats_y, const RD_STATS *new_best_rd_stats_uv,
4834*77c1e3ccSAndroid Build Coastguard Worker THR_MODES new_best_mode, const MACROBLOCK *x, int txfm_search_done) {
4835*77c1e3ccSAndroid Build Coastguard Worker const MACROBLOCKD *xd = &x->e_mbd;
4836*77c1e3ccSAndroid Build Coastguard Worker const MB_MODE_INFO *mbmi = xd->mi[0];
4837*77c1e3ccSAndroid Build Coastguard Worker const int skip_ctx = av1_get_skip_txfm_context(xd);
4838*77c1e3ccSAndroid Build Coastguard Worker const int skip_txfm =
4839*77c1e3ccSAndroid Build Coastguard Worker mbmi->skip_txfm && !is_mode_intra(av1_mode_defs[new_best_mode].mode);
4840*77c1e3ccSAndroid Build Coastguard Worker const TxfmSearchInfo *txfm_info = &x->txfm_search_info;
4841*77c1e3ccSAndroid Build Coastguard Worker
4842*77c1e3ccSAndroid Build Coastguard Worker search_state->best_rd = new_best_rd_stats->rdcost;
4843*77c1e3ccSAndroid Build Coastguard Worker search_state->best_mode_index = new_best_mode;
4844*77c1e3ccSAndroid Build Coastguard Worker *best_rd_stats_dst = *new_best_rd_stats;
4845*77c1e3ccSAndroid Build Coastguard Worker search_state->best_mbmode = *mbmi;
4846*77c1e3ccSAndroid Build Coastguard Worker search_state->best_skip2 = skip_txfm;
4847*77c1e3ccSAndroid Build Coastguard Worker search_state->best_mode_skippable = new_best_rd_stats->skip_txfm;
4848*77c1e3ccSAndroid Build Coastguard Worker // When !txfm_search_done, new_best_rd_stats won't provide correct rate_y and
4849*77c1e3ccSAndroid Build Coastguard Worker // rate_uv because av1_txfm_search process is replaced by rd estimation.
4850*77c1e3ccSAndroid Build Coastguard Worker // Therefore, we should avoid updating best_rate_y and best_rate_uv here.
4851*77c1e3ccSAndroid Build Coastguard Worker // These two values will be updated when av1_txfm_search is called.
4852*77c1e3ccSAndroid Build Coastguard Worker if (txfm_search_done) {
4853*77c1e3ccSAndroid Build Coastguard Worker search_state->best_rate_y =
4854*77c1e3ccSAndroid Build Coastguard Worker new_best_rd_stats_y->rate +
4855*77c1e3ccSAndroid Build Coastguard Worker x->mode_costs.skip_txfm_cost[skip_ctx]
4856*77c1e3ccSAndroid Build Coastguard Worker [new_best_rd_stats->skip_txfm || skip_txfm];
4857*77c1e3ccSAndroid Build Coastguard Worker search_state->best_rate_uv = new_best_rd_stats_uv->rate;
4858*77c1e3ccSAndroid Build Coastguard Worker }
4859*77c1e3ccSAndroid Build Coastguard Worker search_state->best_y_rdcost = *new_best_rd_stats_y;
4860*77c1e3ccSAndroid Build Coastguard Worker memcpy(ctx->blk_skip, txfm_info->blk_skip,
4861*77c1e3ccSAndroid Build Coastguard Worker sizeof(txfm_info->blk_skip[0]) * ctx->num_4x4_blk);
4862*77c1e3ccSAndroid Build Coastguard Worker av1_copy_array(ctx->tx_type_map, xd->tx_type_map, ctx->num_4x4_blk);
4863*77c1e3ccSAndroid Build Coastguard Worker }
4864*77c1e3ccSAndroid Build Coastguard Worker
4865*77c1e3ccSAndroid Build Coastguard Worker // Find the best RD for a reference frame (among single reference modes)
4866*77c1e3ccSAndroid Build Coastguard Worker // and store +10% of it in the 0-th element in ref_frame_rd.
find_top_ref(int64_t ref_frame_rd[REF_FRAMES])4867*77c1e3ccSAndroid Build Coastguard Worker static inline void find_top_ref(int64_t ref_frame_rd[REF_FRAMES]) {
4868*77c1e3ccSAndroid Build Coastguard Worker assert(ref_frame_rd[0] == INT64_MAX);
4869*77c1e3ccSAndroid Build Coastguard Worker int64_t ref_copy[REF_FRAMES - 1];
4870*77c1e3ccSAndroid Build Coastguard Worker memcpy(ref_copy, ref_frame_rd + 1,
4871*77c1e3ccSAndroid Build Coastguard Worker sizeof(ref_frame_rd[0]) * (REF_FRAMES - 1));
4872*77c1e3ccSAndroid Build Coastguard Worker qsort(ref_copy, REF_FRAMES - 1, sizeof(int64_t), compare_int64);
4873*77c1e3ccSAndroid Build Coastguard Worker
4874*77c1e3ccSAndroid Build Coastguard Worker int64_t cutoff = ref_copy[0];
4875*77c1e3ccSAndroid Build Coastguard Worker // The cut-off is within 10% of the best.
4876*77c1e3ccSAndroid Build Coastguard Worker if (cutoff != INT64_MAX) {
4877*77c1e3ccSAndroid Build Coastguard Worker assert(cutoff < INT64_MAX / 200);
4878*77c1e3ccSAndroid Build Coastguard Worker cutoff = (110 * cutoff) / 100;
4879*77c1e3ccSAndroid Build Coastguard Worker }
4880*77c1e3ccSAndroid Build Coastguard Worker ref_frame_rd[0] = cutoff;
4881*77c1e3ccSAndroid Build Coastguard Worker }
4882*77c1e3ccSAndroid Build Coastguard Worker
4883*77c1e3ccSAndroid Build Coastguard Worker // Check if either frame is within the cutoff.
in_single_ref_cutoff(int64_t ref_frame_rd[REF_FRAMES],MV_REFERENCE_FRAME frame1,MV_REFERENCE_FRAME frame2)4884*77c1e3ccSAndroid Build Coastguard Worker static inline bool in_single_ref_cutoff(int64_t ref_frame_rd[REF_FRAMES],
4885*77c1e3ccSAndroid Build Coastguard Worker MV_REFERENCE_FRAME frame1,
4886*77c1e3ccSAndroid Build Coastguard Worker MV_REFERENCE_FRAME frame2) {
4887*77c1e3ccSAndroid Build Coastguard Worker assert(frame2 > 0);
4888*77c1e3ccSAndroid Build Coastguard Worker return ref_frame_rd[frame1] <= ref_frame_rd[0] ||
4889*77c1e3ccSAndroid Build Coastguard Worker ref_frame_rd[frame2] <= ref_frame_rd[0];
4890*77c1e3ccSAndroid Build Coastguard Worker }
4891*77c1e3ccSAndroid Build Coastguard Worker
evaluate_motion_mode_for_winner_candidates(const AV1_COMP * const cpi,MACROBLOCK * const x,RD_STATS * const rd_cost,HandleInterModeArgs * const args,TileDataEnc * const tile_data,PICK_MODE_CONTEXT * const ctx,struct buf_2d yv12_mb[REF_FRAMES][MAX_MB_PLANE],const motion_mode_best_st_candidate * const best_motion_mode_cands,int do_tx_search,const BLOCK_SIZE bsize,int64_t * const best_est_rd,InterModeSearchState * const search_state,int64_t * yrd)4892*77c1e3ccSAndroid Build Coastguard Worker static inline void evaluate_motion_mode_for_winner_candidates(
4893*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMP *const cpi, MACROBLOCK *const x, RD_STATS *const rd_cost,
4894*77c1e3ccSAndroid Build Coastguard Worker HandleInterModeArgs *const args, TileDataEnc *const tile_data,
4895*77c1e3ccSAndroid Build Coastguard Worker PICK_MODE_CONTEXT *const ctx,
4896*77c1e3ccSAndroid Build Coastguard Worker struct buf_2d yv12_mb[REF_FRAMES][MAX_MB_PLANE],
4897*77c1e3ccSAndroid Build Coastguard Worker const motion_mode_best_st_candidate *const best_motion_mode_cands,
4898*77c1e3ccSAndroid Build Coastguard Worker int do_tx_search, const BLOCK_SIZE bsize, int64_t *const best_est_rd,
4899*77c1e3ccSAndroid Build Coastguard Worker InterModeSearchState *const search_state, int64_t *yrd) {
4900*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *const cm = &cpi->common;
4901*77c1e3ccSAndroid Build Coastguard Worker const int num_planes = av1_num_planes(cm);
4902*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *const xd = &x->e_mbd;
4903*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *const mbmi = xd->mi[0];
4904*77c1e3ccSAndroid Build Coastguard Worker InterModesInfo *const inter_modes_info = x->inter_modes_info;
4905*77c1e3ccSAndroid Build Coastguard Worker const int num_best_cand = best_motion_mode_cands->num_motion_mode_cand;
4906*77c1e3ccSAndroid Build Coastguard Worker
4907*77c1e3ccSAndroid Build Coastguard Worker for (int cand = 0; cand < num_best_cand; cand++) {
4908*77c1e3ccSAndroid Build Coastguard Worker RD_STATS rd_stats;
4909*77c1e3ccSAndroid Build Coastguard Worker RD_STATS rd_stats_y;
4910*77c1e3ccSAndroid Build Coastguard Worker RD_STATS rd_stats_uv;
4911*77c1e3ccSAndroid Build Coastguard Worker av1_init_rd_stats(&rd_stats);
4912*77c1e3ccSAndroid Build Coastguard Worker av1_init_rd_stats(&rd_stats_y);
4913*77c1e3ccSAndroid Build Coastguard Worker av1_init_rd_stats(&rd_stats_uv);
4914*77c1e3ccSAndroid Build Coastguard Worker int rate_mv;
4915*77c1e3ccSAndroid Build Coastguard Worker
4916*77c1e3ccSAndroid Build Coastguard Worker rate_mv = best_motion_mode_cands->motion_mode_cand[cand].rate_mv;
4917*77c1e3ccSAndroid Build Coastguard Worker args->skip_motion_mode =
4918*77c1e3ccSAndroid Build Coastguard Worker best_motion_mode_cands->motion_mode_cand[cand].skip_motion_mode;
4919*77c1e3ccSAndroid Build Coastguard Worker *mbmi = best_motion_mode_cands->motion_mode_cand[cand].mbmi;
4920*77c1e3ccSAndroid Build Coastguard Worker rd_stats.rate =
4921*77c1e3ccSAndroid Build Coastguard Worker best_motion_mode_cands->motion_mode_cand[cand].rate2_nocoeff;
4922*77c1e3ccSAndroid Build Coastguard Worker
4923*77c1e3ccSAndroid Build Coastguard Worker // Continue if the best candidate is compound.
4924*77c1e3ccSAndroid Build Coastguard Worker if (!is_inter_singleref_mode(mbmi->mode)) continue;
4925*77c1e3ccSAndroid Build Coastguard Worker
4926*77c1e3ccSAndroid Build Coastguard Worker x->txfm_search_info.skip_txfm = 0;
4927*77c1e3ccSAndroid Build Coastguard Worker struct macroblockd_plane *pd = xd->plane;
4928*77c1e3ccSAndroid Build Coastguard Worker const BUFFER_SET orig_dst = {
4929*77c1e3ccSAndroid Build Coastguard Worker { pd[0].dst.buf, pd[1].dst.buf, pd[2].dst.buf },
4930*77c1e3ccSAndroid Build Coastguard Worker { pd[0].dst.stride, pd[1].dst.stride, pd[2].dst.stride },
4931*77c1e3ccSAndroid Build Coastguard Worker };
4932*77c1e3ccSAndroid Build Coastguard Worker
4933*77c1e3ccSAndroid Build Coastguard Worker set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
4934*77c1e3ccSAndroid Build Coastguard Worker // Initialize motion mode to simple translation
4935*77c1e3ccSAndroid Build Coastguard Worker // Calculation of switchable rate depends on it.
4936*77c1e3ccSAndroid Build Coastguard Worker mbmi->motion_mode = 0;
4937*77c1e3ccSAndroid Build Coastguard Worker const int is_comp_pred = mbmi->ref_frame[1] > INTRA_FRAME;
4938*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < num_planes; i++) {
4939*77c1e3ccSAndroid Build Coastguard Worker xd->plane[i].pre[0] = yv12_mb[mbmi->ref_frame[0]][i];
4940*77c1e3ccSAndroid Build Coastguard Worker if (is_comp_pred) xd->plane[i].pre[1] = yv12_mb[mbmi->ref_frame[1]][i];
4941*77c1e3ccSAndroid Build Coastguard Worker }
4942*77c1e3ccSAndroid Build Coastguard Worker
4943*77c1e3ccSAndroid Build Coastguard Worker int64_t skip_rd[2] = { search_state->best_skip_rd[0],
4944*77c1e3ccSAndroid Build Coastguard Worker search_state->best_skip_rd[1] };
4945*77c1e3ccSAndroid Build Coastguard Worker int64_t this_yrd = INT64_MAX;
4946*77c1e3ccSAndroid Build Coastguard Worker int64_t ret_value = motion_mode_rd(
4947*77c1e3ccSAndroid Build Coastguard Worker cpi, tile_data, x, bsize, &rd_stats, &rd_stats_y, &rd_stats_uv, args,
4948*77c1e3ccSAndroid Build Coastguard Worker search_state->best_rd, skip_rd, &rate_mv, &orig_dst, best_est_rd,
4949*77c1e3ccSAndroid Build Coastguard Worker do_tx_search, inter_modes_info, 1, &this_yrd);
4950*77c1e3ccSAndroid Build Coastguard Worker
4951*77c1e3ccSAndroid Build Coastguard Worker if (ret_value != INT64_MAX) {
4952*77c1e3ccSAndroid Build Coastguard Worker rd_stats.rdcost = RDCOST(x->rdmult, rd_stats.rate, rd_stats.dist);
4953*77c1e3ccSAndroid Build Coastguard Worker const THR_MODES mode_enum = get_prediction_mode_idx(
4954*77c1e3ccSAndroid Build Coastguard Worker mbmi->mode, mbmi->ref_frame[0], mbmi->ref_frame[1]);
4955*77c1e3ccSAndroid Build Coastguard Worker // Collect mode stats for multiwinner mode processing
4956*77c1e3ccSAndroid Build Coastguard Worker store_winner_mode_stats(
4957*77c1e3ccSAndroid Build Coastguard Worker &cpi->common, x, mbmi, &rd_stats, &rd_stats_y, &rd_stats_uv,
4958*77c1e3ccSAndroid Build Coastguard Worker mode_enum, NULL, bsize, rd_stats.rdcost,
4959*77c1e3ccSAndroid Build Coastguard Worker cpi->sf.winner_mode_sf.multi_winner_mode_type, do_tx_search);
4960*77c1e3ccSAndroid Build Coastguard Worker if (rd_stats.rdcost < search_state->best_rd) {
4961*77c1e3ccSAndroid Build Coastguard Worker *yrd = this_yrd;
4962*77c1e3ccSAndroid Build Coastguard Worker update_search_state(search_state, rd_cost, ctx, &rd_stats, &rd_stats_y,
4963*77c1e3ccSAndroid Build Coastguard Worker &rd_stats_uv, mode_enum, x, do_tx_search);
4964*77c1e3ccSAndroid Build Coastguard Worker if (do_tx_search) search_state->best_skip_rd[0] = skip_rd[0];
4965*77c1e3ccSAndroid Build Coastguard Worker }
4966*77c1e3ccSAndroid Build Coastguard Worker }
4967*77c1e3ccSAndroid Build Coastguard Worker }
4968*77c1e3ccSAndroid Build Coastguard Worker }
4969*77c1e3ccSAndroid Build Coastguard Worker
4970*77c1e3ccSAndroid Build Coastguard Worker /*!\cond */
4971*77c1e3ccSAndroid Build Coastguard Worker // Arguments for speed feature pruning of inter mode search
4972*77c1e3ccSAndroid Build Coastguard Worker typedef struct {
4973*77c1e3ccSAndroid Build Coastguard Worker int *skip_motion_mode;
4974*77c1e3ccSAndroid Build Coastguard Worker mode_skip_mask_t *mode_skip_mask;
4975*77c1e3ccSAndroid Build Coastguard Worker InterModeSearchState *search_state;
4976*77c1e3ccSAndroid Build Coastguard Worker int skip_ref_frame_mask;
4977*77c1e3ccSAndroid Build Coastguard Worker int reach_first_comp_mode;
4978*77c1e3ccSAndroid Build Coastguard Worker int mode_thresh_mul_fact;
4979*77c1e3ccSAndroid Build Coastguard Worker int num_single_modes_processed;
4980*77c1e3ccSAndroid Build Coastguard Worker int prune_cpd_using_sr_stats_ready;
4981*77c1e3ccSAndroid Build Coastguard Worker } InterModeSFArgs;
4982*77c1e3ccSAndroid Build Coastguard Worker /*!\endcond */
4983*77c1e3ccSAndroid Build Coastguard Worker
skip_inter_mode(AV1_COMP * cpi,MACROBLOCK * x,const BLOCK_SIZE bsize,int64_t * ref_frame_rd,int midx,InterModeSFArgs * args,int is_low_temp_var)4984*77c1e3ccSAndroid Build Coastguard Worker static int skip_inter_mode(AV1_COMP *cpi, MACROBLOCK *x, const BLOCK_SIZE bsize,
4985*77c1e3ccSAndroid Build Coastguard Worker int64_t *ref_frame_rd, int midx,
4986*77c1e3ccSAndroid Build Coastguard Worker InterModeSFArgs *args, int is_low_temp_var) {
4987*77c1e3ccSAndroid Build Coastguard Worker const SPEED_FEATURES *const sf = &cpi->sf;
4988*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *const xd = &x->e_mbd;
4989*77c1e3ccSAndroid Build Coastguard Worker // Get the actual prediction mode we are trying in this iteration
4990*77c1e3ccSAndroid Build Coastguard Worker const THR_MODES mode_enum = av1_default_mode_order[midx];
4991*77c1e3ccSAndroid Build Coastguard Worker const MODE_DEFINITION *mode_def = &av1_mode_defs[mode_enum];
4992*77c1e3ccSAndroid Build Coastguard Worker const PREDICTION_MODE this_mode = mode_def->mode;
4993*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME *ref_frames = mode_def->ref_frame;
4994*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME ref_frame = ref_frames[0];
4995*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME second_ref_frame = ref_frames[1];
4996*77c1e3ccSAndroid Build Coastguard Worker const int comp_pred = second_ref_frame > INTRA_FRAME;
4997*77c1e3ccSAndroid Build Coastguard Worker
4998*77c1e3ccSAndroid Build Coastguard Worker if (ref_frame == INTRA_FRAME) return 1;
4999*77c1e3ccSAndroid Build Coastguard Worker
5000*77c1e3ccSAndroid Build Coastguard Worker const FRAME_UPDATE_TYPE update_type =
5001*77c1e3ccSAndroid Build Coastguard Worker get_frame_update_type(&cpi->ppi->gf_group, cpi->gf_frame_index);
5002*77c1e3ccSAndroid Build Coastguard Worker if (sf->inter_sf.skip_arf_compound && update_type == ARF_UPDATE &&
5003*77c1e3ccSAndroid Build Coastguard Worker comp_pred) {
5004*77c1e3ccSAndroid Build Coastguard Worker return 1;
5005*77c1e3ccSAndroid Build Coastguard Worker }
5006*77c1e3ccSAndroid Build Coastguard Worker
5007*77c1e3ccSAndroid Build Coastguard Worker // This is for real time encoding.
5008*77c1e3ccSAndroid Build Coastguard Worker if (is_low_temp_var && !comp_pred && ref_frame != LAST_FRAME &&
5009*77c1e3ccSAndroid Build Coastguard Worker this_mode != NEARESTMV)
5010*77c1e3ccSAndroid Build Coastguard Worker return 1;
5011*77c1e3ccSAndroid Build Coastguard Worker
5012*77c1e3ccSAndroid Build Coastguard Worker // Check if this mode should be skipped because it is incompatible with the
5013*77c1e3ccSAndroid Build Coastguard Worker // current frame
5014*77c1e3ccSAndroid Build Coastguard Worker if (inter_mode_compatible_skip(cpi, x, bsize, this_mode, ref_frames))
5015*77c1e3ccSAndroid Build Coastguard Worker return 1;
5016*77c1e3ccSAndroid Build Coastguard Worker const int ret = inter_mode_search_order_independent_skip(
5017*77c1e3ccSAndroid Build Coastguard Worker cpi, x, args->mode_skip_mask, args->search_state,
5018*77c1e3ccSAndroid Build Coastguard Worker args->skip_ref_frame_mask, this_mode, mode_def->ref_frame);
5019*77c1e3ccSAndroid Build Coastguard Worker if (ret == 1) return 1;
5020*77c1e3ccSAndroid Build Coastguard Worker *(args->skip_motion_mode) = (ret == 2);
5021*77c1e3ccSAndroid Build Coastguard Worker
5022*77c1e3ccSAndroid Build Coastguard Worker // We've reached the first compound prediction mode, get stats from the
5023*77c1e3ccSAndroid Build Coastguard Worker // single reference predictors to help with pruning.
5024*77c1e3ccSAndroid Build Coastguard Worker // Disable this pruning logic if interpolation filter search was skipped for
5025*77c1e3ccSAndroid Build Coastguard Worker // single prediction modes as it can result in aggressive pruning of compound
5026*77c1e3ccSAndroid Build Coastguard Worker // prediction modes due to the absence of modelled_rd populated by
5027*77c1e3ccSAndroid Build Coastguard Worker // av1_interpolation_filter_search().
5028*77c1e3ccSAndroid Build Coastguard Worker // TODO(Remya): Check the impact of the sf
5029*77c1e3ccSAndroid Build Coastguard Worker // 'prune_comp_search_by_single_result' if compound prediction modes are
5030*77c1e3ccSAndroid Build Coastguard Worker // enabled in future for REALTIME encode.
5031*77c1e3ccSAndroid Build Coastguard Worker if (!sf->interp_sf.skip_interp_filter_search &&
5032*77c1e3ccSAndroid Build Coastguard Worker sf->inter_sf.prune_comp_search_by_single_result > 0 && comp_pred &&
5033*77c1e3ccSAndroid Build Coastguard Worker args->reach_first_comp_mode == 0) {
5034*77c1e3ccSAndroid Build Coastguard Worker analyze_single_states(cpi, args->search_state);
5035*77c1e3ccSAndroid Build Coastguard Worker args->reach_first_comp_mode = 1;
5036*77c1e3ccSAndroid Build Coastguard Worker }
5037*77c1e3ccSAndroid Build Coastguard Worker
5038*77c1e3ccSAndroid Build Coastguard Worker // Prune aggressively when best mode is skippable.
5039*77c1e3ccSAndroid Build Coastguard Worker int mul_fact = args->search_state->best_mode_skippable
5040*77c1e3ccSAndroid Build Coastguard Worker ? args->mode_thresh_mul_fact
5041*77c1e3ccSAndroid Build Coastguard Worker : (1 << MODE_THRESH_QBITS);
5042*77c1e3ccSAndroid Build Coastguard Worker int64_t mode_threshold =
5043*77c1e3ccSAndroid Build Coastguard Worker (args->search_state->mode_threshold[mode_enum] * mul_fact) >>
5044*77c1e3ccSAndroid Build Coastguard Worker MODE_THRESH_QBITS;
5045*77c1e3ccSAndroid Build Coastguard Worker
5046*77c1e3ccSAndroid Build Coastguard Worker if (args->search_state->best_rd < mode_threshold) return 1;
5047*77c1e3ccSAndroid Build Coastguard Worker
5048*77c1e3ccSAndroid Build Coastguard Worker // Skip this compound mode based on the RD results from the single prediction
5049*77c1e3ccSAndroid Build Coastguard Worker // modes
5050*77c1e3ccSAndroid Build Coastguard Worker if (!sf->interp_sf.skip_interp_filter_search &&
5051*77c1e3ccSAndroid Build Coastguard Worker sf->inter_sf.prune_comp_search_by_single_result > 0 && comp_pred) {
5052*77c1e3ccSAndroid Build Coastguard Worker if (compound_skip_by_single_states(cpi, args->search_state, this_mode,
5053*77c1e3ccSAndroid Build Coastguard Worker ref_frame, second_ref_frame, x))
5054*77c1e3ccSAndroid Build Coastguard Worker return 1;
5055*77c1e3ccSAndroid Build Coastguard Worker }
5056*77c1e3ccSAndroid Build Coastguard Worker
5057*77c1e3ccSAndroid Build Coastguard Worker if (sf->inter_sf.prune_compound_using_single_ref && comp_pred) {
5058*77c1e3ccSAndroid Build Coastguard Worker // After we done with single reference modes, find the 2nd best RD
5059*77c1e3ccSAndroid Build Coastguard Worker // for a reference frame. Only search compound modes that have a reference
5060*77c1e3ccSAndroid Build Coastguard Worker // frame at least as good as the 2nd best.
5061*77c1e3ccSAndroid Build Coastguard Worker if (!args->prune_cpd_using_sr_stats_ready &&
5062*77c1e3ccSAndroid Build Coastguard Worker args->num_single_modes_processed == NUM_SINGLE_REF_MODES) {
5063*77c1e3ccSAndroid Build Coastguard Worker find_top_ref(ref_frame_rd);
5064*77c1e3ccSAndroid Build Coastguard Worker args->prune_cpd_using_sr_stats_ready = 1;
5065*77c1e3ccSAndroid Build Coastguard Worker }
5066*77c1e3ccSAndroid Build Coastguard Worker if (args->prune_cpd_using_sr_stats_ready &&
5067*77c1e3ccSAndroid Build Coastguard Worker !in_single_ref_cutoff(ref_frame_rd, ref_frame, second_ref_frame))
5068*77c1e3ccSAndroid Build Coastguard Worker return 1;
5069*77c1e3ccSAndroid Build Coastguard Worker }
5070*77c1e3ccSAndroid Build Coastguard Worker
5071*77c1e3ccSAndroid Build Coastguard Worker // Skip NEW_NEARMV and NEAR_NEWMV extended compound modes
5072*77c1e3ccSAndroid Build Coastguard Worker if (sf->inter_sf.skip_ext_comp_nearmv_mode &&
5073*77c1e3ccSAndroid Build Coastguard Worker (this_mode == NEW_NEARMV || this_mode == NEAR_NEWMV)) {
5074*77c1e3ccSAndroid Build Coastguard Worker return 1;
5075*77c1e3ccSAndroid Build Coastguard Worker }
5076*77c1e3ccSAndroid Build Coastguard Worker
5077*77c1e3ccSAndroid Build Coastguard Worker if (sf->inter_sf.prune_ext_comp_using_neighbors && comp_pred) {
5078*77c1e3ccSAndroid Build Coastguard Worker if (compound_skip_using_neighbor_refs(
5079*77c1e3ccSAndroid Build Coastguard Worker xd, this_mode, ref_frames,
5080*77c1e3ccSAndroid Build Coastguard Worker sf->inter_sf.prune_ext_comp_using_neighbors))
5081*77c1e3ccSAndroid Build Coastguard Worker return 1;
5082*77c1e3ccSAndroid Build Coastguard Worker }
5083*77c1e3ccSAndroid Build Coastguard Worker
5084*77c1e3ccSAndroid Build Coastguard Worker if (sf->inter_sf.prune_comp_using_best_single_mode_ref && comp_pred) {
5085*77c1e3ccSAndroid Build Coastguard Worker if (skip_compound_using_best_single_mode_ref(
5086*77c1e3ccSAndroid Build Coastguard Worker this_mode, ref_frames, args->search_state->best_single_mode,
5087*77c1e3ccSAndroid Build Coastguard Worker sf->inter_sf.prune_comp_using_best_single_mode_ref))
5088*77c1e3ccSAndroid Build Coastguard Worker return 1;
5089*77c1e3ccSAndroid Build Coastguard Worker }
5090*77c1e3ccSAndroid Build Coastguard Worker
5091*77c1e3ccSAndroid Build Coastguard Worker if (sf->inter_sf.prune_nearest_near_mv_using_refmv_weight && !comp_pred) {
5092*77c1e3ccSAndroid Build Coastguard Worker const int8_t ref_frame_type = av1_ref_frame_type(ref_frames);
5093*77c1e3ccSAndroid Build Coastguard Worker if (skip_nearest_near_mv_using_refmv_weight(
5094*77c1e3ccSAndroid Build Coastguard Worker x, this_mode, ref_frame_type,
5095*77c1e3ccSAndroid Build Coastguard Worker args->search_state->best_mbmode.mode)) {
5096*77c1e3ccSAndroid Build Coastguard Worker // Ensure the mode is pruned only when the current block has obtained a
5097*77c1e3ccSAndroid Build Coastguard Worker // valid inter mode.
5098*77c1e3ccSAndroid Build Coastguard Worker assert(is_inter_mode(args->search_state->best_mbmode.mode));
5099*77c1e3ccSAndroid Build Coastguard Worker return 1;
5100*77c1e3ccSAndroid Build Coastguard Worker }
5101*77c1e3ccSAndroid Build Coastguard Worker }
5102*77c1e3ccSAndroid Build Coastguard Worker
5103*77c1e3ccSAndroid Build Coastguard Worker if (sf->rt_sf.prune_inter_modes_with_golden_ref &&
5104*77c1e3ccSAndroid Build Coastguard Worker ref_frame == GOLDEN_FRAME && !comp_pred) {
5105*77c1e3ccSAndroid Build Coastguard Worker const int subgop_size = AOMMIN(cpi->ppi->gf_group.size, FIXED_GF_INTERVAL);
5106*77c1e3ccSAndroid Build Coastguard Worker if (cpi->rc.frames_since_golden > (subgop_size >> 2) &&
5107*77c1e3ccSAndroid Build Coastguard Worker args->search_state->best_mbmode.ref_frame[0] != GOLDEN_FRAME) {
5108*77c1e3ccSAndroid Build Coastguard Worker if ((bsize > BLOCK_16X16 && this_mode == NEWMV) || this_mode == NEARMV)
5109*77c1e3ccSAndroid Build Coastguard Worker return 1;
5110*77c1e3ccSAndroid Build Coastguard Worker }
5111*77c1e3ccSAndroid Build Coastguard Worker }
5112*77c1e3ccSAndroid Build Coastguard Worker
5113*77c1e3ccSAndroid Build Coastguard Worker return 0;
5114*77c1e3ccSAndroid Build Coastguard Worker }
5115*77c1e3ccSAndroid Build Coastguard Worker
record_best_compound(REFERENCE_MODE reference_mode,RD_STATS * rd_stats,int comp_pred,int rdmult,InterModeSearchState * search_state,int compmode_cost)5116*77c1e3ccSAndroid Build Coastguard Worker static void record_best_compound(REFERENCE_MODE reference_mode,
5117*77c1e3ccSAndroid Build Coastguard Worker RD_STATS *rd_stats, int comp_pred, int rdmult,
5118*77c1e3ccSAndroid Build Coastguard Worker InterModeSearchState *search_state,
5119*77c1e3ccSAndroid Build Coastguard Worker int compmode_cost) {
5120*77c1e3ccSAndroid Build Coastguard Worker int64_t single_rd, hybrid_rd, single_rate, hybrid_rate;
5121*77c1e3ccSAndroid Build Coastguard Worker
5122*77c1e3ccSAndroid Build Coastguard Worker if (reference_mode == REFERENCE_MODE_SELECT) {
5123*77c1e3ccSAndroid Build Coastguard Worker single_rate = rd_stats->rate - compmode_cost;
5124*77c1e3ccSAndroid Build Coastguard Worker hybrid_rate = rd_stats->rate;
5125*77c1e3ccSAndroid Build Coastguard Worker } else {
5126*77c1e3ccSAndroid Build Coastguard Worker single_rate = rd_stats->rate;
5127*77c1e3ccSAndroid Build Coastguard Worker hybrid_rate = rd_stats->rate + compmode_cost;
5128*77c1e3ccSAndroid Build Coastguard Worker }
5129*77c1e3ccSAndroid Build Coastguard Worker
5130*77c1e3ccSAndroid Build Coastguard Worker single_rd = RDCOST(rdmult, single_rate, rd_stats->dist);
5131*77c1e3ccSAndroid Build Coastguard Worker hybrid_rd = RDCOST(rdmult, hybrid_rate, rd_stats->dist);
5132*77c1e3ccSAndroid Build Coastguard Worker
5133*77c1e3ccSAndroid Build Coastguard Worker if (!comp_pred) {
5134*77c1e3ccSAndroid Build Coastguard Worker if (single_rd < search_state->best_pred_rd[SINGLE_REFERENCE])
5135*77c1e3ccSAndroid Build Coastguard Worker search_state->best_pred_rd[SINGLE_REFERENCE] = single_rd;
5136*77c1e3ccSAndroid Build Coastguard Worker } else {
5137*77c1e3ccSAndroid Build Coastguard Worker if (single_rd < search_state->best_pred_rd[COMPOUND_REFERENCE])
5138*77c1e3ccSAndroid Build Coastguard Worker search_state->best_pred_rd[COMPOUND_REFERENCE] = single_rd;
5139*77c1e3ccSAndroid Build Coastguard Worker }
5140*77c1e3ccSAndroid Build Coastguard Worker if (hybrid_rd < search_state->best_pred_rd[REFERENCE_MODE_SELECT])
5141*77c1e3ccSAndroid Build Coastguard Worker search_state->best_pred_rd[REFERENCE_MODE_SELECT] = hybrid_rd;
5142*77c1e3ccSAndroid Build Coastguard Worker }
5143*77c1e3ccSAndroid Build Coastguard Worker
5144*77c1e3ccSAndroid Build Coastguard Worker // Does a transform search over a list of the best inter mode candidates.
5145*77c1e3ccSAndroid Build Coastguard Worker // This is called if the original mode search computed an RD estimate
5146*77c1e3ccSAndroid Build Coastguard Worker // for the transform search rather than doing a full search.
tx_search_best_inter_candidates(AV1_COMP * cpi,TileDataEnc * tile_data,MACROBLOCK * x,int64_t best_rd_so_far,BLOCK_SIZE bsize,struct buf_2d yv12_mb[REF_FRAMES][MAX_MB_PLANE],int mi_row,int mi_col,InterModeSearchState * search_state,RD_STATS * rd_cost,PICK_MODE_CONTEXT * ctx,int64_t * yrd)5147*77c1e3ccSAndroid Build Coastguard Worker static void tx_search_best_inter_candidates(
5148*77c1e3ccSAndroid Build Coastguard Worker AV1_COMP *cpi, TileDataEnc *tile_data, MACROBLOCK *x,
5149*77c1e3ccSAndroid Build Coastguard Worker int64_t best_rd_so_far, BLOCK_SIZE bsize,
5150*77c1e3ccSAndroid Build Coastguard Worker struct buf_2d yv12_mb[REF_FRAMES][MAX_MB_PLANE], int mi_row, int mi_col,
5151*77c1e3ccSAndroid Build Coastguard Worker InterModeSearchState *search_state, RD_STATS *rd_cost,
5152*77c1e3ccSAndroid Build Coastguard Worker PICK_MODE_CONTEXT *ctx, int64_t *yrd) {
5153*77c1e3ccSAndroid Build Coastguard Worker AV1_COMMON *const cm = &cpi->common;
5154*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *const xd = &x->e_mbd;
5155*77c1e3ccSAndroid Build Coastguard Worker TxfmSearchInfo *txfm_info = &x->txfm_search_info;
5156*77c1e3ccSAndroid Build Coastguard Worker const ModeCosts *mode_costs = &x->mode_costs;
5157*77c1e3ccSAndroid Build Coastguard Worker const int num_planes = av1_num_planes(cm);
5158*77c1e3ccSAndroid Build Coastguard Worker const int skip_ctx = av1_get_skip_txfm_context(xd);
5159*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *const mbmi = xd->mi[0];
5160*77c1e3ccSAndroid Build Coastguard Worker InterModesInfo *inter_modes_info = x->inter_modes_info;
5161*77c1e3ccSAndroid Build Coastguard Worker inter_modes_info_sort(inter_modes_info, inter_modes_info->rd_idx_pair_arr);
5162*77c1e3ccSAndroid Build Coastguard Worker search_state->best_rd = best_rd_so_far;
5163*77c1e3ccSAndroid Build Coastguard Worker search_state->best_mode_index = THR_INVALID;
5164*77c1e3ccSAndroid Build Coastguard Worker // Initialize best mode stats for winner mode processing
5165*77c1e3ccSAndroid Build Coastguard Worker x->winner_mode_count = 0;
5166*77c1e3ccSAndroid Build Coastguard Worker store_winner_mode_stats(&cpi->common, x, mbmi, NULL, NULL, NULL, THR_INVALID,
5167*77c1e3ccSAndroid Build Coastguard Worker NULL, bsize, best_rd_so_far,
5168*77c1e3ccSAndroid Build Coastguard Worker cpi->sf.winner_mode_sf.multi_winner_mode_type, 0);
5169*77c1e3ccSAndroid Build Coastguard Worker inter_modes_info->num =
5170*77c1e3ccSAndroid Build Coastguard Worker inter_modes_info->num < cpi->sf.rt_sf.num_inter_modes_for_tx_search
5171*77c1e3ccSAndroid Build Coastguard Worker ? inter_modes_info->num
5172*77c1e3ccSAndroid Build Coastguard Worker : cpi->sf.rt_sf.num_inter_modes_for_tx_search;
5173*77c1e3ccSAndroid Build Coastguard Worker const int64_t top_est_rd =
5174*77c1e3ccSAndroid Build Coastguard Worker inter_modes_info->num > 0
5175*77c1e3ccSAndroid Build Coastguard Worker ? inter_modes_info
5176*77c1e3ccSAndroid Build Coastguard Worker ->est_rd_arr[inter_modes_info->rd_idx_pair_arr[0].idx]
5177*77c1e3ccSAndroid Build Coastguard Worker : INT64_MAX;
5178*77c1e3ccSAndroid Build Coastguard Worker *yrd = INT64_MAX;
5179*77c1e3ccSAndroid Build Coastguard Worker int64_t best_rd_in_this_partition = INT64_MAX;
5180*77c1e3ccSAndroid Build Coastguard Worker int num_inter_mode_cands = inter_modes_info->num;
5181*77c1e3ccSAndroid Build Coastguard Worker int newmv_mode_evaled = 0;
5182*77c1e3ccSAndroid Build Coastguard Worker int max_allowed_cands = INT_MAX;
5183*77c1e3ccSAndroid Build Coastguard Worker if (cpi->sf.inter_sf.limit_inter_mode_cands) {
5184*77c1e3ccSAndroid Build Coastguard Worker // The bound on the no. of inter mode candidates, beyond which the
5185*77c1e3ccSAndroid Build Coastguard Worker // candidates are limited if a newmv mode got evaluated, is set as
5186*77c1e3ccSAndroid Build Coastguard Worker // max_allowed_cands + 1.
5187*77c1e3ccSAndroid Build Coastguard Worker const int num_allowed_cands[5] = { INT_MAX, 10, 9, 6, 2 };
5188*77c1e3ccSAndroid Build Coastguard Worker assert(cpi->sf.inter_sf.limit_inter_mode_cands <= 4);
5189*77c1e3ccSAndroid Build Coastguard Worker max_allowed_cands =
5190*77c1e3ccSAndroid Build Coastguard Worker num_allowed_cands[cpi->sf.inter_sf.limit_inter_mode_cands];
5191*77c1e3ccSAndroid Build Coastguard Worker }
5192*77c1e3ccSAndroid Build Coastguard Worker
5193*77c1e3ccSAndroid Build Coastguard Worker int num_mode_thresh = INT_MAX;
5194*77c1e3ccSAndroid Build Coastguard Worker if (cpi->sf.inter_sf.limit_txfm_eval_per_mode) {
5195*77c1e3ccSAndroid Build Coastguard Worker // Bound the no. of transform searches per prediction mode beyond a
5196*77c1e3ccSAndroid Build Coastguard Worker // threshold.
5197*77c1e3ccSAndroid Build Coastguard Worker const int num_mode_thresh_ary[4] = { INT_MAX, 4, 3, 0 };
5198*77c1e3ccSAndroid Build Coastguard Worker assert(cpi->sf.inter_sf.limit_txfm_eval_per_mode <= 3);
5199*77c1e3ccSAndroid Build Coastguard Worker num_mode_thresh =
5200*77c1e3ccSAndroid Build Coastguard Worker num_mode_thresh_ary[cpi->sf.inter_sf.limit_txfm_eval_per_mode];
5201*77c1e3ccSAndroid Build Coastguard Worker }
5202*77c1e3ccSAndroid Build Coastguard Worker
5203*77c1e3ccSAndroid Build Coastguard Worker int num_tx_cands = 0;
5204*77c1e3ccSAndroid Build Coastguard Worker int num_tx_search_modes[INTER_MODE_END - INTER_MODE_START] = { 0 };
5205*77c1e3ccSAndroid Build Coastguard Worker // Iterate over best inter mode candidates and perform tx search
5206*77c1e3ccSAndroid Build Coastguard Worker for (int j = 0; j < num_inter_mode_cands; ++j) {
5207*77c1e3ccSAndroid Build Coastguard Worker const int data_idx = inter_modes_info->rd_idx_pair_arr[j].idx;
5208*77c1e3ccSAndroid Build Coastguard Worker *mbmi = inter_modes_info->mbmi_arr[data_idx];
5209*77c1e3ccSAndroid Build Coastguard Worker const PREDICTION_MODE prediction_mode = mbmi->mode;
5210*77c1e3ccSAndroid Build Coastguard Worker int64_t curr_est_rd = inter_modes_info->est_rd_arr[data_idx];
5211*77c1e3ccSAndroid Build Coastguard Worker if (curr_est_rd * 0.80 > top_est_rd) break;
5212*77c1e3ccSAndroid Build Coastguard Worker
5213*77c1e3ccSAndroid Build Coastguard Worker if (num_tx_cands > num_mode_thresh) {
5214*77c1e3ccSAndroid Build Coastguard Worker if ((prediction_mode != NEARESTMV &&
5215*77c1e3ccSAndroid Build Coastguard Worker num_tx_search_modes[prediction_mode - INTER_MODE_START] >= 1) ||
5216*77c1e3ccSAndroid Build Coastguard Worker (prediction_mode == NEARESTMV &&
5217*77c1e3ccSAndroid Build Coastguard Worker num_tx_search_modes[prediction_mode - INTER_MODE_START] >= 2))
5218*77c1e3ccSAndroid Build Coastguard Worker continue;
5219*77c1e3ccSAndroid Build Coastguard Worker }
5220*77c1e3ccSAndroid Build Coastguard Worker
5221*77c1e3ccSAndroid Build Coastguard Worker txfm_info->skip_txfm = 0;
5222*77c1e3ccSAndroid Build Coastguard Worker set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
5223*77c1e3ccSAndroid Build Coastguard Worker
5224*77c1e3ccSAndroid Build Coastguard Worker // Select prediction reference frames.
5225*77c1e3ccSAndroid Build Coastguard Worker const int is_comp_pred = mbmi->ref_frame[1] > INTRA_FRAME;
5226*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < num_planes; i++) {
5227*77c1e3ccSAndroid Build Coastguard Worker xd->plane[i].pre[0] = yv12_mb[mbmi->ref_frame[0]][i];
5228*77c1e3ccSAndroid Build Coastguard Worker if (is_comp_pred) xd->plane[i].pre[1] = yv12_mb[mbmi->ref_frame[1]][i];
5229*77c1e3ccSAndroid Build Coastguard Worker }
5230*77c1e3ccSAndroid Build Coastguard Worker
5231*77c1e3ccSAndroid Build Coastguard Worker bool is_predictor_built = false;
5232*77c1e3ccSAndroid Build Coastguard Worker
5233*77c1e3ccSAndroid Build Coastguard Worker // Initialize RD stats
5234*77c1e3ccSAndroid Build Coastguard Worker RD_STATS rd_stats;
5235*77c1e3ccSAndroid Build Coastguard Worker RD_STATS rd_stats_y;
5236*77c1e3ccSAndroid Build Coastguard Worker RD_STATS rd_stats_uv;
5237*77c1e3ccSAndroid Build Coastguard Worker const int mode_rate = inter_modes_info->mode_rate_arr[data_idx];
5238*77c1e3ccSAndroid Build Coastguard Worker int64_t skip_rd = INT64_MAX;
5239*77c1e3ccSAndroid Build Coastguard Worker const int txfm_rd_gate_level = get_txfm_rd_gate_level(
5240*77c1e3ccSAndroid Build Coastguard Worker cm->seq_params->enable_masked_compound,
5241*77c1e3ccSAndroid Build Coastguard Worker cpi->sf.inter_sf.txfm_rd_gate_level, bsize, TX_SEARCH_DEFAULT,
5242*77c1e3ccSAndroid Build Coastguard Worker /*eval_motion_mode=*/0);
5243*77c1e3ccSAndroid Build Coastguard Worker if (txfm_rd_gate_level) {
5244*77c1e3ccSAndroid Build Coastguard Worker // Check if the mode is good enough based on skip RD
5245*77c1e3ccSAndroid Build Coastguard Worker int64_t curr_sse = inter_modes_info->sse_arr[data_idx];
5246*77c1e3ccSAndroid Build Coastguard Worker skip_rd = RDCOST(x->rdmult, mode_rate, curr_sse);
5247*77c1e3ccSAndroid Build Coastguard Worker int eval_txfm = check_txfm_eval(x, bsize, search_state->best_skip_rd[0],
5248*77c1e3ccSAndroid Build Coastguard Worker skip_rd, txfm_rd_gate_level, 0);
5249*77c1e3ccSAndroid Build Coastguard Worker if (!eval_txfm) continue;
5250*77c1e3ccSAndroid Build Coastguard Worker }
5251*77c1e3ccSAndroid Build Coastguard Worker
5252*77c1e3ccSAndroid Build Coastguard Worker // Build the prediction for this mode
5253*77c1e3ccSAndroid Build Coastguard Worker if (!is_predictor_built) {
5254*77c1e3ccSAndroid Build Coastguard Worker av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, NULL, bsize, 0,
5255*77c1e3ccSAndroid Build Coastguard Worker av1_num_planes(cm) - 1);
5256*77c1e3ccSAndroid Build Coastguard Worker }
5257*77c1e3ccSAndroid Build Coastguard Worker if (mbmi->motion_mode == OBMC_CAUSAL) {
5258*77c1e3ccSAndroid Build Coastguard Worker av1_build_obmc_inter_predictors_sb(cm, xd);
5259*77c1e3ccSAndroid Build Coastguard Worker }
5260*77c1e3ccSAndroid Build Coastguard Worker
5261*77c1e3ccSAndroid Build Coastguard Worker num_tx_cands++;
5262*77c1e3ccSAndroid Build Coastguard Worker if (have_newmv_in_inter_mode(prediction_mode)) newmv_mode_evaled = 1;
5263*77c1e3ccSAndroid Build Coastguard Worker num_tx_search_modes[prediction_mode - INTER_MODE_START]++;
5264*77c1e3ccSAndroid Build Coastguard Worker int64_t this_yrd = INT64_MAX;
5265*77c1e3ccSAndroid Build Coastguard Worker // Do the transform search
5266*77c1e3ccSAndroid Build Coastguard Worker if (!av1_txfm_search(cpi, x, bsize, &rd_stats, &rd_stats_y, &rd_stats_uv,
5267*77c1e3ccSAndroid Build Coastguard Worker mode_rate, search_state->best_rd)) {
5268*77c1e3ccSAndroid Build Coastguard Worker continue;
5269*77c1e3ccSAndroid Build Coastguard Worker } else {
5270*77c1e3ccSAndroid Build Coastguard Worker const int y_rate =
5271*77c1e3ccSAndroid Build Coastguard Worker rd_stats.skip_txfm
5272*77c1e3ccSAndroid Build Coastguard Worker ? mode_costs->skip_txfm_cost[skip_ctx][1]
5273*77c1e3ccSAndroid Build Coastguard Worker : (rd_stats_y.rate + mode_costs->skip_txfm_cost[skip_ctx][0]);
5274*77c1e3ccSAndroid Build Coastguard Worker this_yrd = RDCOST(x->rdmult, y_rate + mode_rate, rd_stats_y.dist);
5275*77c1e3ccSAndroid Build Coastguard Worker
5276*77c1e3ccSAndroid Build Coastguard Worker if (cpi->sf.inter_sf.inter_mode_rd_model_estimation == 1) {
5277*77c1e3ccSAndroid Build Coastguard Worker inter_mode_data_push(
5278*77c1e3ccSAndroid Build Coastguard Worker tile_data, mbmi->bsize, rd_stats.sse, rd_stats.dist,
5279*77c1e3ccSAndroid Build Coastguard Worker rd_stats_y.rate + rd_stats_uv.rate +
5280*77c1e3ccSAndroid Build Coastguard Worker mode_costs->skip_txfm_cost[skip_ctx][mbmi->skip_txfm]);
5281*77c1e3ccSAndroid Build Coastguard Worker }
5282*77c1e3ccSAndroid Build Coastguard Worker }
5283*77c1e3ccSAndroid Build Coastguard Worker rd_stats.rdcost = RDCOST(x->rdmult, rd_stats.rate, rd_stats.dist);
5284*77c1e3ccSAndroid Build Coastguard Worker if (rd_stats.rdcost < best_rd_in_this_partition) {
5285*77c1e3ccSAndroid Build Coastguard Worker best_rd_in_this_partition = rd_stats.rdcost;
5286*77c1e3ccSAndroid Build Coastguard Worker *yrd = this_yrd;
5287*77c1e3ccSAndroid Build Coastguard Worker }
5288*77c1e3ccSAndroid Build Coastguard Worker
5289*77c1e3ccSAndroid Build Coastguard Worker const THR_MODES mode_enum = get_prediction_mode_idx(
5290*77c1e3ccSAndroid Build Coastguard Worker prediction_mode, mbmi->ref_frame[0], mbmi->ref_frame[1]);
5291*77c1e3ccSAndroid Build Coastguard Worker
5292*77c1e3ccSAndroid Build Coastguard Worker // Collect mode stats for multiwinner mode processing
5293*77c1e3ccSAndroid Build Coastguard Worker const int txfm_search_done = 1;
5294*77c1e3ccSAndroid Build Coastguard Worker store_winner_mode_stats(
5295*77c1e3ccSAndroid Build Coastguard Worker &cpi->common, x, mbmi, &rd_stats, &rd_stats_y, &rd_stats_uv, mode_enum,
5296*77c1e3ccSAndroid Build Coastguard Worker NULL, bsize, rd_stats.rdcost,
5297*77c1e3ccSAndroid Build Coastguard Worker cpi->sf.winner_mode_sf.multi_winner_mode_type, txfm_search_done);
5298*77c1e3ccSAndroid Build Coastguard Worker
5299*77c1e3ccSAndroid Build Coastguard Worker if (rd_stats.rdcost < search_state->best_rd) {
5300*77c1e3ccSAndroid Build Coastguard Worker update_search_state(search_state, rd_cost, ctx, &rd_stats, &rd_stats_y,
5301*77c1e3ccSAndroid Build Coastguard Worker &rd_stats_uv, mode_enum, x, txfm_search_done);
5302*77c1e3ccSAndroid Build Coastguard Worker search_state->best_skip_rd[0] = skip_rd;
5303*77c1e3ccSAndroid Build Coastguard Worker // Limit the total number of modes to be evaluated if the first is valid
5304*77c1e3ccSAndroid Build Coastguard Worker // and transform skip or compound
5305*77c1e3ccSAndroid Build Coastguard Worker if (cpi->sf.inter_sf.inter_mode_txfm_breakout) {
5306*77c1e3ccSAndroid Build Coastguard Worker if (!j && (search_state->best_mbmode.skip_txfm || rd_stats.skip_txfm)) {
5307*77c1e3ccSAndroid Build Coastguard Worker // Evaluate more candidates at high quantizers where occurrence of
5308*77c1e3ccSAndroid Build Coastguard Worker // transform skip is high.
5309*77c1e3ccSAndroid Build Coastguard Worker const int max_cands_cap[5] = { 2, 3, 5, 7, 9 };
5310*77c1e3ccSAndroid Build Coastguard Worker const int qindex_band = (5 * x->qindex) >> QINDEX_BITS;
5311*77c1e3ccSAndroid Build Coastguard Worker num_inter_mode_cands =
5312*77c1e3ccSAndroid Build Coastguard Worker AOMMIN(max_cands_cap[qindex_band], inter_modes_info->num);
5313*77c1e3ccSAndroid Build Coastguard Worker } else if (!j && has_second_ref(&search_state->best_mbmode)) {
5314*77c1e3ccSAndroid Build Coastguard Worker const int aggr = cpi->sf.inter_sf.inter_mode_txfm_breakout - 1;
5315*77c1e3ccSAndroid Build Coastguard Worker // Evaluate more candidates at low quantizers where occurrence of
5316*77c1e3ccSAndroid Build Coastguard Worker // single reference mode is high.
5317*77c1e3ccSAndroid Build Coastguard Worker const int max_cands_cap_cmp[2][4] = { { 10, 7, 5, 4 },
5318*77c1e3ccSAndroid Build Coastguard Worker { 10, 7, 5, 3 } };
5319*77c1e3ccSAndroid Build Coastguard Worker const int qindex_band_cmp = (4 * x->qindex) >> QINDEX_BITS;
5320*77c1e3ccSAndroid Build Coastguard Worker num_inter_mode_cands = AOMMIN(
5321*77c1e3ccSAndroid Build Coastguard Worker max_cands_cap_cmp[aggr][qindex_band_cmp], inter_modes_info->num);
5322*77c1e3ccSAndroid Build Coastguard Worker }
5323*77c1e3ccSAndroid Build Coastguard Worker }
5324*77c1e3ccSAndroid Build Coastguard Worker }
5325*77c1e3ccSAndroid Build Coastguard Worker // If the number of candidates evaluated exceeds max_allowed_cands, break if
5326*77c1e3ccSAndroid Build Coastguard Worker // a newmv mode was evaluated already.
5327*77c1e3ccSAndroid Build Coastguard Worker if ((num_tx_cands > max_allowed_cands) && newmv_mode_evaled) break;
5328*77c1e3ccSAndroid Build Coastguard Worker }
5329*77c1e3ccSAndroid Build Coastguard Worker }
5330*77c1e3ccSAndroid Build Coastguard Worker
5331*77c1e3ccSAndroid Build Coastguard Worker // Indicates number of winner simple translation modes to be used
5332*77c1e3ccSAndroid Build Coastguard Worker static const unsigned int num_winner_motion_modes[3] = { 0, 10, 3 };
5333*77c1e3ccSAndroid Build Coastguard Worker
5334*77c1e3ccSAndroid Build Coastguard Worker // Adds a motion mode to the candidate list for motion_mode_for_winner_cand
5335*77c1e3ccSAndroid Build Coastguard Worker // speed feature. This list consists of modes that have only searched
5336*77c1e3ccSAndroid Build Coastguard Worker // SIMPLE_TRANSLATION. The final list will be used to search other motion
5337*77c1e3ccSAndroid Build Coastguard Worker // modes after the initial RD search.
handle_winner_cand(MB_MODE_INFO * const mbmi,motion_mode_best_st_candidate * best_motion_mode_cands,int max_winner_motion_mode_cand,int64_t this_rd,motion_mode_candidate * motion_mode_cand,int skip_motion_mode)5338*77c1e3ccSAndroid Build Coastguard Worker static void handle_winner_cand(
5339*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *const mbmi,
5340*77c1e3ccSAndroid Build Coastguard Worker motion_mode_best_st_candidate *best_motion_mode_cands,
5341*77c1e3ccSAndroid Build Coastguard Worker int max_winner_motion_mode_cand, int64_t this_rd,
5342*77c1e3ccSAndroid Build Coastguard Worker motion_mode_candidate *motion_mode_cand, int skip_motion_mode) {
5343*77c1e3ccSAndroid Build Coastguard Worker // Number of current motion mode candidates in list
5344*77c1e3ccSAndroid Build Coastguard Worker const int num_motion_mode_cand = best_motion_mode_cands->num_motion_mode_cand;
5345*77c1e3ccSAndroid Build Coastguard Worker int valid_motion_mode_cand_loc = num_motion_mode_cand;
5346*77c1e3ccSAndroid Build Coastguard Worker
5347*77c1e3ccSAndroid Build Coastguard Worker // find the best location to insert new motion mode candidate
5348*77c1e3ccSAndroid Build Coastguard Worker for (int j = 0; j < num_motion_mode_cand; j++) {
5349*77c1e3ccSAndroid Build Coastguard Worker if (this_rd < best_motion_mode_cands->motion_mode_cand[j].rd_cost) {
5350*77c1e3ccSAndroid Build Coastguard Worker valid_motion_mode_cand_loc = j;
5351*77c1e3ccSAndroid Build Coastguard Worker break;
5352*77c1e3ccSAndroid Build Coastguard Worker }
5353*77c1e3ccSAndroid Build Coastguard Worker }
5354*77c1e3ccSAndroid Build Coastguard Worker
5355*77c1e3ccSAndroid Build Coastguard Worker // Insert motion mode if location is found
5356*77c1e3ccSAndroid Build Coastguard Worker if (valid_motion_mode_cand_loc < max_winner_motion_mode_cand) {
5357*77c1e3ccSAndroid Build Coastguard Worker if (num_motion_mode_cand > 0 &&
5358*77c1e3ccSAndroid Build Coastguard Worker valid_motion_mode_cand_loc < max_winner_motion_mode_cand - 1)
5359*77c1e3ccSAndroid Build Coastguard Worker memmove(
5360*77c1e3ccSAndroid Build Coastguard Worker &best_motion_mode_cands
5361*77c1e3ccSAndroid Build Coastguard Worker ->motion_mode_cand[valid_motion_mode_cand_loc + 1],
5362*77c1e3ccSAndroid Build Coastguard Worker &best_motion_mode_cands->motion_mode_cand[valid_motion_mode_cand_loc],
5363*77c1e3ccSAndroid Build Coastguard Worker (AOMMIN(num_motion_mode_cand, max_winner_motion_mode_cand - 1) -
5364*77c1e3ccSAndroid Build Coastguard Worker valid_motion_mode_cand_loc) *
5365*77c1e3ccSAndroid Build Coastguard Worker sizeof(best_motion_mode_cands->motion_mode_cand[0]));
5366*77c1e3ccSAndroid Build Coastguard Worker motion_mode_cand->mbmi = *mbmi;
5367*77c1e3ccSAndroid Build Coastguard Worker motion_mode_cand->rd_cost = this_rd;
5368*77c1e3ccSAndroid Build Coastguard Worker motion_mode_cand->skip_motion_mode = skip_motion_mode;
5369*77c1e3ccSAndroid Build Coastguard Worker best_motion_mode_cands->motion_mode_cand[valid_motion_mode_cand_loc] =
5370*77c1e3ccSAndroid Build Coastguard Worker *motion_mode_cand;
5371*77c1e3ccSAndroid Build Coastguard Worker best_motion_mode_cands->num_motion_mode_cand =
5372*77c1e3ccSAndroid Build Coastguard Worker AOMMIN(max_winner_motion_mode_cand,
5373*77c1e3ccSAndroid Build Coastguard Worker best_motion_mode_cands->num_motion_mode_cand + 1);
5374*77c1e3ccSAndroid Build Coastguard Worker }
5375*77c1e3ccSAndroid Build Coastguard Worker }
5376*77c1e3ccSAndroid Build Coastguard Worker
5377*77c1e3ccSAndroid Build Coastguard Worker /*!\brief Search intra modes in interframes
5378*77c1e3ccSAndroid Build Coastguard Worker *
5379*77c1e3ccSAndroid Build Coastguard Worker * \ingroup intra_mode_search
5380*77c1e3ccSAndroid Build Coastguard Worker *
5381*77c1e3ccSAndroid Build Coastguard Worker * This function searches for the best intra mode when the current frame is an
5382*77c1e3ccSAndroid Build Coastguard Worker * interframe. This function however does *not* handle luma palette mode.
5383*77c1e3ccSAndroid Build Coastguard Worker * Palette mode is currently handled by \ref av1_search_palette_mode.
5384*77c1e3ccSAndroid Build Coastguard Worker *
5385*77c1e3ccSAndroid Build Coastguard Worker * This function will first iterate through the luma mode candidates to find the
5386*77c1e3ccSAndroid Build Coastguard Worker * best luma intra mode. Once the best luma mode it's found, it will then search
5387*77c1e3ccSAndroid Build Coastguard Worker * for the best chroma mode. Because palette mode is currently not handled by
5388*77c1e3ccSAndroid Build Coastguard Worker * here, a cache of uv mode is stored in
5389*77c1e3ccSAndroid Build Coastguard Worker * InterModeSearchState::intra_search_state so it can be reused later by \ref
5390*77c1e3ccSAndroid Build Coastguard Worker * av1_search_palette_mode.
5391*77c1e3ccSAndroid Build Coastguard Worker *
5392*77c1e3ccSAndroid Build Coastguard Worker * \param[in,out] search_state Struct keep track of the prediction mode
5393*77c1e3ccSAndroid Build Coastguard Worker * search state in interframe.
5394*77c1e3ccSAndroid Build Coastguard Worker *
5395*77c1e3ccSAndroid Build Coastguard Worker * \param[in] cpi Top-level encoder structure.
5396*77c1e3ccSAndroid Build Coastguard Worker * \param[in,out] x Pointer to struct holding all the data for
5397*77c1e3ccSAndroid Build Coastguard Worker * the current prediction block.
5398*77c1e3ccSAndroid Build Coastguard Worker * \param[out] rd_cost Stores the best rd_cost among all the
5399*77c1e3ccSAndroid Build Coastguard Worker * prediction modes searched.
5400*77c1e3ccSAndroid Build Coastguard Worker * \param[in] bsize Current block size.
5401*77c1e3ccSAndroid Build Coastguard Worker * \param[in,out] ctx Structure to hold the number of 4x4 blks to
5402*77c1e3ccSAndroid Build Coastguard Worker * copy the tx_type and txfm_skip arrays.
5403*77c1e3ccSAndroid Build Coastguard Worker * for only the Y plane.
5404*77c1e3ccSAndroid Build Coastguard Worker * \param[in] sf_args Stores the list of intra mode candidates
5405*77c1e3ccSAndroid Build Coastguard Worker * to be searched.
5406*77c1e3ccSAndroid Build Coastguard Worker * \param[in] intra_ref_frame_cost The entropy cost for signaling that the
5407*77c1e3ccSAndroid Build Coastguard Worker * current ref frame is an intra frame.
5408*77c1e3ccSAndroid Build Coastguard Worker * \param[in] yrd_threshold The rdcost threshold for luma intra mode to
5409*77c1e3ccSAndroid Build Coastguard Worker * terminate chroma intra mode search.
5410*77c1e3ccSAndroid Build Coastguard Worker *
5411*77c1e3ccSAndroid Build Coastguard Worker * \remark If a new best mode is found, search_state and rd_costs are updated
5412*77c1e3ccSAndroid Build Coastguard Worker * correspondingly. While x is also modified, it is only used as a temporary
5413*77c1e3ccSAndroid Build Coastguard Worker * buffer, and the final decisions are stored in search_state.
5414*77c1e3ccSAndroid Build Coastguard Worker */
search_intra_modes_in_interframe(InterModeSearchState * search_state,const AV1_COMP * cpi,MACROBLOCK * x,RD_STATS * rd_cost,BLOCK_SIZE bsize,PICK_MODE_CONTEXT * ctx,const InterModeSFArgs * sf_args,unsigned int intra_ref_frame_cost,int64_t yrd_threshold)5415*77c1e3ccSAndroid Build Coastguard Worker static inline void search_intra_modes_in_interframe(
5416*77c1e3ccSAndroid Build Coastguard Worker InterModeSearchState *search_state, const AV1_COMP *cpi, MACROBLOCK *x,
5417*77c1e3ccSAndroid Build Coastguard Worker RD_STATS *rd_cost, BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx,
5418*77c1e3ccSAndroid Build Coastguard Worker const InterModeSFArgs *sf_args, unsigned int intra_ref_frame_cost,
5419*77c1e3ccSAndroid Build Coastguard Worker int64_t yrd_threshold) {
5420*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *const cm = &cpi->common;
5421*77c1e3ccSAndroid Build Coastguard Worker const SPEED_FEATURES *const sf = &cpi->sf;
5422*77c1e3ccSAndroid Build Coastguard Worker const IntraModeCfg *const intra_mode_cfg = &cpi->oxcf.intra_mode_cfg;
5423*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *const xd = &x->e_mbd;
5424*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *const mbmi = xd->mi[0];
5425*77c1e3ccSAndroid Build Coastguard Worker IntraModeSearchState *intra_search_state = &search_state->intra_search_state;
5426*77c1e3ccSAndroid Build Coastguard Worker
5427*77c1e3ccSAndroid Build Coastguard Worker int is_best_y_mode_intra = 0;
5428*77c1e3ccSAndroid Build Coastguard Worker RD_STATS best_intra_rd_stats_y;
5429*77c1e3ccSAndroid Build Coastguard Worker int64_t best_rd_y = INT64_MAX;
5430*77c1e3ccSAndroid Build Coastguard Worker int best_mode_cost_y = -1;
5431*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO best_mbmi = *xd->mi[0];
5432*77c1e3ccSAndroid Build Coastguard Worker THR_MODES best_mode_enum = THR_INVALID;
5433*77c1e3ccSAndroid Build Coastguard Worker uint8_t best_blk_skip[MAX_MIB_SIZE * MAX_MIB_SIZE];
5434*77c1e3ccSAndroid Build Coastguard Worker uint8_t best_tx_type_map[MAX_MIB_SIZE * MAX_MIB_SIZE];
5435*77c1e3ccSAndroid Build Coastguard Worker const int num_4x4 = bsize_to_num_blk(bsize);
5436*77c1e3ccSAndroid Build Coastguard Worker
5437*77c1e3ccSAndroid Build Coastguard Worker // Performs luma search
5438*77c1e3ccSAndroid Build Coastguard Worker int64_t best_model_rd = INT64_MAX;
5439*77c1e3ccSAndroid Build Coastguard Worker int64_t top_intra_model_rd[TOP_INTRA_MODEL_COUNT];
5440*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < TOP_INTRA_MODEL_COUNT; i++) {
5441*77c1e3ccSAndroid Build Coastguard Worker top_intra_model_rd[i] = INT64_MAX;
5442*77c1e3ccSAndroid Build Coastguard Worker }
5443*77c1e3ccSAndroid Build Coastguard Worker for (int mode_idx = 0; mode_idx < LUMA_MODE_COUNT; ++mode_idx) {
5444*77c1e3ccSAndroid Build Coastguard Worker if (sf->intra_sf.skip_intra_in_interframe &&
5445*77c1e3ccSAndroid Build Coastguard Worker search_state->intra_search_state.skip_intra_modes)
5446*77c1e3ccSAndroid Build Coastguard Worker break;
5447*77c1e3ccSAndroid Build Coastguard Worker set_y_mode_and_delta_angle(
5448*77c1e3ccSAndroid Build Coastguard Worker mode_idx, mbmi, sf->intra_sf.prune_luma_odd_delta_angles_in_intra);
5449*77c1e3ccSAndroid Build Coastguard Worker assert(mbmi->mode < INTRA_MODE_END);
5450*77c1e3ccSAndroid Build Coastguard Worker
5451*77c1e3ccSAndroid Build Coastguard Worker // Use intra_y_mode_mask speed feature to skip intra mode evaluation.
5452*77c1e3ccSAndroid Build Coastguard Worker if (sf_args->mode_skip_mask->pred_modes[INTRA_FRAME] & (1 << mbmi->mode))
5453*77c1e3ccSAndroid Build Coastguard Worker continue;
5454*77c1e3ccSAndroid Build Coastguard Worker
5455*77c1e3ccSAndroid Build Coastguard Worker const THR_MODES mode_enum =
5456*77c1e3ccSAndroid Build Coastguard Worker get_prediction_mode_idx(mbmi->mode, INTRA_FRAME, NONE_FRAME);
5457*77c1e3ccSAndroid Build Coastguard Worker if ((!intra_mode_cfg->enable_smooth_intra ||
5458*77c1e3ccSAndroid Build Coastguard Worker cpi->sf.intra_sf.disable_smooth_intra) &&
5459*77c1e3ccSAndroid Build Coastguard Worker (mbmi->mode == SMOOTH_PRED || mbmi->mode == SMOOTH_H_PRED ||
5460*77c1e3ccSAndroid Build Coastguard Worker mbmi->mode == SMOOTH_V_PRED))
5461*77c1e3ccSAndroid Build Coastguard Worker continue;
5462*77c1e3ccSAndroid Build Coastguard Worker if (!intra_mode_cfg->enable_paeth_intra && mbmi->mode == PAETH_PRED)
5463*77c1e3ccSAndroid Build Coastguard Worker continue;
5464*77c1e3ccSAndroid Build Coastguard Worker if (av1_is_directional_mode(mbmi->mode) &&
5465*77c1e3ccSAndroid Build Coastguard Worker !(av1_use_angle_delta(bsize) && intra_mode_cfg->enable_angle_delta) &&
5466*77c1e3ccSAndroid Build Coastguard Worker mbmi->angle_delta[PLANE_TYPE_Y] != 0)
5467*77c1e3ccSAndroid Build Coastguard Worker continue;
5468*77c1e3ccSAndroid Build Coastguard Worker const PREDICTION_MODE this_mode = mbmi->mode;
5469*77c1e3ccSAndroid Build Coastguard Worker
5470*77c1e3ccSAndroid Build Coastguard Worker assert(av1_mode_defs[mode_enum].ref_frame[0] == INTRA_FRAME);
5471*77c1e3ccSAndroid Build Coastguard Worker assert(av1_mode_defs[mode_enum].ref_frame[1] == NONE_FRAME);
5472*77c1e3ccSAndroid Build Coastguard Worker init_mbmi(mbmi, this_mode, av1_mode_defs[mode_enum].ref_frame, cm);
5473*77c1e3ccSAndroid Build Coastguard Worker x->txfm_search_info.skip_txfm = 0;
5474*77c1e3ccSAndroid Build Coastguard Worker
5475*77c1e3ccSAndroid Build Coastguard Worker if (this_mode != DC_PRED) {
5476*77c1e3ccSAndroid Build Coastguard Worker // Only search the oblique modes if the best so far is
5477*77c1e3ccSAndroid Build Coastguard Worker // one of the neighboring directional modes
5478*77c1e3ccSAndroid Build Coastguard Worker if ((sf->rt_sf.mode_search_skip_flags & FLAG_SKIP_INTRA_BESTINTER) &&
5479*77c1e3ccSAndroid Build Coastguard Worker (this_mode >= D45_PRED && this_mode <= PAETH_PRED)) {
5480*77c1e3ccSAndroid Build Coastguard Worker if (search_state->best_mode_index != THR_INVALID &&
5481*77c1e3ccSAndroid Build Coastguard Worker search_state->best_mbmode.ref_frame[0] > INTRA_FRAME)
5482*77c1e3ccSAndroid Build Coastguard Worker continue;
5483*77c1e3ccSAndroid Build Coastguard Worker }
5484*77c1e3ccSAndroid Build Coastguard Worker if (sf->rt_sf.mode_search_skip_flags & FLAG_SKIP_INTRA_DIRMISMATCH) {
5485*77c1e3ccSAndroid Build Coastguard Worker if (conditional_skipintra(
5486*77c1e3ccSAndroid Build Coastguard Worker this_mode, search_state->intra_search_state.best_intra_mode))
5487*77c1e3ccSAndroid Build Coastguard Worker continue;
5488*77c1e3ccSAndroid Build Coastguard Worker }
5489*77c1e3ccSAndroid Build Coastguard Worker }
5490*77c1e3ccSAndroid Build Coastguard Worker
5491*77c1e3ccSAndroid Build Coastguard Worker RD_STATS intra_rd_stats_y;
5492*77c1e3ccSAndroid Build Coastguard Worker int mode_cost_y;
5493*77c1e3ccSAndroid Build Coastguard Worker int64_t intra_rd_y = INT64_MAX;
5494*77c1e3ccSAndroid Build Coastguard Worker const int is_luma_result_valid = av1_handle_intra_y_mode(
5495*77c1e3ccSAndroid Build Coastguard Worker intra_search_state, cpi, x, bsize, intra_ref_frame_cost, ctx,
5496*77c1e3ccSAndroid Build Coastguard Worker &intra_rd_stats_y, search_state->best_rd, &mode_cost_y, &intra_rd_y,
5497*77c1e3ccSAndroid Build Coastguard Worker &best_model_rd, top_intra_model_rd);
5498*77c1e3ccSAndroid Build Coastguard Worker if (is_luma_result_valid && intra_rd_y < yrd_threshold) {
5499*77c1e3ccSAndroid Build Coastguard Worker is_best_y_mode_intra = 1;
5500*77c1e3ccSAndroid Build Coastguard Worker if (intra_rd_y < best_rd_y) {
5501*77c1e3ccSAndroid Build Coastguard Worker best_intra_rd_stats_y = intra_rd_stats_y;
5502*77c1e3ccSAndroid Build Coastguard Worker best_mode_cost_y = mode_cost_y;
5503*77c1e3ccSAndroid Build Coastguard Worker best_rd_y = intra_rd_y;
5504*77c1e3ccSAndroid Build Coastguard Worker best_mbmi = *mbmi;
5505*77c1e3ccSAndroid Build Coastguard Worker best_mode_enum = mode_enum;
5506*77c1e3ccSAndroid Build Coastguard Worker memcpy(best_blk_skip, x->txfm_search_info.blk_skip,
5507*77c1e3ccSAndroid Build Coastguard Worker sizeof(best_blk_skip[0]) * num_4x4);
5508*77c1e3ccSAndroid Build Coastguard Worker av1_copy_array(best_tx_type_map, xd->tx_type_map, num_4x4);
5509*77c1e3ccSAndroid Build Coastguard Worker }
5510*77c1e3ccSAndroid Build Coastguard Worker }
5511*77c1e3ccSAndroid Build Coastguard Worker }
5512*77c1e3ccSAndroid Build Coastguard Worker
5513*77c1e3ccSAndroid Build Coastguard Worker if (!is_best_y_mode_intra) {
5514*77c1e3ccSAndroid Build Coastguard Worker return;
5515*77c1e3ccSAndroid Build Coastguard Worker }
5516*77c1e3ccSAndroid Build Coastguard Worker
5517*77c1e3ccSAndroid Build Coastguard Worker assert(best_rd_y < INT64_MAX);
5518*77c1e3ccSAndroid Build Coastguard Worker
5519*77c1e3ccSAndroid Build Coastguard Worker // Restores the best luma mode
5520*77c1e3ccSAndroid Build Coastguard Worker *mbmi = best_mbmi;
5521*77c1e3ccSAndroid Build Coastguard Worker memcpy(x->txfm_search_info.blk_skip, best_blk_skip,
5522*77c1e3ccSAndroid Build Coastguard Worker sizeof(best_blk_skip[0]) * num_4x4);
5523*77c1e3ccSAndroid Build Coastguard Worker av1_copy_array(xd->tx_type_map, best_tx_type_map, num_4x4);
5524*77c1e3ccSAndroid Build Coastguard Worker
5525*77c1e3ccSAndroid Build Coastguard Worker // Performs chroma search
5526*77c1e3ccSAndroid Build Coastguard Worker RD_STATS intra_rd_stats, intra_rd_stats_uv;
5527*77c1e3ccSAndroid Build Coastguard Worker av1_init_rd_stats(&intra_rd_stats);
5528*77c1e3ccSAndroid Build Coastguard Worker av1_init_rd_stats(&intra_rd_stats_uv);
5529*77c1e3ccSAndroid Build Coastguard Worker const int num_planes = av1_num_planes(cm);
5530*77c1e3ccSAndroid Build Coastguard Worker if (num_planes > 1) {
5531*77c1e3ccSAndroid Build Coastguard Worker const int intra_uv_mode_valid = av1_search_intra_uv_modes_in_interframe(
5532*77c1e3ccSAndroid Build Coastguard Worker intra_search_state, cpi, x, bsize, &intra_rd_stats,
5533*77c1e3ccSAndroid Build Coastguard Worker &best_intra_rd_stats_y, &intra_rd_stats_uv, search_state->best_rd);
5534*77c1e3ccSAndroid Build Coastguard Worker
5535*77c1e3ccSAndroid Build Coastguard Worker if (!intra_uv_mode_valid) {
5536*77c1e3ccSAndroid Build Coastguard Worker return;
5537*77c1e3ccSAndroid Build Coastguard Worker }
5538*77c1e3ccSAndroid Build Coastguard Worker }
5539*77c1e3ccSAndroid Build Coastguard Worker
5540*77c1e3ccSAndroid Build Coastguard Worker // Merge the luma and chroma rd stats
5541*77c1e3ccSAndroid Build Coastguard Worker assert(best_mode_cost_y >= 0);
5542*77c1e3ccSAndroid Build Coastguard Worker intra_rd_stats.rate = best_intra_rd_stats_y.rate + best_mode_cost_y;
5543*77c1e3ccSAndroid Build Coastguard Worker if (!xd->lossless[mbmi->segment_id] && block_signals_txsize(bsize)) {
5544*77c1e3ccSAndroid Build Coastguard Worker // av1_pick_uniform_tx_size_type_yrd above includes the cost of the tx_size
5545*77c1e3ccSAndroid Build Coastguard Worker // in the tokenonly rate, but for intra blocks, tx_size is always coded
5546*77c1e3ccSAndroid Build Coastguard Worker // (prediction granularity), so we account for it in the full rate,
5547*77c1e3ccSAndroid Build Coastguard Worker // not the tokenonly rate.
5548*77c1e3ccSAndroid Build Coastguard Worker best_intra_rd_stats_y.rate -= tx_size_cost(x, bsize, mbmi->tx_size);
5549*77c1e3ccSAndroid Build Coastguard Worker }
5550*77c1e3ccSAndroid Build Coastguard Worker
5551*77c1e3ccSAndroid Build Coastguard Worker const ModeCosts *mode_costs = &x->mode_costs;
5552*77c1e3ccSAndroid Build Coastguard Worker const PREDICTION_MODE mode = mbmi->mode;
5553*77c1e3ccSAndroid Build Coastguard Worker if (num_planes > 1 && xd->is_chroma_ref) {
5554*77c1e3ccSAndroid Build Coastguard Worker const int uv_mode_cost =
5555*77c1e3ccSAndroid Build Coastguard Worker mode_costs->intra_uv_mode_cost[is_cfl_allowed(xd)][mode][mbmi->uv_mode];
5556*77c1e3ccSAndroid Build Coastguard Worker intra_rd_stats.rate +=
5557*77c1e3ccSAndroid Build Coastguard Worker intra_rd_stats_uv.rate +
5558*77c1e3ccSAndroid Build Coastguard Worker intra_mode_info_cost_uv(cpi, x, mbmi, bsize, uv_mode_cost);
5559*77c1e3ccSAndroid Build Coastguard Worker }
5560*77c1e3ccSAndroid Build Coastguard Worker
5561*77c1e3ccSAndroid Build Coastguard Worker // Intra block is always coded as non-skip
5562*77c1e3ccSAndroid Build Coastguard Worker intra_rd_stats.skip_txfm = 0;
5563*77c1e3ccSAndroid Build Coastguard Worker intra_rd_stats.dist = best_intra_rd_stats_y.dist + intra_rd_stats_uv.dist;
5564*77c1e3ccSAndroid Build Coastguard Worker // Add in the cost of the no skip flag.
5565*77c1e3ccSAndroid Build Coastguard Worker const int skip_ctx = av1_get_skip_txfm_context(xd);
5566*77c1e3ccSAndroid Build Coastguard Worker intra_rd_stats.rate += mode_costs->skip_txfm_cost[skip_ctx][0];
5567*77c1e3ccSAndroid Build Coastguard Worker // Calculate the final RD estimate for this mode.
5568*77c1e3ccSAndroid Build Coastguard Worker const int64_t this_rd =
5569*77c1e3ccSAndroid Build Coastguard Worker RDCOST(x->rdmult, intra_rd_stats.rate, intra_rd_stats.dist);
5570*77c1e3ccSAndroid Build Coastguard Worker // Keep record of best intra rd
5571*77c1e3ccSAndroid Build Coastguard Worker if (this_rd < search_state->best_intra_rd) {
5572*77c1e3ccSAndroid Build Coastguard Worker search_state->best_intra_rd = this_rd;
5573*77c1e3ccSAndroid Build Coastguard Worker intra_search_state->best_intra_mode = mode;
5574*77c1e3ccSAndroid Build Coastguard Worker }
5575*77c1e3ccSAndroid Build Coastguard Worker
5576*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < REFERENCE_MODES; ++i) {
5577*77c1e3ccSAndroid Build Coastguard Worker search_state->best_pred_rd[i] =
5578*77c1e3ccSAndroid Build Coastguard Worker AOMMIN(search_state->best_pred_rd[i], this_rd);
5579*77c1e3ccSAndroid Build Coastguard Worker }
5580*77c1e3ccSAndroid Build Coastguard Worker
5581*77c1e3ccSAndroid Build Coastguard Worker intra_rd_stats.rdcost = this_rd;
5582*77c1e3ccSAndroid Build Coastguard Worker
5583*77c1e3ccSAndroid Build Coastguard Worker // Collect mode stats for multiwinner mode processing
5584*77c1e3ccSAndroid Build Coastguard Worker const int txfm_search_done = 1;
5585*77c1e3ccSAndroid Build Coastguard Worker store_winner_mode_stats(
5586*77c1e3ccSAndroid Build Coastguard Worker &cpi->common, x, mbmi, &intra_rd_stats, &best_intra_rd_stats_y,
5587*77c1e3ccSAndroid Build Coastguard Worker &intra_rd_stats_uv, best_mode_enum, NULL, bsize, intra_rd_stats.rdcost,
5588*77c1e3ccSAndroid Build Coastguard Worker cpi->sf.winner_mode_sf.multi_winner_mode_type, txfm_search_done);
5589*77c1e3ccSAndroid Build Coastguard Worker if (intra_rd_stats.rdcost < search_state->best_rd) {
5590*77c1e3ccSAndroid Build Coastguard Worker update_search_state(search_state, rd_cost, ctx, &intra_rd_stats,
5591*77c1e3ccSAndroid Build Coastguard Worker &best_intra_rd_stats_y, &intra_rd_stats_uv,
5592*77c1e3ccSAndroid Build Coastguard Worker best_mode_enum, x, txfm_search_done);
5593*77c1e3ccSAndroid Build Coastguard Worker }
5594*77c1e3ccSAndroid Build Coastguard Worker }
5595*77c1e3ccSAndroid Build Coastguard Worker
5596*77c1e3ccSAndroid Build Coastguard Worker #if !CONFIG_REALTIME_ONLY
5597*77c1e3ccSAndroid Build Coastguard Worker // Prepare inter_cost and intra_cost from TPL stats, which are used as ML
5598*77c1e3ccSAndroid Build Coastguard Worker // features in intra mode pruning.
calculate_cost_from_tpl_data(const AV1_COMP * cpi,MACROBLOCK * x,BLOCK_SIZE bsize,int mi_row,int mi_col,int64_t * inter_cost,int64_t * intra_cost)5599*77c1e3ccSAndroid Build Coastguard Worker static inline void calculate_cost_from_tpl_data(const AV1_COMP *cpi,
5600*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCK *x, BLOCK_SIZE bsize,
5601*77c1e3ccSAndroid Build Coastguard Worker int mi_row, int mi_col,
5602*77c1e3ccSAndroid Build Coastguard Worker int64_t *inter_cost,
5603*77c1e3ccSAndroid Build Coastguard Worker int64_t *intra_cost) {
5604*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *const cm = &cpi->common;
5605*77c1e3ccSAndroid Build Coastguard Worker // Only consider full SB.
5606*77c1e3ccSAndroid Build Coastguard Worker const BLOCK_SIZE sb_size = cm->seq_params->sb_size;
5607*77c1e3ccSAndroid Build Coastguard Worker const int tpl_bsize_1d = cpi->ppi->tpl_data.tpl_bsize_1d;
5608*77c1e3ccSAndroid Build Coastguard Worker const int len = (block_size_wide[sb_size] / tpl_bsize_1d) *
5609*77c1e3ccSAndroid Build Coastguard Worker (block_size_high[sb_size] / tpl_bsize_1d);
5610*77c1e3ccSAndroid Build Coastguard Worker SuperBlockEnc *sb_enc = &x->sb_enc;
5611*77c1e3ccSAndroid Build Coastguard Worker if (sb_enc->tpl_data_count == len) {
5612*77c1e3ccSAndroid Build Coastguard Worker const BLOCK_SIZE tpl_bsize = convert_length_to_bsize(tpl_bsize_1d);
5613*77c1e3ccSAndroid Build Coastguard Worker const int tpl_stride = sb_enc->tpl_stride;
5614*77c1e3ccSAndroid Build Coastguard Worker const int tplw = mi_size_wide[tpl_bsize];
5615*77c1e3ccSAndroid Build Coastguard Worker const int tplh = mi_size_high[tpl_bsize];
5616*77c1e3ccSAndroid Build Coastguard Worker const int nw = mi_size_wide[bsize] / tplw;
5617*77c1e3ccSAndroid Build Coastguard Worker const int nh = mi_size_high[bsize] / tplh;
5618*77c1e3ccSAndroid Build Coastguard Worker if (nw >= 1 && nh >= 1) {
5619*77c1e3ccSAndroid Build Coastguard Worker const int of_h = mi_row % mi_size_high[sb_size];
5620*77c1e3ccSAndroid Build Coastguard Worker const int of_w = mi_col % mi_size_wide[sb_size];
5621*77c1e3ccSAndroid Build Coastguard Worker const int start = of_h / tplh * tpl_stride + of_w / tplw;
5622*77c1e3ccSAndroid Build Coastguard Worker
5623*77c1e3ccSAndroid Build Coastguard Worker for (int k = 0; k < nh; k++) {
5624*77c1e3ccSAndroid Build Coastguard Worker for (int l = 0; l < nw; l++) {
5625*77c1e3ccSAndroid Build Coastguard Worker *inter_cost += sb_enc->tpl_inter_cost[start + k * tpl_stride + l];
5626*77c1e3ccSAndroid Build Coastguard Worker *intra_cost += sb_enc->tpl_intra_cost[start + k * tpl_stride + l];
5627*77c1e3ccSAndroid Build Coastguard Worker }
5628*77c1e3ccSAndroid Build Coastguard Worker }
5629*77c1e3ccSAndroid Build Coastguard Worker *inter_cost /= nw * nh;
5630*77c1e3ccSAndroid Build Coastguard Worker *intra_cost /= nw * nh;
5631*77c1e3ccSAndroid Build Coastguard Worker }
5632*77c1e3ccSAndroid Build Coastguard Worker }
5633*77c1e3ccSAndroid Build Coastguard Worker }
5634*77c1e3ccSAndroid Build Coastguard Worker #endif // !CONFIG_REALTIME_ONLY
5635*77c1e3ccSAndroid Build Coastguard Worker
5636*77c1e3ccSAndroid Build Coastguard Worker // When the speed feature skip_intra_in_interframe > 0, enable ML model to prune
5637*77c1e3ccSAndroid Build Coastguard Worker // intra mode search.
skip_intra_modes_in_interframe(AV1_COMMON * const cm,struct macroblock * x,BLOCK_SIZE bsize,InterModeSearchState * search_state,const SPEED_FEATURES * const sf,int64_t inter_cost,int64_t intra_cost)5638*77c1e3ccSAndroid Build Coastguard Worker static inline void skip_intra_modes_in_interframe(
5639*77c1e3ccSAndroid Build Coastguard Worker AV1_COMMON *const cm, struct macroblock *x, BLOCK_SIZE bsize,
5640*77c1e3ccSAndroid Build Coastguard Worker InterModeSearchState *search_state, const SPEED_FEATURES *const sf,
5641*77c1e3ccSAndroid Build Coastguard Worker int64_t inter_cost, int64_t intra_cost) {
5642*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *const xd = &x->e_mbd;
5643*77c1e3ccSAndroid Build Coastguard Worker const int comp_pred = search_state->best_mbmode.ref_frame[1] > INTRA_FRAME;
5644*77c1e3ccSAndroid Build Coastguard Worker if (sf->rt_sf.prune_intra_mode_based_on_mv_range &&
5645*77c1e3ccSAndroid Build Coastguard Worker bsize > sf->part_sf.max_intra_bsize && !comp_pred) {
5646*77c1e3ccSAndroid Build Coastguard Worker const MV best_mv = search_state->best_mbmode.mv[0].as_mv;
5647*77c1e3ccSAndroid Build Coastguard Worker const int mv_thresh = 16 << sf->rt_sf.prune_intra_mode_based_on_mv_range;
5648*77c1e3ccSAndroid Build Coastguard Worker if (abs(best_mv.row) < mv_thresh && abs(best_mv.col) < mv_thresh &&
5649*77c1e3ccSAndroid Build Coastguard Worker x->source_variance > 128) {
5650*77c1e3ccSAndroid Build Coastguard Worker search_state->intra_search_state.skip_intra_modes = 1;
5651*77c1e3ccSAndroid Build Coastguard Worker return;
5652*77c1e3ccSAndroid Build Coastguard Worker }
5653*77c1e3ccSAndroid Build Coastguard Worker }
5654*77c1e3ccSAndroid Build Coastguard Worker
5655*77c1e3ccSAndroid Build Coastguard Worker const unsigned int src_var_thresh_intra_skip = 1;
5656*77c1e3ccSAndroid Build Coastguard Worker const int skip_intra_in_interframe = sf->intra_sf.skip_intra_in_interframe;
5657*77c1e3ccSAndroid Build Coastguard Worker if (!(skip_intra_in_interframe &&
5658*77c1e3ccSAndroid Build Coastguard Worker (x->source_variance > src_var_thresh_intra_skip)))
5659*77c1e3ccSAndroid Build Coastguard Worker return;
5660*77c1e3ccSAndroid Build Coastguard Worker
5661*77c1e3ccSAndroid Build Coastguard Worker // Prune intra search based on best inter mode being transfrom skip.
5662*77c1e3ccSAndroid Build Coastguard Worker if ((skip_intra_in_interframe >= 2) && search_state->best_mbmode.skip_txfm) {
5663*77c1e3ccSAndroid Build Coastguard Worker const int qindex_thresh[2] = { 200, MAXQ };
5664*77c1e3ccSAndroid Build Coastguard Worker const int ind = (skip_intra_in_interframe >= 3) ? 1 : 0;
5665*77c1e3ccSAndroid Build Coastguard Worker if (!have_newmv_in_inter_mode(search_state->best_mbmode.mode) &&
5666*77c1e3ccSAndroid Build Coastguard Worker (x->qindex <= qindex_thresh[ind])) {
5667*77c1e3ccSAndroid Build Coastguard Worker search_state->intra_search_state.skip_intra_modes = 1;
5668*77c1e3ccSAndroid Build Coastguard Worker return;
5669*77c1e3ccSAndroid Build Coastguard Worker } else if ((skip_intra_in_interframe >= 4) &&
5670*77c1e3ccSAndroid Build Coastguard Worker (inter_cost < 0 || intra_cost < 0)) {
5671*77c1e3ccSAndroid Build Coastguard Worker search_state->intra_search_state.skip_intra_modes = 1;
5672*77c1e3ccSAndroid Build Coastguard Worker return;
5673*77c1e3ccSAndroid Build Coastguard Worker }
5674*77c1e3ccSAndroid Build Coastguard Worker }
5675*77c1e3ccSAndroid Build Coastguard Worker // Use ML model to prune intra search.
5676*77c1e3ccSAndroid Build Coastguard Worker if (inter_cost >= 0 && intra_cost >= 0) {
5677*77c1e3ccSAndroid Build Coastguard Worker const NN_CONFIG *nn_config = (AOMMIN(cm->width, cm->height) <= 480)
5678*77c1e3ccSAndroid Build Coastguard Worker ? &av1_intrap_nn_config
5679*77c1e3ccSAndroid Build Coastguard Worker : &av1_intrap_hd_nn_config;
5680*77c1e3ccSAndroid Build Coastguard Worker float nn_features[6];
5681*77c1e3ccSAndroid Build Coastguard Worker float scores[2] = { 0.0f };
5682*77c1e3ccSAndroid Build Coastguard Worker
5683*77c1e3ccSAndroid Build Coastguard Worker nn_features[0] = (float)search_state->best_mbmode.skip_txfm;
5684*77c1e3ccSAndroid Build Coastguard Worker nn_features[1] = (float)mi_size_wide_log2[bsize];
5685*77c1e3ccSAndroid Build Coastguard Worker nn_features[2] = (float)mi_size_high_log2[bsize];
5686*77c1e3ccSAndroid Build Coastguard Worker nn_features[3] = (float)intra_cost;
5687*77c1e3ccSAndroid Build Coastguard Worker nn_features[4] = (float)inter_cost;
5688*77c1e3ccSAndroid Build Coastguard Worker const int ac_q = av1_ac_quant_QTX(x->qindex, 0, xd->bd);
5689*77c1e3ccSAndroid Build Coastguard Worker const int ac_q_max = av1_ac_quant_QTX(255, 0, xd->bd);
5690*77c1e3ccSAndroid Build Coastguard Worker nn_features[5] = (float)(ac_q_max / ac_q);
5691*77c1e3ccSAndroid Build Coastguard Worker
5692*77c1e3ccSAndroid Build Coastguard Worker av1_nn_predict(nn_features, nn_config, 1, scores);
5693*77c1e3ccSAndroid Build Coastguard Worker
5694*77c1e3ccSAndroid Build Coastguard Worker // For two parameters, the max prob returned from av1_nn_softmax equals
5695*77c1e3ccSAndroid Build Coastguard Worker // 1.0 / (1.0 + e^(-|diff_score|)). Here use scores directly to avoid the
5696*77c1e3ccSAndroid Build Coastguard Worker // calling of av1_nn_softmax.
5697*77c1e3ccSAndroid Build Coastguard Worker const float thresh[5] = { 1.4f, 1.4f, 1.4f, 1.4f, 1.4f };
5698*77c1e3ccSAndroid Build Coastguard Worker assert(skip_intra_in_interframe <= 5);
5699*77c1e3ccSAndroid Build Coastguard Worker if (scores[1] > scores[0] + thresh[skip_intra_in_interframe - 1]) {
5700*77c1e3ccSAndroid Build Coastguard Worker search_state->intra_search_state.skip_intra_modes = 1;
5701*77c1e3ccSAndroid Build Coastguard Worker }
5702*77c1e3ccSAndroid Build Coastguard Worker }
5703*77c1e3ccSAndroid Build Coastguard Worker }
5704*77c1e3ccSAndroid Build Coastguard Worker
skip_interp_filter_search(const AV1_COMP * cpi,int is_single_pred)5705*77c1e3ccSAndroid Build Coastguard Worker static inline bool skip_interp_filter_search(const AV1_COMP *cpi,
5706*77c1e3ccSAndroid Build Coastguard Worker int is_single_pred) {
5707*77c1e3ccSAndroid Build Coastguard Worker const MODE encoding_mode = cpi->oxcf.mode;
5708*77c1e3ccSAndroid Build Coastguard Worker if (encoding_mode == REALTIME) {
5709*77c1e3ccSAndroid Build Coastguard Worker return (cpi->common.current_frame.reference_mode == SINGLE_REFERENCE &&
5710*77c1e3ccSAndroid Build Coastguard Worker (cpi->sf.interp_sf.skip_interp_filter_search ||
5711*77c1e3ccSAndroid Build Coastguard Worker cpi->sf.winner_mode_sf.winner_mode_ifs));
5712*77c1e3ccSAndroid Build Coastguard Worker } else if (encoding_mode == GOOD) {
5713*77c1e3ccSAndroid Build Coastguard Worker // Skip interpolation filter search for single prediction modes.
5714*77c1e3ccSAndroid Build Coastguard Worker return (cpi->sf.interp_sf.skip_interp_filter_search && is_single_pred);
5715*77c1e3ccSAndroid Build Coastguard Worker }
5716*77c1e3ccSAndroid Build Coastguard Worker return false;
5717*77c1e3ccSAndroid Build Coastguard Worker }
5718*77c1e3ccSAndroid Build Coastguard Worker
get_block_temp_var(const AV1_COMP * cpi,const MACROBLOCK * x,BLOCK_SIZE bsize)5719*77c1e3ccSAndroid Build Coastguard Worker static inline int get_block_temp_var(const AV1_COMP *cpi, const MACROBLOCK *x,
5720*77c1e3ccSAndroid Build Coastguard Worker BLOCK_SIZE bsize) {
5721*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *const cm = &cpi->common;
5722*77c1e3ccSAndroid Build Coastguard Worker const SPEED_FEATURES *const sf = &cpi->sf;
5723*77c1e3ccSAndroid Build Coastguard Worker
5724*77c1e3ccSAndroid Build Coastguard Worker if (sf->part_sf.partition_search_type != VAR_BASED_PARTITION ||
5725*77c1e3ccSAndroid Build Coastguard Worker !sf->rt_sf.short_circuit_low_temp_var ||
5726*77c1e3ccSAndroid Build Coastguard Worker !sf->rt_sf.prune_inter_modes_using_temp_var) {
5727*77c1e3ccSAndroid Build Coastguard Worker return 0;
5728*77c1e3ccSAndroid Build Coastguard Worker }
5729*77c1e3ccSAndroid Build Coastguard Worker
5730*77c1e3ccSAndroid Build Coastguard Worker const int mi_row = x->e_mbd.mi_row;
5731*77c1e3ccSAndroid Build Coastguard Worker const int mi_col = x->e_mbd.mi_col;
5732*77c1e3ccSAndroid Build Coastguard Worker int is_low_temp_var = 0;
5733*77c1e3ccSAndroid Build Coastguard Worker
5734*77c1e3ccSAndroid Build Coastguard Worker if (cm->seq_params->sb_size == BLOCK_64X64)
5735*77c1e3ccSAndroid Build Coastguard Worker is_low_temp_var = av1_get_force_skip_low_temp_var_small_sb(
5736*77c1e3ccSAndroid Build Coastguard Worker &x->part_search_info.variance_low[0], mi_row, mi_col, bsize);
5737*77c1e3ccSAndroid Build Coastguard Worker else
5738*77c1e3ccSAndroid Build Coastguard Worker is_low_temp_var = av1_get_force_skip_low_temp_var(
5739*77c1e3ccSAndroid Build Coastguard Worker &x->part_search_info.variance_low[0], mi_row, mi_col, bsize);
5740*77c1e3ccSAndroid Build Coastguard Worker
5741*77c1e3ccSAndroid Build Coastguard Worker return is_low_temp_var;
5742*77c1e3ccSAndroid Build Coastguard Worker }
5743*77c1e3ccSAndroid Build Coastguard Worker
5744*77c1e3ccSAndroid Build Coastguard Worker // TODO([email protected]): See the todo for av1_rd_pick_intra_mode_sb.
av1_rd_pick_inter_mode(struct AV1_COMP * cpi,struct TileDataEnc * tile_data,struct macroblock * x,struct RD_STATS * rd_cost,BLOCK_SIZE bsize,PICK_MODE_CONTEXT * ctx,int64_t best_rd_so_far)5745*77c1e3ccSAndroid Build Coastguard Worker void av1_rd_pick_inter_mode(struct AV1_COMP *cpi, struct TileDataEnc *tile_data,
5746*77c1e3ccSAndroid Build Coastguard Worker struct macroblock *x, struct RD_STATS *rd_cost,
5747*77c1e3ccSAndroid Build Coastguard Worker BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx,
5748*77c1e3ccSAndroid Build Coastguard Worker int64_t best_rd_so_far) {
5749*77c1e3ccSAndroid Build Coastguard Worker AV1_COMMON *const cm = &cpi->common;
5750*77c1e3ccSAndroid Build Coastguard Worker const FeatureFlags *const features = &cm->features;
5751*77c1e3ccSAndroid Build Coastguard Worker const int num_planes = av1_num_planes(cm);
5752*77c1e3ccSAndroid Build Coastguard Worker const SPEED_FEATURES *const sf = &cpi->sf;
5753*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *const xd = &x->e_mbd;
5754*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *const mbmi = xd->mi[0];
5755*77c1e3ccSAndroid Build Coastguard Worker TxfmSearchInfo *txfm_info = &x->txfm_search_info;
5756*77c1e3ccSAndroid Build Coastguard Worker int i;
5757*77c1e3ccSAndroid Build Coastguard Worker const ModeCosts *mode_costs = &x->mode_costs;
5758*77c1e3ccSAndroid Build Coastguard Worker const int *comp_inter_cost =
5759*77c1e3ccSAndroid Build Coastguard Worker mode_costs->comp_inter_cost[av1_get_reference_mode_context(xd)];
5760*77c1e3ccSAndroid Build Coastguard Worker
5761*77c1e3ccSAndroid Build Coastguard Worker InterModeSearchState search_state;
5762*77c1e3ccSAndroid Build Coastguard Worker init_inter_mode_search_state(&search_state, cpi, x, bsize, best_rd_so_far);
5763*77c1e3ccSAndroid Build Coastguard Worker INTERINTRA_MODE interintra_modes[REF_FRAMES] = {
5764*77c1e3ccSAndroid Build Coastguard Worker INTERINTRA_MODES, INTERINTRA_MODES, INTERINTRA_MODES, INTERINTRA_MODES,
5765*77c1e3ccSAndroid Build Coastguard Worker INTERINTRA_MODES, INTERINTRA_MODES, INTERINTRA_MODES, INTERINTRA_MODES
5766*77c1e3ccSAndroid Build Coastguard Worker };
5767*77c1e3ccSAndroid Build Coastguard Worker HandleInterModeArgs args = { { NULL },
5768*77c1e3ccSAndroid Build Coastguard Worker { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE },
5769*77c1e3ccSAndroid Build Coastguard Worker { NULL },
5770*77c1e3ccSAndroid Build Coastguard Worker { MAX_SB_SIZE >> 1, MAX_SB_SIZE >> 1,
5771*77c1e3ccSAndroid Build Coastguard Worker MAX_SB_SIZE >> 1 },
5772*77c1e3ccSAndroid Build Coastguard Worker NULL,
5773*77c1e3ccSAndroid Build Coastguard Worker NULL,
5774*77c1e3ccSAndroid Build Coastguard Worker NULL,
5775*77c1e3ccSAndroid Build Coastguard Worker search_state.modelled_rd,
5776*77c1e3ccSAndroid Build Coastguard Worker INT_MAX,
5777*77c1e3ccSAndroid Build Coastguard Worker INT_MAX,
5778*77c1e3ccSAndroid Build Coastguard Worker search_state.simple_rd,
5779*77c1e3ccSAndroid Build Coastguard Worker 0,
5780*77c1e3ccSAndroid Build Coastguard Worker false,
5781*77c1e3ccSAndroid Build Coastguard Worker interintra_modes,
5782*77c1e3ccSAndroid Build Coastguard Worker { { { 0 }, { { 0 } }, { 0 }, 0, 0, 0, 0 } },
5783*77c1e3ccSAndroid Build Coastguard Worker { { 0, 0 } },
5784*77c1e3ccSAndroid Build Coastguard Worker { 0 },
5785*77c1e3ccSAndroid Build Coastguard Worker 0,
5786*77c1e3ccSAndroid Build Coastguard Worker 0,
5787*77c1e3ccSAndroid Build Coastguard Worker -1,
5788*77c1e3ccSAndroid Build Coastguard Worker -1,
5789*77c1e3ccSAndroid Build Coastguard Worker -1,
5790*77c1e3ccSAndroid Build Coastguard Worker { 0 },
5791*77c1e3ccSAndroid Build Coastguard Worker { 0 },
5792*77c1e3ccSAndroid Build Coastguard Worker UINT_MAX };
5793*77c1e3ccSAndroid Build Coastguard Worker // Currently, is_low_temp_var is used in real time encoding.
5794*77c1e3ccSAndroid Build Coastguard Worker const int is_low_temp_var = get_block_temp_var(cpi, x, bsize);
5795*77c1e3ccSAndroid Build Coastguard Worker
5796*77c1e3ccSAndroid Build Coastguard Worker for (i = 0; i < MODE_CTX_REF_FRAMES; ++i) args.cmp_mode[i] = -1;
5797*77c1e3ccSAndroid Build Coastguard Worker // Indicates the appropriate number of simple translation winner modes for
5798*77c1e3ccSAndroid Build Coastguard Worker // exhaustive motion mode evaluation
5799*77c1e3ccSAndroid Build Coastguard Worker const int max_winner_motion_mode_cand =
5800*77c1e3ccSAndroid Build Coastguard Worker num_winner_motion_modes[sf->winner_mode_sf.motion_mode_for_winner_cand];
5801*77c1e3ccSAndroid Build Coastguard Worker assert(max_winner_motion_mode_cand <= MAX_WINNER_MOTION_MODES);
5802*77c1e3ccSAndroid Build Coastguard Worker motion_mode_candidate motion_mode_cand;
5803*77c1e3ccSAndroid Build Coastguard Worker motion_mode_best_st_candidate best_motion_mode_cands;
5804*77c1e3ccSAndroid Build Coastguard Worker // Initializing the number of motion mode candidates to zero.
5805*77c1e3ccSAndroid Build Coastguard Worker best_motion_mode_cands.num_motion_mode_cand = 0;
5806*77c1e3ccSAndroid Build Coastguard Worker for (i = 0; i < MAX_WINNER_MOTION_MODES; ++i)
5807*77c1e3ccSAndroid Build Coastguard Worker best_motion_mode_cands.motion_mode_cand[i].rd_cost = INT64_MAX;
5808*77c1e3ccSAndroid Build Coastguard Worker
5809*77c1e3ccSAndroid Build Coastguard Worker for (i = 0; i < REF_FRAMES; ++i) x->pred_sse[i] = INT_MAX;
5810*77c1e3ccSAndroid Build Coastguard Worker
5811*77c1e3ccSAndroid Build Coastguard Worker av1_invalid_rd_stats(rd_cost);
5812*77c1e3ccSAndroid Build Coastguard Worker
5813*77c1e3ccSAndroid Build Coastguard Worker for (i = 0; i < REF_FRAMES; ++i) {
5814*77c1e3ccSAndroid Build Coastguard Worker x->warp_sample_info[i].num = -1;
5815*77c1e3ccSAndroid Build Coastguard Worker }
5816*77c1e3ccSAndroid Build Coastguard Worker
5817*77c1e3ccSAndroid Build Coastguard Worker // Ref frames that are selected by square partition blocks.
5818*77c1e3ccSAndroid Build Coastguard Worker int picked_ref_frames_mask = 0;
5819*77c1e3ccSAndroid Build Coastguard Worker if (sf->inter_sf.prune_ref_frame_for_rect_partitions &&
5820*77c1e3ccSAndroid Build Coastguard Worker mbmi->partition != PARTITION_NONE) {
5821*77c1e3ccSAndroid Build Coastguard Worker // prune_ref_frame_for_rect_partitions = 1 implies prune only extended
5822*77c1e3ccSAndroid Build Coastguard Worker // partition blocks. prune_ref_frame_for_rect_partitions >=2
5823*77c1e3ccSAndroid Build Coastguard Worker // implies prune for vert, horiz and extended partition blocks.
5824*77c1e3ccSAndroid Build Coastguard Worker if ((mbmi->partition != PARTITION_VERT &&
5825*77c1e3ccSAndroid Build Coastguard Worker mbmi->partition != PARTITION_HORZ) ||
5826*77c1e3ccSAndroid Build Coastguard Worker sf->inter_sf.prune_ref_frame_for_rect_partitions >= 2) {
5827*77c1e3ccSAndroid Build Coastguard Worker picked_ref_frames_mask =
5828*77c1e3ccSAndroid Build Coastguard Worker fetch_picked_ref_frames_mask(x, bsize, cm->seq_params->mib_size);
5829*77c1e3ccSAndroid Build Coastguard Worker }
5830*77c1e3ccSAndroid Build Coastguard Worker }
5831*77c1e3ccSAndroid Build Coastguard Worker
5832*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_COLLECT_COMPONENT_TIMING
5833*77c1e3ccSAndroid Build Coastguard Worker start_timing(cpi, set_params_rd_pick_inter_mode_time);
5834*77c1e3ccSAndroid Build Coastguard Worker #endif
5835*77c1e3ccSAndroid Build Coastguard Worker // Skip ref frames that never selected by square blocks.
5836*77c1e3ccSAndroid Build Coastguard Worker const int skip_ref_frame_mask =
5837*77c1e3ccSAndroid Build Coastguard Worker picked_ref_frames_mask ? ~picked_ref_frames_mask : 0;
5838*77c1e3ccSAndroid Build Coastguard Worker mode_skip_mask_t mode_skip_mask;
5839*77c1e3ccSAndroid Build Coastguard Worker unsigned int ref_costs_single[REF_FRAMES];
5840*77c1e3ccSAndroid Build Coastguard Worker unsigned int ref_costs_comp[REF_FRAMES][REF_FRAMES];
5841*77c1e3ccSAndroid Build Coastguard Worker struct buf_2d yv12_mb[REF_FRAMES][MAX_MB_PLANE];
5842*77c1e3ccSAndroid Build Coastguard Worker // init params, set frame modes, speed features
5843*77c1e3ccSAndroid Build Coastguard Worker set_params_rd_pick_inter_mode(cpi, x, &args, bsize, &mode_skip_mask,
5844*77c1e3ccSAndroid Build Coastguard Worker skip_ref_frame_mask, ref_costs_single,
5845*77c1e3ccSAndroid Build Coastguard Worker ref_costs_comp, yv12_mb);
5846*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_COLLECT_COMPONENT_TIMING
5847*77c1e3ccSAndroid Build Coastguard Worker end_timing(cpi, set_params_rd_pick_inter_mode_time);
5848*77c1e3ccSAndroid Build Coastguard Worker #endif
5849*77c1e3ccSAndroid Build Coastguard Worker
5850*77c1e3ccSAndroid Build Coastguard Worker int64_t best_est_rd = INT64_MAX;
5851*77c1e3ccSAndroid Build Coastguard Worker const InterModeRdModel *md = &tile_data->inter_mode_rd_models[bsize];
5852*77c1e3ccSAndroid Build Coastguard Worker // If do_tx_search is 0, only estimated RD should be computed.
5853*77c1e3ccSAndroid Build Coastguard Worker // If do_tx_search is 1, all modes have TX search performed.
5854*77c1e3ccSAndroid Build Coastguard Worker const int do_tx_search =
5855*77c1e3ccSAndroid Build Coastguard Worker !((sf->inter_sf.inter_mode_rd_model_estimation == 1 && md->ready) ||
5856*77c1e3ccSAndroid Build Coastguard Worker (sf->inter_sf.inter_mode_rd_model_estimation == 2 &&
5857*77c1e3ccSAndroid Build Coastguard Worker num_pels_log2_lookup[bsize] > 8));
5858*77c1e3ccSAndroid Build Coastguard Worker InterModesInfo *inter_modes_info = x->inter_modes_info;
5859*77c1e3ccSAndroid Build Coastguard Worker inter_modes_info->num = 0;
5860*77c1e3ccSAndroid Build Coastguard Worker
5861*77c1e3ccSAndroid Build Coastguard Worker // Temporary buffers used by handle_inter_mode().
5862*77c1e3ccSAndroid Build Coastguard Worker uint8_t *const tmp_buf = get_buf_by_bd(xd, x->tmp_pred_bufs[0]);
5863*77c1e3ccSAndroid Build Coastguard Worker
5864*77c1e3ccSAndroid Build Coastguard Worker // The best RD found for the reference frame, among single reference modes.
5865*77c1e3ccSAndroid Build Coastguard Worker // Note that the 0-th element will contain a cut-off that is later used
5866*77c1e3ccSAndroid Build Coastguard Worker // to determine if we should skip a compound mode.
5867*77c1e3ccSAndroid Build Coastguard Worker int64_t ref_frame_rd[REF_FRAMES] = { INT64_MAX, INT64_MAX, INT64_MAX,
5868*77c1e3ccSAndroid Build Coastguard Worker INT64_MAX, INT64_MAX, INT64_MAX,
5869*77c1e3ccSAndroid Build Coastguard Worker INT64_MAX, INT64_MAX };
5870*77c1e3ccSAndroid Build Coastguard Worker
5871*77c1e3ccSAndroid Build Coastguard Worker // Prepared stats used later to check if we could skip intra mode eval.
5872*77c1e3ccSAndroid Build Coastguard Worker int64_t inter_cost = -1;
5873*77c1e3ccSAndroid Build Coastguard Worker int64_t intra_cost = -1;
5874*77c1e3ccSAndroid Build Coastguard Worker // Need to tweak the threshold for hdres speed 0 & 1.
5875*77c1e3ccSAndroid Build Coastguard Worker const int mi_row = xd->mi_row;
5876*77c1e3ccSAndroid Build Coastguard Worker const int mi_col = xd->mi_col;
5877*77c1e3ccSAndroid Build Coastguard Worker
5878*77c1e3ccSAndroid Build Coastguard Worker // Obtain the relevant tpl stats for pruning inter modes
5879*77c1e3ccSAndroid Build Coastguard Worker PruneInfoFromTpl inter_cost_info_from_tpl;
5880*77c1e3ccSAndroid Build Coastguard Worker #if !CONFIG_REALTIME_ONLY
5881*77c1e3ccSAndroid Build Coastguard Worker if (sf->inter_sf.prune_inter_modes_based_on_tpl) {
5882*77c1e3ccSAndroid Build Coastguard Worker // x->tpl_keep_ref_frame[id] = 1 => no pruning in
5883*77c1e3ccSAndroid Build Coastguard Worker // prune_ref_by_selective_ref_frame()
5884*77c1e3ccSAndroid Build Coastguard Worker // x->tpl_keep_ref_frame[id] = 0 => ref frame can be pruned in
5885*77c1e3ccSAndroid Build Coastguard Worker // prune_ref_by_selective_ref_frame()
5886*77c1e3ccSAndroid Build Coastguard Worker // Populating valid_refs[idx] = 1 ensures that
5887*77c1e3ccSAndroid Build Coastguard Worker // 'inter_cost_info_from_tpl.best_inter_cost' does not correspond to a
5888*77c1e3ccSAndroid Build Coastguard Worker // pruned ref frame.
5889*77c1e3ccSAndroid Build Coastguard Worker int valid_refs[INTER_REFS_PER_FRAME];
5890*77c1e3ccSAndroid Build Coastguard Worker for (MV_REFERENCE_FRAME frame = LAST_FRAME; frame < REF_FRAMES; frame++) {
5891*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME refs[2] = { frame, NONE_FRAME };
5892*77c1e3ccSAndroid Build Coastguard Worker valid_refs[frame - 1] =
5893*77c1e3ccSAndroid Build Coastguard Worker x->tpl_keep_ref_frame[frame] ||
5894*77c1e3ccSAndroid Build Coastguard Worker !prune_ref_by_selective_ref_frame(
5895*77c1e3ccSAndroid Build Coastguard Worker cpi, x, refs, cm->cur_frame->ref_display_order_hint);
5896*77c1e3ccSAndroid Build Coastguard Worker }
5897*77c1e3ccSAndroid Build Coastguard Worker av1_zero(inter_cost_info_from_tpl);
5898*77c1e3ccSAndroid Build Coastguard Worker get_block_level_tpl_stats(cpi, bsize, mi_row, mi_col, valid_refs,
5899*77c1e3ccSAndroid Build Coastguard Worker &inter_cost_info_from_tpl);
5900*77c1e3ccSAndroid Build Coastguard Worker }
5901*77c1e3ccSAndroid Build Coastguard Worker
5902*77c1e3ccSAndroid Build Coastguard Worker const int do_pruning =
5903*77c1e3ccSAndroid Build Coastguard Worker (AOMMIN(cm->width, cm->height) > 480 && cpi->speed <= 1) ? 0 : 1;
5904*77c1e3ccSAndroid Build Coastguard Worker if (do_pruning && sf->intra_sf.skip_intra_in_interframe &&
5905*77c1e3ccSAndroid Build Coastguard Worker cpi->oxcf.algo_cfg.enable_tpl_model)
5906*77c1e3ccSAndroid Build Coastguard Worker calculate_cost_from_tpl_data(cpi, x, bsize, mi_row, mi_col, &inter_cost,
5907*77c1e3ccSAndroid Build Coastguard Worker &intra_cost);
5908*77c1e3ccSAndroid Build Coastguard Worker #endif // !CONFIG_REALTIME_ONLY
5909*77c1e3ccSAndroid Build Coastguard Worker
5910*77c1e3ccSAndroid Build Coastguard Worker // Initialize best mode stats for winner mode processing.
5911*77c1e3ccSAndroid Build Coastguard Worker const int max_winner_mode_count =
5912*77c1e3ccSAndroid Build Coastguard Worker winner_mode_count_allowed[sf->winner_mode_sf.multi_winner_mode_type];
5913*77c1e3ccSAndroid Build Coastguard Worker zero_winner_mode_stats(bsize, max_winner_mode_count, x->winner_mode_stats);
5914*77c1e3ccSAndroid Build Coastguard Worker x->winner_mode_count = 0;
5915*77c1e3ccSAndroid Build Coastguard Worker store_winner_mode_stats(&cpi->common, x, mbmi, NULL, NULL, NULL, THR_INVALID,
5916*77c1e3ccSAndroid Build Coastguard Worker NULL, bsize, best_rd_so_far,
5917*77c1e3ccSAndroid Build Coastguard Worker sf->winner_mode_sf.multi_winner_mode_type, 0);
5918*77c1e3ccSAndroid Build Coastguard Worker
5919*77c1e3ccSAndroid Build Coastguard Worker int mode_thresh_mul_fact = (1 << MODE_THRESH_QBITS);
5920*77c1e3ccSAndroid Build Coastguard Worker if (sf->inter_sf.prune_inter_modes_if_skippable) {
5921*77c1e3ccSAndroid Build Coastguard Worker // Higher multiplication factor values for lower quantizers.
5922*77c1e3ccSAndroid Build Coastguard Worker mode_thresh_mul_fact = mode_threshold_mul_factor[x->qindex];
5923*77c1e3ccSAndroid Build Coastguard Worker }
5924*77c1e3ccSAndroid Build Coastguard Worker
5925*77c1e3ccSAndroid Build Coastguard Worker // Initialize arguments for mode loop speed features
5926*77c1e3ccSAndroid Build Coastguard Worker InterModeSFArgs sf_args = { &args.skip_motion_mode,
5927*77c1e3ccSAndroid Build Coastguard Worker &mode_skip_mask,
5928*77c1e3ccSAndroid Build Coastguard Worker &search_state,
5929*77c1e3ccSAndroid Build Coastguard Worker skip_ref_frame_mask,
5930*77c1e3ccSAndroid Build Coastguard Worker 0,
5931*77c1e3ccSAndroid Build Coastguard Worker mode_thresh_mul_fact,
5932*77c1e3ccSAndroid Build Coastguard Worker 0,
5933*77c1e3ccSAndroid Build Coastguard Worker 0 };
5934*77c1e3ccSAndroid Build Coastguard Worker int64_t best_inter_yrd = INT64_MAX;
5935*77c1e3ccSAndroid Build Coastguard Worker
5936*77c1e3ccSAndroid Build Coastguard Worker // This is the main loop of this function. It loops over all possible inter
5937*77c1e3ccSAndroid Build Coastguard Worker // modes and calls handle_inter_mode() to compute the RD for each.
5938*77c1e3ccSAndroid Build Coastguard Worker // Here midx is just an iterator index that should not be used by itself
5939*77c1e3ccSAndroid Build Coastguard Worker // except to keep track of the number of modes searched. It should be used
5940*77c1e3ccSAndroid Build Coastguard Worker // with av1_default_mode_order to get the enum that defines the mode, which
5941*77c1e3ccSAndroid Build Coastguard Worker // can be used with av1_mode_defs to get the prediction mode and the ref
5942*77c1e3ccSAndroid Build Coastguard Worker // frames.
5943*77c1e3ccSAndroid Build Coastguard Worker // TODO(yunqing, any): Setting mode_start and mode_end outside for-loop brings
5944*77c1e3ccSAndroid Build Coastguard Worker // good speedup for real time case. If we decide to use compound mode in real
5945*77c1e3ccSAndroid Build Coastguard Worker // time, maybe we can modify av1_default_mode_order table.
5946*77c1e3ccSAndroid Build Coastguard Worker THR_MODES mode_start = THR_INTER_MODE_START;
5947*77c1e3ccSAndroid Build Coastguard Worker THR_MODES mode_end = THR_INTER_MODE_END;
5948*77c1e3ccSAndroid Build Coastguard Worker const CurrentFrame *const current_frame = &cm->current_frame;
5949*77c1e3ccSAndroid Build Coastguard Worker if (current_frame->reference_mode == SINGLE_REFERENCE) {
5950*77c1e3ccSAndroid Build Coastguard Worker mode_start = SINGLE_REF_MODE_START;
5951*77c1e3ccSAndroid Build Coastguard Worker mode_end = SINGLE_REF_MODE_END;
5952*77c1e3ccSAndroid Build Coastguard Worker }
5953*77c1e3ccSAndroid Build Coastguard Worker
5954*77c1e3ccSAndroid Build Coastguard Worker for (THR_MODES midx = mode_start; midx < mode_end; ++midx) {
5955*77c1e3ccSAndroid Build Coastguard Worker // Get the actual prediction mode we are trying in this iteration
5956*77c1e3ccSAndroid Build Coastguard Worker const THR_MODES mode_enum = av1_default_mode_order[midx];
5957*77c1e3ccSAndroid Build Coastguard Worker const MODE_DEFINITION *mode_def = &av1_mode_defs[mode_enum];
5958*77c1e3ccSAndroid Build Coastguard Worker const PREDICTION_MODE this_mode = mode_def->mode;
5959*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME *ref_frames = mode_def->ref_frame;
5960*77c1e3ccSAndroid Build Coastguard Worker
5961*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME ref_frame = ref_frames[0];
5962*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME second_ref_frame = ref_frames[1];
5963*77c1e3ccSAndroid Build Coastguard Worker const int is_single_pred =
5964*77c1e3ccSAndroid Build Coastguard Worker ref_frame > INTRA_FRAME && second_ref_frame == NONE_FRAME;
5965*77c1e3ccSAndroid Build Coastguard Worker const int comp_pred = second_ref_frame > INTRA_FRAME;
5966*77c1e3ccSAndroid Build Coastguard Worker
5967*77c1e3ccSAndroid Build Coastguard Worker init_mbmi(mbmi, this_mode, ref_frames, cm);
5968*77c1e3ccSAndroid Build Coastguard Worker
5969*77c1e3ccSAndroid Build Coastguard Worker txfm_info->skip_txfm = 0;
5970*77c1e3ccSAndroid Build Coastguard Worker sf_args.num_single_modes_processed += is_single_pred;
5971*77c1e3ccSAndroid Build Coastguard Worker set_ref_ptrs(cm, xd, ref_frame, second_ref_frame);
5972*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_COLLECT_COMPONENT_TIMING
5973*77c1e3ccSAndroid Build Coastguard Worker start_timing(cpi, skip_inter_mode_time);
5974*77c1e3ccSAndroid Build Coastguard Worker #endif
5975*77c1e3ccSAndroid Build Coastguard Worker // Apply speed features to decide if this inter mode can be skipped
5976*77c1e3ccSAndroid Build Coastguard Worker const int is_skip_inter_mode = skip_inter_mode(
5977*77c1e3ccSAndroid Build Coastguard Worker cpi, x, bsize, ref_frame_rd, midx, &sf_args, is_low_temp_var);
5978*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_COLLECT_COMPONENT_TIMING
5979*77c1e3ccSAndroid Build Coastguard Worker end_timing(cpi, skip_inter_mode_time);
5980*77c1e3ccSAndroid Build Coastguard Worker #endif
5981*77c1e3ccSAndroid Build Coastguard Worker if (is_skip_inter_mode) continue;
5982*77c1e3ccSAndroid Build Coastguard Worker
5983*77c1e3ccSAndroid Build Coastguard Worker // Select prediction reference frames.
5984*77c1e3ccSAndroid Build Coastguard Worker for (i = 0; i < num_planes; i++) {
5985*77c1e3ccSAndroid Build Coastguard Worker xd->plane[i].pre[0] = yv12_mb[ref_frame][i];
5986*77c1e3ccSAndroid Build Coastguard Worker if (comp_pred) xd->plane[i].pre[1] = yv12_mb[second_ref_frame][i];
5987*77c1e3ccSAndroid Build Coastguard Worker }
5988*77c1e3ccSAndroid Build Coastguard Worker
5989*77c1e3ccSAndroid Build Coastguard Worker mbmi->angle_delta[PLANE_TYPE_Y] = 0;
5990*77c1e3ccSAndroid Build Coastguard Worker mbmi->angle_delta[PLANE_TYPE_UV] = 0;
5991*77c1e3ccSAndroid Build Coastguard Worker mbmi->filter_intra_mode_info.use_filter_intra = 0;
5992*77c1e3ccSAndroid Build Coastguard Worker mbmi->ref_mv_idx = 0;
5993*77c1e3ccSAndroid Build Coastguard Worker
5994*77c1e3ccSAndroid Build Coastguard Worker const int64_t ref_best_rd = search_state.best_rd;
5995*77c1e3ccSAndroid Build Coastguard Worker RD_STATS rd_stats, rd_stats_y, rd_stats_uv;
5996*77c1e3ccSAndroid Build Coastguard Worker av1_init_rd_stats(&rd_stats);
5997*77c1e3ccSAndroid Build Coastguard Worker
5998*77c1e3ccSAndroid Build Coastguard Worker const int ref_frame_cost = comp_pred
5999*77c1e3ccSAndroid Build Coastguard Worker ? ref_costs_comp[ref_frame][second_ref_frame]
6000*77c1e3ccSAndroid Build Coastguard Worker : ref_costs_single[ref_frame];
6001*77c1e3ccSAndroid Build Coastguard Worker const int compmode_cost =
6002*77c1e3ccSAndroid Build Coastguard Worker is_comp_ref_allowed(mbmi->bsize) ? comp_inter_cost[comp_pred] : 0;
6003*77c1e3ccSAndroid Build Coastguard Worker const int real_compmode_cost =
6004*77c1e3ccSAndroid Build Coastguard Worker cm->current_frame.reference_mode == REFERENCE_MODE_SELECT
6005*77c1e3ccSAndroid Build Coastguard Worker ? compmode_cost
6006*77c1e3ccSAndroid Build Coastguard Worker : 0;
6007*77c1e3ccSAndroid Build Coastguard Worker // Point to variables that are maintained between loop iterations
6008*77c1e3ccSAndroid Build Coastguard Worker args.single_newmv = search_state.single_newmv;
6009*77c1e3ccSAndroid Build Coastguard Worker args.single_newmv_rate = search_state.single_newmv_rate;
6010*77c1e3ccSAndroid Build Coastguard Worker args.single_newmv_valid = search_state.single_newmv_valid;
6011*77c1e3ccSAndroid Build Coastguard Worker args.single_comp_cost = real_compmode_cost;
6012*77c1e3ccSAndroid Build Coastguard Worker args.ref_frame_cost = ref_frame_cost;
6013*77c1e3ccSAndroid Build Coastguard Worker args.best_pred_sse = search_state.best_pred_sse;
6014*77c1e3ccSAndroid Build Coastguard Worker args.skip_ifs = skip_interp_filter_search(cpi, is_single_pred);
6015*77c1e3ccSAndroid Build Coastguard Worker
6016*77c1e3ccSAndroid Build Coastguard Worker int64_t skip_rd[2] = { search_state.best_skip_rd[0],
6017*77c1e3ccSAndroid Build Coastguard Worker search_state.best_skip_rd[1] };
6018*77c1e3ccSAndroid Build Coastguard Worker int64_t this_yrd = INT64_MAX;
6019*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_COLLECT_COMPONENT_TIMING
6020*77c1e3ccSAndroid Build Coastguard Worker start_timing(cpi, handle_inter_mode_time);
6021*77c1e3ccSAndroid Build Coastguard Worker #endif
6022*77c1e3ccSAndroid Build Coastguard Worker int64_t this_rd = handle_inter_mode(
6023*77c1e3ccSAndroid Build Coastguard Worker cpi, tile_data, x, bsize, &rd_stats, &rd_stats_y, &rd_stats_uv, &args,
6024*77c1e3ccSAndroid Build Coastguard Worker ref_best_rd, tmp_buf, &x->comp_rd_buffer, &best_est_rd, do_tx_search,
6025*77c1e3ccSAndroid Build Coastguard Worker inter_modes_info, &motion_mode_cand, skip_rd, &inter_cost_info_from_tpl,
6026*77c1e3ccSAndroid Build Coastguard Worker &this_yrd);
6027*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_COLLECT_COMPONENT_TIMING
6028*77c1e3ccSAndroid Build Coastguard Worker end_timing(cpi, handle_inter_mode_time);
6029*77c1e3ccSAndroid Build Coastguard Worker #endif
6030*77c1e3ccSAndroid Build Coastguard Worker if (current_frame->reference_mode != SINGLE_REFERENCE) {
6031*77c1e3ccSAndroid Build Coastguard Worker if (!args.skip_ifs &&
6032*77c1e3ccSAndroid Build Coastguard Worker sf->inter_sf.prune_comp_search_by_single_result > 0 &&
6033*77c1e3ccSAndroid Build Coastguard Worker is_inter_singleref_mode(this_mode)) {
6034*77c1e3ccSAndroid Build Coastguard Worker collect_single_states(x, &search_state, mbmi);
6035*77c1e3ccSAndroid Build Coastguard Worker }
6036*77c1e3ccSAndroid Build Coastguard Worker
6037*77c1e3ccSAndroid Build Coastguard Worker if (sf->inter_sf.prune_comp_using_best_single_mode_ref > 0 &&
6038*77c1e3ccSAndroid Build Coastguard Worker is_inter_singleref_mode(this_mode))
6039*77c1e3ccSAndroid Build Coastguard Worker update_best_single_mode(&search_state, this_mode, ref_frame, this_rd);
6040*77c1e3ccSAndroid Build Coastguard Worker }
6041*77c1e3ccSAndroid Build Coastguard Worker
6042*77c1e3ccSAndroid Build Coastguard Worker if (this_rd == INT64_MAX) continue;
6043*77c1e3ccSAndroid Build Coastguard Worker
6044*77c1e3ccSAndroid Build Coastguard Worker if (mbmi->skip_txfm) {
6045*77c1e3ccSAndroid Build Coastguard Worker rd_stats_y.rate = 0;
6046*77c1e3ccSAndroid Build Coastguard Worker rd_stats_uv.rate = 0;
6047*77c1e3ccSAndroid Build Coastguard Worker }
6048*77c1e3ccSAndroid Build Coastguard Worker
6049*77c1e3ccSAndroid Build Coastguard Worker if (sf->inter_sf.prune_compound_using_single_ref && is_single_pred &&
6050*77c1e3ccSAndroid Build Coastguard Worker this_rd < ref_frame_rd[ref_frame]) {
6051*77c1e3ccSAndroid Build Coastguard Worker ref_frame_rd[ref_frame] = this_rd;
6052*77c1e3ccSAndroid Build Coastguard Worker }
6053*77c1e3ccSAndroid Build Coastguard Worker
6054*77c1e3ccSAndroid Build Coastguard Worker // Did this mode help, i.e., is it the new best mode
6055*77c1e3ccSAndroid Build Coastguard Worker if (this_rd < search_state.best_rd) {
6056*77c1e3ccSAndroid Build Coastguard Worker assert(IMPLIES(comp_pred,
6057*77c1e3ccSAndroid Build Coastguard Worker cm->current_frame.reference_mode != SINGLE_REFERENCE));
6058*77c1e3ccSAndroid Build Coastguard Worker search_state.best_pred_sse = x->pred_sse[ref_frame];
6059*77c1e3ccSAndroid Build Coastguard Worker best_inter_yrd = this_yrd;
6060*77c1e3ccSAndroid Build Coastguard Worker update_search_state(&search_state, rd_cost, ctx, &rd_stats, &rd_stats_y,
6061*77c1e3ccSAndroid Build Coastguard Worker &rd_stats_uv, mode_enum, x, do_tx_search);
6062*77c1e3ccSAndroid Build Coastguard Worker if (do_tx_search) search_state.best_skip_rd[0] = skip_rd[0];
6063*77c1e3ccSAndroid Build Coastguard Worker // skip_rd[0] is the best total rd for a skip mode so far.
6064*77c1e3ccSAndroid Build Coastguard Worker // skip_rd[1] is the best total rd for a skip mode so far in luma.
6065*77c1e3ccSAndroid Build Coastguard Worker // When do_tx_search = 1, both skip_rd[0] and skip_rd[1] are updated.
6066*77c1e3ccSAndroid Build Coastguard Worker // When do_tx_search = 0, skip_rd[1] is updated.
6067*77c1e3ccSAndroid Build Coastguard Worker search_state.best_skip_rd[1] = skip_rd[1];
6068*77c1e3ccSAndroid Build Coastguard Worker }
6069*77c1e3ccSAndroid Build Coastguard Worker if (sf->winner_mode_sf.motion_mode_for_winner_cand) {
6070*77c1e3ccSAndroid Build Coastguard Worker // Add this mode to motion mode candidate list for motion mode search
6071*77c1e3ccSAndroid Build Coastguard Worker // if using motion_mode_for_winner_cand speed feature
6072*77c1e3ccSAndroid Build Coastguard Worker handle_winner_cand(mbmi, &best_motion_mode_cands,
6073*77c1e3ccSAndroid Build Coastguard Worker max_winner_motion_mode_cand, this_rd,
6074*77c1e3ccSAndroid Build Coastguard Worker &motion_mode_cand, args.skip_motion_mode);
6075*77c1e3ccSAndroid Build Coastguard Worker }
6076*77c1e3ccSAndroid Build Coastguard Worker
6077*77c1e3ccSAndroid Build Coastguard Worker /* keep record of best compound/single-only prediction */
6078*77c1e3ccSAndroid Build Coastguard Worker record_best_compound(cm->current_frame.reference_mode, &rd_stats, comp_pred,
6079*77c1e3ccSAndroid Build Coastguard Worker x->rdmult, &search_state, compmode_cost);
6080*77c1e3ccSAndroid Build Coastguard Worker }
6081*77c1e3ccSAndroid Build Coastguard Worker
6082*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_COLLECT_COMPONENT_TIMING
6083*77c1e3ccSAndroid Build Coastguard Worker start_timing(cpi, evaluate_motion_mode_for_winner_candidates_time);
6084*77c1e3ccSAndroid Build Coastguard Worker #endif
6085*77c1e3ccSAndroid Build Coastguard Worker if (sf->winner_mode_sf.motion_mode_for_winner_cand) {
6086*77c1e3ccSAndroid Build Coastguard Worker // For the single ref winner candidates, evaluate other motion modes (non
6087*77c1e3ccSAndroid Build Coastguard Worker // simple translation).
6088*77c1e3ccSAndroid Build Coastguard Worker evaluate_motion_mode_for_winner_candidates(
6089*77c1e3ccSAndroid Build Coastguard Worker cpi, x, rd_cost, &args, tile_data, ctx, yv12_mb,
6090*77c1e3ccSAndroid Build Coastguard Worker &best_motion_mode_cands, do_tx_search, bsize, &best_est_rd,
6091*77c1e3ccSAndroid Build Coastguard Worker &search_state, &best_inter_yrd);
6092*77c1e3ccSAndroid Build Coastguard Worker }
6093*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_COLLECT_COMPONENT_TIMING
6094*77c1e3ccSAndroid Build Coastguard Worker end_timing(cpi, evaluate_motion_mode_for_winner_candidates_time);
6095*77c1e3ccSAndroid Build Coastguard Worker #endif
6096*77c1e3ccSAndroid Build Coastguard Worker
6097*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_COLLECT_COMPONENT_TIMING
6098*77c1e3ccSAndroid Build Coastguard Worker start_timing(cpi, do_tx_search_time);
6099*77c1e3ccSAndroid Build Coastguard Worker #endif
6100*77c1e3ccSAndroid Build Coastguard Worker if (do_tx_search != 1) {
6101*77c1e3ccSAndroid Build Coastguard Worker // A full tx search has not yet been done, do tx search for
6102*77c1e3ccSAndroid Build Coastguard Worker // top mode candidates
6103*77c1e3ccSAndroid Build Coastguard Worker tx_search_best_inter_candidates(cpi, tile_data, x, best_rd_so_far, bsize,
6104*77c1e3ccSAndroid Build Coastguard Worker yv12_mb, mi_row, mi_col, &search_state,
6105*77c1e3ccSAndroid Build Coastguard Worker rd_cost, ctx, &best_inter_yrd);
6106*77c1e3ccSAndroid Build Coastguard Worker }
6107*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_COLLECT_COMPONENT_TIMING
6108*77c1e3ccSAndroid Build Coastguard Worker end_timing(cpi, do_tx_search_time);
6109*77c1e3ccSAndroid Build Coastguard Worker #endif
6110*77c1e3ccSAndroid Build Coastguard Worker
6111*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_COLLECT_COMPONENT_TIMING
6112*77c1e3ccSAndroid Build Coastguard Worker start_timing(cpi, handle_intra_mode_time);
6113*77c1e3ccSAndroid Build Coastguard Worker #endif
6114*77c1e3ccSAndroid Build Coastguard Worker // Gate intra mode evaluation if best of inter is skip except when source
6115*77c1e3ccSAndroid Build Coastguard Worker // variance is extremely low and also based on max intra bsize.
6116*77c1e3ccSAndroid Build Coastguard Worker skip_intra_modes_in_interframe(cm, x, bsize, &search_state, sf, inter_cost,
6117*77c1e3ccSAndroid Build Coastguard Worker intra_cost);
6118*77c1e3ccSAndroid Build Coastguard Worker
6119*77c1e3ccSAndroid Build Coastguard Worker const unsigned int intra_ref_frame_cost = ref_costs_single[INTRA_FRAME];
6120*77c1e3ccSAndroid Build Coastguard Worker search_intra_modes_in_interframe(&search_state, cpi, x, rd_cost, bsize, ctx,
6121*77c1e3ccSAndroid Build Coastguard Worker &sf_args, intra_ref_frame_cost,
6122*77c1e3ccSAndroid Build Coastguard Worker best_inter_yrd);
6123*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_COLLECT_COMPONENT_TIMING
6124*77c1e3ccSAndroid Build Coastguard Worker end_timing(cpi, handle_intra_mode_time);
6125*77c1e3ccSAndroid Build Coastguard Worker #endif
6126*77c1e3ccSAndroid Build Coastguard Worker
6127*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_COLLECT_COMPONENT_TIMING
6128*77c1e3ccSAndroid Build Coastguard Worker start_timing(cpi, refine_winner_mode_tx_time);
6129*77c1e3ccSAndroid Build Coastguard Worker #endif
6130*77c1e3ccSAndroid Build Coastguard Worker int winner_mode_count =
6131*77c1e3ccSAndroid Build Coastguard Worker sf->winner_mode_sf.multi_winner_mode_type ? x->winner_mode_count : 1;
6132*77c1e3ccSAndroid Build Coastguard Worker // In effect only when fast tx search speed features are enabled.
6133*77c1e3ccSAndroid Build Coastguard Worker refine_winner_mode_tx(
6134*77c1e3ccSAndroid Build Coastguard Worker cpi, x, rd_cost, bsize, ctx, &search_state.best_mode_index,
6135*77c1e3ccSAndroid Build Coastguard Worker &search_state.best_mbmode, yv12_mb, search_state.best_rate_y,
6136*77c1e3ccSAndroid Build Coastguard Worker search_state.best_rate_uv, &search_state.best_skip2, winner_mode_count);
6137*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_COLLECT_COMPONENT_TIMING
6138*77c1e3ccSAndroid Build Coastguard Worker end_timing(cpi, refine_winner_mode_tx_time);
6139*77c1e3ccSAndroid Build Coastguard Worker #endif
6140*77c1e3ccSAndroid Build Coastguard Worker
6141*77c1e3ccSAndroid Build Coastguard Worker // Initialize default mode evaluation params
6142*77c1e3ccSAndroid Build Coastguard Worker set_mode_eval_params(cpi, x, DEFAULT_EVAL);
6143*77c1e3ccSAndroid Build Coastguard Worker
6144*77c1e3ccSAndroid Build Coastguard Worker // Only try palette mode when the best mode so far is an intra mode.
6145*77c1e3ccSAndroid Build Coastguard Worker const int try_palette =
6146*77c1e3ccSAndroid Build Coastguard Worker cpi->oxcf.tool_cfg.enable_palette &&
6147*77c1e3ccSAndroid Build Coastguard Worker av1_allow_palette(features->allow_screen_content_tools, mbmi->bsize) &&
6148*77c1e3ccSAndroid Build Coastguard Worker !is_inter_mode(search_state.best_mbmode.mode) && rd_cost->rate != INT_MAX;
6149*77c1e3ccSAndroid Build Coastguard Worker RD_STATS this_rd_cost;
6150*77c1e3ccSAndroid Build Coastguard Worker int this_skippable = 0;
6151*77c1e3ccSAndroid Build Coastguard Worker if (try_palette) {
6152*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_COLLECT_COMPONENT_TIMING
6153*77c1e3ccSAndroid Build Coastguard Worker start_timing(cpi, av1_search_palette_mode_time);
6154*77c1e3ccSAndroid Build Coastguard Worker #endif
6155*77c1e3ccSAndroid Build Coastguard Worker this_skippable = av1_search_palette_mode(
6156*77c1e3ccSAndroid Build Coastguard Worker &search_state.intra_search_state, cpi, x, bsize, intra_ref_frame_cost,
6157*77c1e3ccSAndroid Build Coastguard Worker ctx, &this_rd_cost, search_state.best_rd);
6158*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_COLLECT_COMPONENT_TIMING
6159*77c1e3ccSAndroid Build Coastguard Worker end_timing(cpi, av1_search_palette_mode_time);
6160*77c1e3ccSAndroid Build Coastguard Worker #endif
6161*77c1e3ccSAndroid Build Coastguard Worker if (this_rd_cost.rdcost < search_state.best_rd) {
6162*77c1e3ccSAndroid Build Coastguard Worker search_state.best_mode_index = THR_DC;
6163*77c1e3ccSAndroid Build Coastguard Worker mbmi->mv[0].as_int = 0;
6164*77c1e3ccSAndroid Build Coastguard Worker rd_cost->rate = this_rd_cost.rate;
6165*77c1e3ccSAndroid Build Coastguard Worker rd_cost->dist = this_rd_cost.dist;
6166*77c1e3ccSAndroid Build Coastguard Worker rd_cost->rdcost = this_rd_cost.rdcost;
6167*77c1e3ccSAndroid Build Coastguard Worker search_state.best_rd = rd_cost->rdcost;
6168*77c1e3ccSAndroid Build Coastguard Worker search_state.best_mbmode = *mbmi;
6169*77c1e3ccSAndroid Build Coastguard Worker search_state.best_skip2 = 0;
6170*77c1e3ccSAndroid Build Coastguard Worker search_state.best_mode_skippable = this_skippable;
6171*77c1e3ccSAndroid Build Coastguard Worker memcpy(ctx->blk_skip, txfm_info->blk_skip,
6172*77c1e3ccSAndroid Build Coastguard Worker sizeof(txfm_info->blk_skip[0]) * ctx->num_4x4_blk);
6173*77c1e3ccSAndroid Build Coastguard Worker av1_copy_array(ctx->tx_type_map, xd->tx_type_map, ctx->num_4x4_blk);
6174*77c1e3ccSAndroid Build Coastguard Worker }
6175*77c1e3ccSAndroid Build Coastguard Worker }
6176*77c1e3ccSAndroid Build Coastguard Worker
6177*77c1e3ccSAndroid Build Coastguard Worker search_state.best_mbmode.skip_mode = 0;
6178*77c1e3ccSAndroid Build Coastguard Worker if (cm->current_frame.skip_mode_info.skip_mode_flag &&
6179*77c1e3ccSAndroid Build Coastguard Worker is_comp_ref_allowed(bsize)) {
6180*77c1e3ccSAndroid Build Coastguard Worker const struct segmentation *const seg = &cm->seg;
6181*77c1e3ccSAndroid Build Coastguard Worker unsigned char segment_id = mbmi->segment_id;
6182*77c1e3ccSAndroid Build Coastguard Worker if (!segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME)) {
6183*77c1e3ccSAndroid Build Coastguard Worker rd_pick_skip_mode(rd_cost, &search_state, cpi, x, bsize, yv12_mb);
6184*77c1e3ccSAndroid Build Coastguard Worker }
6185*77c1e3ccSAndroid Build Coastguard Worker }
6186*77c1e3ccSAndroid Build Coastguard Worker
6187*77c1e3ccSAndroid Build Coastguard Worker // Make sure that the ref_mv_idx is only nonzero when we're
6188*77c1e3ccSAndroid Build Coastguard Worker // using a mode which can support ref_mv_idx
6189*77c1e3ccSAndroid Build Coastguard Worker if (search_state.best_mbmode.ref_mv_idx != 0 &&
6190*77c1e3ccSAndroid Build Coastguard Worker !(search_state.best_mbmode.mode == NEWMV ||
6191*77c1e3ccSAndroid Build Coastguard Worker search_state.best_mbmode.mode == NEW_NEWMV ||
6192*77c1e3ccSAndroid Build Coastguard Worker have_nearmv_in_inter_mode(search_state.best_mbmode.mode))) {
6193*77c1e3ccSAndroid Build Coastguard Worker search_state.best_mbmode.ref_mv_idx = 0;
6194*77c1e3ccSAndroid Build Coastguard Worker }
6195*77c1e3ccSAndroid Build Coastguard Worker
6196*77c1e3ccSAndroid Build Coastguard Worker if (search_state.best_mode_index == THR_INVALID ||
6197*77c1e3ccSAndroid Build Coastguard Worker search_state.best_rd >= best_rd_so_far) {
6198*77c1e3ccSAndroid Build Coastguard Worker rd_cost->rate = INT_MAX;
6199*77c1e3ccSAndroid Build Coastguard Worker rd_cost->rdcost = INT64_MAX;
6200*77c1e3ccSAndroid Build Coastguard Worker return;
6201*77c1e3ccSAndroid Build Coastguard Worker }
6202*77c1e3ccSAndroid Build Coastguard Worker
6203*77c1e3ccSAndroid Build Coastguard Worker const InterpFilter interp_filter = features->interp_filter;
6204*77c1e3ccSAndroid Build Coastguard Worker assert((interp_filter == SWITCHABLE) ||
6205*77c1e3ccSAndroid Build Coastguard Worker (interp_filter ==
6206*77c1e3ccSAndroid Build Coastguard Worker search_state.best_mbmode.interp_filters.as_filters.y_filter) ||
6207*77c1e3ccSAndroid Build Coastguard Worker !is_inter_block(&search_state.best_mbmode));
6208*77c1e3ccSAndroid Build Coastguard Worker assert((interp_filter == SWITCHABLE) ||
6209*77c1e3ccSAndroid Build Coastguard Worker (interp_filter ==
6210*77c1e3ccSAndroid Build Coastguard Worker search_state.best_mbmode.interp_filters.as_filters.x_filter) ||
6211*77c1e3ccSAndroid Build Coastguard Worker !is_inter_block(&search_state.best_mbmode));
6212*77c1e3ccSAndroid Build Coastguard Worker
6213*77c1e3ccSAndroid Build Coastguard Worker if (!cpi->rc.is_src_frame_alt_ref && sf->inter_sf.adaptive_rd_thresh) {
6214*77c1e3ccSAndroid Build Coastguard Worker av1_update_rd_thresh_fact(
6215*77c1e3ccSAndroid Build Coastguard Worker cm, x->thresh_freq_fact, sf->inter_sf.adaptive_rd_thresh, bsize,
6216*77c1e3ccSAndroid Build Coastguard Worker search_state.best_mode_index, mode_start, mode_end, THR_DC, MAX_MODES);
6217*77c1e3ccSAndroid Build Coastguard Worker }
6218*77c1e3ccSAndroid Build Coastguard Worker
6219*77c1e3ccSAndroid Build Coastguard Worker // macroblock modes
6220*77c1e3ccSAndroid Build Coastguard Worker *mbmi = search_state.best_mbmode;
6221*77c1e3ccSAndroid Build Coastguard Worker txfm_info->skip_txfm |= search_state.best_skip2;
6222*77c1e3ccSAndroid Build Coastguard Worker
6223*77c1e3ccSAndroid Build Coastguard Worker // Note: this section is needed since the mode may have been forced to
6224*77c1e3ccSAndroid Build Coastguard Worker // GLOBALMV by the all-zero mode handling of ref-mv.
6225*77c1e3ccSAndroid Build Coastguard Worker if (mbmi->mode == GLOBALMV || mbmi->mode == GLOBAL_GLOBALMV) {
6226*77c1e3ccSAndroid Build Coastguard Worker // Correct the interp filters for GLOBALMV
6227*77c1e3ccSAndroid Build Coastguard Worker if (is_nontrans_global_motion(xd, xd->mi[0])) {
6228*77c1e3ccSAndroid Build Coastguard Worker int_interpfilters filters =
6229*77c1e3ccSAndroid Build Coastguard Worker av1_broadcast_interp_filter(av1_unswitchable_filter(interp_filter));
6230*77c1e3ccSAndroid Build Coastguard Worker assert(mbmi->interp_filters.as_int == filters.as_int);
6231*77c1e3ccSAndroid Build Coastguard Worker (void)filters;
6232*77c1e3ccSAndroid Build Coastguard Worker }
6233*77c1e3ccSAndroid Build Coastguard Worker }
6234*77c1e3ccSAndroid Build Coastguard Worker
6235*77c1e3ccSAndroid Build Coastguard Worker txfm_info->skip_txfm |= search_state.best_mode_skippable;
6236*77c1e3ccSAndroid Build Coastguard Worker
6237*77c1e3ccSAndroid Build Coastguard Worker assert(search_state.best_mode_index != THR_INVALID);
6238*77c1e3ccSAndroid Build Coastguard Worker
6239*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_INTERNAL_STATS
6240*77c1e3ccSAndroid Build Coastguard Worker store_coding_context(x, ctx, search_state.best_mode_index,
6241*77c1e3ccSAndroid Build Coastguard Worker search_state.best_mode_skippable);
6242*77c1e3ccSAndroid Build Coastguard Worker #else
6243*77c1e3ccSAndroid Build Coastguard Worker store_coding_context(x, ctx, search_state.best_mode_skippable);
6244*77c1e3ccSAndroid Build Coastguard Worker #endif // CONFIG_INTERNAL_STATS
6245*77c1e3ccSAndroid Build Coastguard Worker
6246*77c1e3ccSAndroid Build Coastguard Worker if (mbmi->palette_mode_info.palette_size[1] > 0) {
6247*77c1e3ccSAndroid Build Coastguard Worker assert(try_palette);
6248*77c1e3ccSAndroid Build Coastguard Worker av1_restore_uv_color_map(cpi, x);
6249*77c1e3ccSAndroid Build Coastguard Worker }
6250*77c1e3ccSAndroid Build Coastguard Worker }
6251*77c1e3ccSAndroid Build Coastguard Worker
av1_rd_pick_inter_mode_sb_seg_skip(const AV1_COMP * cpi,TileDataEnc * tile_data,MACROBLOCK * x,int mi_row,int mi_col,RD_STATS * rd_cost,BLOCK_SIZE bsize,PICK_MODE_CONTEXT * ctx,int64_t best_rd_so_far)6252*77c1e3ccSAndroid Build Coastguard Worker void av1_rd_pick_inter_mode_sb_seg_skip(const AV1_COMP *cpi,
6253*77c1e3ccSAndroid Build Coastguard Worker TileDataEnc *tile_data, MACROBLOCK *x,
6254*77c1e3ccSAndroid Build Coastguard Worker int mi_row, int mi_col,
6255*77c1e3ccSAndroid Build Coastguard Worker RD_STATS *rd_cost, BLOCK_SIZE bsize,
6256*77c1e3ccSAndroid Build Coastguard Worker PICK_MODE_CONTEXT *ctx,
6257*77c1e3ccSAndroid Build Coastguard Worker int64_t best_rd_so_far) {
6258*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *const cm = &cpi->common;
6259*77c1e3ccSAndroid Build Coastguard Worker const FeatureFlags *const features = &cm->features;
6260*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *const xd = &x->e_mbd;
6261*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *const mbmi = xd->mi[0];
6262*77c1e3ccSAndroid Build Coastguard Worker unsigned char segment_id = mbmi->segment_id;
6263*77c1e3ccSAndroid Build Coastguard Worker const int comp_pred = 0;
6264*77c1e3ccSAndroid Build Coastguard Worker int i;
6265*77c1e3ccSAndroid Build Coastguard Worker unsigned int ref_costs_single[REF_FRAMES];
6266*77c1e3ccSAndroid Build Coastguard Worker unsigned int ref_costs_comp[REF_FRAMES][REF_FRAMES];
6267*77c1e3ccSAndroid Build Coastguard Worker const ModeCosts *mode_costs = &x->mode_costs;
6268*77c1e3ccSAndroid Build Coastguard Worker const int *comp_inter_cost =
6269*77c1e3ccSAndroid Build Coastguard Worker mode_costs->comp_inter_cost[av1_get_reference_mode_context(xd)];
6270*77c1e3ccSAndroid Build Coastguard Worker InterpFilter best_filter = SWITCHABLE;
6271*77c1e3ccSAndroid Build Coastguard Worker int64_t this_rd = INT64_MAX;
6272*77c1e3ccSAndroid Build Coastguard Worker int rate2 = 0;
6273*77c1e3ccSAndroid Build Coastguard Worker const int64_t distortion2 = 0;
6274*77c1e3ccSAndroid Build Coastguard Worker (void)mi_row;
6275*77c1e3ccSAndroid Build Coastguard Worker (void)mi_col;
6276*77c1e3ccSAndroid Build Coastguard Worker (void)tile_data;
6277*77c1e3ccSAndroid Build Coastguard Worker
6278*77c1e3ccSAndroid Build Coastguard Worker av1_collect_neighbors_ref_counts(xd);
6279*77c1e3ccSAndroid Build Coastguard Worker
6280*77c1e3ccSAndroid Build Coastguard Worker estimate_ref_frame_costs(cm, xd, mode_costs, segment_id, ref_costs_single,
6281*77c1e3ccSAndroid Build Coastguard Worker ref_costs_comp);
6282*77c1e3ccSAndroid Build Coastguard Worker
6283*77c1e3ccSAndroid Build Coastguard Worker for (i = 0; i < REF_FRAMES; ++i) x->pred_sse[i] = INT_MAX;
6284*77c1e3ccSAndroid Build Coastguard Worker for (i = LAST_FRAME; i < REF_FRAMES; ++i) x->pred_mv_sad[i] = INT_MAX;
6285*77c1e3ccSAndroid Build Coastguard Worker
6286*77c1e3ccSAndroid Build Coastguard Worker rd_cost->rate = INT_MAX;
6287*77c1e3ccSAndroid Build Coastguard Worker
6288*77c1e3ccSAndroid Build Coastguard Worker assert(segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP));
6289*77c1e3ccSAndroid Build Coastguard Worker
6290*77c1e3ccSAndroid Build Coastguard Worker mbmi->palette_mode_info.palette_size[0] = 0;
6291*77c1e3ccSAndroid Build Coastguard Worker mbmi->palette_mode_info.palette_size[1] = 0;
6292*77c1e3ccSAndroid Build Coastguard Worker mbmi->filter_intra_mode_info.use_filter_intra = 0;
6293*77c1e3ccSAndroid Build Coastguard Worker mbmi->mode = GLOBALMV;
6294*77c1e3ccSAndroid Build Coastguard Worker mbmi->motion_mode = SIMPLE_TRANSLATION;
6295*77c1e3ccSAndroid Build Coastguard Worker mbmi->uv_mode = UV_DC_PRED;
6296*77c1e3ccSAndroid Build Coastguard Worker if (segfeature_active(&cm->seg, segment_id, SEG_LVL_REF_FRAME))
6297*77c1e3ccSAndroid Build Coastguard Worker mbmi->ref_frame[0] = get_segdata(&cm->seg, segment_id, SEG_LVL_REF_FRAME);
6298*77c1e3ccSAndroid Build Coastguard Worker else
6299*77c1e3ccSAndroid Build Coastguard Worker mbmi->ref_frame[0] = LAST_FRAME;
6300*77c1e3ccSAndroid Build Coastguard Worker mbmi->ref_frame[1] = NONE_FRAME;
6301*77c1e3ccSAndroid Build Coastguard Worker mbmi->mv[0].as_int =
6302*77c1e3ccSAndroid Build Coastguard Worker gm_get_motion_vector(&cm->global_motion[mbmi->ref_frame[0]],
6303*77c1e3ccSAndroid Build Coastguard Worker features->allow_high_precision_mv, bsize, mi_col,
6304*77c1e3ccSAndroid Build Coastguard Worker mi_row, features->cur_frame_force_integer_mv)
6305*77c1e3ccSAndroid Build Coastguard Worker .as_int;
6306*77c1e3ccSAndroid Build Coastguard Worker mbmi->tx_size = max_txsize_lookup[bsize];
6307*77c1e3ccSAndroid Build Coastguard Worker x->txfm_search_info.skip_txfm = 1;
6308*77c1e3ccSAndroid Build Coastguard Worker
6309*77c1e3ccSAndroid Build Coastguard Worker mbmi->ref_mv_idx = 0;
6310*77c1e3ccSAndroid Build Coastguard Worker
6311*77c1e3ccSAndroid Build Coastguard Worker mbmi->motion_mode = SIMPLE_TRANSLATION;
6312*77c1e3ccSAndroid Build Coastguard Worker av1_count_overlappable_neighbors(cm, xd);
6313*77c1e3ccSAndroid Build Coastguard Worker if (is_motion_variation_allowed_bsize(bsize) && !has_second_ref(mbmi)) {
6314*77c1e3ccSAndroid Build Coastguard Worker int pts[SAMPLES_ARRAY_SIZE], pts_inref[SAMPLES_ARRAY_SIZE];
6315*77c1e3ccSAndroid Build Coastguard Worker mbmi->num_proj_ref = av1_findSamples(cm, xd, pts, pts_inref);
6316*77c1e3ccSAndroid Build Coastguard Worker // Select the samples according to motion vector difference
6317*77c1e3ccSAndroid Build Coastguard Worker if (mbmi->num_proj_ref > 1) {
6318*77c1e3ccSAndroid Build Coastguard Worker mbmi->num_proj_ref = av1_selectSamples(&mbmi->mv[0].as_mv, pts, pts_inref,
6319*77c1e3ccSAndroid Build Coastguard Worker mbmi->num_proj_ref, bsize);
6320*77c1e3ccSAndroid Build Coastguard Worker }
6321*77c1e3ccSAndroid Build Coastguard Worker }
6322*77c1e3ccSAndroid Build Coastguard Worker
6323*77c1e3ccSAndroid Build Coastguard Worker const InterpFilter interp_filter = features->interp_filter;
6324*77c1e3ccSAndroid Build Coastguard Worker set_default_interp_filters(mbmi, interp_filter);
6325*77c1e3ccSAndroid Build Coastguard Worker
6326*77c1e3ccSAndroid Build Coastguard Worker if (interp_filter != SWITCHABLE) {
6327*77c1e3ccSAndroid Build Coastguard Worker best_filter = interp_filter;
6328*77c1e3ccSAndroid Build Coastguard Worker } else {
6329*77c1e3ccSAndroid Build Coastguard Worker best_filter = EIGHTTAP_REGULAR;
6330*77c1e3ccSAndroid Build Coastguard Worker if (av1_is_interp_needed(xd)) {
6331*77c1e3ccSAndroid Build Coastguard Worker int rs;
6332*77c1e3ccSAndroid Build Coastguard Worker int best_rs = INT_MAX;
6333*77c1e3ccSAndroid Build Coastguard Worker for (i = 0; i < SWITCHABLE_FILTERS; ++i) {
6334*77c1e3ccSAndroid Build Coastguard Worker mbmi->interp_filters = av1_broadcast_interp_filter(i);
6335*77c1e3ccSAndroid Build Coastguard Worker rs = av1_get_switchable_rate(x, xd, interp_filter,
6336*77c1e3ccSAndroid Build Coastguard Worker cm->seq_params->enable_dual_filter);
6337*77c1e3ccSAndroid Build Coastguard Worker if (rs < best_rs) {
6338*77c1e3ccSAndroid Build Coastguard Worker best_rs = rs;
6339*77c1e3ccSAndroid Build Coastguard Worker best_filter = mbmi->interp_filters.as_filters.y_filter;
6340*77c1e3ccSAndroid Build Coastguard Worker }
6341*77c1e3ccSAndroid Build Coastguard Worker }
6342*77c1e3ccSAndroid Build Coastguard Worker }
6343*77c1e3ccSAndroid Build Coastguard Worker }
6344*77c1e3ccSAndroid Build Coastguard Worker // Set the appropriate filter
6345*77c1e3ccSAndroid Build Coastguard Worker mbmi->interp_filters = av1_broadcast_interp_filter(best_filter);
6346*77c1e3ccSAndroid Build Coastguard Worker rate2 += av1_get_switchable_rate(x, xd, interp_filter,
6347*77c1e3ccSAndroid Build Coastguard Worker cm->seq_params->enable_dual_filter);
6348*77c1e3ccSAndroid Build Coastguard Worker
6349*77c1e3ccSAndroid Build Coastguard Worker if (cm->current_frame.reference_mode == REFERENCE_MODE_SELECT)
6350*77c1e3ccSAndroid Build Coastguard Worker rate2 += comp_inter_cost[comp_pred];
6351*77c1e3ccSAndroid Build Coastguard Worker
6352*77c1e3ccSAndroid Build Coastguard Worker // Estimate the reference frame signaling cost and add it
6353*77c1e3ccSAndroid Build Coastguard Worker // to the rolling cost variable.
6354*77c1e3ccSAndroid Build Coastguard Worker rate2 += ref_costs_single[LAST_FRAME];
6355*77c1e3ccSAndroid Build Coastguard Worker this_rd = RDCOST(x->rdmult, rate2, distortion2);
6356*77c1e3ccSAndroid Build Coastguard Worker
6357*77c1e3ccSAndroid Build Coastguard Worker rd_cost->rate = rate2;
6358*77c1e3ccSAndroid Build Coastguard Worker rd_cost->dist = distortion2;
6359*77c1e3ccSAndroid Build Coastguard Worker rd_cost->rdcost = this_rd;
6360*77c1e3ccSAndroid Build Coastguard Worker
6361*77c1e3ccSAndroid Build Coastguard Worker if (this_rd >= best_rd_so_far) {
6362*77c1e3ccSAndroid Build Coastguard Worker rd_cost->rate = INT_MAX;
6363*77c1e3ccSAndroid Build Coastguard Worker rd_cost->rdcost = INT64_MAX;
6364*77c1e3ccSAndroid Build Coastguard Worker return;
6365*77c1e3ccSAndroid Build Coastguard Worker }
6366*77c1e3ccSAndroid Build Coastguard Worker
6367*77c1e3ccSAndroid Build Coastguard Worker assert((interp_filter == SWITCHABLE) ||
6368*77c1e3ccSAndroid Build Coastguard Worker (interp_filter == mbmi->interp_filters.as_filters.y_filter));
6369*77c1e3ccSAndroid Build Coastguard Worker
6370*77c1e3ccSAndroid Build Coastguard Worker if (cpi->sf.inter_sf.adaptive_rd_thresh) {
6371*77c1e3ccSAndroid Build Coastguard Worker av1_update_rd_thresh_fact(cm, x->thresh_freq_fact,
6372*77c1e3ccSAndroid Build Coastguard Worker cpi->sf.inter_sf.adaptive_rd_thresh, bsize,
6373*77c1e3ccSAndroid Build Coastguard Worker THR_GLOBALMV, THR_INTER_MODE_START,
6374*77c1e3ccSAndroid Build Coastguard Worker THR_INTER_MODE_END, THR_DC, MAX_MODES);
6375*77c1e3ccSAndroid Build Coastguard Worker }
6376*77c1e3ccSAndroid Build Coastguard Worker
6377*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_INTERNAL_STATS
6378*77c1e3ccSAndroid Build Coastguard Worker store_coding_context(x, ctx, THR_GLOBALMV, 0);
6379*77c1e3ccSAndroid Build Coastguard Worker #else
6380*77c1e3ccSAndroid Build Coastguard Worker store_coding_context(x, ctx, 0);
6381*77c1e3ccSAndroid Build Coastguard Worker #endif // CONFIG_INTERNAL_STATS
6382*77c1e3ccSAndroid Build Coastguard Worker }
6383*77c1e3ccSAndroid Build Coastguard Worker
6384*77c1e3ccSAndroid Build Coastguard Worker /*!\cond */
6385*77c1e3ccSAndroid Build Coastguard Worker struct calc_target_weighted_pred_ctxt {
6386*77c1e3ccSAndroid Build Coastguard Worker const OBMCBuffer *obmc_buffer;
6387*77c1e3ccSAndroid Build Coastguard Worker const uint8_t *tmp;
6388*77c1e3ccSAndroid Build Coastguard Worker int tmp_stride;
6389*77c1e3ccSAndroid Build Coastguard Worker int overlap;
6390*77c1e3ccSAndroid Build Coastguard Worker };
6391*77c1e3ccSAndroid Build Coastguard Worker /*!\endcond */
6392*77c1e3ccSAndroid Build Coastguard Worker
calc_target_weighted_pred_above(MACROBLOCKD * xd,int rel_mi_row,int rel_mi_col,uint8_t op_mi_size,int dir,MB_MODE_INFO * nb_mi,void * fun_ctxt,const int num_planes)6393*77c1e3ccSAndroid Build Coastguard Worker static inline void calc_target_weighted_pred_above(
6394*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *xd, int rel_mi_row, int rel_mi_col, uint8_t op_mi_size,
6395*77c1e3ccSAndroid Build Coastguard Worker int dir, MB_MODE_INFO *nb_mi, void *fun_ctxt, const int num_planes) {
6396*77c1e3ccSAndroid Build Coastguard Worker (void)nb_mi;
6397*77c1e3ccSAndroid Build Coastguard Worker (void)num_planes;
6398*77c1e3ccSAndroid Build Coastguard Worker (void)rel_mi_row;
6399*77c1e3ccSAndroid Build Coastguard Worker (void)dir;
6400*77c1e3ccSAndroid Build Coastguard Worker
6401*77c1e3ccSAndroid Build Coastguard Worker struct calc_target_weighted_pred_ctxt *ctxt =
6402*77c1e3ccSAndroid Build Coastguard Worker (struct calc_target_weighted_pred_ctxt *)fun_ctxt;
6403*77c1e3ccSAndroid Build Coastguard Worker
6404*77c1e3ccSAndroid Build Coastguard Worker const int bw = xd->width << MI_SIZE_LOG2;
6405*77c1e3ccSAndroid Build Coastguard Worker const uint8_t *const mask1d = av1_get_obmc_mask(ctxt->overlap);
6406*77c1e3ccSAndroid Build Coastguard Worker
6407*77c1e3ccSAndroid Build Coastguard Worker int32_t *wsrc = ctxt->obmc_buffer->wsrc + (rel_mi_col * MI_SIZE);
6408*77c1e3ccSAndroid Build Coastguard Worker int32_t *mask = ctxt->obmc_buffer->mask + (rel_mi_col * MI_SIZE);
6409*77c1e3ccSAndroid Build Coastguard Worker const uint8_t *tmp = ctxt->tmp + rel_mi_col * MI_SIZE;
6410*77c1e3ccSAndroid Build Coastguard Worker const int is_hbd = is_cur_buf_hbd(xd);
6411*77c1e3ccSAndroid Build Coastguard Worker
6412*77c1e3ccSAndroid Build Coastguard Worker if (!is_hbd) {
6413*77c1e3ccSAndroid Build Coastguard Worker for (int row = 0; row < ctxt->overlap; ++row) {
6414*77c1e3ccSAndroid Build Coastguard Worker const uint8_t m0 = mask1d[row];
6415*77c1e3ccSAndroid Build Coastguard Worker const uint8_t m1 = AOM_BLEND_A64_MAX_ALPHA - m0;
6416*77c1e3ccSAndroid Build Coastguard Worker for (int col = 0; col < op_mi_size * MI_SIZE; ++col) {
6417*77c1e3ccSAndroid Build Coastguard Worker wsrc[col] = m1 * tmp[col];
6418*77c1e3ccSAndroid Build Coastguard Worker mask[col] = m0;
6419*77c1e3ccSAndroid Build Coastguard Worker }
6420*77c1e3ccSAndroid Build Coastguard Worker wsrc += bw;
6421*77c1e3ccSAndroid Build Coastguard Worker mask += bw;
6422*77c1e3ccSAndroid Build Coastguard Worker tmp += ctxt->tmp_stride;
6423*77c1e3ccSAndroid Build Coastguard Worker }
6424*77c1e3ccSAndroid Build Coastguard Worker } else {
6425*77c1e3ccSAndroid Build Coastguard Worker const uint16_t *tmp16 = CONVERT_TO_SHORTPTR(tmp);
6426*77c1e3ccSAndroid Build Coastguard Worker
6427*77c1e3ccSAndroid Build Coastguard Worker for (int row = 0; row < ctxt->overlap; ++row) {
6428*77c1e3ccSAndroid Build Coastguard Worker const uint8_t m0 = mask1d[row];
6429*77c1e3ccSAndroid Build Coastguard Worker const uint8_t m1 = AOM_BLEND_A64_MAX_ALPHA - m0;
6430*77c1e3ccSAndroid Build Coastguard Worker for (int col = 0; col < op_mi_size * MI_SIZE; ++col) {
6431*77c1e3ccSAndroid Build Coastguard Worker wsrc[col] = m1 * tmp16[col];
6432*77c1e3ccSAndroid Build Coastguard Worker mask[col] = m0;
6433*77c1e3ccSAndroid Build Coastguard Worker }
6434*77c1e3ccSAndroid Build Coastguard Worker wsrc += bw;
6435*77c1e3ccSAndroid Build Coastguard Worker mask += bw;
6436*77c1e3ccSAndroid Build Coastguard Worker tmp16 += ctxt->tmp_stride;
6437*77c1e3ccSAndroid Build Coastguard Worker }
6438*77c1e3ccSAndroid Build Coastguard Worker }
6439*77c1e3ccSAndroid Build Coastguard Worker }
6440*77c1e3ccSAndroid Build Coastguard Worker
calc_target_weighted_pred_left(MACROBLOCKD * xd,int rel_mi_row,int rel_mi_col,uint8_t op_mi_size,int dir,MB_MODE_INFO * nb_mi,void * fun_ctxt,const int num_planes)6441*77c1e3ccSAndroid Build Coastguard Worker static inline void calc_target_weighted_pred_left(
6442*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *xd, int rel_mi_row, int rel_mi_col, uint8_t op_mi_size,
6443*77c1e3ccSAndroid Build Coastguard Worker int dir, MB_MODE_INFO *nb_mi, void *fun_ctxt, const int num_planes) {
6444*77c1e3ccSAndroid Build Coastguard Worker (void)nb_mi;
6445*77c1e3ccSAndroid Build Coastguard Worker (void)num_planes;
6446*77c1e3ccSAndroid Build Coastguard Worker (void)rel_mi_col;
6447*77c1e3ccSAndroid Build Coastguard Worker (void)dir;
6448*77c1e3ccSAndroid Build Coastguard Worker
6449*77c1e3ccSAndroid Build Coastguard Worker struct calc_target_weighted_pred_ctxt *ctxt =
6450*77c1e3ccSAndroid Build Coastguard Worker (struct calc_target_weighted_pred_ctxt *)fun_ctxt;
6451*77c1e3ccSAndroid Build Coastguard Worker
6452*77c1e3ccSAndroid Build Coastguard Worker const int bw = xd->width << MI_SIZE_LOG2;
6453*77c1e3ccSAndroid Build Coastguard Worker const uint8_t *const mask1d = av1_get_obmc_mask(ctxt->overlap);
6454*77c1e3ccSAndroid Build Coastguard Worker
6455*77c1e3ccSAndroid Build Coastguard Worker int32_t *wsrc = ctxt->obmc_buffer->wsrc + (rel_mi_row * MI_SIZE * bw);
6456*77c1e3ccSAndroid Build Coastguard Worker int32_t *mask = ctxt->obmc_buffer->mask + (rel_mi_row * MI_SIZE * bw);
6457*77c1e3ccSAndroid Build Coastguard Worker const uint8_t *tmp = ctxt->tmp + (rel_mi_row * MI_SIZE * ctxt->tmp_stride);
6458*77c1e3ccSAndroid Build Coastguard Worker const int is_hbd = is_cur_buf_hbd(xd);
6459*77c1e3ccSAndroid Build Coastguard Worker
6460*77c1e3ccSAndroid Build Coastguard Worker if (!is_hbd) {
6461*77c1e3ccSAndroid Build Coastguard Worker for (int row = 0; row < op_mi_size * MI_SIZE; ++row) {
6462*77c1e3ccSAndroid Build Coastguard Worker for (int col = 0; col < ctxt->overlap; ++col) {
6463*77c1e3ccSAndroid Build Coastguard Worker const uint8_t m0 = mask1d[col];
6464*77c1e3ccSAndroid Build Coastguard Worker const uint8_t m1 = AOM_BLEND_A64_MAX_ALPHA - m0;
6465*77c1e3ccSAndroid Build Coastguard Worker wsrc[col] = (wsrc[col] >> AOM_BLEND_A64_ROUND_BITS) * m0 +
6466*77c1e3ccSAndroid Build Coastguard Worker (tmp[col] << AOM_BLEND_A64_ROUND_BITS) * m1;
6467*77c1e3ccSAndroid Build Coastguard Worker mask[col] = (mask[col] >> AOM_BLEND_A64_ROUND_BITS) * m0;
6468*77c1e3ccSAndroid Build Coastguard Worker }
6469*77c1e3ccSAndroid Build Coastguard Worker wsrc += bw;
6470*77c1e3ccSAndroid Build Coastguard Worker mask += bw;
6471*77c1e3ccSAndroid Build Coastguard Worker tmp += ctxt->tmp_stride;
6472*77c1e3ccSAndroid Build Coastguard Worker }
6473*77c1e3ccSAndroid Build Coastguard Worker } else {
6474*77c1e3ccSAndroid Build Coastguard Worker const uint16_t *tmp16 = CONVERT_TO_SHORTPTR(tmp);
6475*77c1e3ccSAndroid Build Coastguard Worker
6476*77c1e3ccSAndroid Build Coastguard Worker for (int row = 0; row < op_mi_size * MI_SIZE; ++row) {
6477*77c1e3ccSAndroid Build Coastguard Worker for (int col = 0; col < ctxt->overlap; ++col) {
6478*77c1e3ccSAndroid Build Coastguard Worker const uint8_t m0 = mask1d[col];
6479*77c1e3ccSAndroid Build Coastguard Worker const uint8_t m1 = AOM_BLEND_A64_MAX_ALPHA - m0;
6480*77c1e3ccSAndroid Build Coastguard Worker wsrc[col] = (wsrc[col] >> AOM_BLEND_A64_ROUND_BITS) * m0 +
6481*77c1e3ccSAndroid Build Coastguard Worker (tmp16[col] << AOM_BLEND_A64_ROUND_BITS) * m1;
6482*77c1e3ccSAndroid Build Coastguard Worker mask[col] = (mask[col] >> AOM_BLEND_A64_ROUND_BITS) * m0;
6483*77c1e3ccSAndroid Build Coastguard Worker }
6484*77c1e3ccSAndroid Build Coastguard Worker wsrc += bw;
6485*77c1e3ccSAndroid Build Coastguard Worker mask += bw;
6486*77c1e3ccSAndroid Build Coastguard Worker tmp16 += ctxt->tmp_stride;
6487*77c1e3ccSAndroid Build Coastguard Worker }
6488*77c1e3ccSAndroid Build Coastguard Worker }
6489*77c1e3ccSAndroid Build Coastguard Worker }
6490*77c1e3ccSAndroid Build Coastguard Worker
6491*77c1e3ccSAndroid Build Coastguard Worker // This function has a structure similar to av1_build_obmc_inter_prediction
6492*77c1e3ccSAndroid Build Coastguard Worker //
6493*77c1e3ccSAndroid Build Coastguard Worker // The OBMC predictor is computed as:
6494*77c1e3ccSAndroid Build Coastguard Worker //
6495*77c1e3ccSAndroid Build Coastguard Worker // PObmc(x,y) =
6496*77c1e3ccSAndroid Build Coastguard Worker // AOM_BLEND_A64(Mh(x),
6497*77c1e3ccSAndroid Build Coastguard Worker // AOM_BLEND_A64(Mv(y), P(x,y), PAbove(x,y)),
6498*77c1e3ccSAndroid Build Coastguard Worker // PLeft(x, y))
6499*77c1e3ccSAndroid Build Coastguard Worker //
6500*77c1e3ccSAndroid Build Coastguard Worker // Scaling up by AOM_BLEND_A64_MAX_ALPHA ** 2 and omitting the intermediate
6501*77c1e3ccSAndroid Build Coastguard Worker // rounding, this can be written as:
6502*77c1e3ccSAndroid Build Coastguard Worker //
6503*77c1e3ccSAndroid Build Coastguard Worker // AOM_BLEND_A64_MAX_ALPHA * AOM_BLEND_A64_MAX_ALPHA * Pobmc(x,y) =
6504*77c1e3ccSAndroid Build Coastguard Worker // Mh(x) * Mv(y) * P(x,y) +
6505*77c1e3ccSAndroid Build Coastguard Worker // Mh(x) * Cv(y) * Pabove(x,y) +
6506*77c1e3ccSAndroid Build Coastguard Worker // AOM_BLEND_A64_MAX_ALPHA * Ch(x) * PLeft(x, y)
6507*77c1e3ccSAndroid Build Coastguard Worker //
6508*77c1e3ccSAndroid Build Coastguard Worker // Where :
6509*77c1e3ccSAndroid Build Coastguard Worker //
6510*77c1e3ccSAndroid Build Coastguard Worker // Cv(y) = AOM_BLEND_A64_MAX_ALPHA - Mv(y)
6511*77c1e3ccSAndroid Build Coastguard Worker // Ch(y) = AOM_BLEND_A64_MAX_ALPHA - Mh(y)
6512*77c1e3ccSAndroid Build Coastguard Worker //
6513*77c1e3ccSAndroid Build Coastguard Worker // This function computes 'wsrc' and 'mask' as:
6514*77c1e3ccSAndroid Build Coastguard Worker //
6515*77c1e3ccSAndroid Build Coastguard Worker // wsrc(x, y) =
6516*77c1e3ccSAndroid Build Coastguard Worker // AOM_BLEND_A64_MAX_ALPHA * AOM_BLEND_A64_MAX_ALPHA * src(x, y) -
6517*77c1e3ccSAndroid Build Coastguard Worker // Mh(x) * Cv(y) * Pabove(x,y) +
6518*77c1e3ccSAndroid Build Coastguard Worker // AOM_BLEND_A64_MAX_ALPHA * Ch(x) * PLeft(x, y)
6519*77c1e3ccSAndroid Build Coastguard Worker //
6520*77c1e3ccSAndroid Build Coastguard Worker // mask(x, y) = Mh(x) * Mv(y)
6521*77c1e3ccSAndroid Build Coastguard Worker //
6522*77c1e3ccSAndroid Build Coastguard Worker // These can then be used to efficiently approximate the error for any
6523*77c1e3ccSAndroid Build Coastguard Worker // predictor P in the context of the provided neighbouring predictors by
6524*77c1e3ccSAndroid Build Coastguard Worker // computing:
6525*77c1e3ccSAndroid Build Coastguard Worker //
6526*77c1e3ccSAndroid Build Coastguard Worker // error(x, y) =
6527*77c1e3ccSAndroid Build Coastguard Worker // wsrc(x, y) - mask(x, y) * P(x, y) / (AOM_BLEND_A64_MAX_ALPHA ** 2)
6528*77c1e3ccSAndroid Build Coastguard Worker //
calc_target_weighted_pred(const AV1_COMMON * cm,const MACROBLOCK * x,const MACROBLOCKD * xd,const uint8_t * above,int above_stride,const uint8_t * left,int left_stride)6529*77c1e3ccSAndroid Build Coastguard Worker static inline void calc_target_weighted_pred(
6530*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *cm, const MACROBLOCK *x, const MACROBLOCKD *xd,
6531*77c1e3ccSAndroid Build Coastguard Worker const uint8_t *above, int above_stride, const uint8_t *left,
6532*77c1e3ccSAndroid Build Coastguard Worker int left_stride) {
6533*77c1e3ccSAndroid Build Coastguard Worker const BLOCK_SIZE bsize = xd->mi[0]->bsize;
6534*77c1e3ccSAndroid Build Coastguard Worker const int bw = xd->width << MI_SIZE_LOG2;
6535*77c1e3ccSAndroid Build Coastguard Worker const int bh = xd->height << MI_SIZE_LOG2;
6536*77c1e3ccSAndroid Build Coastguard Worker const OBMCBuffer *obmc_buffer = &x->obmc_buffer;
6537*77c1e3ccSAndroid Build Coastguard Worker int32_t *mask_buf = obmc_buffer->mask;
6538*77c1e3ccSAndroid Build Coastguard Worker int32_t *wsrc_buf = obmc_buffer->wsrc;
6539*77c1e3ccSAndroid Build Coastguard Worker
6540*77c1e3ccSAndroid Build Coastguard Worker const int is_hbd = is_cur_buf_hbd(xd);
6541*77c1e3ccSAndroid Build Coastguard Worker const int src_scale = AOM_BLEND_A64_MAX_ALPHA * AOM_BLEND_A64_MAX_ALPHA;
6542*77c1e3ccSAndroid Build Coastguard Worker
6543*77c1e3ccSAndroid Build Coastguard Worker // plane 0 should not be sub-sampled
6544*77c1e3ccSAndroid Build Coastguard Worker assert(xd->plane[0].subsampling_x == 0);
6545*77c1e3ccSAndroid Build Coastguard Worker assert(xd->plane[0].subsampling_y == 0);
6546*77c1e3ccSAndroid Build Coastguard Worker
6547*77c1e3ccSAndroid Build Coastguard Worker av1_zero_array(wsrc_buf, bw * bh);
6548*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < bw * bh; ++i) mask_buf[i] = AOM_BLEND_A64_MAX_ALPHA;
6549*77c1e3ccSAndroid Build Coastguard Worker
6550*77c1e3ccSAndroid Build Coastguard Worker // handle above row
6551*77c1e3ccSAndroid Build Coastguard Worker if (xd->up_available) {
6552*77c1e3ccSAndroid Build Coastguard Worker const int overlap =
6553*77c1e3ccSAndroid Build Coastguard Worker AOMMIN(block_size_high[bsize], block_size_high[BLOCK_64X64]) >> 1;
6554*77c1e3ccSAndroid Build Coastguard Worker struct calc_target_weighted_pred_ctxt ctxt = { obmc_buffer, above,
6555*77c1e3ccSAndroid Build Coastguard Worker above_stride, overlap };
6556*77c1e3ccSAndroid Build Coastguard Worker foreach_overlappable_nb_above(cm, (MACROBLOCKD *)xd,
6557*77c1e3ccSAndroid Build Coastguard Worker max_neighbor_obmc[mi_size_wide_log2[bsize]],
6558*77c1e3ccSAndroid Build Coastguard Worker calc_target_weighted_pred_above, &ctxt);
6559*77c1e3ccSAndroid Build Coastguard Worker }
6560*77c1e3ccSAndroid Build Coastguard Worker
6561*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < bw * bh; ++i) {
6562*77c1e3ccSAndroid Build Coastguard Worker wsrc_buf[i] *= AOM_BLEND_A64_MAX_ALPHA;
6563*77c1e3ccSAndroid Build Coastguard Worker mask_buf[i] *= AOM_BLEND_A64_MAX_ALPHA;
6564*77c1e3ccSAndroid Build Coastguard Worker }
6565*77c1e3ccSAndroid Build Coastguard Worker
6566*77c1e3ccSAndroid Build Coastguard Worker // handle left column
6567*77c1e3ccSAndroid Build Coastguard Worker if (xd->left_available) {
6568*77c1e3ccSAndroid Build Coastguard Worker const int overlap =
6569*77c1e3ccSAndroid Build Coastguard Worker AOMMIN(block_size_wide[bsize], block_size_wide[BLOCK_64X64]) >> 1;
6570*77c1e3ccSAndroid Build Coastguard Worker struct calc_target_weighted_pred_ctxt ctxt = { obmc_buffer, left,
6571*77c1e3ccSAndroid Build Coastguard Worker left_stride, overlap };
6572*77c1e3ccSAndroid Build Coastguard Worker foreach_overlappable_nb_left(cm, (MACROBLOCKD *)xd,
6573*77c1e3ccSAndroid Build Coastguard Worker max_neighbor_obmc[mi_size_high_log2[bsize]],
6574*77c1e3ccSAndroid Build Coastguard Worker calc_target_weighted_pred_left, &ctxt);
6575*77c1e3ccSAndroid Build Coastguard Worker }
6576*77c1e3ccSAndroid Build Coastguard Worker
6577*77c1e3ccSAndroid Build Coastguard Worker if (!is_hbd) {
6578*77c1e3ccSAndroid Build Coastguard Worker const uint8_t *src = x->plane[0].src.buf;
6579*77c1e3ccSAndroid Build Coastguard Worker
6580*77c1e3ccSAndroid Build Coastguard Worker for (int row = 0; row < bh; ++row) {
6581*77c1e3ccSAndroid Build Coastguard Worker for (int col = 0; col < bw; ++col) {
6582*77c1e3ccSAndroid Build Coastguard Worker wsrc_buf[col] = src[col] * src_scale - wsrc_buf[col];
6583*77c1e3ccSAndroid Build Coastguard Worker }
6584*77c1e3ccSAndroid Build Coastguard Worker wsrc_buf += bw;
6585*77c1e3ccSAndroid Build Coastguard Worker src += x->plane[0].src.stride;
6586*77c1e3ccSAndroid Build Coastguard Worker }
6587*77c1e3ccSAndroid Build Coastguard Worker } else {
6588*77c1e3ccSAndroid Build Coastguard Worker const uint16_t *src = CONVERT_TO_SHORTPTR(x->plane[0].src.buf);
6589*77c1e3ccSAndroid Build Coastguard Worker
6590*77c1e3ccSAndroid Build Coastguard Worker for (int row = 0; row < bh; ++row) {
6591*77c1e3ccSAndroid Build Coastguard Worker for (int col = 0; col < bw; ++col) {
6592*77c1e3ccSAndroid Build Coastguard Worker wsrc_buf[col] = src[col] * src_scale - wsrc_buf[col];
6593*77c1e3ccSAndroid Build Coastguard Worker }
6594*77c1e3ccSAndroid Build Coastguard Worker wsrc_buf += bw;
6595*77c1e3ccSAndroid Build Coastguard Worker src += x->plane[0].src.stride;
6596*77c1e3ccSAndroid Build Coastguard Worker }
6597*77c1e3ccSAndroid Build Coastguard Worker }
6598*77c1e3ccSAndroid Build Coastguard Worker }
6599