blob: dac41b797561b0ffb8dc837e9c1c680e3bf5a5f0 [file] [log] [blame]
Yaowu Xuc27fc142016-08-22 16:08:15 -07001/*
Yaowu Xu2ab7ff02016-09-02 12:04:54 -07002 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Yaowu Xuc27fc142016-08-22 16:08:15 -07003 *
Yaowu Xu2ab7ff02016-09-02 12:04:54 -07004 * This source code is subject to the terms of the BSD 2 Clause License and
5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6 * was not distributed with this source code in the LICENSE file, you can
7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8 * Media Patent License 1.0 was not distributed with this source code in the
9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
Yaowu Xuc27fc142016-08-22 16:08:15 -070010 */
11
12#include <assert.h>
13#include <math.h>
14
Yaowu Xuf883b422016-08-30 14:01:10 -070015#include "./aom_dsp_rtcd.h"
Jingning Han1aab8182016-06-03 11:09:06 -070016#include "./av1_rtcd.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070017
Yaowu Xuf883b422016-08-30 14:01:10 -070018#include "aom_dsp/aom_dsp_common.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070019#include "aom_dsp/blend.h"
Yaowu Xuf883b422016-08-30 14:01:10 -070020#include "aom_mem/aom_mem.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070021#include "aom_ports/mem.h"
22#include "aom_ports/system_state.h"
23
David Michael Barr5b2021e2017-08-17 18:12:39 +090024#if CONFIG_CFL
25#include "av1/common/cfl.h"
26#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -070027#include "av1/common/common.h"
28#include "av1/common/common_data.h"
29#include "av1/common/entropy.h"
30#include "av1/common/entropymode.h"
31#include "av1/common/idct.h"
32#include "av1/common/mvref_common.h"
Rupert Swarbrickc0cea7f2017-08-22 14:06:56 +010033#include "av1/common/obmc.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070034#include "av1/common/pred_common.h"
35#include "av1/common/quant_common.h"
36#include "av1/common/reconinter.h"
37#include "av1/common/reconintra.h"
38#include "av1/common/scan.h"
39#include "av1/common/seg_common.h"
Angie Chiang47e4b362017-03-24 11:25:10 -070040#if CONFIG_LV_MAP
41#include "av1/common/txb_common.h"
42#endif
Yue Chen69f18e12016-09-08 14:48:15 -070043#if CONFIG_WARPED_MOTION
44#include "av1/common/warped_motion.h"
45#endif // CONFIG_WARPED_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -070046
Jingning Han1aab8182016-06-03 11:09:06 -070047#include "av1/encoder/aq_variance.h"
Tom Finegan17ce8b12017-02-08 12:46:31 -080048#include "av1/encoder/av1_quantize.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070049#include "av1/encoder/cost.h"
50#include "av1/encoder/encodemb.h"
51#include "av1/encoder/encodemv.h"
52#include "av1/encoder/encoder.h"
Angie Chiang47e4b362017-03-24 11:25:10 -070053#if CONFIG_LV_MAP
54#include "av1/encoder/encodetxb.h"
55#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -070056#include "av1/encoder/hybrid_fwd_txfm.h"
57#include "av1/encoder/mcomp.h"
58#include "av1/encoder/palette.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070059#include "av1/encoder/ratectrl.h"
60#include "av1/encoder/rd.h"
61#include "av1/encoder/rdopt.h"
Debargha Mukherjeeceebb702016-10-11 05:26:50 -070062#include "av1/encoder/tokenize.h"
Yushin Cho77bba8d2016-11-04 16:36:56 -070063#if CONFIG_PVQ
64#include "av1/encoder/pvq_encoder.h"
Yushin Cho7a428ba2017-01-12 16:28:49 -080065#include "av1/common/pvq.h"
Yushin Cho55104332017-08-14 16:15:43 -070066#endif // CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -070067#if CONFIG_DUAL_FILTER
Angie Chiang5678ad92016-11-21 09:38:40 -080068#define DUAL_FILTER_SET_SIZE (SWITCHABLE_FILTERS * SWITCHABLE_FILTERS)
Angie Chiangaadbb022017-06-01 16:08:03 -070069#if USE_EXTRA_FILTER
Angie Chiang5678ad92016-11-21 09:38:40 -080070static const int filter_sets[DUAL_FILTER_SET_SIZE][2] = {
Angie Chiangd91ab372016-11-21 18:16:49 -080071 { 0, 0 }, { 0, 1 }, { 0, 2 }, { 0, 3 }, { 1, 0 }, { 1, 1 },
72 { 1, 2 }, { 1, 3 }, { 2, 0 }, { 2, 1 }, { 2, 2 }, { 2, 3 },
73 { 3, 0 }, { 3, 1 }, { 3, 2 }, { 3, 3 },
Yaowu Xuc27fc142016-08-22 16:08:15 -070074};
Angie Chiangaadbb022017-06-01 16:08:03 -070075#else // USE_EXTRA_FILTER
76static const int filter_sets[DUAL_FILTER_SET_SIZE][2] = {
77 { 0, 0 }, { 0, 1 }, { 0, 2 }, { 1, 0 }, { 1, 1 },
78 { 1, 2 }, { 2, 0 }, { 2, 1 }, { 2, 2 },
79};
80#endif // USE_EXTRA_FILTER
Angie Chiang5678ad92016-11-21 09:38:40 -080081#endif // CONFIG_DUAL_FILTER
Yaowu Xuc27fc142016-08-22 16:08:15 -070082
83#if CONFIG_EXT_REFS
84
Zoe Liue9b15e22017-07-19 15:53:01 -070085#define LAST_FRAME_MODE_MASK \
86 ((1 << INTRA_FRAME) | (1 << LAST2_FRAME) | (1 << LAST3_FRAME) | \
87 (1 << GOLDEN_FRAME) | (1 << BWDREF_FRAME) | (1 << ALTREF2_FRAME) | \
88 (1 << ALTREF_FRAME))
89#define LAST2_FRAME_MODE_MASK \
90 ((1 << INTRA_FRAME) | (1 << LAST_FRAME) | (1 << LAST3_FRAME) | \
91 (1 << GOLDEN_FRAME) | (1 << BWDREF_FRAME) | (1 << ALTREF2_FRAME) | \
92 (1 << ALTREF_FRAME))
93#define LAST3_FRAME_MODE_MASK \
94 ((1 << INTRA_FRAME) | (1 << LAST_FRAME) | (1 << LAST2_FRAME) | \
95 (1 << GOLDEN_FRAME) | (1 << BWDREF_FRAME) | (1 << ALTREF2_FRAME) | \
96 (1 << ALTREF_FRAME))
97#define GOLDEN_FRAME_MODE_MASK \
98 ((1 << INTRA_FRAME) | (1 << LAST_FRAME) | (1 << LAST2_FRAME) | \
99 (1 << LAST3_FRAME) | (1 << BWDREF_FRAME) | (1 << ALTREF2_FRAME) | \
100 (1 << ALTREF_FRAME))
101#define BWDREF_FRAME_MODE_MASK \
102 ((1 << INTRA_FRAME) | (1 << LAST_FRAME) | (1 << LAST2_FRAME) | \
103 (1 << LAST3_FRAME) | (1 << GOLDEN_FRAME) | (1 << ALTREF2_FRAME) | \
104 (1 << ALTREF_FRAME))
105#define ALTREF2_FRAME_MODE_MASK \
106 ((1 << INTRA_FRAME) | (1 << LAST_FRAME) | (1 << LAST2_FRAME) | \
107 (1 << LAST3_FRAME) | (1 << GOLDEN_FRAME) | (1 << BWDREF_FRAME) | \
108 (1 << ALTREF_FRAME))
109#define ALTREF_FRAME_MODE_MASK \
110 ((1 << INTRA_FRAME) | (1 << LAST_FRAME) | (1 << LAST2_FRAME) | \
111 (1 << LAST3_FRAME) | (1 << GOLDEN_FRAME) | (1 << BWDREF_FRAME) | \
112 (1 << ALTREF2_FRAME))
113
Zoe Liue9b15e22017-07-19 15:53:01 -0700114#else // !CONFIG_EXT_REFS
Yaowu Xuc27fc142016-08-22 16:08:15 -0700115
116#define LAST_FRAME_MODE_MASK \
117 ((1 << GOLDEN_FRAME) | (1 << ALTREF_FRAME) | (1 << INTRA_FRAME))
118#define GOLDEN_FRAME_MODE_MASK \
119 ((1 << LAST_FRAME) | (1 << ALTREF_FRAME) | (1 << INTRA_FRAME))
120#define ALTREF_FRAME_MODE_MASK \
121 ((1 << LAST_FRAME) | (1 << GOLDEN_FRAME) | (1 << INTRA_FRAME))
122
123#endif // CONFIG_EXT_REFS
124
125#if CONFIG_EXT_REFS
Zoe Liuc082bbc2017-05-17 13:31:37 -0700126#if CONFIG_EXT_COMP_REFS
Zoe Liuac889702017-08-23 14:22:58 -0700127#define SECOND_REF_FRAME_MASK \
128 ((1 << ALTREF_FRAME) | (1 << ALTREF2_FRAME) | (1 << BWDREF_FRAME) | \
129 (1 << GOLDEN_FRAME) | (1 << LAST2_FRAME) | 0x01)
Zoe Liu3ac20932017-08-30 16:35:55 -0700130#else // !CONFIG_EXT_COMP_REFS
Zoe Liue9b15e22017-07-19 15:53:01 -0700131#define SECOND_REF_FRAME_MASK \
132 ((1 << ALTREF_FRAME) | (1 << ALTREF2_FRAME) | (1 << BWDREF_FRAME) | 0x01)
Zoe Liuc082bbc2017-05-17 13:31:37 -0700133#endif // CONFIG_EXT_COMP_REFS
134#else // !CONFIG_EXT_REFS
Yaowu Xuc27fc142016-08-22 16:08:15 -0700135#define SECOND_REF_FRAME_MASK ((1 << ALTREF_FRAME) | 0x01)
136#endif // CONFIG_EXT_REFS
137
138#define MIN_EARLY_TERM_INDEX 3
139#define NEW_MV_DISCOUNT_FACTOR 8
140
141#if CONFIG_EXT_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -0700142#define ANGLE_SKIP_THRESH 10
143#define FILTER_FAST_SEARCH 1
144#endif // CONFIG_EXT_INTRA
145
Sarah Parker345366a2017-06-15 12:13:01 -0700146// Setting this to 1 will disable trellis optimization within the
147// transform search. Trellis optimization will still be applied
148// in the final encode.
Angie Chiang91a1cf92017-08-20 10:50:31 -0700149#ifndef DISABLE_TRELLISQ_SEARCH
Yushin Choba40b522017-09-25 10:25:36 -0700150#define DISABLE_TRELLISQ_SEARCH 0
Angie Chiang91a1cf92017-08-20 10:50:31 -0700151#endif
Sarah Parker345366a2017-06-15 12:13:01 -0700152
James Zern67932792017-08-21 11:13:19 -0700153static const double ADST_FLIP_SVM[8] = {
154 /* vertical */
155 -6.6623, -2.8062, -3.2531, 3.1671,
156 /* horizontal */
157 -7.7051, -3.2234, -3.6193, 3.4533
158};
Yaowu Xuc27fc142016-08-22 16:08:15 -0700159
160typedef struct {
161 PREDICTION_MODE mode;
162 MV_REFERENCE_FRAME ref_frame[2];
163} MODE_DEFINITION;
164
165typedef struct { MV_REFERENCE_FRAME ref_frame[2]; } REF_DEFINITION;
166
167struct rdcost_block_args {
Yaowu Xuf883b422016-08-30 14:01:10 -0700168 const AV1_COMP *cpi;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700169 MACROBLOCK *x;
170 ENTROPY_CONTEXT t_above[2 * MAX_MIB_SIZE];
171 ENTROPY_CONTEXT t_left[2 * MAX_MIB_SIZE];
Angie Chiang7c2b7f22016-11-07 16:00:00 -0800172 RD_STATS rd_stats;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700173 int64_t this_rd;
174 int64_t best_rd;
175 int exit_early;
176 int use_fast_coef_costing;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700177};
178
179#define LAST_NEW_MV_INDEX 6
Yaowu Xuf883b422016-08-30 14:01:10 -0700180static const MODE_DEFINITION av1_mode_order[MAX_MODES] = {
Emil Keyder01770b32017-01-20 18:03:11 -0500181 { NEARESTMV, { LAST_FRAME, NONE_FRAME } },
Yaowu Xuc27fc142016-08-22 16:08:15 -0700182#if CONFIG_EXT_REFS
Emil Keyder01770b32017-01-20 18:03:11 -0500183 { NEARESTMV, { LAST2_FRAME, NONE_FRAME } },
184 { NEARESTMV, { LAST3_FRAME, NONE_FRAME } },
185 { NEARESTMV, { BWDREF_FRAME, NONE_FRAME } },
Zoe Liue9b15e22017-07-19 15:53:01 -0700186 { NEARESTMV, { ALTREF2_FRAME, NONE_FRAME } },
Yaowu Xuc27fc142016-08-22 16:08:15 -0700187#endif // CONFIG_EXT_REFS
Emil Keyder01770b32017-01-20 18:03:11 -0500188 { NEARESTMV, { ALTREF_FRAME, NONE_FRAME } },
189 { NEARESTMV, { GOLDEN_FRAME, NONE_FRAME } },
Yaowu Xuc27fc142016-08-22 16:08:15 -0700190
Emil Keyder01770b32017-01-20 18:03:11 -0500191 { DC_PRED, { INTRA_FRAME, NONE_FRAME } },
Yaowu Xuc27fc142016-08-22 16:08:15 -0700192
Emil Keyder01770b32017-01-20 18:03:11 -0500193 { NEWMV, { LAST_FRAME, NONE_FRAME } },
Yaowu Xuc27fc142016-08-22 16:08:15 -0700194#if CONFIG_EXT_REFS
Emil Keyder01770b32017-01-20 18:03:11 -0500195 { NEWMV, { LAST2_FRAME, NONE_FRAME } },
196 { NEWMV, { LAST3_FRAME, NONE_FRAME } },
197 { NEWMV, { BWDREF_FRAME, NONE_FRAME } },
Zoe Liue9b15e22017-07-19 15:53:01 -0700198 { NEWMV, { ALTREF2_FRAME, NONE_FRAME } },
Yaowu Xuc27fc142016-08-22 16:08:15 -0700199#endif // CONFIG_EXT_REFS
Emil Keyder01770b32017-01-20 18:03:11 -0500200 { NEWMV, { ALTREF_FRAME, NONE_FRAME } },
201 { NEWMV, { GOLDEN_FRAME, NONE_FRAME } },
Yaowu Xuc27fc142016-08-22 16:08:15 -0700202
Emil Keyder01770b32017-01-20 18:03:11 -0500203 { NEARMV, { LAST_FRAME, NONE_FRAME } },
Yaowu Xuc27fc142016-08-22 16:08:15 -0700204#if CONFIG_EXT_REFS
Emil Keyder01770b32017-01-20 18:03:11 -0500205 { NEARMV, { LAST2_FRAME, NONE_FRAME } },
206 { NEARMV, { LAST3_FRAME, NONE_FRAME } },
207 { NEARMV, { BWDREF_FRAME, NONE_FRAME } },
Zoe Liue9b15e22017-07-19 15:53:01 -0700208 { NEARMV, { ALTREF2_FRAME, NONE_FRAME } },
Yaowu Xuc27fc142016-08-22 16:08:15 -0700209#endif // CONFIG_EXT_REFS
Emil Keyder01770b32017-01-20 18:03:11 -0500210 { NEARMV, { ALTREF_FRAME, NONE_FRAME } },
211 { NEARMV, { GOLDEN_FRAME, NONE_FRAME } },
Yaowu Xuc27fc142016-08-22 16:08:15 -0700212
Emil Keyder01770b32017-01-20 18:03:11 -0500213 { ZEROMV, { LAST_FRAME, NONE_FRAME } },
Yaowu Xuc27fc142016-08-22 16:08:15 -0700214#if CONFIG_EXT_REFS
Emil Keyder01770b32017-01-20 18:03:11 -0500215 { ZEROMV, { LAST2_FRAME, NONE_FRAME } },
216 { ZEROMV, { LAST3_FRAME, NONE_FRAME } },
217 { ZEROMV, { BWDREF_FRAME, NONE_FRAME } },
Zoe Liue9b15e22017-07-19 15:53:01 -0700218 { ZEROMV, { ALTREF2_FRAME, NONE_FRAME } },
Yaowu Xuc27fc142016-08-22 16:08:15 -0700219#endif // CONFIG_EXT_REFS
Emil Keyder01770b32017-01-20 18:03:11 -0500220 { ZEROMV, { GOLDEN_FRAME, NONE_FRAME } },
221 { ZEROMV, { ALTREF_FRAME, NONE_FRAME } },
Yaowu Xuc27fc142016-08-22 16:08:15 -0700222
223// TODO(zoeliu): May need to reconsider the order on the modes to check
224
Zoe Liu85b66462017-04-20 14:28:19 -0700225#if CONFIG_COMPOUND_SINGLEREF
226 // Single ref comp mode
227 { SR_NEAREST_NEARMV, { LAST_FRAME, NONE_FRAME } },
228#if CONFIG_EXT_REFS
229 { SR_NEAREST_NEARMV, { LAST2_FRAME, NONE_FRAME } },
230 { SR_NEAREST_NEARMV, { LAST3_FRAME, NONE_FRAME } },
231 { SR_NEAREST_NEARMV, { BWDREF_FRAME, NONE_FRAME } },
232#endif // CONFIG_EXT_REFS
233 { SR_NEAREST_NEARMV, { GOLDEN_FRAME, NONE_FRAME } },
234 { SR_NEAREST_NEARMV, { ALTREF_FRAME, NONE_FRAME } },
235
236 /*
237 { SR_NEAREST_NEWMV, { LAST_FRAME, NONE_FRAME } },
238#if CONFIG_EXT_REFS
239 { SR_NEAREST_NEWMV, { LAST2_FRAME, NONE_FRAME } },
240 { SR_NEAREST_NEWMV, { LAST3_FRAME, NONE_FRAME } },
241 { SR_NEAREST_NEWMV, { BWDREF_FRAME, NONE_FRAME } },
242#endif // CONFIG_EXT_REFS
243 { SR_NEAREST_NEWMV, { GOLDEN_FRAME, NONE_FRAME } },
244 { SR_NEAREST_NEWMV, { ALTREF_FRAME, NONE_FRAME } },*/
245
246 { SR_NEAR_NEWMV, { LAST_FRAME, NONE_FRAME } },
247#if CONFIG_EXT_REFS
248 { SR_NEAR_NEWMV, { LAST2_FRAME, NONE_FRAME } },
249 { SR_NEAR_NEWMV, { LAST3_FRAME, NONE_FRAME } },
250 { SR_NEAR_NEWMV, { BWDREF_FRAME, NONE_FRAME } },
251#endif // CONFIG_EXT_REFS
252 { SR_NEAR_NEWMV, { GOLDEN_FRAME, NONE_FRAME } },
253 { SR_NEAR_NEWMV, { ALTREF_FRAME, NONE_FRAME } },
254
255 { SR_ZERO_NEWMV, { LAST_FRAME, NONE_FRAME } },
256#if CONFIG_EXT_REFS
257 { SR_ZERO_NEWMV, { LAST2_FRAME, NONE_FRAME } },
258 { SR_ZERO_NEWMV, { LAST3_FRAME, NONE_FRAME } },
259 { SR_ZERO_NEWMV, { BWDREF_FRAME, NONE_FRAME } },
260#endif // CONFIG_EXT_REFS
261 { SR_ZERO_NEWMV, { GOLDEN_FRAME, NONE_FRAME } },
262 { SR_ZERO_NEWMV, { ALTREF_FRAME, NONE_FRAME } },
263
264 { SR_NEW_NEWMV, { LAST_FRAME, NONE_FRAME } },
265#if CONFIG_EXT_REFS
266 { SR_NEW_NEWMV, { LAST2_FRAME, NONE_FRAME } },
267 { SR_NEW_NEWMV, { LAST3_FRAME, NONE_FRAME } },
268 { SR_NEW_NEWMV, { BWDREF_FRAME, NONE_FRAME } },
269#endif // CONFIG_EXT_REFS
270 { SR_NEW_NEWMV, { GOLDEN_FRAME, NONE_FRAME } },
271 { SR_NEW_NEWMV, { ALTREF_FRAME, NONE_FRAME } },
272#endif // CONFIG_COMPOUND_SINGLEREF
273
Yaowu Xuc27fc142016-08-22 16:08:15 -0700274 { NEAREST_NEARESTMV, { LAST_FRAME, ALTREF_FRAME } },
275#if CONFIG_EXT_REFS
276 { NEAREST_NEARESTMV, { LAST2_FRAME, ALTREF_FRAME } },
277 { NEAREST_NEARESTMV, { LAST3_FRAME, ALTREF_FRAME } },
278#endif // CONFIG_EXT_REFS
279 { NEAREST_NEARESTMV, { GOLDEN_FRAME, ALTREF_FRAME } },
280#if CONFIG_EXT_REFS
281 { NEAREST_NEARESTMV, { LAST_FRAME, BWDREF_FRAME } },
282 { NEAREST_NEARESTMV, { LAST2_FRAME, BWDREF_FRAME } },
283 { NEAREST_NEARESTMV, { LAST3_FRAME, BWDREF_FRAME } },
284 { NEAREST_NEARESTMV, { GOLDEN_FRAME, BWDREF_FRAME } },
Zoe Liue9b15e22017-07-19 15:53:01 -0700285 { NEAREST_NEARESTMV, { LAST_FRAME, ALTREF2_FRAME } },
286 { NEAREST_NEARESTMV, { LAST2_FRAME, ALTREF2_FRAME } },
287 { NEAREST_NEARESTMV, { LAST3_FRAME, ALTREF2_FRAME } },
288 { NEAREST_NEARESTMV, { GOLDEN_FRAME, ALTREF2_FRAME } },
Zoe Liuc082bbc2017-05-17 13:31:37 -0700289
290#if CONFIG_EXT_COMP_REFS
291 { NEAREST_NEARESTMV, { LAST_FRAME, LAST2_FRAME } },
Zoe Liufcf5fa22017-06-26 16:00:38 -0700292 { NEAREST_NEARESTMV, { LAST_FRAME, LAST3_FRAME } },
Zoe Liuc082bbc2017-05-17 13:31:37 -0700293 { NEAREST_NEARESTMV, { LAST_FRAME, GOLDEN_FRAME } },
294 { NEAREST_NEARESTMV, { BWDREF_FRAME, ALTREF_FRAME } },
295#endif // CONFIG_EXT_COMP_REFS
Yaowu Xuc27fc142016-08-22 16:08:15 -0700296#endif // CONFIG_EXT_REFS
297
Urvang Joshi96d1c0a2017-10-10 13:15:32 -0700298 { PAETH_PRED, { INTRA_FRAME, NONE_FRAME } },
Yaowu Xuc27fc142016-08-22 16:08:15 -0700299
Emil Keyder01770b32017-01-20 18:03:11 -0500300 { SMOOTH_PRED, { INTRA_FRAME, NONE_FRAME } },
Urvang Joshie6ca8e82017-03-15 14:57:41 -0700301#if CONFIG_SMOOTH_HV
302 { SMOOTH_V_PRED, { INTRA_FRAME, NONE_FRAME } },
303 { SMOOTH_H_PRED, { INTRA_FRAME, NONE_FRAME } },
304#endif // CONFIG_SMOOTH_HV
Urvang Joshi6be4a542016-11-03 15:24:05 -0700305
Yaowu Xuc27fc142016-08-22 16:08:15 -0700306 { NEAR_NEARMV, { LAST_FRAME, ALTREF_FRAME } },
307 { NEW_NEARESTMV, { LAST_FRAME, ALTREF_FRAME } },
308 { NEAREST_NEWMV, { LAST_FRAME, ALTREF_FRAME } },
309 { NEW_NEARMV, { LAST_FRAME, ALTREF_FRAME } },
310 { NEAR_NEWMV, { LAST_FRAME, ALTREF_FRAME } },
311 { NEW_NEWMV, { LAST_FRAME, ALTREF_FRAME } },
312 { ZERO_ZEROMV, { LAST_FRAME, ALTREF_FRAME } },
313
314#if CONFIG_EXT_REFS
Yaowu Xuc27fc142016-08-22 16:08:15 -0700315 { NEAR_NEARMV, { LAST2_FRAME, ALTREF_FRAME } },
316 { NEW_NEARESTMV, { LAST2_FRAME, ALTREF_FRAME } },
317 { NEAREST_NEWMV, { LAST2_FRAME, ALTREF_FRAME } },
318 { NEW_NEARMV, { LAST2_FRAME, ALTREF_FRAME } },
319 { NEAR_NEWMV, { LAST2_FRAME, ALTREF_FRAME } },
320 { NEW_NEWMV, { LAST2_FRAME, ALTREF_FRAME } },
321 { ZERO_ZEROMV, { LAST2_FRAME, ALTREF_FRAME } },
322
Yaowu Xuc27fc142016-08-22 16:08:15 -0700323 { NEAR_NEARMV, { LAST3_FRAME, ALTREF_FRAME } },
324 { NEW_NEARESTMV, { LAST3_FRAME, ALTREF_FRAME } },
325 { NEAREST_NEWMV, { LAST3_FRAME, ALTREF_FRAME } },
326 { NEW_NEARMV, { LAST3_FRAME, ALTREF_FRAME } },
327 { NEAR_NEWMV, { LAST3_FRAME, ALTREF_FRAME } },
328 { NEW_NEWMV, { LAST3_FRAME, ALTREF_FRAME } },
329 { ZERO_ZEROMV, { LAST3_FRAME, ALTREF_FRAME } },
330#endif // CONFIG_EXT_REFS
331
Yaowu Xuc27fc142016-08-22 16:08:15 -0700332 { NEAR_NEARMV, { GOLDEN_FRAME, ALTREF_FRAME } },
333 { NEW_NEARESTMV, { GOLDEN_FRAME, ALTREF_FRAME } },
334 { NEAREST_NEWMV, { GOLDEN_FRAME, ALTREF_FRAME } },
335 { NEW_NEARMV, { GOLDEN_FRAME, ALTREF_FRAME } },
336 { NEAR_NEWMV, { GOLDEN_FRAME, ALTREF_FRAME } },
337 { NEW_NEWMV, { GOLDEN_FRAME, ALTREF_FRAME } },
338 { ZERO_ZEROMV, { GOLDEN_FRAME, ALTREF_FRAME } },
339
340#if CONFIG_EXT_REFS
Yaowu Xuc27fc142016-08-22 16:08:15 -0700341 { NEAR_NEARMV, { LAST_FRAME, BWDREF_FRAME } },
342 { NEW_NEARESTMV, { LAST_FRAME, BWDREF_FRAME } },
343 { NEAREST_NEWMV, { LAST_FRAME, BWDREF_FRAME } },
344 { NEW_NEARMV, { LAST_FRAME, BWDREF_FRAME } },
345 { NEAR_NEWMV, { LAST_FRAME, BWDREF_FRAME } },
346 { NEW_NEWMV, { LAST_FRAME, BWDREF_FRAME } },
347 { ZERO_ZEROMV, { LAST_FRAME, BWDREF_FRAME } },
348
Yaowu Xuc27fc142016-08-22 16:08:15 -0700349 { NEAR_NEARMV, { LAST2_FRAME, BWDREF_FRAME } },
350 { NEW_NEARESTMV, { LAST2_FRAME, BWDREF_FRAME } },
351 { NEAREST_NEWMV, { LAST2_FRAME, BWDREF_FRAME } },
352 { NEW_NEARMV, { LAST2_FRAME, BWDREF_FRAME } },
353 { NEAR_NEWMV, { LAST2_FRAME, BWDREF_FRAME } },
354 { NEW_NEWMV, { LAST2_FRAME, BWDREF_FRAME } },
355 { ZERO_ZEROMV, { LAST2_FRAME, BWDREF_FRAME } },
356
Yaowu Xuc27fc142016-08-22 16:08:15 -0700357 { NEAR_NEARMV, { LAST3_FRAME, BWDREF_FRAME } },
358 { NEW_NEARESTMV, { LAST3_FRAME, BWDREF_FRAME } },
359 { NEAREST_NEWMV, { LAST3_FRAME, BWDREF_FRAME } },
360 { NEW_NEARMV, { LAST3_FRAME, BWDREF_FRAME } },
361 { NEAR_NEWMV, { LAST3_FRAME, BWDREF_FRAME } },
362 { NEW_NEWMV, { LAST3_FRAME, BWDREF_FRAME } },
363 { ZERO_ZEROMV, { LAST3_FRAME, BWDREF_FRAME } },
364
Yaowu Xuc27fc142016-08-22 16:08:15 -0700365 { NEAR_NEARMV, { GOLDEN_FRAME, BWDREF_FRAME } },
366 { NEW_NEARESTMV, { GOLDEN_FRAME, BWDREF_FRAME } },
367 { NEAREST_NEWMV, { GOLDEN_FRAME, BWDREF_FRAME } },
368 { NEW_NEARMV, { GOLDEN_FRAME, BWDREF_FRAME } },
369 { NEAR_NEWMV, { GOLDEN_FRAME, BWDREF_FRAME } },
370 { NEW_NEWMV, { GOLDEN_FRAME, BWDREF_FRAME } },
371 { ZERO_ZEROMV, { GOLDEN_FRAME, BWDREF_FRAME } },
Zoe Liuc082bbc2017-05-17 13:31:37 -0700372
Zoe Liue9b15e22017-07-19 15:53:01 -0700373 { NEAR_NEARMV, { LAST_FRAME, ALTREF2_FRAME } },
374 { NEW_NEARESTMV, { LAST_FRAME, ALTREF2_FRAME } },
375 { NEAREST_NEWMV, { LAST_FRAME, ALTREF2_FRAME } },
376 { NEW_NEARMV, { LAST_FRAME, ALTREF2_FRAME } },
377 { NEAR_NEWMV, { LAST_FRAME, ALTREF2_FRAME } },
378 { NEW_NEWMV, { LAST_FRAME, ALTREF2_FRAME } },
379 { ZERO_ZEROMV, { LAST_FRAME, ALTREF2_FRAME } },
380
381 { NEAR_NEARMV, { LAST2_FRAME, ALTREF2_FRAME } },
382 { NEW_NEARESTMV, { LAST2_FRAME, ALTREF2_FRAME } },
383 { NEAREST_NEWMV, { LAST2_FRAME, ALTREF2_FRAME } },
384 { NEW_NEARMV, { LAST2_FRAME, ALTREF2_FRAME } },
385 { NEAR_NEWMV, { LAST2_FRAME, ALTREF2_FRAME } },
386 { NEW_NEWMV, { LAST2_FRAME, ALTREF2_FRAME } },
387 { ZERO_ZEROMV, { LAST2_FRAME, ALTREF2_FRAME } },
388
389 { NEAR_NEARMV, { LAST3_FRAME, ALTREF2_FRAME } },
390 { NEW_NEARESTMV, { LAST3_FRAME, ALTREF2_FRAME } },
391 { NEAREST_NEWMV, { LAST3_FRAME, ALTREF2_FRAME } },
392 { NEW_NEARMV, { LAST3_FRAME, ALTREF2_FRAME } },
393 { NEAR_NEWMV, { LAST3_FRAME, ALTREF2_FRAME } },
394 { NEW_NEWMV, { LAST3_FRAME, ALTREF2_FRAME } },
395 { ZERO_ZEROMV, { LAST3_FRAME, ALTREF2_FRAME } },
396
397 { NEAR_NEARMV, { GOLDEN_FRAME, ALTREF2_FRAME } },
398 { NEW_NEARESTMV, { GOLDEN_FRAME, ALTREF2_FRAME } },
399 { NEAREST_NEWMV, { GOLDEN_FRAME, ALTREF2_FRAME } },
400 { NEW_NEARMV, { GOLDEN_FRAME, ALTREF2_FRAME } },
401 { NEAR_NEWMV, { GOLDEN_FRAME, ALTREF2_FRAME } },
402 { NEW_NEWMV, { GOLDEN_FRAME, ALTREF2_FRAME } },
403 { ZERO_ZEROMV, { GOLDEN_FRAME, ALTREF2_FRAME } },
Zoe Liue9b15e22017-07-19 15:53:01 -0700404
Zoe Liuc082bbc2017-05-17 13:31:37 -0700405#if CONFIG_EXT_COMP_REFS
406 { NEAR_NEARMV, { LAST_FRAME, LAST2_FRAME } },
407 { NEW_NEARESTMV, { LAST_FRAME, LAST2_FRAME } },
408 { NEAREST_NEWMV, { LAST_FRAME, LAST2_FRAME } },
409 { NEW_NEARMV, { LAST_FRAME, LAST2_FRAME } },
410 { NEAR_NEWMV, { LAST_FRAME, LAST2_FRAME } },
411 { NEW_NEWMV, { LAST_FRAME, LAST2_FRAME } },
412 { ZERO_ZEROMV, { LAST_FRAME, LAST2_FRAME } },
413
Zoe Liufcf5fa22017-06-26 16:00:38 -0700414 { NEAR_NEARMV, { LAST_FRAME, LAST3_FRAME } },
415 { NEW_NEARESTMV, { LAST_FRAME, LAST3_FRAME } },
416 { NEAREST_NEWMV, { LAST_FRAME, LAST3_FRAME } },
417 { NEW_NEARMV, { LAST_FRAME, LAST3_FRAME } },
418 { NEAR_NEWMV, { LAST_FRAME, LAST3_FRAME } },
419 { NEW_NEWMV, { LAST_FRAME, LAST3_FRAME } },
420 { ZERO_ZEROMV, { LAST_FRAME, LAST3_FRAME } },
421
Zoe Liuc082bbc2017-05-17 13:31:37 -0700422 { NEAR_NEARMV, { LAST_FRAME, GOLDEN_FRAME } },
423 { NEW_NEARESTMV, { LAST_FRAME, GOLDEN_FRAME } },
424 { NEAREST_NEWMV, { LAST_FRAME, GOLDEN_FRAME } },
425 { NEW_NEARMV, { LAST_FRAME, GOLDEN_FRAME } },
426 { NEAR_NEWMV, { LAST_FRAME, GOLDEN_FRAME } },
427 { NEW_NEWMV, { LAST_FRAME, GOLDEN_FRAME } },
428 { ZERO_ZEROMV, { LAST_FRAME, GOLDEN_FRAME } },
429
430 { NEAR_NEARMV, { BWDREF_FRAME, ALTREF_FRAME } },
431 { NEW_NEARESTMV, { BWDREF_FRAME, ALTREF_FRAME } },
432 { NEAREST_NEWMV, { BWDREF_FRAME, ALTREF_FRAME } },
433 { NEW_NEARMV, { BWDREF_FRAME, ALTREF_FRAME } },
434 { NEAR_NEWMV, { BWDREF_FRAME, ALTREF_FRAME } },
435 { NEW_NEWMV, { BWDREF_FRAME, ALTREF_FRAME } },
436 { ZERO_ZEROMV, { BWDREF_FRAME, ALTREF_FRAME } },
437#endif // CONFIG_EXT_COMP_REFS
Yaowu Xuc27fc142016-08-22 16:08:15 -0700438#endif // CONFIG_EXT_REFS
439
Emil Keyder01770b32017-01-20 18:03:11 -0500440 { H_PRED, { INTRA_FRAME, NONE_FRAME } },
441 { V_PRED, { INTRA_FRAME, NONE_FRAME } },
442 { D135_PRED, { INTRA_FRAME, NONE_FRAME } },
443 { D207_PRED, { INTRA_FRAME, NONE_FRAME } },
444 { D153_PRED, { INTRA_FRAME, NONE_FRAME } },
445 { D63_PRED, { INTRA_FRAME, NONE_FRAME } },
446 { D117_PRED, { INTRA_FRAME, NONE_FRAME } },
447 { D45_PRED, { INTRA_FRAME, NONE_FRAME } },
Yaowu Xuc27fc142016-08-22 16:08:15 -0700448
Yaowu Xuc27fc142016-08-22 16:08:15 -0700449 { ZEROMV, { LAST_FRAME, INTRA_FRAME } },
450 { NEARESTMV, { LAST_FRAME, INTRA_FRAME } },
451 { NEARMV, { LAST_FRAME, INTRA_FRAME } },
452 { NEWMV, { LAST_FRAME, INTRA_FRAME } },
453
454#if CONFIG_EXT_REFS
455 { ZEROMV, { LAST2_FRAME, INTRA_FRAME } },
456 { NEARESTMV, { LAST2_FRAME, INTRA_FRAME } },
457 { NEARMV, { LAST2_FRAME, INTRA_FRAME } },
458 { NEWMV, { LAST2_FRAME, INTRA_FRAME } },
459
460 { ZEROMV, { LAST3_FRAME, INTRA_FRAME } },
461 { NEARESTMV, { LAST3_FRAME, INTRA_FRAME } },
462 { NEARMV, { LAST3_FRAME, INTRA_FRAME } },
463 { NEWMV, { LAST3_FRAME, INTRA_FRAME } },
464#endif // CONFIG_EXT_REFS
465
466 { ZEROMV, { GOLDEN_FRAME, INTRA_FRAME } },
467 { NEARESTMV, { GOLDEN_FRAME, INTRA_FRAME } },
468 { NEARMV, { GOLDEN_FRAME, INTRA_FRAME } },
469 { NEWMV, { GOLDEN_FRAME, INTRA_FRAME } },
470
471#if CONFIG_EXT_REFS
472 { ZEROMV, { BWDREF_FRAME, INTRA_FRAME } },
473 { NEARESTMV, { BWDREF_FRAME, INTRA_FRAME } },
474 { NEARMV, { BWDREF_FRAME, INTRA_FRAME } },
475 { NEWMV, { BWDREF_FRAME, INTRA_FRAME } },
Zoe Liue9b15e22017-07-19 15:53:01 -0700476
Zoe Liue9b15e22017-07-19 15:53:01 -0700477 { ZEROMV, { ALTREF2_FRAME, INTRA_FRAME } },
478 { NEARESTMV, { ALTREF2_FRAME, INTRA_FRAME } },
479 { NEARMV, { ALTREF2_FRAME, INTRA_FRAME } },
480 { NEWMV, { ALTREF2_FRAME, INTRA_FRAME } },
Yaowu Xuc27fc142016-08-22 16:08:15 -0700481#endif // CONFIG_EXT_REFS
482
483 { ZEROMV, { ALTREF_FRAME, INTRA_FRAME } },
484 { NEARESTMV, { ALTREF_FRAME, INTRA_FRAME } },
485 { NEARMV, { ALTREF_FRAME, INTRA_FRAME } },
486 { NEWMV, { ALTREF_FRAME, INTRA_FRAME } },
Yaowu Xuc27fc142016-08-22 16:08:15 -0700487};
488
hui su8a516a82017-07-06 10:00:36 -0700489static const PREDICTION_MODE intra_rd_search_mode_order[INTRA_MODES] = {
Urvang Joshi96d1c0a2017-10-10 13:15:32 -0700490 DC_PRED, H_PRED, V_PRED, SMOOTH_PRED, PAETH_PRED,
Urvang Joshi93b543a2017-06-01 17:32:41 -0700491#if CONFIG_SMOOTH_HV
hui su8a516a82017-07-06 10:00:36 -0700492 SMOOTH_V_PRED, SMOOTH_H_PRED,
Urvang Joshi93b543a2017-06-01 17:32:41 -0700493#endif // CONFIG_SMOOTH_HV
Urvang Joshi96d1c0a2017-10-10 13:15:32 -0700494 D135_PRED, D207_PRED, D153_PRED, D63_PRED, D117_PRED, D45_PRED,
hui su8a516a82017-07-06 10:00:36 -0700495};
496
Luc Trudeaud6d9eee2017-07-12 12:36:50 -0400497#if CONFIG_CFL
498static const UV_PREDICTION_MODE uv_rd_search_mode_order[UV_INTRA_MODES] = {
Urvang Joshi93b543a2017-06-01 17:32:41 -0700499 UV_DC_PRED, UV_CFL_PRED, UV_H_PRED,
Urvang Joshi96d1c0a2017-10-10 13:15:32 -0700500 UV_V_PRED, UV_SMOOTH_PRED, UV_PAETH_PRED,
Urvang Joshi93b543a2017-06-01 17:32:41 -0700501#if CONFIG_SMOOTH_HV
Luc Trudeaud6d9eee2017-07-12 12:36:50 -0400502 UV_SMOOTH_V_PRED, UV_SMOOTH_H_PRED,
Urvang Joshi93b543a2017-06-01 17:32:41 -0700503#endif // CONFIG_SMOOTH_HV
504 UV_D135_PRED, UV_D207_PRED, UV_D153_PRED,
505 UV_D63_PRED, UV_D117_PRED, UV_D45_PRED,
Luc Trudeaud6d9eee2017-07-12 12:36:50 -0400506};
507#else
508#define uv_rd_search_mode_order intra_rd_search_mode_order
509#endif // CONFIG_CFL
510
Yaowu Xuc27fc142016-08-22 16:08:15 -0700511static INLINE int write_uniform_cost(int n, int v) {
hui su37499292017-04-26 09:49:53 -0700512 const int l = get_unsigned_bits(n);
513 const int m = (1 << l) - n;
Yaowu Xuc27fc142016-08-22 16:08:15 -0700514 if (l == 0) return 0;
515 if (v < m)
Yaowu Xuf883b422016-08-30 14:01:10 -0700516 return (l - 1) * av1_cost_bit(128, 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700517 else
Yaowu Xuf883b422016-08-30 14:01:10 -0700518 return l * av1_cost_bit(128, 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700519}
520
521// constants for prune 1 and prune 2 decision boundaries
522#define FAST_EXT_TX_CORR_MID 0.0
523#define FAST_EXT_TX_EDST_MID 0.1
524#define FAST_EXT_TX_CORR_MARGIN 0.5
525#define FAST_EXT_TX_EDST_MARGIN 0.3
526
Yushin Cho2f025aa2017-09-28 17:39:21 -0700527static unsigned pixel_dist_visible_only(
528 const AV1_COMP *const cpi, const MACROBLOCK *x, const uint8_t *src,
529 const int src_stride, const uint8_t *dst, const int dst_stride,
530 const BLOCK_SIZE tx_bsize, int txb_rows, int txb_cols, int visible_rows,
531 int visible_cols) {
532 unsigned sse;
533
534 if (txb_rows == visible_rows && txb_cols == visible_cols
535#if CONFIG_RECT_TX_EXT && (CONFIG_EXT_TX || CONFIG_VAR_TX)
536 && tx_bsize < BLOCK_SIZES
537#endif
538 ) {
539 cpi->fn_ptr[tx_bsize].vf(src, src_stride, dst, dst_stride, &sse);
540 return sse;
541 }
542#if CONFIG_HIGHBITDEPTH
543 const MACROBLOCKD *xd = &x->e_mbd;
544
545 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
546 uint64_t sse64 = aom_highbd_sse_odd_size(src, src_stride, dst, dst_stride,
547 visible_cols, visible_rows);
548 return (unsigned int)ROUND_POWER_OF_TWO(sse64, (xd->bd - 8) * 2);
549 }
550#else
551 (void)x;
552#endif // CONFIG_HIGHBITDEPTH
553 sse = aom_sse_odd_size(src, src_stride, dst, dst_stride, visible_cols,
554 visible_rows);
555 return sse;
556}
557
Yushin Choe30a47c2017-08-15 13:08:30 -0700558#if CONFIG_DIST_8X8
Yushin Choc49177e2017-07-18 17:18:09 -0700559static uint64_t cdef_dist_8x8_16bit(uint16_t *dst, int dstride, uint16_t *src,
560 int sstride, int coeff_shift) {
561 uint64_t svar = 0;
562 uint64_t dvar = 0;
563 uint64_t sum_s = 0;
564 uint64_t sum_d = 0;
565 uint64_t sum_s2 = 0;
566 uint64_t sum_d2 = 0;
567 uint64_t sum_sd = 0;
568 uint64_t dist = 0;
569
570 int i, j;
571 for (i = 0; i < 8; i++) {
572 for (j = 0; j < 8; j++) {
573 sum_s += src[i * sstride + j];
574 sum_d += dst[i * dstride + j];
575 sum_s2 += src[i * sstride + j] * src[i * sstride + j];
576 sum_d2 += dst[i * dstride + j] * dst[i * dstride + j];
577 sum_sd += src[i * sstride + j] * dst[i * dstride + j];
578 }
579 }
580 /* Compute the variance -- the calculation cannot go negative. */
581 svar = sum_s2 - ((sum_s * sum_s + 32) >> 6);
582 dvar = sum_d2 - ((sum_d * sum_d + 32) >> 6);
583
584 // Tuning of jm's original dering distortion metric used in CDEF tool,
585 // suggested by jm
586 const uint64_t a = 4;
587 const uint64_t b = 2;
588 const uint64_t c1 = (400 * a << 2 * coeff_shift);
589 const uint64_t c2 = (b * 20000 * a * a << 4 * coeff_shift);
590
591 dist =
592 (uint64_t)floor(.5 +
593 (sum_d2 + sum_s2 - 2 * sum_sd) * .5 * (svar + dvar + c1) /
594 (sqrt(svar * (double)dvar + c2)));
595
596 // Calibrate dist to have similar rate for the same QP with MSE only
597 // distortion (as in master branch)
598 dist = (uint64_t)((float)dist * 0.75);
599
600 return dist;
601}
Yushin Choc49177e2017-07-18 17:18:09 -0700602
Yushin Chob7b60c52017-07-14 16:18:52 -0700603static int od_compute_var_4x4(uint16_t *x, int stride) {
Yushin Cho7a428ba2017-01-12 16:28:49 -0800604 int sum;
605 int s2;
606 int i;
607 sum = 0;
608 s2 = 0;
609 for (i = 0; i < 4; i++) {
610 int j;
611 for (j = 0; j < 4; j++) {
612 int t;
613
614 t = x[i * stride + j];
615 sum += t;
616 s2 += t * t;
617 }
618 }
Yushin Chob7b60c52017-07-14 16:18:52 -0700619
Yushin Cho7a428ba2017-01-12 16:28:49 -0800620 return (s2 - (sum * sum >> 4)) >> 4;
621}
622
Jean-Marc Valin79c0f322017-01-18 01:58:33 -0500623/* OD_DIST_LP_MID controls the frequency weighting filter used for computing
624 the distortion. For a value X, the filter is [1 X 1]/(X + 2) and
625 is applied both horizontally and vertically. For X=5, the filter is
626 a good approximation for the OD_QM8_Q4_HVS quantization matrix. */
627#define OD_DIST_LP_MID (5)
628#define OD_DIST_LP_NORM (OD_DIST_LP_MID + 2)
629
Yushin Chob7b60c52017-07-14 16:18:52 -0700630static double od_compute_dist_8x8(int use_activity_masking, uint16_t *x,
631 uint16_t *y, od_coeff *e_lp, int stride) {
Yushin Cho7a428ba2017-01-12 16:28:49 -0800632 double sum;
633 int min_var;
634 double mean_var;
635 double var_stat;
636 double activity;
637 double calibration;
638 int i;
639 int j;
640 double vardist;
Yushin Cho7a428ba2017-01-12 16:28:49 -0800641
642 vardist = 0;
Yushin Chob7b60c52017-07-14 16:18:52 -0700643
Yushin Cho7a428ba2017-01-12 16:28:49 -0800644#if 1
645 min_var = INT_MAX;
646 mean_var = 0;
647 for (i = 0; i < 3; i++) {
648 for (j = 0; j < 3; j++) {
649 int varx;
650 int vary;
651 varx = od_compute_var_4x4(x + 2 * i * stride + 2 * j, stride);
652 vary = od_compute_var_4x4(y + 2 * i * stride + 2 * j, stride);
653 min_var = OD_MINI(min_var, varx);
654 mean_var += 1. / (1 + varx);
655 /* The cast to (double) is to avoid an overflow before the sqrt.*/
656 vardist += varx - 2 * sqrt(varx * (double)vary) + vary;
657 }
658 }
659 /* We use a different variance statistic depending on whether activity
James Zern89a015b2017-08-08 12:39:00 -0400660 masking is used, since the harmonic mean appeared slightly worse with
Yushin Cho7a428ba2017-01-12 16:28:49 -0800661 masking off. The calibration constant just ensures that we preserve the
662 rate compared to activity=1. */
663 if (use_activity_masking) {
664 calibration = 1.95;
665 var_stat = 9. / mean_var;
666 } else {
667 calibration = 1.62;
668 var_stat = min_var;
669 }
670 /* 1.62 is a calibration constant, 0.25 is a noise floor and 1/6 is the
671 activity masking constant. */
672 activity = calibration * pow(.25 + var_stat, -1. / 6);
673#else
674 activity = 1;
Fergus Simpson4063a682017-02-28 16:52:22 -0800675#endif // 1
Yushin Cho7a428ba2017-01-12 16:28:49 -0800676 sum = 0;
677 for (i = 0; i < 8; i++) {
678 for (j = 0; j < 8; j++)
Jean-Marc Valin79c0f322017-01-18 01:58:33 -0500679 sum += e_lp[i * stride + j] * (double)e_lp[i * stride + j];
Yushin Cho7a428ba2017-01-12 16:28:49 -0800680 }
Jean-Marc Valin79c0f322017-01-18 01:58:33 -0500681 /* Normalize the filter to unit DC response. */
682 sum *= 1. / (OD_DIST_LP_NORM * OD_DIST_LP_NORM * OD_DIST_LP_NORM *
683 OD_DIST_LP_NORM);
Yushin Cho7a428ba2017-01-12 16:28:49 -0800684 return activity * activity * (sum + vardist);
685}
686
687// Note : Inputs x and y are in a pixel domain
Yushin Chob7b60c52017-07-14 16:18:52 -0700688static double od_compute_dist_common(int activity_masking, uint16_t *x,
689 uint16_t *y, int bsize_w, int bsize_h,
Yushin Cho75b01002017-06-21 13:43:57 -0700690 int qindex, od_coeff *tmp,
691 od_coeff *e_lp) {
692 int i, j;
693 double sum = 0;
694 const int mid = OD_DIST_LP_MID;
695
696 for (j = 0; j < bsize_w; j++) {
697 e_lp[j] = mid * tmp[j] + 2 * tmp[bsize_w + j];
698 e_lp[(bsize_h - 1) * bsize_w + j] = mid * tmp[(bsize_h - 1) * bsize_w + j] +
699 2 * tmp[(bsize_h - 2) * bsize_w + j];
700 }
701 for (i = 1; i < bsize_h - 1; i++) {
702 for (j = 0; j < bsize_w; j++) {
703 e_lp[i * bsize_w + j] = mid * tmp[i * bsize_w + j] +
704 tmp[(i - 1) * bsize_w + j] +
705 tmp[(i + 1) * bsize_w + j];
706 }
707 }
708 for (i = 0; i < bsize_h; i += 8) {
709 for (j = 0; j < bsize_w; j += 8) {
Yushin Chob7b60c52017-07-14 16:18:52 -0700710 sum += od_compute_dist_8x8(activity_masking, &x[i * bsize_w + j],
Yushin Cho75b01002017-06-21 13:43:57 -0700711 &y[i * bsize_w + j], &e_lp[i * bsize_w + j],
712 bsize_w);
713 }
714 }
715 /* Scale according to linear regression against SSE, for 8x8 blocks. */
716 if (activity_masking) {
717 sum *= 2.2 + (1.7 - 2.2) * (qindex - 99) / (210 - 99) +
718 (qindex < 99 ? 2.5 * (qindex - 99) / 99 * (qindex - 99) / 99 : 0);
719 } else {
720 sum *= qindex >= 128
721 ? 1.4 + (0.9 - 1.4) * (qindex - 128) / (209 - 128)
722 : qindex <= 43 ? 1.5 + (2.0 - 1.5) * (qindex - 43) / (16 - 43)
723 : 1.5 + (1.4 - 1.5) * (qindex - 43) / (128 - 43);
724 }
725
726 return sum;
727}
728
Yushin Chob7b60c52017-07-14 16:18:52 -0700729static double od_compute_dist(uint16_t *x, uint16_t *y, int bsize_w,
730 int bsize_h, int qindex) {
Yushin Cho7a428ba2017-01-12 16:28:49 -0800731 assert(bsize_w >= 8 && bsize_h >= 8);
Yushin Chob7b60c52017-07-14 16:18:52 -0700732#if CONFIG_PVQ
733 int activity_masking = 1;
734#else
735 int activity_masking = 0;
736#endif
Luc Trudeau1f7c4112017-09-13 15:10:08 -0400737 int i, j;
738 DECLARE_ALIGNED(16, od_coeff, e[MAX_TX_SQUARE]);
739 DECLARE_ALIGNED(16, od_coeff, tmp[MAX_TX_SQUARE]);
740 DECLARE_ALIGNED(16, od_coeff, e_lp[MAX_TX_SQUARE]);
741 for (i = 0; i < bsize_h; i++) {
742 for (j = 0; j < bsize_w; j++) {
743 e[i * bsize_w + j] = x[i * bsize_w + j] - y[i * bsize_w + j];
Jean-Marc Valin79c0f322017-01-18 01:58:33 -0500744 }
Yushin Cho75b01002017-06-21 13:43:57 -0700745 }
Luc Trudeau1f7c4112017-09-13 15:10:08 -0400746 int mid = OD_DIST_LP_MID;
747 for (i = 0; i < bsize_h; i++) {
748 tmp[i * bsize_w] = mid * e[i * bsize_w] + 2 * e[i * bsize_w + 1];
749 tmp[i * bsize_w + bsize_w - 1] =
750 mid * e[i * bsize_w + bsize_w - 1] + 2 * e[i * bsize_w + bsize_w - 2];
751 for (j = 1; j < bsize_w - 1; j++) {
752 tmp[i * bsize_w + j] = mid * e[i * bsize_w + j] + e[i * bsize_w + j - 1] +
753 e[i * bsize_w + j + 1];
754 }
755 }
756 return od_compute_dist_common(activity_masking, x, y, bsize_w, bsize_h,
757 qindex, tmp, e_lp);
Yushin Cho75b01002017-06-21 13:43:57 -0700758}
759
Yushin Chob7b60c52017-07-14 16:18:52 -0700760static double od_compute_dist_diff(uint16_t *x, int16_t *e, int bsize_w,
761 int bsize_h, int qindex) {
Yushin Cho75b01002017-06-21 13:43:57 -0700762 assert(bsize_w >= 8 && bsize_h >= 8);
Yushin Chob7b60c52017-07-14 16:18:52 -0700763#if CONFIG_PVQ
764 int activity_masking = 1;
765#else
766 int activity_masking = 0;
767#endif
Luc Trudeau1f7c4112017-09-13 15:10:08 -0400768 DECLARE_ALIGNED(16, uint16_t, y[MAX_TX_SQUARE]);
769 DECLARE_ALIGNED(16, od_coeff, tmp[MAX_TX_SQUARE]);
770 DECLARE_ALIGNED(16, od_coeff, e_lp[MAX_TX_SQUARE]);
771 int i, j;
772 for (i = 0; i < bsize_h; i++) {
773 for (j = 0; j < bsize_w; j++) {
774 y[i * bsize_w + j] = x[i * bsize_w + j] - e[i * bsize_w + j];
Jean-Marc Valin79c0f322017-01-18 01:58:33 -0500775 }
Yushin Cho7a428ba2017-01-12 16:28:49 -0800776 }
Luc Trudeau1f7c4112017-09-13 15:10:08 -0400777 int mid = OD_DIST_LP_MID;
778 for (i = 0; i < bsize_h; i++) {
779 tmp[i * bsize_w] = mid * e[i * bsize_w] + 2 * e[i * bsize_w + 1];
780 tmp[i * bsize_w + bsize_w - 1] =
781 mid * e[i * bsize_w + bsize_w - 1] + 2 * e[i * bsize_w + bsize_w - 2];
782 for (j = 1; j < bsize_w - 1; j++) {
783 tmp[i * bsize_w + j] = mid * e[i * bsize_w + j] + e[i * bsize_w + j - 1] +
784 e[i * bsize_w + j + 1];
785 }
786 }
787 return od_compute_dist_common(activity_masking, x, y, bsize_w, bsize_h,
788 qindex, tmp, e_lp);
Yushin Cho7a428ba2017-01-12 16:28:49 -0800789}
790
Yushin Choe30a47c2017-08-15 13:08:30 -0700791int64_t av1_dist_8x8(const AV1_COMP *const cpi, const MACROBLOCK *x,
Yushin Chob7b60c52017-07-14 16:18:52 -0700792 const uint8_t *src, int src_stride, const uint8_t *dst,
793 int dst_stride, const BLOCK_SIZE tx_bsize, int bsw,
794 int bsh, int visible_w, int visible_h, int qindex) {
795 int64_t d = 0;
Yushin Cho7a428ba2017-01-12 16:28:49 -0800796 int i, j;
Yushin Choe30a47c2017-08-15 13:08:30 -0700797 const MACROBLOCKD *xd = &x->e_mbd;
Yushin Chob7b60c52017-07-14 16:18:52 -0700798
799 DECLARE_ALIGNED(16, uint16_t, orig[MAX_TX_SQUARE]);
800 DECLARE_ALIGNED(16, uint16_t, rec[MAX_TX_SQUARE]);
Yushin Chob7b60c52017-07-14 16:18:52 -0700801
Yushin Choee810272017-09-13 17:30:25 -0700802 assert(bsw >= 8);
803 assert(bsh >= 8);
804 assert((bsw & 0x07) == 0);
805 assert((bsh & 0x07) == 0);
806
Yushin Choe30a47c2017-08-15 13:08:30 -0700807 if (x->tune_metric == AOM_TUNE_CDEF_DIST ||
808 x->tune_metric == AOM_TUNE_DAALA_DIST) {
Yushin Cho8ab875d2017-06-23 14:47:21 -0700809#if CONFIG_HIGHBITDEPTH
Yushin Choe30a47c2017-08-15 13:08:30 -0700810 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
Yushin Cho75b01002017-06-21 13:43:57 -0700811 for (j = 0; j < bsh; j++)
Yushin Cho8ab875d2017-06-23 14:47:21 -0700812 for (i = 0; i < bsw; i++)
Yushin Choe30a47c2017-08-15 13:08:30 -0700813 orig[j * bsw + i] = CONVERT_TO_SHORTPTR(src)[j * src_stride + i];
Yushin Cho75b01002017-06-21 13:43:57 -0700814
Yushin Choe30a47c2017-08-15 13:08:30 -0700815 if ((bsw == visible_w) && (bsh == visible_h)) {
Yushin Cho8ab875d2017-06-23 14:47:21 -0700816 for (j = 0; j < bsh; j++)
Yushin Cho8ab875d2017-06-23 14:47:21 -0700817 for (i = 0; i < bsw; i++)
Yushin Choe30a47c2017-08-15 13:08:30 -0700818 rec[j * bsw + i] = CONVERT_TO_SHORTPTR(dst)[j * dst_stride + i];
819 } else {
820 for (j = 0; j < visible_h; j++)
821 for (i = 0; i < visible_w; i++)
822 rec[j * bsw + i] = CONVERT_TO_SHORTPTR(dst)[j * dst_stride + i];
Yushin Cho8ab875d2017-06-23 14:47:21 -0700823
Yushin Choe30a47c2017-08-15 13:08:30 -0700824 if (visible_w < bsw) {
825 for (j = 0; j < bsh; j++)
826 for (i = visible_w; i < bsw; i++)
827 rec[j * bsw + i] = CONVERT_TO_SHORTPTR(src)[j * src_stride + i];
828 }
829
830 if (visible_h < bsh) {
831 for (j = visible_h; j < bsh; j++)
832 for (i = 0; i < bsw; i++)
833 rec[j * bsw + i] = CONVERT_TO_SHORTPTR(src)[j * src_stride + i];
834 }
835 }
Yushin Cho8ab875d2017-06-23 14:47:21 -0700836 } else {
Yushin Choe30a47c2017-08-15 13:08:30 -0700837#endif
838 for (j = 0; j < bsh; j++)
839 for (i = 0; i < bsw; i++) orig[j * bsw + i] = src[j * src_stride + i];
Yushin Cho8ab875d2017-06-23 14:47:21 -0700840
Yushin Choe30a47c2017-08-15 13:08:30 -0700841 if ((bsw == visible_w) && (bsh == visible_h)) {
Yushin Cho8ab875d2017-06-23 14:47:21 -0700842 for (j = 0; j < bsh; j++)
Yushin Choe30a47c2017-08-15 13:08:30 -0700843 for (i = 0; i < bsw; i++) rec[j * bsw + i] = dst[j * dst_stride + i];
844 } else {
845 for (j = 0; j < visible_h; j++)
846 for (i = 0; i < visible_w; i++)
847 rec[j * bsw + i] = dst[j * dst_stride + i];
Yushin Cho8ab875d2017-06-23 14:47:21 -0700848
Yushin Choe30a47c2017-08-15 13:08:30 -0700849 if (visible_w < bsw) {
850 for (j = 0; j < bsh; j++)
851 for (i = visible_w; i < bsw; i++)
852 rec[j * bsw + i] = src[j * src_stride + i];
853 }
854
855 if (visible_h < bsh) {
856 for (j = visible_h; j < bsh; j++)
857 for (i = 0; i < bsw; i++)
858 rec[j * bsw + i] = src[j * src_stride + i];
859 }
Yushin Cho8ab875d2017-06-23 14:47:21 -0700860 }
Yushin Cho8ab875d2017-06-23 14:47:21 -0700861#if CONFIG_HIGHBITDEPTH
Yushin Choe30a47c2017-08-15 13:08:30 -0700862 }
Yushin Cho8ab875d2017-06-23 14:47:21 -0700863#endif // CONFIG_HIGHBITDEPTH
Yushin Choe30a47c2017-08-15 13:08:30 -0700864 }
Yushin Cho8ab875d2017-06-23 14:47:21 -0700865
Yushin Choe30a47c2017-08-15 13:08:30 -0700866 if (x->tune_metric == AOM_TUNE_DAALA_DIST) {
867 d = (int64_t)od_compute_dist(orig, rec, bsw, bsh, qindex);
868 } else if (x->tune_metric == AOM_TUNE_CDEF_DIST) {
Yushin Choc49177e2017-07-18 17:18:09 -0700869 int coeff_shift = AOMMAX(xd->bd - 8, 0);
870
871 for (i = 0; i < bsh; i += 8) {
872 for (j = 0; j < bsw; j += 8) {
873 d += cdef_dist_8x8_16bit(&rec[i * bsw + j], bsw, &orig[i * bsw + j],
874 bsw, coeff_shift);
875 }
876 }
877#if CONFIG_HIGHBITDEPTH
878 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
879 d = ((uint64_t)d) >> 2 * coeff_shift;
880#endif
Yushin Choe30a47c2017-08-15 13:08:30 -0700881 } else {
882 // Otherwise, MSE by default
Yushin Cho2f025aa2017-09-28 17:39:21 -0700883 d = pixel_dist_visible_only(cpi, x, src, src_stride, dst, dst_stride,
884 tx_bsize, bsh, bsw, visible_h, visible_w);
Yushin Choc49177e2017-07-18 17:18:09 -0700885 }
Yushin Chob7b60c52017-07-14 16:18:52 -0700886
Yushin Cho7a428ba2017-01-12 16:28:49 -0800887 return d;
888}
Yushin Cho75b01002017-06-21 13:43:57 -0700889
Yushin Choe30a47c2017-08-15 13:08:30 -0700890static int64_t av1_dist_8x8_diff(const MACROBLOCK *x, const uint8_t *src,
Yushin Chob7b60c52017-07-14 16:18:52 -0700891 int src_stride, const int16_t *diff,
892 int diff_stride, int bsw, int bsh,
893 int visible_w, int visible_h, int qindex) {
894 int64_t d = 0;
Yushin Cho75b01002017-06-21 13:43:57 -0700895 int i, j;
Yushin Choe30a47c2017-08-15 13:08:30 -0700896 const MACROBLOCKD *xd = &x->e_mbd;
Yushin Chob7b60c52017-07-14 16:18:52 -0700897
898 DECLARE_ALIGNED(16, uint16_t, orig[MAX_TX_SQUARE]);
899 DECLARE_ALIGNED(16, int16_t, diff16[MAX_TX_SQUARE]);
Yushin Chob7b60c52017-07-14 16:18:52 -0700900
Yushin Choee810272017-09-13 17:30:25 -0700901 assert(bsw >= 8);
902 assert(bsh >= 8);
903 assert((bsw & 0x07) == 0);
904 assert((bsh & 0x07) == 0);
905
Yushin Choe30a47c2017-08-15 13:08:30 -0700906 if (x->tune_metric == AOM_TUNE_CDEF_DIST ||
907 x->tune_metric == AOM_TUNE_DAALA_DIST) {
Yushin Cho8ab875d2017-06-23 14:47:21 -0700908#if CONFIG_HIGHBITDEPTH
Yushin Choe30a47c2017-08-15 13:08:30 -0700909 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
910 for (j = 0; j < bsh; j++)
911 for (i = 0; i < bsw; i++)
912 orig[j * bsw + i] = CONVERT_TO_SHORTPTR(src)[j * src_stride + i];
913 } else {
Yushin Cho8ab875d2017-06-23 14:47:21 -0700914#endif
Yushin Choe30a47c2017-08-15 13:08:30 -0700915 for (j = 0; j < bsh; j++)
916 for (i = 0; i < bsw; i++) orig[j * bsw + i] = src[j * src_stride + i];
Yushin Cho8ab875d2017-06-23 14:47:21 -0700917#if CONFIG_HIGHBITDEPTH
Yushin Choe30a47c2017-08-15 13:08:30 -0700918 }
Yushin Cho8ab875d2017-06-23 14:47:21 -0700919#endif // CONFIG_HIGHBITDEPTH
Yushin Cho75b01002017-06-21 13:43:57 -0700920
Yushin Choe30a47c2017-08-15 13:08:30 -0700921 if ((bsw == visible_w) && (bsh == visible_h)) {
Yushin Cho75b01002017-06-21 13:43:57 -0700922 for (j = 0; j < bsh; j++)
Yushin Choe30a47c2017-08-15 13:08:30 -0700923 for (i = 0; i < bsw; i++)
924 diff16[j * bsw + i] = diff[j * diff_stride + i];
925 } else {
926 for (j = 0; j < visible_h; j++)
927 for (i = 0; i < visible_w; i++)
928 diff16[j * bsw + i] = diff[j * diff_stride + i];
Yushin Cho75b01002017-06-21 13:43:57 -0700929
Yushin Choe30a47c2017-08-15 13:08:30 -0700930 if (visible_w < bsw) {
931 for (j = 0; j < bsh; j++)
932 for (i = visible_w; i < bsw; i++) diff16[j * bsw + i] = 0;
933 }
934
935 if (visible_h < bsh) {
936 for (j = visible_h; j < bsh; j++)
937 for (i = 0; i < bsw; i++) diff16[j * bsw + i] = 0;
938 }
Yushin Cho75b01002017-06-21 13:43:57 -0700939 }
940 }
Yushin Cho8ab875d2017-06-23 14:47:21 -0700941
Yushin Choe30a47c2017-08-15 13:08:30 -0700942 if (x->tune_metric == AOM_TUNE_DAALA_DIST) {
943 d = (int64_t)od_compute_dist_diff(orig, diff16, bsw, bsh, qindex);
944 } else if (x->tune_metric == AOM_TUNE_CDEF_DIST) {
Yushin Choc49177e2017-07-18 17:18:09 -0700945 int coeff_shift = AOMMAX(xd->bd - 8, 0);
946 DECLARE_ALIGNED(16, uint16_t, dst16[MAX_TX_SQUARE]);
947
948 for (i = 0; i < bsh; i++) {
949 for (j = 0; j < bsw; j++) {
950 dst16[i * bsw + j] = orig[i * bsw + j] - diff16[i * bsw + j];
951 }
952 }
953
954 for (i = 0; i < bsh; i += 8) {
955 for (j = 0; j < bsw; j += 8) {
956 d += cdef_dist_8x8_16bit(&dst16[i * bsw + j], bsw, &orig[i * bsw + j],
957 bsw, coeff_shift);
958 }
959 }
960 // Don't scale 'd' for HBD since it will be done by caller side for diff
961 // input
Yushin Choe30a47c2017-08-15 13:08:30 -0700962 } else {
963 // Otherwise, MSE by default
Yushin Cho2f025aa2017-09-28 17:39:21 -0700964 d = aom_sum_squares_2d_i16(diff, diff_stride, visible_w, visible_h);
Yushin Choc49177e2017-07-18 17:18:09 -0700965 }
Yushin Cho75b01002017-06-21 13:43:57 -0700966
967 return d;
968}
Yushin Chob7b60c52017-07-14 16:18:52 -0700969#endif // CONFIG_DIST_8X8
Yushin Cho7a428ba2017-01-12 16:28:49 -0800970
Yaowu Xuf883b422016-08-30 14:01:10 -0700971static void get_energy_distribution_fine(const AV1_COMP *cpi, BLOCK_SIZE bsize,
Alex Converse9f217762017-04-20 15:34:54 -0700972 const uint8_t *src, int src_stride,
973 const uint8_t *dst, int dst_stride,
Yaowu Xuc27fc142016-08-22 16:08:15 -0700974 double *hordist, double *verdist) {
Alex Converse9f217762017-04-20 15:34:54 -0700975 const int bw = block_size_wide[bsize];
976 const int bh = block_size_high[bsize];
Yaowu Xuc27fc142016-08-22 16:08:15 -0700977 unsigned int esq[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
Yaowu Xuc27fc142016-08-22 16:08:15 -0700978
979 const int f_index = bsize - BLOCK_16X16;
980 if (f_index < 0) {
Alex Converse9f217762017-04-20 15:34:54 -0700981 const int w_shift = bw == 8 ? 1 : 2;
982 const int h_shift = bh == 8 ? 1 : 2;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200983#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700984 if (cpi->common.use_highbitdepth) {
Alex Converse9f217762017-04-20 15:34:54 -0700985 const uint16_t *src16 = CONVERT_TO_SHORTPTR(src);
986 const uint16_t *dst16 = CONVERT_TO_SHORTPTR(dst);
987 for (int i = 0; i < bh; ++i)
988 for (int j = 0; j < bw; ++j) {
989 const int index = (j >> w_shift) + ((i >> h_shift) << 2);
Yaowu Xuc27fc142016-08-22 16:08:15 -0700990 esq[index] +=
991 (src16[j + i * src_stride] - dst16[j + i * dst_stride]) *
992 (src16[j + i * src_stride] - dst16[j + i * dst_stride]);
993 }
994 } else {
Sebastien Alaiwan71e87842017-04-12 16:03:28 +0200995#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -0700996
Alex Converse9f217762017-04-20 15:34:54 -0700997 for (int i = 0; i < bh; ++i)
998 for (int j = 0; j < bw; ++j) {
999 const int index = (j >> w_shift) + ((i >> h_shift) << 2);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001000 esq[index] += (src[j + i * src_stride] - dst[j + i * dst_stride]) *
1001 (src[j + i * src_stride] - dst[j + i * dst_stride]);
1002 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02001003#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07001004 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02001005#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07001006 } else {
Alex Converse9f217762017-04-20 15:34:54 -07001007 cpi->fn_ptr[f_index].vf(src, src_stride, dst, dst_stride, &esq[0]);
1008 cpi->fn_ptr[f_index].vf(src + bw / 4, src_stride, dst + bw / 4, dst_stride,
1009 &esq[1]);
1010 cpi->fn_ptr[f_index].vf(src + bw / 2, src_stride, dst + bw / 2, dst_stride,
1011 &esq[2]);
1012 cpi->fn_ptr[f_index].vf(src + 3 * bw / 4, src_stride, dst + 3 * bw / 4,
1013 dst_stride, &esq[3]);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001014 src += bh / 4 * src_stride;
1015 dst += bh / 4 * dst_stride;
1016
Alex Converse9f217762017-04-20 15:34:54 -07001017 cpi->fn_ptr[f_index].vf(src, src_stride, dst, dst_stride, &esq[4]);
1018 cpi->fn_ptr[f_index].vf(src + bw / 4, src_stride, dst + bw / 4, dst_stride,
1019 &esq[5]);
1020 cpi->fn_ptr[f_index].vf(src + bw / 2, src_stride, dst + bw / 2, dst_stride,
1021 &esq[6]);
1022 cpi->fn_ptr[f_index].vf(src + 3 * bw / 4, src_stride, dst + 3 * bw / 4,
1023 dst_stride, &esq[7]);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001024 src += bh / 4 * src_stride;
1025 dst += bh / 4 * dst_stride;
1026
Alex Converse9f217762017-04-20 15:34:54 -07001027 cpi->fn_ptr[f_index].vf(src, src_stride, dst, dst_stride, &esq[8]);
1028 cpi->fn_ptr[f_index].vf(src + bw / 4, src_stride, dst + bw / 4, dst_stride,
1029 &esq[9]);
1030 cpi->fn_ptr[f_index].vf(src + bw / 2, src_stride, dst + bw / 2, dst_stride,
1031 &esq[10]);
1032 cpi->fn_ptr[f_index].vf(src + 3 * bw / 4, src_stride, dst + 3 * bw / 4,
1033 dst_stride, &esq[11]);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001034 src += bh / 4 * src_stride;
1035 dst += bh / 4 * dst_stride;
1036
Alex Converse9f217762017-04-20 15:34:54 -07001037 cpi->fn_ptr[f_index].vf(src, src_stride, dst, dst_stride, &esq[12]);
1038 cpi->fn_ptr[f_index].vf(src + bw / 4, src_stride, dst + bw / 4, dst_stride,
1039 &esq[13]);
1040 cpi->fn_ptr[f_index].vf(src + bw / 2, src_stride, dst + bw / 2, dst_stride,
1041 &esq[14]);
1042 cpi->fn_ptr[f_index].vf(src + 3 * bw / 4, src_stride, dst + 3 * bw / 4,
1043 dst_stride, &esq[15]);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001044 }
1045
Alex Converse9f217762017-04-20 15:34:54 -07001046 double total = (double)esq[0] + esq[1] + esq[2] + esq[3] + esq[4] + esq[5] +
1047 esq[6] + esq[7] + esq[8] + esq[9] + esq[10] + esq[11] +
1048 esq[12] + esq[13] + esq[14] + esq[15];
Yaowu Xuc27fc142016-08-22 16:08:15 -07001049 if (total > 0) {
1050 const double e_recip = 1.0 / total;
Alex Converse9f217762017-04-20 15:34:54 -07001051 hordist[0] = ((double)esq[0] + esq[4] + esq[8] + esq[12]) * e_recip;
1052 hordist[1] = ((double)esq[1] + esq[5] + esq[9] + esq[13]) * e_recip;
1053 hordist[2] = ((double)esq[2] + esq[6] + esq[10] + esq[14]) * e_recip;
1054 verdist[0] = ((double)esq[0] + esq[1] + esq[2] + esq[3]) * e_recip;
1055 verdist[1] = ((double)esq[4] + esq[5] + esq[6] + esq[7]) * e_recip;
1056 verdist[2] = ((double)esq[8] + esq[9] + esq[10] + esq[11]) * e_recip;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001057 } else {
1058 hordist[0] = verdist[0] = 0.25;
1059 hordist[1] = verdist[1] = 0.25;
1060 hordist[2] = verdist[2] = 0.25;
1061 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07001062}
1063
Urvang Joshi0d1e4ff2017-04-27 16:17:25 -07001064static int adst_vs_flipadst(const AV1_COMP *cpi, BLOCK_SIZE bsize,
1065 const uint8_t *src, int src_stride,
1066 const uint8_t *dst, int dst_stride) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07001067 int prune_bitmask = 0;
1068 double svm_proj_h = 0, svm_proj_v = 0;
Alex Converse89912f92017-04-21 13:28:50 -07001069 double hdist[3] = { 0, 0, 0 }, vdist[3] = { 0, 0, 0 };
Yaowu Xuc27fc142016-08-22 16:08:15 -07001070 get_energy_distribution_fine(cpi, bsize, src, src_stride, dst, dst_stride,
1071 hdist, vdist);
1072
1073 svm_proj_v = vdist[0] * ADST_FLIP_SVM[0] + vdist[1] * ADST_FLIP_SVM[1] +
1074 vdist[2] * ADST_FLIP_SVM[2] + ADST_FLIP_SVM[3];
1075 svm_proj_h = hdist[0] * ADST_FLIP_SVM[4] + hdist[1] * ADST_FLIP_SVM[5] +
1076 hdist[2] * ADST_FLIP_SVM[6] + ADST_FLIP_SVM[7];
1077 if (svm_proj_v > FAST_EXT_TX_EDST_MID + FAST_EXT_TX_EDST_MARGIN)
1078 prune_bitmask |= 1 << FLIPADST_1D;
1079 else if (svm_proj_v < FAST_EXT_TX_EDST_MID - FAST_EXT_TX_EDST_MARGIN)
1080 prune_bitmask |= 1 << ADST_1D;
1081
1082 if (svm_proj_h > FAST_EXT_TX_EDST_MID + FAST_EXT_TX_EDST_MARGIN)
1083 prune_bitmask |= 1 << (FLIPADST_1D + 8);
1084 else if (svm_proj_h < FAST_EXT_TX_EDST_MID - FAST_EXT_TX_EDST_MARGIN)
1085 prune_bitmask |= 1 << (ADST_1D + 8);
1086
1087 return prune_bitmask;
1088}
1089
1090#if CONFIG_EXT_TX
Alex Converse89912f92017-04-21 13:28:50 -07001091static void get_horver_correlation(const int16_t *diff, int stride, int w,
1092 int h, double *hcorr, double *vcorr) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07001093 // Returns hor/ver correlation coefficient
1094 const int num = (h - 1) * (w - 1);
1095 double num_r;
1096 int i, j;
1097 int64_t xy_sum = 0, xz_sum = 0;
1098 int64_t x_sum = 0, y_sum = 0, z_sum = 0;
1099 int64_t x2_sum = 0, y2_sum = 0, z2_sum = 0;
1100 double x_var_n, y_var_n, z_var_n, xy_var_n, xz_var_n;
1101 *hcorr = *vcorr = 1;
1102
1103 assert(num > 0);
1104 num_r = 1.0 / num;
1105 for (i = 1; i < h; ++i) {
1106 for (j = 1; j < w; ++j) {
1107 const int16_t x = diff[i * stride + j];
1108 const int16_t y = diff[i * stride + j - 1];
1109 const int16_t z = diff[(i - 1) * stride + j];
1110 xy_sum += x * y;
1111 xz_sum += x * z;
1112 x_sum += x;
1113 y_sum += y;
1114 z_sum += z;
1115 x2_sum += x * x;
1116 y2_sum += y * y;
1117 z2_sum += z * z;
1118 }
1119 }
1120 x_var_n = x2_sum - (x_sum * x_sum) * num_r;
1121 y_var_n = y2_sum - (y_sum * y_sum) * num_r;
1122 z_var_n = z2_sum - (z_sum * z_sum) * num_r;
1123 xy_var_n = xy_sum - (x_sum * y_sum) * num_r;
1124 xz_var_n = xz_sum - (x_sum * z_sum) * num_r;
1125 if (x_var_n > 0 && y_var_n > 0) {
1126 *hcorr = xy_var_n / sqrt(x_var_n * y_var_n);
1127 *hcorr = *hcorr < 0 ? 0 : *hcorr;
1128 }
1129 if (x_var_n > 0 && z_var_n > 0) {
1130 *vcorr = xz_var_n / sqrt(x_var_n * z_var_n);
1131 *vcorr = *vcorr < 0 ? 0 : *vcorr;
1132 }
1133}
1134
Alex Converse89912f92017-04-21 13:28:50 -07001135int dct_vs_idtx(const int16_t *diff, int stride, int w, int h) {
1136 double hcorr, vcorr;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001137 int prune_bitmask = 0;
Alex Converse89912f92017-04-21 13:28:50 -07001138 get_horver_correlation(diff, stride, w, h, &hcorr, &vcorr);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001139
Alex Converse89912f92017-04-21 13:28:50 -07001140 if (vcorr > FAST_EXT_TX_CORR_MID + FAST_EXT_TX_CORR_MARGIN)
Yaowu Xuc27fc142016-08-22 16:08:15 -07001141 prune_bitmask |= 1 << IDTX_1D;
Alex Converse89912f92017-04-21 13:28:50 -07001142 else if (vcorr < FAST_EXT_TX_CORR_MID - FAST_EXT_TX_CORR_MARGIN)
Yaowu Xuc27fc142016-08-22 16:08:15 -07001143 prune_bitmask |= 1 << DCT_1D;
1144
Alex Converse89912f92017-04-21 13:28:50 -07001145 if (hcorr > FAST_EXT_TX_CORR_MID + FAST_EXT_TX_CORR_MARGIN)
Yaowu Xuc27fc142016-08-22 16:08:15 -07001146 prune_bitmask |= 1 << (IDTX_1D + 8);
Alex Converse89912f92017-04-21 13:28:50 -07001147 else if (hcorr < FAST_EXT_TX_CORR_MID - FAST_EXT_TX_CORR_MARGIN)
Yaowu Xuc27fc142016-08-22 16:08:15 -07001148 prune_bitmask |= 1 << (DCT_1D + 8);
1149 return prune_bitmask;
1150}
1151
1152// Performance drop: 0.5%, Speed improvement: 24%
Yaowu Xuf883b422016-08-30 14:01:10 -07001153static int prune_two_for_sby(const AV1_COMP *cpi, BLOCK_SIZE bsize,
Alex Converse89912f92017-04-21 13:28:50 -07001154 MACROBLOCK *x, const MACROBLOCKD *xd,
1155 int adst_flipadst, int dct_idtx) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07001156 int prune = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001157
Alex Converse89912f92017-04-21 13:28:50 -07001158 if (adst_flipadst) {
1159 const struct macroblock_plane *const p = &x->plane[0];
1160 const struct macroblockd_plane *const pd = &xd->plane[0];
Yaowu Xuc27fc142016-08-22 16:08:15 -07001161 prune |= adst_vs_flipadst(cpi, bsize, p->src.buf, p->src.stride,
Alex Converse89912f92017-04-21 13:28:50 -07001162 pd->dst.buf, pd->dst.stride);
1163 }
1164 if (dct_idtx) {
1165 av1_subtract_plane(x, bsize, 0);
1166 const struct macroblock_plane *const p = &x->plane[0];
1167 const int bw = 4 << (b_width_log2_lookup[bsize]);
1168 const int bh = 4 << (b_height_log2_lookup[bsize]);
1169 prune |= dct_vs_idtx(p->src_diff, bw, bw, bh);
1170 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07001171
1172 return prune;
1173}
1174#endif // CONFIG_EXT_TX
1175
1176// Performance drop: 0.3%, Speed improvement: 5%
Yaowu Xuf883b422016-08-30 14:01:10 -07001177static int prune_one_for_sby(const AV1_COMP *cpi, BLOCK_SIZE bsize,
Alex Converse89912f92017-04-21 13:28:50 -07001178 const MACROBLOCK *x, const MACROBLOCKD *xd) {
1179 const struct macroblock_plane *const p = &x->plane[0];
1180 const struct macroblockd_plane *const pd = &xd->plane[0];
Yaowu Xuc27fc142016-08-22 16:08:15 -07001181 return adst_vs_flipadst(cpi, bsize, p->src.buf, p->src.stride, pd->dst.buf,
Alex Converse89912f92017-04-21 13:28:50 -07001182 pd->dst.stride);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001183}
1184
Hui Su032ab8b2017-09-19 14:53:40 -07001185#if CONFIG_EXT_TX
1186// 1D Transforms used in inter set, this needs to be changed if
1187// ext_tx_used_inter is changed
1188static const int ext_tx_used_inter_1D[EXT_TX_SETS_INTER][TX_TYPES_1D] = {
1189 { 1, 0, 0, 0 }, { 1, 1, 1, 1 }, { 1, 1, 1, 1 }, { 1, 0, 0, 1 },
1190#if CONFIG_MRC_TX
1191 { 1, 0, 0, 1 },
1192#endif // CONFIG_MRC_TX
1193};
1194#endif // CONFIG_EXT_TX
1195
Yaowu Xuf883b422016-08-30 14:01:10 -07001196static int prune_tx_types(const AV1_COMP *cpi, BLOCK_SIZE bsize, MACROBLOCK *x,
Urvang Joshi0d1e4ff2017-04-27 16:17:25 -07001197 const MACROBLOCKD *const xd, int tx_set) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07001198#if CONFIG_EXT_TX
Yaowu Xu37fe5fb2017-05-09 11:43:45 -07001199 const int *tx_set_1D = tx_set >= 0 ? ext_tx_used_inter_1D[tx_set] : NULL;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001200#else
1201 const int tx_set_1D[TX_TYPES_1D] = { 0 };
Fergus Simpson4063a682017-02-28 16:52:22 -08001202#endif // CONFIG_EXT_TX
Yaowu Xuc27fc142016-08-22 16:08:15 -07001203
1204 switch (cpi->sf.tx_type_search.prune_mode) {
1205 case NO_PRUNE: return 0; break;
1206 case PRUNE_ONE:
Sarah Parker68a26b62016-10-28 13:19:33 -07001207 if ((tx_set >= 0) && !(tx_set_1D[FLIPADST_1D] & tx_set_1D[ADST_1D]))
Yaowu Xuc27fc142016-08-22 16:08:15 -07001208 return 0;
1209 return prune_one_for_sby(cpi, bsize, x, xd);
1210 break;
1211#if CONFIG_EXT_TX
1212 case PRUNE_TWO:
Sarah Parker68a26b62016-10-28 13:19:33 -07001213 if ((tx_set >= 0) && !(tx_set_1D[FLIPADST_1D] & tx_set_1D[ADST_1D])) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07001214 if (!(tx_set_1D[DCT_1D] & tx_set_1D[IDTX_1D])) return 0;
1215 return prune_two_for_sby(cpi, bsize, x, xd, 0, 1);
1216 }
Sarah Parker68a26b62016-10-28 13:19:33 -07001217 if ((tx_set >= 0) && !(tx_set_1D[DCT_1D] & tx_set_1D[IDTX_1D]))
Yaowu Xuc27fc142016-08-22 16:08:15 -07001218 return prune_two_for_sby(cpi, bsize, x, xd, 1, 0);
1219 return prune_two_for_sby(cpi, bsize, x, xd, 1, 1);
1220 break;
Fergus Simpson4063a682017-02-28 16:52:22 -08001221#endif // CONFIG_EXT_TX
Yaowu Xuc27fc142016-08-22 16:08:15 -07001222 }
1223 assert(0);
1224 return 0;
1225}
1226
1227static int do_tx_type_search(TX_TYPE tx_type, int prune) {
1228// TODO(sarahparker) implement for non ext tx
1229#if CONFIG_EXT_TX
1230 return !(((prune >> vtx_tab[tx_type]) & 1) |
1231 ((prune >> (htx_tab[tx_type] + 8)) & 1));
1232#else
1233 // temporary to avoid compiler warnings
1234 (void)vtx_tab;
1235 (void)htx_tab;
1236 (void)tx_type;
1237 (void)prune;
1238 return 1;
Fergus Simpson4063a682017-02-28 16:52:22 -08001239#endif // CONFIG_EXT_TX
Yaowu Xuc27fc142016-08-22 16:08:15 -07001240}
1241
Yaowu Xuf883b422016-08-30 14:01:10 -07001242static void model_rd_from_sse(const AV1_COMP *const cpi,
Yaowu Xuc27fc142016-08-22 16:08:15 -07001243 const MACROBLOCKD *const xd, BLOCK_SIZE bsize,
1244 int plane, int64_t sse, int *rate,
1245 int64_t *dist) {
1246 const struct macroblockd_plane *const pd = &xd->plane[plane];
1247 const int dequant_shift =
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02001248#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07001249 (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) ? xd->bd - 5 :
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02001250#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07001251 3;
1252
1253 // Fast approximate the modelling function.
1254 if (cpi->sf.simple_model_rd_from_var) {
1255 const int64_t square_error = sse;
1256 int quantizer = (pd->dequant[1] >> dequant_shift);
1257
1258 if (quantizer < 120)
1259 *rate = (int)((square_error * (280 - quantizer)) >>
Yaowu Xuf883b422016-08-30 14:01:10 -07001260 (16 - AV1_PROB_COST_SHIFT));
Yaowu Xuc27fc142016-08-22 16:08:15 -07001261 else
1262 *rate = 0;
1263 *dist = (square_error * quantizer) >> 8;
1264 } else {
Yaowu Xuf883b422016-08-30 14:01:10 -07001265 av1_model_rd_from_var_lapndz(sse, num_pels_log2_lookup[bsize],
1266 pd->dequant[1] >> dequant_shift, rate, dist);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001267 }
1268
1269 *dist <<= 4;
1270}
1271
Yaowu Xuf883b422016-08-30 14:01:10 -07001272static void model_rd_for_sb(const AV1_COMP *const cpi, BLOCK_SIZE bsize,
Yaowu Xuc27fc142016-08-22 16:08:15 -07001273 MACROBLOCK *x, MACROBLOCKD *xd, int plane_from,
1274 int plane_to, int *out_rate_sum,
1275 int64_t *out_dist_sum, int *skip_txfm_sb,
1276 int64_t *skip_sse_sb) {
1277 // Note our transform coeffs are 8 times an orthogonal transform.
1278 // Hence quantizer step is also 8 times. To get effective quantizer
1279 // we need to divide by 8 before sending to modeling function.
1280 int plane;
1281 const int ref = xd->mi[0]->mbmi.ref_frame[0];
1282
1283 int64_t rate_sum = 0;
1284 int64_t dist_sum = 0;
1285 int64_t total_sse = 0;
1286
1287 x->pred_sse[ref] = 0;
1288
1289 for (plane = plane_from; plane <= plane_to; ++plane) {
1290 struct macroblock_plane *const p = &x->plane[plane];
1291 struct macroblockd_plane *const pd = &xd->plane[plane];
Timothy B. Terriberry81ec2612017-04-26 16:53:47 -07001292#if CONFIG_CHROMA_SUB8X8
Jingning Han9ce464c2017-02-20 15:36:30 -08001293 const BLOCK_SIZE bs = AOMMAX(BLOCK_4X4, get_plane_block_size(bsize, pd));
1294#else
Yaowu Xuc27fc142016-08-22 16:08:15 -07001295 const BLOCK_SIZE bs = get_plane_block_size(bsize, pd);
Timothy B. Terriberry81ec2612017-04-26 16:53:47 -07001296#endif // CONFIG_CHROMA_SUB8X8
Yaowu Xuc27fc142016-08-22 16:08:15 -07001297
1298 unsigned int sse;
1299 int rate;
1300 int64_t dist;
1301
Jingning Han9ce464c2017-02-20 15:36:30 -08001302#if CONFIG_CB4X4
1303 if (x->skip_chroma_rd && plane) continue;
Fergus Simpson4063a682017-02-28 16:52:22 -08001304#endif // CONFIG_CB4X4
Jingning Han9ce464c2017-02-20 15:36:30 -08001305
Yaowu Xuc27fc142016-08-22 16:08:15 -07001306 // TODO(geza): Write direct sse functions that do not compute
1307 // variance as well.
1308 cpi->fn_ptr[bs].vf(p->src.buf, p->src.stride, pd->dst.buf, pd->dst.stride,
1309 &sse);
1310
1311 if (plane == 0) x->pred_sse[ref] = sse;
1312
1313 total_sse += sse;
1314
1315 model_rd_from_sse(cpi, xd, bs, plane, sse, &rate, &dist);
1316
1317 rate_sum += rate;
1318 dist_sum += dist;
1319 }
1320
1321 *skip_txfm_sb = total_sse == 0;
1322 *skip_sse_sb = total_sse << 4;
1323 *out_rate_sum = (int)rate_sum;
1324 *out_dist_sum = dist_sum;
1325}
1326
Yaowu Xuf883b422016-08-30 14:01:10 -07001327int64_t av1_block_error_c(const tran_low_t *coeff, const tran_low_t *dqcoeff,
1328 intptr_t block_size, int64_t *ssz) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07001329 int i;
1330 int64_t error = 0, sqcoeff = 0;
1331
1332 for (i = 0; i < block_size; i++) {
1333 const int diff = coeff[i] - dqcoeff[i];
1334 error += diff * diff;
1335 sqcoeff += coeff[i] * coeff[i];
1336 }
1337
1338 *ssz = sqcoeff;
1339 return error;
1340}
1341
Yaowu Xuf883b422016-08-30 14:01:10 -07001342int64_t av1_block_error_fp_c(const int16_t *coeff, const int16_t *dqcoeff,
1343 int block_size) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07001344 int i;
1345 int64_t error = 0;
1346
1347 for (i = 0; i < block_size; i++) {
1348 const int diff = coeff[i] - dqcoeff[i];
1349 error += diff * diff;
1350 }
1351
1352 return error;
1353}
1354
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02001355#if CONFIG_HIGHBITDEPTH
Yaowu Xuf883b422016-08-30 14:01:10 -07001356int64_t av1_highbd_block_error_c(const tran_low_t *coeff,
1357 const tran_low_t *dqcoeff, intptr_t block_size,
1358 int64_t *ssz, int bd) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07001359 int i;
1360 int64_t error = 0, sqcoeff = 0;
1361 int shift = 2 * (bd - 8);
1362 int rounding = shift > 0 ? 1 << (shift - 1) : 0;
1363
1364 for (i = 0; i < block_size; i++) {
1365 const int64_t diff = coeff[i] - dqcoeff[i];
1366 error += diff * diff;
1367 sqcoeff += (int64_t)coeff[i] * (int64_t)coeff[i];
1368 }
1369 assert(error >= 0 && sqcoeff >= 0);
1370 error = (error + rounding) >> shift;
1371 sqcoeff = (sqcoeff + rounding) >> shift;
1372
1373 *ssz = sqcoeff;
1374 return error;
1375}
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02001376#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07001377
Thomas Daede6ff6af62017-02-03 16:29:24 -08001378#if CONFIG_PVQ
1379// Without PVQ, av1_block_error_c() return two kind of errors,
1380// 1) reconstruction (i.e. decoded) error and
1381// 2) Squared sum of transformed residue (i.e. 'coeff')
1382// However, if PVQ is enabled, coeff does not keep the transformed residue
1383// but instead a transformed original is kept.
1384// Hence, new parameter ref vector (i.e. transformed predicted signal)
1385// is required to derive the residue signal,
1386// i.e. coeff - ref = residue (all transformed).
1387
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02001388#if CONFIG_HIGHBITDEPTH
Thomas Daede6ff6af62017-02-03 16:29:24 -08001389static int64_t av1_highbd_block_error2_c(const tran_low_t *coeff,
1390 const tran_low_t *dqcoeff,
1391 const tran_low_t *ref,
1392 intptr_t block_size, int64_t *ssz,
1393 int bd) {
1394 int64_t error;
1395 int64_t sqcoeff;
1396 int shift = 2 * (bd - 8);
1397 int rounding = shift > 0 ? 1 << (shift - 1) : 0;
1398 // Use the existing sse codes for calculating distortion of decoded signal:
1399 // i.e. (orig - decoded)^2
1400 // For high bit depth, throw away ssz until a 32-bit version of
1401 // av1_block_error_fp is written.
1402 int64_t ssz_trash;
1403 error = av1_block_error(coeff, dqcoeff, block_size, &ssz_trash);
1404 // prediction residue^2 = (orig - ref)^2
1405 sqcoeff = av1_block_error(coeff, ref, block_size, &ssz_trash);
1406 error = (error + rounding) >> shift;
1407 sqcoeff = (sqcoeff + rounding) >> shift;
1408 *ssz = sqcoeff;
1409 return error;
1410}
1411#else
1412// TODO(yushin) : Since 4x4 case does not need ssz, better to refactor into
1413// a separate function that does not do the extra computations for ssz.
1414static int64_t av1_block_error2_c(const tran_low_t *coeff,
1415 const tran_low_t *dqcoeff,
1416 const tran_low_t *ref, intptr_t block_size,
1417 int64_t *ssz) {
1418 int64_t error;
Yushin Choead552a2017-09-25 15:10:25 -07001419 int64_t ssz_trash;
Thomas Daede6ff6af62017-02-03 16:29:24 -08001420 // Use the existing sse codes for calculating distortion of decoded signal:
1421 // i.e. (orig - decoded)^2
Yushin Choead552a2017-09-25 15:10:25 -07001422 error = av1_block_error(coeff, dqcoeff, block_size, &ssz_trash);
Thomas Daede6ff6af62017-02-03 16:29:24 -08001423 // prediction residue^2 = (orig - ref)^2
Yushin Choead552a2017-09-25 15:10:25 -07001424 *ssz = av1_block_error(coeff, ref, block_size, &ssz_trash);
Thomas Daede6ff6af62017-02-03 16:29:24 -08001425 return error;
1426}
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02001427#endif // CONFIG_HIGHBITDEPTH
Thomas Daede6ff6af62017-02-03 16:29:24 -08001428#endif // CONFIG_PVQ
1429
Jingning Hanab77e732017-02-28 15:20:59 -08001430#if !CONFIG_PVQ || CONFIG_VAR_TX
Angie Chiang47e4b362017-03-24 11:25:10 -07001431#if !CONFIG_LV_MAP
1432static int cost_coeffs(const AV1_COMMON *const cm, MACROBLOCK *x, int plane,
1433 int block, TX_SIZE tx_size, const SCAN_ORDER *scan_order,
1434 const ENTROPY_CONTEXT *a, const ENTROPY_CONTEXT *l,
1435 int use_fast_coef_costing) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07001436 MACROBLOCKD *const xd = &x->e_mbd;
1437 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
1438 const struct macroblock_plane *p = &x->plane[plane];
1439 const struct macroblockd_plane *pd = &xd->plane[plane];
1440 const PLANE_TYPE type = pd->plane_type;
1441 const uint16_t *band_count = &band_count_table[tx_size][1];
1442 const int eob = p->eobs[block];
1443 const tran_low_t *const qcoeff = BLOCK_OFFSET(p->qcoeff, block);
Urvang Joshi9752a2e2017-10-02 17:32:27 -07001444 const TX_SIZE tx_size_ctx = txsize_sqr_map[tx_size];
Yaowu Xuc27fc142016-08-22 16:08:15 -07001445 uint8_t token_cache[MAX_TX_SQUARE];
Angie Chiang77368af2017-03-23 16:22:07 -07001446 int pt = combine_entropy_contexts(*a, *l);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001447 int c, cost;
Angie Chiang77368af2017-03-23 16:22:07 -07001448 const int16_t *scan = scan_order->scan;
1449 const int16_t *nb = scan_order->neighbors;
Thomas Daviesed8e2d22017-01-04 16:42:09 +00001450 const int ref = is_inter_block(mbmi);
hui suc0cf71d2017-07-20 16:38:50 -07001451 int(*head_token_costs)[COEFF_CONTEXTS][TAIL_TOKENS] =
1452 x->token_head_costs[tx_size_ctx][type][ref];
1453 int(*tail_token_costs)[COEFF_CONTEXTS][TAIL_TOKENS] =
1454 x->token_tail_costs[tx_size_ctx][type][ref];
1455 const int seg_eob = av1_get_tx_eob(&cm->seg, mbmi->segment_id, tx_size);
1456 int eob_val;
Thomas Davies10525752017-03-06 12:10:46 +00001457
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02001458#if CONFIG_HIGHBITDEPTH
Alex Converseda3d94f2017-03-15 14:54:29 -07001459 const int cat6_bits = av1_get_cat6_extrabits_size(tx_size, xd->bd);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001460#else
Alex Converseda3d94f2017-03-15 14:54:29 -07001461 const int cat6_bits = av1_get_cat6_extrabits_size(tx_size, 8);
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02001462#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07001463
1464#if !CONFIG_VAR_TX && !CONFIG_SUPERTX
1465 // Check for consistency of tx_size with mode info
hui su0c6244b2017-07-12 17:11:43 -07001466 assert(tx_size == av1_get_tx_size(plane, xd));
Yaowu Xuc27fc142016-08-22 16:08:15 -07001467#endif // !CONFIG_VAR_TX && !CONFIG_SUPERTX
Angie Chiang22ba7512016-10-20 17:10:33 -07001468 (void)cm;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001469
1470 if (eob == 0) {
hui suc0cf71d2017-07-20 16:38:50 -07001471 // block zero
1472 cost = (*head_token_costs)[pt][0];
Yaowu Xuc27fc142016-08-22 16:08:15 -07001473 } else {
1474 if (use_fast_coef_costing) {
1475 int band_left = *band_count++;
1476
1477 // dc token
1478 int v = qcoeff[0];
1479 int16_t prev_t;
Alex Converseda3d94f2017-03-15 14:54:29 -07001480 cost = av1_get_token_cost(v, &prev_t, cat6_bits);
hui suc0cf71d2017-07-20 16:38:50 -07001481 eob_val = (eob == 1) ? EARLY_EOB : NO_EOB;
1482 cost += av1_get_coeff_token_cost(
1483 prev_t, eob_val, 1, (*head_token_costs)[pt], (*tail_token_costs)[pt]);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001484
Yaowu Xuf883b422016-08-30 14:01:10 -07001485 token_cache[0] = av1_pt_energy_class[prev_t];
hui suc0cf71d2017-07-20 16:38:50 -07001486 ++head_token_costs;
1487 ++tail_token_costs;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001488
1489 // ac tokens
1490 for (c = 1; c < eob; c++) {
1491 const int rc = scan[c];
1492 int16_t t;
1493
1494 v = qcoeff[rc];
Alex Converseda3d94f2017-03-15 14:54:29 -07001495 cost += av1_get_token_cost(v, &t, cat6_bits);
hui suc0cf71d2017-07-20 16:38:50 -07001496 eob_val =
1497 (c + 1 == eob) ? (c + 1 == seg_eob ? LAST_EOB : EARLY_EOB) : NO_EOB;
1498 cost += av1_get_coeff_token_cost(t, eob_val, 0,
1499 (*head_token_costs)[!prev_t],
1500 (*tail_token_costs)[!prev_t]);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001501 prev_t = t;
1502 if (!--band_left) {
1503 band_left = *band_count++;
hui suc0cf71d2017-07-20 16:38:50 -07001504 ++head_token_costs;
1505 ++tail_token_costs;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001506 }
1507 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07001508 } else { // !use_fast_coef_costing
1509 int band_left = *band_count++;
1510
1511 // dc token
1512 int v = qcoeff[0];
1513 int16_t tok;
Alex Converseda3d94f2017-03-15 14:54:29 -07001514 cost = av1_get_token_cost(v, &tok, cat6_bits);
hui suc0cf71d2017-07-20 16:38:50 -07001515 eob_val = (eob == 1) ? EARLY_EOB : NO_EOB;
1516 cost += av1_get_coeff_token_cost(tok, eob_val, 1, (*head_token_costs)[pt],
1517 (*tail_token_costs)[pt]);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001518
Yaowu Xuf883b422016-08-30 14:01:10 -07001519 token_cache[0] = av1_pt_energy_class[tok];
hui suc0cf71d2017-07-20 16:38:50 -07001520 ++head_token_costs;
1521 ++tail_token_costs;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001522
Yaowu Xuc27fc142016-08-22 16:08:15 -07001523 // ac tokens
1524 for (c = 1; c < eob; c++) {
1525 const int rc = scan[c];
1526
1527 v = qcoeff[rc];
Alex Converseda3d94f2017-03-15 14:54:29 -07001528 cost += av1_get_token_cost(v, &tok, cat6_bits);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001529 pt = get_coef_context(nb, token_cache, c);
hui suc0cf71d2017-07-20 16:38:50 -07001530 eob_val =
1531 (c + 1 == eob) ? (c + 1 == seg_eob ? LAST_EOB : EARLY_EOB) : NO_EOB;
1532 cost += av1_get_coeff_token_cost(
1533 tok, eob_val, 0, (*head_token_costs)[pt], (*tail_token_costs)[pt]);
Yaowu Xuf883b422016-08-30 14:01:10 -07001534 token_cache[rc] = av1_pt_energy_class[tok];
Yaowu Xuc27fc142016-08-22 16:08:15 -07001535 if (!--band_left) {
1536 band_left = *band_count++;
hui suc0cf71d2017-07-20 16:38:50 -07001537 ++head_token_costs;
1538 ++tail_token_costs;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001539 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07001540 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07001541 }
1542 }
1543
Yaowu Xuc27fc142016-08-22 16:08:15 -07001544 return cost;
1545}
Angie Chiang47e4b362017-03-24 11:25:10 -07001546#endif // !CONFIG_LV_MAP
1547
Angie Chiang05917872017-04-15 12:28:56 -07001548int av1_cost_coeffs(const AV1_COMP *const cpi, MACROBLOCK *x, int plane,
Jingning Han7eab9ff2017-07-06 10:12:54 -07001549 int blk_row, int blk_col, int block, TX_SIZE tx_size,
1550 const SCAN_ORDER *scan_order, const ENTROPY_CONTEXT *a,
1551 const ENTROPY_CONTEXT *l, int use_fast_coef_costing) {
Angie Chiang3627de22017-08-18 20:15:59 -07001552 const AV1_COMMON *const cm = &cpi->common;
Angie Chiang47e4b362017-03-24 11:25:10 -07001553#if !CONFIG_LV_MAP
Jingning Han7eab9ff2017-07-06 10:12:54 -07001554 (void)blk_row;
1555 (void)blk_col;
Sarah Parker99e7daa2017-08-29 10:30:13 -07001556#if CONFIG_MRC_TX
1557 const MACROBLOCKD *xd = &x->e_mbd;
1558 const MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
1559 const TX_TYPE tx_type = av1_get_tx_type(xd->plane[plane].plane_type, xd,
1560 blk_row, blk_col, block, tx_size);
1561 const int is_inter = is_inter_block(mbmi);
1562 if (tx_type == MRC_DCT && ((is_inter && SIGNAL_MRC_MASK_INTER) ||
1563 (!is_inter && SIGNAL_MRC_MASK_INTRA))) {
1564 const int mrc_mask_cost =
1565 av1_cost_color_map(x, plane, block, mbmi->sb_type, tx_size, MRC_MAP);
1566 return cost_coeffs(cm, x, plane, block, tx_size, scan_order, a, l,
1567 use_fast_coef_costing) +
1568 mrc_mask_cost;
1569 }
1570#endif
Angie Chiang47e4b362017-03-24 11:25:10 -07001571 return cost_coeffs(cm, x, plane, block, tx_size, scan_order, a, l,
1572 use_fast_coef_costing);
1573#else // !CONFIG_LV_MAP
1574 (void)scan_order;
1575 (void)use_fast_coef_costing;
1576 const MACROBLOCKD *xd = &x->e_mbd;
1577 const MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
1578 const struct macroblockd_plane *pd = &xd->plane[plane];
1579 const BLOCK_SIZE bsize = mbmi->sb_type;
Timothy B. Terriberry81ec2612017-04-26 16:53:47 -07001580#if CONFIG_CHROMA_SUB8X8
Angie Chiang47e4b362017-03-24 11:25:10 -07001581 const BLOCK_SIZE plane_bsize =
1582 AOMMAX(BLOCK_4X4, get_plane_block_size(bsize, pd));
Timothy B. Terriberry81ec2612017-04-26 16:53:47 -07001583#elif CONFIG_CB4X4
1584 const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd);
Angie Chiang47e4b362017-03-24 11:25:10 -07001585#else // CONFIG_CB4X4
1586 const BLOCK_SIZE plane_bsize =
1587 get_plane_block_size(AOMMAX(BLOCK_8X8, bsize), pd);
1588#endif // CONFIG_CB4X4
1589
1590 TXB_CTX txb_ctx;
1591 get_txb_ctx(plane_bsize, tx_size, plane, a, l, &txb_ctx);
Angie Chiang3627de22017-08-18 20:15:59 -07001592 return av1_cost_coeffs_txb(cm, x, plane, blk_row, blk_col, block, tx_size,
Jingning Han7eab9ff2017-07-06 10:12:54 -07001593 &txb_ctx);
Angie Chiang47e4b362017-03-24 11:25:10 -07001594#endif // !CONFIG_LV_MAP
1595}
Fergus Simpson0b96b472017-03-07 15:20:28 -08001596#endif // !CONFIG_PVQ || CONFIG_VAR_TX
Yaowu Xuc27fc142016-08-22 16:08:15 -07001597
Alex Converse61f37b82017-03-29 15:26:03 -07001598// Get transform block visible dimensions cropped to the MI units.
1599static void get_txb_dimensions(const MACROBLOCKD *xd, int plane,
1600 BLOCK_SIZE plane_bsize, int blk_row, int blk_col,
1601 BLOCK_SIZE tx_bsize, int *width, int *height,
1602 int *visible_width, int *visible_height) {
Yue Chend6bdd462017-07-19 16:05:43 -07001603#if !(CONFIG_RECT_TX_EXT && (CONFIG_EXT_TX || CONFIG_VAR_TX))
Alex Converse61f37b82017-03-29 15:26:03 -07001604 assert(tx_bsize <= plane_bsize);
Yue Chend6bdd462017-07-19 16:05:43 -07001605#endif
Alex Converse61f37b82017-03-29 15:26:03 -07001606 int txb_height = block_size_high[tx_bsize];
1607 int txb_width = block_size_wide[tx_bsize];
1608 const int block_height = block_size_high[plane_bsize];
1609 const int block_width = block_size_wide[plane_bsize];
1610 const struct macroblockd_plane *const pd = &xd->plane[plane];
1611 // TODO(aconverse@google.com): Investigate using crop_width/height here rather
1612 // than the MI size
1613 const int block_rows =
1614 (xd->mb_to_bottom_edge >= 0)
1615 ? block_height
1616 : (xd->mb_to_bottom_edge >> (3 + pd->subsampling_y)) + block_height;
1617 const int block_cols =
1618 (xd->mb_to_right_edge >= 0)
1619 ? block_width
1620 : (xd->mb_to_right_edge >> (3 + pd->subsampling_x)) + block_width;
1621 const int tx_unit_size = tx_size_wide_log2[0];
1622 if (width) *width = txb_width;
1623 if (height) *height = txb_height;
1624 *visible_width = clamp(block_cols - (blk_col << tx_unit_size), 0, txb_width);
1625 *visible_height =
1626 clamp(block_rows - (blk_row << tx_unit_size), 0, txb_height);
1627}
1628
Yushin Cho75b01002017-06-21 13:43:57 -07001629// Compute the pixel domain distortion from src and dst on all visible 4x4s in
1630// the
Alex Converse61f37b82017-03-29 15:26:03 -07001631// transform block.
Yushin Cho75b01002017-06-21 13:43:57 -07001632static unsigned pixel_dist(const AV1_COMP *const cpi, const MACROBLOCK *x,
1633 int plane, const uint8_t *src, const int src_stride,
1634 const uint8_t *dst, const int dst_stride,
1635 int blk_row, int blk_col,
1636 const BLOCK_SIZE plane_bsize,
1637 const BLOCK_SIZE tx_bsize) {
Alex Converse61f37b82017-03-29 15:26:03 -07001638 int txb_rows, txb_cols, visible_rows, visible_cols;
Yushin Cho75b01002017-06-21 13:43:57 -07001639 const MACROBLOCKD *xd = &x->e_mbd;
Yushin Chob7b60c52017-07-14 16:18:52 -07001640
Alex Converse61f37b82017-03-29 15:26:03 -07001641 get_txb_dimensions(xd, plane, plane_bsize, blk_row, blk_col, tx_bsize,
1642 &txb_cols, &txb_rows, &visible_cols, &visible_rows);
1643 assert(visible_rows > 0);
1644 assert(visible_cols > 0);
Yushin Cho75b01002017-06-21 13:43:57 -07001645
Yushin Chob7b60c52017-07-14 16:18:52 -07001646#if CONFIG_DIST_8X8
Yushin Cho55104332017-08-14 16:15:43 -07001647 if (x->using_dist_8x8 && plane == 0 && txb_cols >= 8 && txb_rows >= 8)
Yushin Chofcddadf2017-08-30 13:49:38 -07001648 return (unsigned)av1_dist_8x8(cpi, x, src, src_stride, dst, dst_stride,
1649 tx_bsize, txb_cols, txb_rows, visible_cols,
1650 visible_rows, x->qindex);
Yushin Chob7b60c52017-07-14 16:18:52 -07001651#endif // CONFIG_DIST_8X8
Yushin Cho75b01002017-06-21 13:43:57 -07001652
Yushin Cho2f025aa2017-09-28 17:39:21 -07001653 unsigned sse = pixel_dist_visible_only(cpi, x, src, src_stride, dst,
1654 dst_stride, tx_bsize, txb_rows,
1655 txb_cols, visible_rows, visible_cols);
1656
Alex Converse61f37b82017-03-29 15:26:03 -07001657 return sse;
1658}
1659
Yushin Cho75b01002017-06-21 13:43:57 -07001660// Compute the pixel domain distortion from diff on all visible 4x4s in the
1661// transform block.
1662static int64_t pixel_diff_dist(const MACROBLOCK *x, int plane,
1663 const int16_t *diff, const int diff_stride,
1664 int blk_row, int blk_col,
1665 const BLOCK_SIZE plane_bsize,
1666 const BLOCK_SIZE tx_bsize) {
Alex Converse61f37b82017-03-29 15:26:03 -07001667 int visible_rows, visible_cols;
Yushin Cho75b01002017-06-21 13:43:57 -07001668 const MACROBLOCKD *xd = &x->e_mbd;
Yushin Chob7b60c52017-07-14 16:18:52 -07001669#if CONFIG_DIST_8X8
Yushin Cho75b01002017-06-21 13:43:57 -07001670 int txb_height = block_size_high[tx_bsize];
1671 int txb_width = block_size_wide[tx_bsize];
1672 const int src_stride = x->plane[plane].src.stride;
1673 const int src_idx = (blk_row * src_stride + blk_col) << tx_size_wide_log2[0];
1674 const uint8_t *src = &x->plane[plane].src.buf[src_idx];
Yushin Cho75b01002017-06-21 13:43:57 -07001675#endif
1676
Alex Converse61f37b82017-03-29 15:26:03 -07001677 get_txb_dimensions(xd, plane, plane_bsize, blk_row, blk_col, tx_bsize, NULL,
1678 NULL, &visible_cols, &visible_rows);
Yushin Cho75b01002017-06-21 13:43:57 -07001679
Yushin Chob7b60c52017-07-14 16:18:52 -07001680#if CONFIG_DIST_8X8
Yushin Cho55104332017-08-14 16:15:43 -07001681 if (x->using_dist_8x8 && plane == 0 && txb_width >= 8 && txb_height >= 8)
Yushin Choe30a47c2017-08-15 13:08:30 -07001682 return av1_dist_8x8_diff(x, src, src_stride, diff, diff_stride, txb_width,
Yushin Chob7b60c52017-07-14 16:18:52 -07001683 txb_height, visible_cols, visible_rows, x->qindex);
Yushin Cho75b01002017-06-21 13:43:57 -07001684 else
1685#endif
1686 return aom_sum_squares_2d_i16(diff, diff_stride, visible_cols,
1687 visible_rows);
Alex Converse61f37b82017-03-29 15:26:03 -07001688}
1689
hui sud9a812b2017-07-06 14:34:37 -07001690int av1_count_colors(const uint8_t *src, int stride, int rows, int cols) {
1691 int val_count[256];
1692 memset(val_count, 0, sizeof(val_count));
1693 for (int r = 0; r < rows; ++r) {
1694 for (int c = 0; c < cols; ++c) {
1695 ++val_count[src[r * stride + c]];
1696 }
1697 }
1698 int n = 0;
1699 for (int i = 0; i < 256; ++i) {
1700 if (val_count[i]) ++n;
1701 }
1702 return n;
1703}
1704
1705#if CONFIG_HIGHBITDEPTH
1706int av1_count_colors_highbd(const uint8_t *src8, int stride, int rows, int cols,
1707 int bit_depth) {
1708 assert(bit_depth <= 12);
1709 const uint16_t *src = CONVERT_TO_SHORTPTR(src8);
1710 int val_count[1 << 12];
1711 memset(val_count, 0, (1 << 12) * sizeof(val_count[0]));
1712 for (int r = 0; r < rows; ++r) {
1713 for (int c = 0; c < cols; ++c) {
1714 ++val_count[src[r * stride + c]];
1715 }
1716 }
1717 int n = 0;
1718 for (int i = 0; i < (1 << bit_depth); ++i) {
1719 if (val_count[i]) ++n;
1720 }
1721 return n;
1722}
1723#endif // CONFIG_HIGHBITDEPTH
hui sud9a812b2017-07-06 14:34:37 -07001724
Angie Chiang808d8592017-04-06 18:36:55 -07001725void av1_dist_block(const AV1_COMP *cpi, MACROBLOCK *x, int plane,
1726 BLOCK_SIZE plane_bsize, int block, int blk_row, int blk_col,
1727 TX_SIZE tx_size, int64_t *out_dist, int64_t *out_sse,
1728 OUTPUT_STATUS output_status) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07001729 MACROBLOCKD *const xd = &x->e_mbd;
1730 const struct macroblock_plane *const p = &x->plane[plane];
Yushin Chob7b60c52017-07-14 16:18:52 -07001731#if CONFIG_DIST_8X8
Yushin Cho4483e3d2017-04-18 19:41:20 -07001732 struct macroblockd_plane *const pd = &xd->plane[plane];
Yushin Chob7b60c52017-07-14 16:18:52 -07001733#else // CONFIG_DIST_8X8
Yushin Cho4483e3d2017-04-18 19:41:20 -07001734 const struct macroblockd_plane *const pd = &xd->plane[plane];
Yushin Chob7b60c52017-07-14 16:18:52 -07001735#endif // CONFIG_DIST_8X8
Yushin Cho7a428ba2017-01-12 16:28:49 -08001736
Yushin Cho55104332017-08-14 16:15:43 -07001737 if (cpi->sf.use_transform_domain_distortion
1738#if CONFIG_DIST_8X8
1739 && !x->using_dist_8x8
1740#endif
1741 ) {
hui sud2f12ba2017-04-12 10:08:43 -07001742 // Transform domain distortion computation is more efficient as it does
Yaowu Xuc27fc142016-08-22 16:08:15 -07001743 // not involve an inverse transform, but it is less accurate.
Jingning Hanb9c57272016-10-25 10:15:39 -07001744 const int buffer_length = tx_size_2d[tx_size];
Yaowu Xuc27fc142016-08-22 16:08:15 -07001745 int64_t this_sse;
Jingning Hanff705452017-04-27 11:32:15 -07001746 int shift = (MAX_TX_SCALE - av1_get_tx_scale(tx_size)) * 2;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001747 tran_low_t *const coeff = BLOCK_OFFSET(p->coeff, block);
1748 tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
Yushin Cho77bba8d2016-11-04 16:36:56 -07001749#if CONFIG_PVQ
Yaowu Xud6ea71c2016-11-07 10:24:14 -08001750 tran_low_t *ref_coeff = BLOCK_OFFSET(pd->pvq_ref_coeff, block);
Thomas Daede6ff6af62017-02-03 16:29:24 -08001751
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02001752#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07001753 const int bd = (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) ? xd->bd : 8;
Thomas Daede6ff6af62017-02-03 16:29:24 -08001754 *out_dist = av1_highbd_block_error2_c(coeff, dqcoeff, ref_coeff,
Debargha Mukherjeeb02d2f32017-10-03 11:06:40 -07001755 buffer_length, &this_sse, bd);
Thomas Daede6ff6af62017-02-03 16:29:24 -08001756#else
Debargha Mukherjeeb02d2f32017-10-03 11:06:40 -07001757 *out_dist =
1758 av1_block_error2_c(coeff, dqcoeff, ref_coeff, buffer_length, &this_sse);
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02001759#endif // CONFIG_HIGHBITDEPTH
Yi Luod61e6082017-05-26 16:14:39 -07001760#else // !CONFIG_PVQ
1761#if CONFIG_HIGHBITDEPTH
1762 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
1763 *out_dist = av1_highbd_block_error(coeff, dqcoeff, buffer_length,
Debargha Mukherjeeb02d2f32017-10-03 11:06:40 -07001764 &this_sse, xd->bd);
Yi Luod61e6082017-05-26 16:14:39 -07001765 else
1766#endif
Debargha Mukherjeeb02d2f32017-10-03 11:06:40 -07001767 *out_dist = av1_block_error(coeff, dqcoeff, buffer_length, &this_sse);
Thomas Daede6ff6af62017-02-03 16:29:24 -08001768#endif // CONFIG_PVQ
Debargha Mukherjeeb02d2f32017-10-03 11:06:40 -07001769 *out_dist = RIGHT_SIGNED_SHIFT(*out_dist, shift);
1770 *out_sse = RIGHT_SIGNED_SHIFT(this_sse, shift);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001771 } else {
1772 const BLOCK_SIZE tx_bsize = txsize_to_bsize[tx_size];
Yushin Chob7b60c52017-07-14 16:18:52 -07001773#if !CONFIG_PVQ || CONFIG_DIST_8X8
Jingning Hanb9c57272016-10-25 10:15:39 -07001774 const int bsw = block_size_wide[tx_bsize];
1775 const int bsh = block_size_high[tx_bsize];
Angie Chiang50910f62017-04-03 12:31:34 -07001776#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07001777 const int src_stride = x->plane[plane].src.stride;
1778 const int dst_stride = xd->plane[plane].dst.stride;
Jingning Hanb9c57272016-10-25 10:15:39 -07001779 // Scale the transform block index to pixel unit.
1780 const int src_idx = (blk_row * src_stride + blk_col)
1781 << tx_size_wide_log2[0];
1782 const int dst_idx = (blk_row * dst_stride + blk_col)
1783 << tx_size_wide_log2[0];
Yaowu Xuc27fc142016-08-22 16:08:15 -07001784 const uint8_t *src = &x->plane[plane].src.buf[src_idx];
1785 const uint8_t *dst = &xd->plane[plane].dst.buf[dst_idx];
1786 const tran_low_t *dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
1787 const uint16_t eob = p->eobs[block];
1788
Yaowu Xuc27fc142016-08-22 16:08:15 -07001789 assert(cpi != NULL);
Jingning Hanb9c57272016-10-25 10:15:39 -07001790 assert(tx_size_wide_log2[0] == tx_size_high_log2[0]);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001791
Angie Chiangc0cf6c02017-04-04 13:47:27 -07001792 {
1793 const int diff_stride = block_size_wide[plane_bsize];
1794 const int diff_idx = (blk_row * diff_stride + blk_col)
1795 << tx_size_wide_log2[0];
1796 const int16_t *diff = &p->src_diff[diff_idx];
Yushin Cho75b01002017-06-21 13:43:57 -07001797 *out_sse = pixel_diff_dist(x, plane, diff, diff_stride, blk_row, blk_col,
1798 plane_bsize, tx_bsize);
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02001799#if CONFIG_HIGHBITDEPTH
hui sub1cc1f92017-04-11 17:41:29 -07001800 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
Alex Conversef323f012017-04-24 09:26:33 -07001801 *out_sse = ROUND_POWER_OF_TWO(*out_sse, (xd->bd - 8) * 2);
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02001802#endif // CONFIG_HIGHBITDEPTH
Angie Chiangc0cf6c02017-04-04 13:47:27 -07001803 }
Alex Conversef323f012017-04-24 09:26:33 -07001804 *out_sse *= 16;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001805
1806 if (eob) {
Angie Chiang228cc182017-04-07 15:22:16 -07001807 if (output_status == OUTPUT_HAS_DECODED_PIXELS) {
Yushin Cho75b01002017-06-21 13:43:57 -07001808 *out_dist = pixel_dist(cpi, x, plane, src, src_stride, dst, dst_stride,
1809 blk_row, blk_col, plane_bsize, tx_bsize);
Angie Chiang8f6ddec2017-04-04 17:07:00 -07001810 } else {
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02001811#if CONFIG_HIGHBITDEPTH
Jingning Han6a9dbef2017-04-10 10:25:14 -07001812 uint8_t *recon;
Angie Chiang8f6ddec2017-04-04 17:07:00 -07001813 DECLARE_ALIGNED(16, uint16_t, recon16[MAX_TX_SQUARE]);
Jingning Han6a9dbef2017-04-10 10:25:14 -07001814
1815 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
1816 recon = CONVERT_TO_BYTEPTR(recon16);
1817 else
1818 recon = (uint8_t *)recon16;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001819#else
Angie Chiang8f6ddec2017-04-04 17:07:00 -07001820 DECLARE_ALIGNED(16, uint8_t, recon[MAX_TX_SQUARE]);
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02001821#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07001822
Angie Chiang50910f62017-04-03 12:31:34 -07001823#if !CONFIG_PVQ
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02001824#if CONFIG_HIGHBITDEPTH
Angie Chiang8f6ddec2017-04-04 17:07:00 -07001825 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
1826 aom_highbd_convolve_copy(dst, dst_stride, recon, MAX_TX_SIZE, NULL, 0,
1827 NULL, 0, bsw, bsh, xd->bd);
1828 } else {
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02001829#endif // CONFIG_HIGHBITDEPTH
Angie Chiang8f6ddec2017-04-04 17:07:00 -07001830 aom_convolve_copy(dst, dst_stride, recon, MAX_TX_SIZE, NULL, 0, NULL,
1831 0, bsw, bsh);
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02001832#if CONFIG_HIGHBITDEPTH
Angie Chiang8f6ddec2017-04-04 17:07:00 -07001833 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02001834#endif // CONFIG_HIGHBITDEPTH
Angie Chiangc0cf6c02017-04-04 13:47:27 -07001835#else
Angie Chiang8f6ddec2017-04-04 17:07:00 -07001836 (void)dst;
Angie Chiang50910f62017-04-03 12:31:34 -07001837#endif // !CONFIG_PVQ
Angie Chiang41fffae2017-04-03 10:33:18 -07001838
Sarah Parker99e7daa2017-08-29 10:30:13 -07001839#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
1840 uint8_t *mrc_mask = BLOCK_OFFSET(xd->mrc_mask, block);
1841#endif // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
Angie Chiang8f6ddec2017-04-04 17:07:00 -07001842 const PLANE_TYPE plane_type = get_plane_type(plane);
Jingning Han19b5c8f2017-07-06 15:10:12 -07001843 TX_TYPE tx_type =
1844 av1_get_tx_type(plane_type, xd, blk_row, blk_col, block, tx_size);
Lester Lu708c1ec2017-06-14 14:54:49 -07001845 av1_inverse_transform_block(xd, dqcoeff,
Lester Lu432012f2017-08-17 14:39:29 -07001846#if CONFIG_LGT_FROM_PRED
Lester Lu708c1ec2017-06-14 14:54:49 -07001847 xd->mi[0]->mbmi.mode,
1848#endif
Sarah Parker99e7daa2017-08-29 10:30:13 -07001849#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
1850 mrc_mask,
1851#endif // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
Lester Lu708c1ec2017-06-14 14:54:49 -07001852 tx_type, tx_size, recon, MAX_TX_SIZE, eob);
Angie Chiang41fffae2017-04-03 10:33:18 -07001853
Yushin Chob7b60c52017-07-14 16:18:52 -07001854#if CONFIG_DIST_8X8
Yushin Cho55104332017-08-14 16:15:43 -07001855 if (x->using_dist_8x8 && plane == 0 && (bsw < 8 || bsh < 8)) {
Yushin Cho75b01002017-06-21 13:43:57 -07001856 // Save decoded pixels for inter block in pd->pred to avoid
1857 // block_8x8_rd_txfm_daala_dist() need to produce them
1858 // by calling av1_inverse_transform_block() again.
1859 const int pred_stride = block_size_wide[plane_bsize];
1860 const int pred_idx = (blk_row * pred_stride + blk_col)
1861 << tx_size_wide_log2[0];
1862 int16_t *pred = &pd->pred[pred_idx];
1863 int i, j;
Yushin Cho4483e3d2017-04-18 19:41:20 -07001864
Yushin Cho8ab875d2017-06-23 14:47:21 -07001865#if CONFIG_HIGHBITDEPTH
1866 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
1867 for (j = 0; j < bsh; j++)
1868 for (i = 0; i < bsw; i++)
1869 pred[j * pred_stride + i] =
1870 CONVERT_TO_SHORTPTR(recon)[j * MAX_TX_SIZE + i];
1871 } else {
1872#endif
1873 for (j = 0; j < bsh; j++)
1874 for (i = 0; i < bsw; i++)
1875 pred[j * pred_stride + i] = recon[j * MAX_TX_SIZE + i];
1876#if CONFIG_HIGHBITDEPTH
1877 }
1878#endif // CONFIG_HIGHBITDEPTH
Angie Chiang8f6ddec2017-04-04 17:07:00 -07001879 }
Yushin Chob7b60c52017-07-14 16:18:52 -07001880#endif // CONFIG_DIST_8X8
Yushin Cho75b01002017-06-21 13:43:57 -07001881 *out_dist =
1882 pixel_dist(cpi, x, plane, src, src_stride, recon, MAX_TX_SIZE,
1883 blk_row, blk_col, plane_bsize, tx_bsize);
Angie Chiang8f6ddec2017-04-04 17:07:00 -07001884 }
Alex Conversef323f012017-04-24 09:26:33 -07001885 *out_dist *= 16;
1886 } else {
1887 *out_dist = *out_sse;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001888 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07001889 }
1890}
1891
Yaowu Xuc27fc142016-08-22 16:08:15 -07001892static void block_rd_txfm(int plane, int block, int blk_row, int blk_col,
1893 BLOCK_SIZE plane_bsize, TX_SIZE tx_size, void *arg) {
1894 struct rdcost_block_args *args = arg;
1895 MACROBLOCK *const x = args->x;
1896 MACROBLOCKD *const xd = &x->e_mbd;
Urvang Joshi0d1e4ff2017-04-27 16:17:25 -07001897 const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Angie Chiange50f3ec2017-04-10 15:50:33 -07001898 const AV1_COMP *cpi = args->cpi;
Angie Chiang65a39bb2017-04-11 16:50:04 -07001899 ENTROPY_CONTEXT *a = args->t_above + blk_col;
1900 ENTROPY_CONTEXT *l = args->t_left + blk_row;
Angie Chiang18ad8942017-04-11 12:37:07 -07001901 const AV1_COMMON *cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -07001902 int64_t rd1, rd2, rd;
Angie Chiang7c2b7f22016-11-07 16:00:00 -08001903 RD_STATS this_rd_stats;
Yushin Choc00769a2017-09-14 14:44:30 -07001904
1905#if CONFIG_DIST_8X8
1906 // If sub8x8 tx, 8x8 or larger partition, and luma channel,
1907 // dist-8x8 disables early skip, because the distortion metrics for
1908 // sub8x8 tx (MSE) and reference distortion from 8x8 or larger partition
1909 // (new distortion metric) are different.
1910 // Exception is: dist-8x8 is enabled but still MSE is used,
1911 // i.e. "--tune=" encoder option is not used.
1912 int disable_early_skip =
1913 x->using_dist_8x8 && plane == 0 && plane_bsize >= BLOCK_8X8 &&
1914 (tx_size == TX_4X4 || tx_size == TX_4X8 || tx_size == TX_8X4) &&
1915 x->tune_metric != AOM_TUNE_PSNR;
Yushin Choa4817a62017-07-27 13:09:43 -07001916#endif // CONFIG_DIST_8X8
Yushin Cho6341f5c2017-03-24 14:36:28 -07001917
Jingning Hane65436b2017-06-14 09:26:11 -07001918#if !CONFIG_SUPERTX && !CONFIG_VAR_TX
hui su0c6244b2017-07-12 17:11:43 -07001919 assert(tx_size == av1_get_tx_size(plane, xd));
Yue Chen8e689e42017-06-02 10:56:10 -07001920#endif // !CONFIG_SUPERTX
Angie Chiangbc2288c2017-04-09 15:41:17 -07001921
Angie Chiang7c2b7f22016-11-07 16:00:00 -08001922 av1_init_rd_stats(&this_rd_stats);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001923
1924 if (args->exit_early) return;
1925
1926 if (!is_inter_block(mbmi)) {
David Barker761b1ac2017-09-25 11:23:03 +01001927 av1_predict_intra_block_facade(cm, xd, plane, block, blk_col, blk_row,
1928 tx_size);
Angie Chiang62e54cd2017-04-06 10:45:56 -07001929 av1_subtract_txb(x, plane, plane_bsize, blk_col, blk_row, tx_size);
1930 }
1931
Angie Chiangcd9b03f2017-04-16 13:37:13 -07001932#if !CONFIG_TXK_SEL
Angie Chiang62e54cd2017-04-06 10:45:56 -07001933 // full forward transform and quantization
Urvang Joshi0d1e4ff2017-04-27 16:17:25 -07001934 const int coeff_ctx = combine_entropy_contexts(*a, *l);
Sarah Parker345366a2017-06-15 12:13:01 -07001935#if DISABLE_TRELLISQ_SEARCH
1936 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
1937 coeff_ctx, AV1_XFORM_QUANT_B);
1938#else
Angie Chiang62e54cd2017-04-06 10:45:56 -07001939 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
1940 coeff_ctx, AV1_XFORM_QUANT_FP);
Jingning Han3bce7542017-07-25 10:53:57 -07001941
1942 const int shift = (MAX_TX_SCALE - av1_get_tx_scale(tx_size)) * 2;
1943 tran_low_t *const coeff = BLOCK_OFFSET(x->plane[plane].coeff, block);
1944 tran_low_t *const dqcoeff = BLOCK_OFFSET(xd->plane[plane].dqcoeff, block);
1945 const int buffer_length = tx_size_2d[tx_size];
1946 int64_t tmp_dist;
1947 int64_t tmp;
1948#if CONFIG_HIGHBITDEPTH
1949 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
1950 tmp_dist =
Debargha Mukherjeeb02d2f32017-10-03 11:06:40 -07001951 av1_highbd_block_error(coeff, dqcoeff, buffer_length, &tmp, xd->bd);
Jingning Han3bce7542017-07-25 10:53:57 -07001952 else
1953#endif
Debargha Mukherjeeb02d2f32017-10-03 11:06:40 -07001954 tmp_dist = av1_block_error(coeff, dqcoeff, buffer_length, &tmp);
1955 tmp_dist = RIGHT_SIGNED_SHIFT(tmp_dist, shift);
Jingning Han3bce7542017-07-25 10:53:57 -07001956
Yushin Choa4817a62017-07-27 13:09:43 -07001957 if (
1958#if CONFIG_DIST_8X8
Yushin Choc00769a2017-09-14 14:44:30 -07001959 disable_early_skip ||
Yushin Choa4817a62017-07-27 13:09:43 -07001960#endif
1961 RDCOST(x->rdmult, 0, tmp_dist) + args->this_rd < args->best_rd) {
Jingning Han3bce7542017-07-25 10:53:57 -07001962 av1_optimize_b(cm, x, plane, blk_row, blk_col, block, plane_bsize, tx_size,
Angie Chiang25645b72017-09-24 14:28:49 -07001963 a, l, 1);
Jingning Han3bce7542017-07-25 10:53:57 -07001964 } else {
1965 args->exit_early = 1;
1966 return;
1967 }
Sarah Parker345366a2017-06-15 12:13:01 -07001968#endif // DISABLE_TRELLISQ_SEARCH
Angie Chiang62e54cd2017-04-06 10:45:56 -07001969
Sarah Parkerc5ccd4c2017-08-03 11:27:50 -07001970#if CONFIG_MRC_TX
1971 if (mbmi->tx_type == MRC_DCT && !mbmi->valid_mrc_mask) {
1972 args->exit_early = 1;
1973 return;
1974 }
1975#endif // CONFIG_MRC_TX
1976
Angie Chiang62e54cd2017-04-06 10:45:56 -07001977 if (!is_inter_block(mbmi)) {
1978 struct macroblock_plane *const p = &x->plane[plane];
Angie Chiangbc2288c2017-04-09 15:41:17 -07001979 av1_inverse_transform_block_facade(xd, plane, block, blk_row, blk_col,
1980 p->eobs[block]);
Angie Chiang808d8592017-04-06 18:36:55 -07001981 av1_dist_block(args->cpi, x, plane, plane_bsize, block, blk_row, blk_col,
1982 tx_size, &this_rd_stats.dist, &this_rd_stats.sse,
1983 OUTPUT_HAS_DECODED_PIXELS);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001984 } else {
Angie Chiang808d8592017-04-06 18:36:55 -07001985 av1_dist_block(args->cpi, x, plane, plane_bsize, block, blk_row, blk_col,
1986 tx_size, &this_rd_stats.dist, &this_rd_stats.sse,
1987 OUTPUT_HAS_PREDICTED_PIXELS);
Yaowu Xuc27fc142016-08-22 16:08:15 -07001988 }
Luc Trudeauaa94baa2017-04-27 10:52:21 -04001989#if CONFIG_CFL
Luc Trudeaufcca37a2017-08-14 15:05:07 -04001990 if (plane == AOM_PLANE_Y && xd->cfl->store_y) {
Luc Trudeaub05eeae2017-08-18 15:14:30 -04001991#if CONFIG_CHROMA_SUB8X8
1992 assert(!is_inter_block(mbmi) || plane_bsize < BLOCK_8X8);
1993#else
1994 assert(!is_inter_block(mbmi));
1995#endif // CONFIG_CHROMA_SUB8X8
1996 cfl_store_tx(xd, blk_row, blk_col, tx_size, plane_bsize);
Luc Trudeauaa94baa2017-04-27 10:52:21 -04001997 }
Luc Trudeaub05eeae2017-08-18 15:14:30 -04001998#endif // CONFIG_CFL
Urvang Joshi70006e42017-06-14 16:08:55 -07001999 rd = RDCOST(x->rdmult, 0, this_rd_stats.dist);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002000 if (args->this_rd + rd > args->best_rd) {
2001 args->exit_early = 1;
2002 return;
2003 }
Yushin Cho77bba8d2016-11-04 16:36:56 -07002004#if !CONFIG_PVQ
Urvang Joshi0d1e4ff2017-04-27 16:17:25 -07002005 const PLANE_TYPE plane_type = get_plane_type(plane);
Jingning Han19b5c8f2017-07-06 15:10:12 -07002006 const TX_TYPE tx_type =
2007 av1_get_tx_type(plane_type, xd, blk_row, blk_col, block, tx_size);
Angie Chiangbd99b382017-06-20 15:11:16 -07002008 const SCAN_ORDER *scan_order = get_scan(cm, tx_size, tx_type, mbmi);
Angie Chiang05917872017-04-15 12:28:56 -07002009 this_rd_stats.rate =
Jingning Han7eab9ff2017-07-06 10:12:54 -07002010 av1_cost_coeffs(cpi, x, plane, blk_row, blk_col, block, tx_size,
2011 scan_order, a, l, args->use_fast_coef_costing);
Angie Chiang65a39bb2017-04-11 16:50:04 -07002012#else // !CONFIG_PVQ
2013 this_rd_stats.rate = x->rate;
2014#endif // !CONFIG_PVQ
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002015#else // !CONFIG_TXK_SEL
Angie Chiang65a39bb2017-04-11 16:50:04 -07002016 av1_search_txk_type(cpi, x, plane, block, blk_row, blk_col, plane_bsize,
2017 tx_size, a, l, args->use_fast_coef_costing,
2018 &this_rd_stats);
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002019#endif // !CONFIG_TXK_SEL
Angie Chiang65a39bb2017-04-11 16:50:04 -07002020
2021#if !CONFIG_PVQ
Angie Chiang3963d632016-11-10 18:41:40 -08002022#if CONFIG_RD_DEBUG
Angie Chiange94556b2016-11-09 10:59:30 -08002023 av1_update_txb_coeff_cost(&this_rd_stats, plane, tx_size, blk_row, blk_col,
2024 this_rd_stats.rate);
Fergus Simpson4063a682017-02-28 16:52:22 -08002025#endif // CONFIG_RD_DEBUG
Yushin Cho6341f5c2017-03-24 14:36:28 -07002026 av1_set_txb_context(x, plane, block, tx_size, a, l);
Fergus Simpson4063a682017-02-28 16:52:22 -08002027#endif // !CONFIG_PVQ
Angie Chiangb3a12b52017-03-23 14:53:10 -07002028
Urvang Joshi70006e42017-06-14 16:08:55 -07002029 rd1 = RDCOST(x->rdmult, this_rd_stats.rate, this_rd_stats.dist);
2030 rd2 = RDCOST(x->rdmult, 0, this_rd_stats.sse);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002031
2032 // TODO(jingning): temporarily enabled only for luma component
Yaowu Xuf883b422016-08-30 14:01:10 -07002033 rd = AOMMIN(rd1, rd2);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002034
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002035#if !CONFIG_PVQ
2036 this_rd_stats.skip &= !x->plane[plane].eobs[block];
2037#else
2038 this_rd_stats.skip &= x->pvq_skip[plane];
Fergus Simpson4063a682017-02-28 16:52:22 -08002039#endif // !CONFIG_PVQ
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002040 av1_merge_rd_stats(&args->rd_stats, &this_rd_stats);
Yushin Cho7a428ba2017-01-12 16:28:49 -08002041
Yaowu Xuc27fc142016-08-22 16:08:15 -07002042 args->this_rd += rd;
2043
Yushin Chob7b60c52017-07-14 16:18:52 -07002044#if CONFIG_DIST_8X8
Yushin Choc00769a2017-09-14 14:44:30 -07002045 if (!disable_early_skip)
Yushin Cho30a2c5f2017-06-07 14:18:54 -07002046#endif
2047 if (args->this_rd > args->best_rd) {
2048 args->exit_early = 1;
2049 return;
2050 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07002051}
2052
Yushin Chob7b60c52017-07-14 16:18:52 -07002053#if CONFIG_DIST_8X8
2054static void dist_8x8_sub8x8_txfm_rd(const AV1_COMP *const cpi, MACROBLOCK *x,
2055 BLOCK_SIZE bsize,
2056 struct rdcost_block_args *args) {
Yushin Cho7a428ba2017-01-12 16:28:49 -08002057 MACROBLOCKD *const xd = &x->e_mbd;
Yushin Cho30a2c5f2017-06-07 14:18:54 -07002058 const struct macroblockd_plane *const pd = &xd->plane[0];
2059 const struct macroblock_plane *const p = &x->plane[0];
Yushin Cho4483e3d2017-04-18 19:41:20 -07002060 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Yushin Cho30a2c5f2017-06-07 14:18:54 -07002061 const int src_stride = p->src.stride;
2062 const int dst_stride = pd->dst.stride;
Yushin Cho30a2c5f2017-06-07 14:18:54 -07002063 const uint8_t *src = &p->src.buf[0];
2064 const uint8_t *dst = &pd->dst.buf[0];
2065 const int16_t *pred = &pd->pred[0];
Yushin Cho2f025aa2017-09-28 17:39:21 -07002066 int bw = block_size_wide[bsize];
2067 int bh = block_size_high[bsize];
2068 int visible_w = bw;
2069 int visible_h = bh;
Yushin Cho7a428ba2017-01-12 16:28:49 -08002070
Yushin Cho30a2c5f2017-06-07 14:18:54 -07002071 int i, j;
2072 int64_t rd, rd1, rd2;
Yushin Cho30a2c5f2017-06-07 14:18:54 -07002073 unsigned int tmp1, tmp2;
2074 int qindex = x->qindex;
Yushin Cho7a428ba2017-01-12 16:28:49 -08002075
Yushin Cho30a2c5f2017-06-07 14:18:54 -07002076 assert((bw & 0x07) == 0);
2077 assert((bh & 0x07) == 0);
Yushin Cho7a428ba2017-01-12 16:28:49 -08002078
Yushin Cho2f025aa2017-09-28 17:39:21 -07002079 get_txb_dimensions(xd, 0, bsize, 0, 0, bsize, &bw, &bh, &visible_w,
2080 &visible_h);
2081
Yushin Cho8ab875d2017-06-23 14:47:21 -07002082#if CONFIG_HIGHBITDEPTH
2083 uint8_t *pred8;
2084 DECLARE_ALIGNED(16, uint16_t, pred16[MAX_TX_SQUARE]);
Yushin Cho7a428ba2017-01-12 16:28:49 -08002085
Yushin Cho8ab875d2017-06-23 14:47:21 -07002086 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
2087 pred8 = CONVERT_TO_BYTEPTR(pred16);
2088 else
2089 pred8 = (uint8_t *)pred16;
2090#else
2091 DECLARE_ALIGNED(16, uint8_t, pred8[MAX_TX_SQUARE]);
2092#endif // CONFIG_HIGHBITDEPTH
Yushin Cho7a428ba2017-01-12 16:28:49 -08002093
Yushin Cho8ab875d2017-06-23 14:47:21 -07002094#if CONFIG_HIGHBITDEPTH
2095 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
2096 for (j = 0; j < bh; j++)
2097 for (i = 0; i < bw; i++)
2098 CONVERT_TO_SHORTPTR(pred8)[j * bw + i] = pred[j * bw + i];
2099 } else {
2100#endif
2101 for (j = 0; j < bh; j++)
Yaowu Xu7a471702017-09-29 08:38:37 -07002102 for (i = 0; i < bw; i++) pred8[j * bw + i] = (uint8_t)pred[j * bw + i];
Yushin Cho8ab875d2017-06-23 14:47:21 -07002103#if CONFIG_HIGHBITDEPTH
2104 }
2105#endif // CONFIG_HIGHBITDEPTH
2106
Yushin Chofcddadf2017-08-30 13:49:38 -07002107 tmp1 = (unsigned)av1_dist_8x8(cpi, x, src, src_stride, pred8, bw, bsize, bw,
Yushin Cho2f025aa2017-09-28 17:39:21 -07002108 bh, visible_w, visible_h, qindex);
Yushin Chofcddadf2017-08-30 13:49:38 -07002109 tmp2 = (unsigned)av1_dist_8x8(cpi, x, src, src_stride, dst, dst_stride, bsize,
Yushin Cho2f025aa2017-09-28 17:39:21 -07002110 bw, bh, visible_w, visible_h, qindex);
Yushin Cho4483e3d2017-04-18 19:41:20 -07002111
Yushin Cho30a2c5f2017-06-07 14:18:54 -07002112 if (!is_inter_block(mbmi)) {
Yushin Cho2f025aa2017-09-28 17:39:21 -07002113 if (x->tune_metric == AOM_TUNE_PSNR) {
2114 assert(args->rd_stats.sse == tmp1 * 16);
2115 assert(args->rd_stats.dist == tmp2 * 16);
2116 }
Yushin Cho30a2c5f2017-06-07 14:18:54 -07002117 args->rd_stats.sse = (int64_t)tmp1 * 16;
2118 args->rd_stats.dist = (int64_t)tmp2 * 16;
2119 } else {
2120 // For inter mode, the decoded pixels are provided in pd->pred,
2121 // while the predicted pixels are in dst.
Yushin Cho2f025aa2017-09-28 17:39:21 -07002122 if (x->tune_metric == AOM_TUNE_PSNR) {
2123 assert(args->rd_stats.sse == tmp2 * 16);
2124 assert(args->rd_stats.dist == tmp1 * 16);
2125 }
Yushin Cho30a2c5f2017-06-07 14:18:54 -07002126 args->rd_stats.sse = (int64_t)tmp2 * 16;
2127 args->rd_stats.dist = (int64_t)tmp1 * 16;
Yushin Cho7a428ba2017-01-12 16:28:49 -08002128 }
2129
Urvang Joshi70006e42017-06-14 16:08:55 -07002130 rd1 = RDCOST(x->rdmult, args->rd_stats.rate, args->rd_stats.dist);
2131 rd2 = RDCOST(x->rdmult, 0, args->rd_stats.sse);
Yushin Cho7a428ba2017-01-12 16:28:49 -08002132 rd = AOMMIN(rd1, rd2);
2133
Yushin Cho30a2c5f2017-06-07 14:18:54 -07002134 args->rd_stats.rdcost = rd;
2135 args->this_rd = rd;
Yushin Cho04eb9592017-06-21 17:35:06 -07002136
2137 if (args->this_rd > args->best_rd) args->exit_early = 1;
Yushin Cho7a428ba2017-01-12 16:28:49 -08002138}
Yushin Chob7b60c52017-07-14 16:18:52 -07002139#endif // CONFIG_DIST_8X8
Yushin Cho7a428ba2017-01-12 16:28:49 -08002140
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002141static void txfm_rd_in_plane(MACROBLOCK *x, const AV1_COMP *cpi,
2142 RD_STATS *rd_stats, int64_t ref_best_rd, int plane,
2143 BLOCK_SIZE bsize, TX_SIZE tx_size,
2144 int use_fast_coef_casting) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07002145 MACROBLOCKD *const xd = &x->e_mbd;
2146 const struct macroblockd_plane *const pd = &xd->plane[plane];
Yaowu Xuc27fc142016-08-22 16:08:15 -07002147 struct rdcost_block_args args;
Yaowu Xuf883b422016-08-30 14:01:10 -07002148 av1_zero(args);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002149 args.x = x;
2150 args.cpi = cpi;
2151 args.best_rd = ref_best_rd;
2152 args.use_fast_coef_costing = use_fast_coef_casting;
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002153 av1_init_rd_stats(&args.rd_stats);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002154
2155 if (plane == 0) xd->mi[0]->mbmi.tx_size = tx_size;
2156
Yaowu Xuf883b422016-08-30 14:01:10 -07002157 av1_get_entropy_contexts(bsize, tx_size, pd, args.t_above, args.t_left);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002158
Yushin Cho30a2c5f2017-06-07 14:18:54 -07002159 av1_foreach_transformed_block_in_plane(xd, bsize, plane, block_rd_txfm,
2160 &args);
Yushin Chob7b60c52017-07-14 16:18:52 -07002161#if CONFIG_DIST_8X8
Yushin Cho55104332017-08-14 16:15:43 -07002162 if (x->using_dist_8x8 && !args.exit_early && plane == 0 &&
2163 bsize >= BLOCK_8X8 &&
Yushin Cho7a428ba2017-01-12 16:28:49 -08002164 (tx_size == TX_4X4 || tx_size == TX_4X8 || tx_size == TX_8X4))
Yushin Chob7b60c52017-07-14 16:18:52 -07002165 dist_8x8_sub8x8_txfm_rd(cpi, x, bsize, &args);
Yushin Cho30a2c5f2017-06-07 14:18:54 -07002166#endif
Yushin Cho7a428ba2017-01-12 16:28:49 -08002167
Yaowu Xuc27fc142016-08-22 16:08:15 -07002168 if (args.exit_early) {
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002169 av1_invalid_rd_stats(rd_stats);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002170 } else {
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002171 *rd_stats = args.rd_stats;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002172 }
2173}
2174
2175#if CONFIG_SUPERTX
Yaowu Xuf883b422016-08-30 14:01:10 -07002176void av1_txfm_rd_in_plane_supertx(MACROBLOCK *x, const AV1_COMP *cpi, int *rate,
2177 int64_t *distortion, int *skippable,
2178 int64_t *sse, int64_t ref_best_rd, int plane,
2179 BLOCK_SIZE bsize, TX_SIZE tx_size,
2180 int use_fast_coef_casting) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07002181 MACROBLOCKD *const xd = &x->e_mbd;
2182 const struct macroblockd_plane *const pd = &xd->plane[plane];
2183 struct rdcost_block_args args;
Yaowu Xuf883b422016-08-30 14:01:10 -07002184 av1_zero(args);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002185 args.cpi = cpi;
2186 args.x = x;
2187 args.best_rd = ref_best_rd;
2188 args.use_fast_coef_costing = use_fast_coef_casting;
2189
2190#if CONFIG_EXT_TX
2191 assert(tx_size < TX_SIZES);
2192#endif // CONFIG_EXT_TX
2193
2194 if (plane == 0) xd->mi[0]->mbmi.tx_size = tx_size;
2195
Yaowu Xuf883b422016-08-30 14:01:10 -07002196 av1_get_entropy_contexts(bsize, tx_size, pd, args.t_above, args.t_left);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002197
Yaowu Xuc27fc142016-08-22 16:08:15 -07002198 block_rd_txfm(plane, 0, 0, 0, get_plane_block_size(bsize, pd), tx_size,
2199 &args);
2200
2201 if (args.exit_early) {
2202 *rate = INT_MAX;
2203 *distortion = INT64_MAX;
2204 *sse = INT64_MAX;
2205 *skippable = 0;
2206 } else {
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002207 *distortion = args.rd_stats.dist;
2208 *rate = args.rd_stats.rate;
2209 *sse = args.rd_stats.sse;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002210 *skippable = !x->plane[plane].eobs[0];
2211 }
2212}
2213#endif // CONFIG_SUPERTX
2214
Urvang Joshiab8840e2017-10-06 16:38:24 -07002215static int tx_size_cost(const AV1_COMP *const cpi, const MACROBLOCK *const x,
2216 BLOCK_SIZE bsize, TX_SIZE tx_size) {
Urvang Joshifeb925f2016-12-05 10:37:29 -08002217 const AV1_COMMON *const cm = &cpi->common;
Urvang Joshi0d1e4ff2017-04-27 16:17:25 -07002218 const MACROBLOCKD *const xd = &x->e_mbd;
2219 const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Urvang Joshifeb925f2016-12-05 10:37:29 -08002220
Rupert Swarbrickfcff0b22017-10-05 09:26:04 +01002221 if (cm->tx_mode == TX_MODE_SELECT && block_signals_txsize(mbmi->sb_type)) {
Urvang Joshifeb925f2016-12-05 10:37:29 -08002222 const int is_inter = is_inter_block(mbmi);
Urvang Joshiab8840e2017-10-06 16:38:24 -07002223 const int32_t tx_size_cat = is_inter ? inter_tx_size_cat_lookup[bsize]
Urvang Joshi9752a2e2017-10-02 17:32:27 -07002224 : intra_tx_size_cat_lookup[bsize];
Urvang Joshifeb925f2016-12-05 10:37:29 -08002225 const TX_SIZE coded_tx_size = txsize_sqr_up_map[tx_size];
2226 const int depth = tx_size_to_depth(coded_tx_size);
Urvang Joshiab8840e2017-10-06 16:38:24 -07002227 const int tx_size_ctx = get_tx_size_context(xd);
Yue Chenb23d00a2017-07-28 17:01:21 -07002228 int r_tx_size = x->tx_size_cost[tx_size_cat][tx_size_ctx][depth];
Yue Chend6bdd462017-07-19 16:05:43 -07002229#if CONFIG_RECT_TX_EXT && (CONFIG_EXT_TX || CONFIG_VAR_TX)
Yue Chen56e226e2017-05-02 16:21:40 -07002230 if (is_quarter_tx_allowed(xd, mbmi, is_inter) && tx_size != coded_tx_size)
2231 r_tx_size += av1_cost_bit(cm->fc->quarter_tx_size_prob,
2232 tx_size == quarter_txsize_lookup[bsize]);
Yue Chend6bdd462017-07-19 16:05:43 -07002233#endif
Urvang Joshifeb925f2016-12-05 10:37:29 -08002234 return r_tx_size;
2235 } else {
2236 return 0;
2237 }
2238}
2239
Lester Lu432012f2017-08-17 14:39:29 -07002240#if CONFIG_LGT_FROM_PRED
2241int av1_lgt_cost(const AV1_COMMON *cm, const MACROBLOCK *x,
2242 const MACROBLOCKD *xd, BLOCK_SIZE bsize, int plane,
2243 TX_SIZE tx_size, int use_lgt) {
2244 if (plane > 0) return 0;
2245 const MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
2246 const int is_inter = is_inter_block(mbmi);
2247
2248 assert(is_lgt_allowed(mbmi->mode, tx_size));
2249 if (get_ext_tx_types(tx_size, bsize, is_inter, cm->reduced_tx_set_used) > 1 &&
2250 !xd->lossless[xd->mi[0]->mbmi.segment_id]) {
2251 const int ext_tx_set =
2252 get_ext_tx_set(tx_size, bsize, is_inter, cm->reduced_tx_set_used);
2253 if (LGT_FROM_PRED_INTRA && !is_inter && ext_tx_set > 0 &&
2254 ALLOW_INTRA_EXT_TX)
2255 return x->intra_lgt_cost[txsize_sqr_map[tx_size]][mbmi->mode][use_lgt];
2256 if (LGT_FROM_PRED_INTRA && is_inter && ext_tx_set > 0)
2257 return x->inter_lgt_cost[txsize_sqr_map[tx_size]][use_lgt];
2258 }
2259 return 0;
2260}
2261#endif // CONFIG_LGT_FROM_PRED
2262
Hui Suddbcde22017-09-18 17:22:02 -07002263// TODO(angiebird): use this function whenever it's possible
Yue Chenb23d00a2017-07-28 17:01:21 -07002264int av1_tx_type_cost(const AV1_COMMON *cm, const MACROBLOCK *x,
2265 const MACROBLOCKD *xd, BLOCK_SIZE bsize, int plane,
2266 TX_SIZE tx_size, TX_TYPE tx_type) {
Angie Chiang05917872017-04-15 12:28:56 -07002267 if (plane > 0) return 0;
2268
Lester Lu432012f2017-08-17 14:39:29 -07002269#if CONFIG_LGT_FROM_PRED
2270 assert(!xd->mi[0]->mbmi.use_lgt);
2271#endif
Jingning Han243b66b2017-06-23 12:11:47 -07002272#if CONFIG_VAR_TX
2273 tx_size = get_min_tx_size(tx_size);
2274#endif
2275
Angie Chiang65201562017-04-10 15:23:28 -07002276 const MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
2277 const int is_inter = is_inter_block(mbmi);
2278#if CONFIG_EXT_TX
Angie Chiang65201562017-04-10 15:23:28 -07002279 if (get_ext_tx_types(tx_size, bsize, is_inter, cm->reduced_tx_set_used) > 1 &&
2280 !xd->lossless[xd->mi[0]->mbmi.segment_id]) {
2281 const int ext_tx_set =
2282 get_ext_tx_set(tx_size, bsize, is_inter, cm->reduced_tx_set_used);
2283 if (is_inter) {
2284 if (ext_tx_set > 0)
Yue Chenb23d00a2017-07-28 17:01:21 -07002285 return x
Angie Chiang65201562017-04-10 15:23:28 -07002286 ->inter_tx_type_costs[ext_tx_set][txsize_sqr_map[tx_size]][tx_type];
2287 } else {
2288 if (ext_tx_set > 0 && ALLOW_INTRA_EXT_TX)
Yue Chenb23d00a2017-07-28 17:01:21 -07002289 return x->intra_tx_type_costs[ext_tx_set][txsize_sqr_map[tx_size]]
2290 [mbmi->mode][tx_type];
Angie Chiang65201562017-04-10 15:23:28 -07002291 }
2292 }
2293#else
2294 (void)bsize;
Yue Chenb23d00a2017-07-28 17:01:21 -07002295 (void)cm;
Angie Chiang65201562017-04-10 15:23:28 -07002296 if (tx_size < TX_32X32 && !xd->lossless[xd->mi[0]->mbmi.segment_id] &&
2297 !FIXED_TX_TYPE) {
2298 if (is_inter) {
Yue Chenb23d00a2017-07-28 17:01:21 -07002299 return x->inter_tx_type_costs[tx_size][tx_type];
Angie Chiang65201562017-04-10 15:23:28 -07002300 } else {
Yue Chenb23d00a2017-07-28 17:01:21 -07002301 return x->intra_tx_type_costs[tx_size]
2302 [intra_mode_to_tx_type_context[mbmi->mode]]
2303 [tx_type];
Angie Chiang65201562017-04-10 15:23:28 -07002304 }
2305 }
2306#endif // CONFIG_EXT_TX
2307 return 0;
2308}
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002309static int64_t txfm_yrd(const AV1_COMP *const cpi, MACROBLOCK *x,
2310 RD_STATS *rd_stats, int64_t ref_best_rd, BLOCK_SIZE bs,
Urvang Joshi9752a2e2017-10-02 17:32:27 -07002311 TX_TYPE tx_type, TX_SIZE tx_size) {
Urvang Joshi52648442016-10-13 17:27:51 -07002312 const AV1_COMMON *const cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002313 MACROBLOCKD *const xd = &x->e_mbd;
2314 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
2315 int64_t rd = INT64_MAX;
Yaowu Xuf883b422016-08-30 14:01:10 -07002316 aom_prob skip_prob = av1_get_skip_prob(cm, xd);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002317 int s0, s1;
2318 const int is_inter = is_inter_block(mbmi);
Jingning Hanbf9c6b72016-12-14 14:50:45 -08002319 const int tx_select =
2320 cm->tx_mode == TX_MODE_SELECT && mbmi->sb_type >= BLOCK_8X8;
Urvang Joshifeb925f2016-12-05 10:37:29 -08002321
2322 const int r_tx_size = tx_size_cost(cpi, x, bs, tx_size);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002323
Yushin Chocd4f4a22017-07-10 18:19:05 -07002324#if CONFIG_PVQ
2325 assert(tx_size >= TX_4X4);
2326#endif // CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -07002327 assert(skip_prob > 0);
2328#if CONFIG_EXT_TX && CONFIG_RECT_TX
2329 assert(IMPLIES(is_rect_tx(tx_size), is_rect_tx_allowed_bsize(bs)));
2330#endif // CONFIG_EXT_TX && CONFIG_RECT_TX
2331
Yaowu Xuf883b422016-08-30 14:01:10 -07002332 s0 = av1_cost_bit(skip_prob, 0);
2333 s1 = av1_cost_bit(skip_prob, 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002334
2335 mbmi->tx_type = tx_type;
2336 mbmi->tx_size = tx_size;
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002337 txfm_rd_in_plane(x, cpi, rd_stats, ref_best_rd, 0, bs, tx_size,
Yaowu Xuc27fc142016-08-22 16:08:15 -07002338 cpi->sf.use_fast_coef_costing);
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002339 if (rd_stats->rate == INT_MAX) return INT64_MAX;
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002340#if !CONFIG_TXK_SEL
Angie Chiang05917872017-04-15 12:28:56 -07002341 int plane = 0;
Lester Lu432012f2017-08-17 14:39:29 -07002342#if CONFIG_LGT_FROM_PRED
2343 if (is_lgt_allowed(mbmi->mode, tx_size))
2344 rd_stats->rate +=
2345 av1_lgt_cost(cm, x, xd, bs, plane, tx_size, mbmi->use_lgt);
2346 if (!mbmi->use_lgt)
2347 rd_stats->rate += av1_tx_type_cost(cm, x, xd, bs, plane, tx_size, tx_type);
2348#else
Yue Chenb23d00a2017-07-28 17:01:21 -07002349 rd_stats->rate += av1_tx_type_cost(cm, x, xd, bs, plane, tx_size, tx_type);
Lester Lu432012f2017-08-17 14:39:29 -07002350#endif // CONFIG_LGT_FROM_PRED
Angie Chiang05917872017-04-15 12:28:56 -07002351#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07002352
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002353 if (rd_stats->skip) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07002354 if (is_inter) {
Urvang Joshi70006e42017-06-14 16:08:55 -07002355 rd = RDCOST(x->rdmult, s1, rd_stats->sse);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002356 } else {
Urvang Joshi70006e42017-06-14 16:08:55 -07002357 rd = RDCOST(x->rdmult, s1 + r_tx_size * tx_select, rd_stats->sse);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002358 }
2359 } else {
Urvang Joshi70006e42017-06-14 16:08:55 -07002360 rd = RDCOST(x->rdmult, rd_stats->rate + s0 + r_tx_size * tx_select,
2361 rd_stats->dist);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002362 }
2363
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002364 if (tx_select) rd_stats->rate += r_tx_size;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002365
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002366 if (is_inter && !xd->lossless[xd->mi[0]->mbmi.segment_id] &&
2367 !(rd_stats->skip))
Urvang Joshi70006e42017-06-14 16:08:55 -07002368 rd = AOMMIN(rd, RDCOST(x->rdmult, s1, rd_stats->sse));
Yaowu Xuc27fc142016-08-22 16:08:15 -07002369
2370 return rd;
2371}
2372
Angie Chiang2d147c12017-04-05 11:23:59 -07002373static int skip_txfm_search(const AV1_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bs,
2374 TX_TYPE tx_type, TX_SIZE tx_size) {
Urvang Joshi0d1e4ff2017-04-27 16:17:25 -07002375 const MACROBLOCKD *const xd = &x->e_mbd;
2376 const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Angie Chiang2d147c12017-04-05 11:23:59 -07002377 const TX_SIZE max_tx_size = max_txsize_lookup[bs];
2378 const int is_inter = is_inter_block(mbmi);
2379 int prune = 0;
2380 if (is_inter && cpi->sf.tx_type_search.prune_mode > NO_PRUNE)
2381 // passing -1 in for tx_type indicates that all 1D
2382 // transforms should be considered for pruning
2383 prune = prune_tx_types(cpi, bs, x, xd, -1);
2384
Sarah Parker53f93db2017-07-11 17:20:04 -07002385#if CONFIG_MRC_TX
2386 // MRC_DCT only implemented for TX_32X32 so only include this tx in
2387 // the search for TX_32X32
Sarah Parker2e08d962017-08-01 19:51:20 -07002388 if (tx_type == MRC_DCT &&
2389 ((is_inter && !USE_MRC_INTER) || (!is_inter && !USE_MRC_INTRA) ||
2390 tx_size != TX_32X32))
2391 return 1;
Sarah Parker53f93db2017-07-11 17:20:04 -07002392#endif // CONFIG_MRC_TX
Lester Lu432012f2017-08-17 14:39:29 -07002393#if CONFIG_LGT_FROM_PRED
2394 if (mbmi->use_lgt && mbmi->ref_mv_idx > 0) return 1;
2395#endif // CONFIG_LGT_FROM_PRED
Angie Chianga4fa1902017-04-05 15:26:09 -07002396 if (mbmi->ref_mv_idx > 0 && tx_type != DCT_DCT) return 1;
Angie Chiang2d147c12017-04-05 11:23:59 -07002397 if (FIXED_TX_TYPE && tx_type != get_default_tx_type(0, xd, 0, tx_size))
2398 return 1;
2399 if (!is_inter && x->use_default_intra_tx_type &&
2400 tx_type != get_default_tx_type(0, xd, 0, tx_size))
2401 return 1;
2402 if (is_inter && x->use_default_inter_tx_type &&
2403 tx_type != get_default_tx_type(0, xd, 0, tx_size))
2404 return 1;
2405 if (max_tx_size >= TX_32X32 && tx_size == TX_4X4) return 1;
2406#if CONFIG_EXT_TX
2407 const AV1_COMMON *const cm = &cpi->common;
Hui Suddbcde22017-09-18 17:22:02 -07002408 const TxSetType tx_set_type =
2409 get_ext_tx_set_type(tx_size, bs, is_inter, cm->reduced_tx_set_used);
2410 if (!av1_ext_tx_used[tx_set_type][tx_type]) return 1;
Angie Chiang2d147c12017-04-05 11:23:59 -07002411 if (is_inter) {
Angie Chiang2d147c12017-04-05 11:23:59 -07002412 if (cpi->sf.tx_type_search.prune_mode > NO_PRUNE) {
2413 if (!do_tx_type_search(tx_type, prune)) return 1;
2414 }
2415 } else {
2416 if (!ALLOW_INTRA_EXT_TX && bs >= BLOCK_8X8) {
2417 if (tx_type != intra_mode_to_tx_type_context[mbmi->mode]) return 1;
2418 }
Angie Chiang2d147c12017-04-05 11:23:59 -07002419 }
2420#else // CONFIG_EXT_TX
2421 if (tx_size >= TX_32X32 && tx_type != DCT_DCT) return 1;
2422 if (is_inter && cpi->sf.tx_type_search.prune_mode > NO_PRUNE &&
2423 !do_tx_type_search(tx_type, prune))
2424 return 1;
2425#endif // CONFIG_EXT_TX
2426 return 0;
2427}
2428
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02002429#if (CONFIG_WEDGE || CONFIG_COMPOUND_SEGMENT || CONFIG_INTERINTRA)
Urvang Joshi52648442016-10-13 17:27:51 -07002430static int64_t estimate_yrd_for_sb(const AV1_COMP *const cpi, BLOCK_SIZE bs,
2431 MACROBLOCK *x, int *r, int64_t *d, int *s,
2432 int64_t *sse, int64_t ref_best_rd) {
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002433 RD_STATS rd_stats;
2434 int64_t rd = txfm_yrd(cpi, x, &rd_stats, ref_best_rd, bs, DCT_DCT,
2435 max_txsize_lookup[bs]);
2436 *r = rd_stats.rate;
2437 *d = rd_stats.dist;
2438 *s = rd_stats.skip;
2439 *sse = rd_stats.sse;
2440 return rd;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002441}
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02002442#endif // (CONFIG_WEDGE || CONFIG_COMPOUND_SEGMENT)
Yaowu Xuc27fc142016-08-22 16:08:15 -07002443
Urvang Joshi52648442016-10-13 17:27:51 -07002444static void choose_largest_tx_size(const AV1_COMP *const cpi, MACROBLOCK *x,
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002445 RD_STATS *rd_stats, int64_t ref_best_rd,
Urvang Joshi52648442016-10-13 17:27:51 -07002446 BLOCK_SIZE bs) {
2447 const AV1_COMMON *const cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002448 MACROBLOCKD *const xd = &x->e_mbd;
2449 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
2450 TX_TYPE tx_type, best_tx_type = DCT_DCT;
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002451 int64_t this_rd, best_rd = INT64_MAX;
Yaowu Xuf883b422016-08-30 14:01:10 -07002452 aom_prob skip_prob = av1_get_skip_prob(cm, xd);
2453 int s0 = av1_cost_bit(skip_prob, 0);
2454 int s1 = av1_cost_bit(skip_prob, 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002455 const int is_inter = is_inter_block(mbmi);
2456 int prune = 0;
Angie Chiangaa0c34b2017-04-25 12:25:38 -07002457 const int plane = 0;
Lester Lu432012f2017-08-17 14:39:29 -07002458#if CONFIG_LGT_FROM_PRED
2459 int is_lgt_best = 0;
2460 int search_lgt = is_inter
2461 ? LGT_FROM_PRED_INTER && !x->use_default_inter_tx_type &&
2462 !cpi->sf.tx_type_search.prune_mode > NO_PRUNE
2463 : LGT_FROM_PRED_INTRA && !x->use_default_intra_tx_type &&
2464 ALLOW_INTRA_EXT_TX;
2465#endif // CONFIG_LGT_FROM_PRED
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002466 av1_invalid_rd_stats(rd_stats);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002467
2468 mbmi->tx_size = tx_size_from_tx_mode(bs, cm->tx_mode, is_inter);
Jingning Hane67b38a2016-11-04 10:30:00 -07002469#if CONFIG_VAR_TX
2470 mbmi->min_tx_size = get_min_tx_size(mbmi->tx_size);
Fergus Simpson4063a682017-02-28 16:52:22 -08002471#endif // CONFIG_VAR_TX
Yaowu Xuc27fc142016-08-22 16:08:15 -07002472#if CONFIG_EXT_TX
Hui Suddbcde22017-09-18 17:22:02 -07002473 int ext_tx_set =
Sarah Parkere68a3e42017-02-16 14:03:24 -08002474 get_ext_tx_set(mbmi->tx_size, bs, is_inter, cm->reduced_tx_set_used);
Hui Suddbcde22017-09-18 17:22:02 -07002475 const TxSetType tx_set_type =
2476 get_ext_tx_set_type(mbmi->tx_size, bs, is_inter, cm->reduced_tx_set_used);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002477#endif // CONFIG_EXT_TX
2478
2479 if (is_inter && cpi->sf.tx_type_search.prune_mode > NO_PRUNE)
2480#if CONFIG_EXT_TX
2481 prune = prune_tx_types(cpi, bs, x, xd, ext_tx_set);
2482#else
2483 prune = prune_tx_types(cpi, bs, x, xd, 0);
Fergus Simpson4063a682017-02-28 16:52:22 -08002484#endif // CONFIG_EXT_TX
Yaowu Xuc27fc142016-08-22 16:08:15 -07002485#if CONFIG_EXT_TX
Sarah Parkere68a3e42017-02-16 14:03:24 -08002486 if (get_ext_tx_types(mbmi->tx_size, bs, is_inter, cm->reduced_tx_set_used) >
2487 1 &&
Yaowu Xuc27fc142016-08-22 16:08:15 -07002488 !xd->lossless[mbmi->segment_id]) {
Yushin Cho77bba8d2016-11-04 16:36:56 -07002489#if CONFIG_PVQ
2490 od_rollback_buffer pre_buf, post_buf;
2491
2492 od_encode_checkpoint(&x->daala_enc, &pre_buf);
2493 od_encode_checkpoint(&x->daala_enc, &post_buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08002494#endif // CONFIG_PVQ
Yushin Cho77bba8d2016-11-04 16:36:56 -07002495
2496 for (tx_type = DCT_DCT; tx_type < TX_TYPES; ++tx_type) {
Hui Suddbcde22017-09-18 17:22:02 -07002497 if (!av1_ext_tx_used[tx_set_type][tx_type]) continue;
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002498 RD_STATS this_rd_stats;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002499 if (is_inter) {
2500 if (x->use_default_inter_tx_type &&
2501 tx_type != get_default_tx_type(0, xd, 0, mbmi->tx_size))
2502 continue;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002503 if (cpi->sf.tx_type_search.prune_mode > NO_PRUNE) {
2504 if (!do_tx_type_search(tx_type, prune)) continue;
2505 }
2506 } else {
2507 if (x->use_default_intra_tx_type &&
2508 tx_type != get_default_tx_type(0, xd, 0, mbmi->tx_size))
2509 continue;
2510 if (!ALLOW_INTRA_EXT_TX && bs >= BLOCK_8X8) {
2511 if (tx_type != intra_mode_to_tx_type_context[mbmi->mode]) continue;
2512 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07002513 }
2514
2515 mbmi->tx_type = tx_type;
2516
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002517 txfm_rd_in_plane(x, cpi, &this_rd_stats, ref_best_rd, 0, bs,
Yaowu Xuc27fc142016-08-22 16:08:15 -07002518 mbmi->tx_size, cpi->sf.use_fast_coef_costing);
Yushin Cho77bba8d2016-11-04 16:36:56 -07002519#if CONFIG_PVQ
2520 od_encode_rollback(&x->daala_enc, &pre_buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08002521#endif // CONFIG_PVQ
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002522 if (this_rd_stats.rate == INT_MAX) continue;
Yue Chenb23d00a2017-07-28 17:01:21 -07002523 av1_tx_type_cost(cm, x, xd, bs, plane, mbmi->tx_size, tx_type);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002524
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002525 if (this_rd_stats.skip)
Urvang Joshi70006e42017-06-14 16:08:55 -07002526 this_rd = RDCOST(x->rdmult, s1, this_rd_stats.sse);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002527 else
Urvang Joshi70006e42017-06-14 16:08:55 -07002528 this_rd =
2529 RDCOST(x->rdmult, this_rd_stats.rate + s0, this_rd_stats.dist);
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002530 if (is_inter_block(mbmi) && !xd->lossless[mbmi->segment_id] &&
2531 !this_rd_stats.skip)
Urvang Joshi70006e42017-06-14 16:08:55 -07002532 this_rd = AOMMIN(this_rd, RDCOST(x->rdmult, s1, this_rd_stats.sse));
Yaowu Xuc27fc142016-08-22 16:08:15 -07002533
2534 if (this_rd < best_rd) {
2535 best_rd = this_rd;
2536 best_tx_type = mbmi->tx_type;
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002537 *rd_stats = this_rd_stats;
Yushin Cho77bba8d2016-11-04 16:36:56 -07002538#if CONFIG_PVQ
2539 od_encode_checkpoint(&x->daala_enc, &post_buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08002540#endif // CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -07002541 }
2542 }
Yushin Cho77bba8d2016-11-04 16:36:56 -07002543#if CONFIG_PVQ
2544 od_encode_rollback(&x->daala_enc, &post_buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08002545#endif // CONFIG_PVQ
Lester Lu432012f2017-08-17 14:39:29 -07002546#if CONFIG_LGT_FROM_PRED
2547 // search LGT
2548 if (search_lgt && is_lgt_allowed(mbmi->mode, mbmi->tx_size) &&
2549 !cm->reduced_tx_set_used) {
2550 RD_STATS this_rd_stats;
2551 mbmi->use_lgt = 1;
2552 txfm_rd_in_plane(x, cpi, &this_rd_stats, ref_best_rd, 0, bs,
2553 mbmi->tx_size, cpi->sf.use_fast_coef_costing);
2554 if (this_rd_stats.rate != INT_MAX) {
2555 av1_lgt_cost(cm, x, xd, bs, plane, mbmi->tx_size, 1);
2556 if (this_rd_stats.skip)
2557 this_rd = RDCOST(x->rdmult, s1, this_rd_stats.sse);
2558 else
2559 this_rd =
2560 RDCOST(x->rdmult, this_rd_stats.rate + s0, this_rd_stats.dist);
2561 if (is_inter_block(mbmi) && !xd->lossless[mbmi->segment_id] &&
2562 !this_rd_stats.skip)
2563 this_rd = AOMMIN(this_rd, RDCOST(x->rdmult, s1, this_rd_stats.sse));
2564 if (this_rd < best_rd) {
2565 best_rd = this_rd;
2566 is_lgt_best = 1;
2567 *rd_stats = this_rd_stats;
2568 }
2569 }
2570 mbmi->use_lgt = 0;
2571 }
2572#endif // CONFIG_LGT_FROM_PRED
Guillaume Martres4e4d3a02016-08-21 19:02:33 -07002573 } else {
2574 mbmi->tx_type = DCT_DCT;
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002575 txfm_rd_in_plane(x, cpi, rd_stats, ref_best_rd, 0, bs, mbmi->tx_size,
2576 cpi->sf.use_fast_coef_costing);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002577 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07002578#else // CONFIG_EXT_TX
2579 if (mbmi->tx_size < TX_32X32 && !xd->lossless[mbmi->segment_id]) {
2580 for (tx_type = 0; tx_type < TX_TYPES; ++tx_type) {
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002581 RD_STATS this_rd_stats;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002582 if (!is_inter && x->use_default_intra_tx_type &&
2583 tx_type != get_default_tx_type(0, xd, 0, mbmi->tx_size))
2584 continue;
2585 if (is_inter && x->use_default_inter_tx_type &&
2586 tx_type != get_default_tx_type(0, xd, 0, mbmi->tx_size))
2587 continue;
2588 mbmi->tx_type = tx_type;
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002589 txfm_rd_in_plane(x, cpi, &this_rd_stats, ref_best_rd, 0, bs,
Yaowu Xuc27fc142016-08-22 16:08:15 -07002590 mbmi->tx_size, cpi->sf.use_fast_coef_costing);
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002591 if (this_rd_stats.rate == INT_MAX) continue;
Angie Chiangaa0c34b2017-04-25 12:25:38 -07002592
Yue Chenb23d00a2017-07-28 17:01:21 -07002593 av1_tx_type_cost(cm, x, xd, bs, plane, mbmi->tx_size, tx_type);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002594 if (is_inter) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07002595 if (cpi->sf.tx_type_search.prune_mode > NO_PRUNE &&
2596 !do_tx_type_search(tx_type, prune))
2597 continue;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002598 }
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002599 if (this_rd_stats.skip)
Urvang Joshi70006e42017-06-14 16:08:55 -07002600 this_rd = RDCOST(x->rdmult, s1, this_rd_stats.sse);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002601 else
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002602 this_rd =
Urvang Joshi70006e42017-06-14 16:08:55 -07002603 RDCOST(x->rdmult, this_rd_stats.rate + s0, this_rd_stats.dist);
2604 if (is_inter && !xd->lossless[mbmi->segment_id] && !this_rd_stats.skip)
2605 this_rd = AOMMIN(this_rd, RDCOST(x->rdmult, s1, this_rd_stats.sse));
Yaowu Xuc27fc142016-08-22 16:08:15 -07002606
2607 if (this_rd < best_rd) {
2608 best_rd = this_rd;
2609 best_tx_type = mbmi->tx_type;
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002610 *rd_stats = this_rd_stats;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002611 }
2612 }
Guillaume Martres4e4d3a02016-08-21 19:02:33 -07002613 } else {
2614 mbmi->tx_type = DCT_DCT;
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002615 txfm_rd_in_plane(x, cpi, rd_stats, ref_best_rd, 0, bs, mbmi->tx_size,
2616 cpi->sf.use_fast_coef_costing);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002617 }
2618#endif // CONFIG_EXT_TX
2619 mbmi->tx_type = best_tx_type;
Lester Lu432012f2017-08-17 14:39:29 -07002620#if CONFIG_LGT_FROM_PRED
2621 mbmi->use_lgt = is_lgt_best;
2622#endif // CONFIG_LGT_FROM_PRED
Yaowu Xuc27fc142016-08-22 16:08:15 -07002623}
2624
Urvang Joshi52648442016-10-13 17:27:51 -07002625static void choose_smallest_tx_size(const AV1_COMP *const cpi, MACROBLOCK *x,
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002626 RD_STATS *rd_stats, int64_t ref_best_rd,
Yaowu Xuc27fc142016-08-22 16:08:15 -07002627 BLOCK_SIZE bs) {
2628 MACROBLOCKD *const xd = &x->e_mbd;
2629 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
2630
2631 mbmi->tx_size = TX_4X4;
2632 mbmi->tx_type = DCT_DCT;
Jingning Hane67b38a2016-11-04 10:30:00 -07002633#if CONFIG_VAR_TX
2634 mbmi->min_tx_size = get_min_tx_size(TX_4X4);
Fergus Simpson4063a682017-02-28 16:52:22 -08002635#endif // CONFIG_VAR_TX
Yaowu Xuc27fc142016-08-22 16:08:15 -07002636
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002637 txfm_rd_in_plane(x, cpi, rd_stats, ref_best_rd, 0, bs, mbmi->tx_size,
2638 cpi->sf.use_fast_coef_costing);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002639}
2640
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002641#if CONFIG_TXK_SEL || CONFIG_VAR_TX
Angie Chiangf1cb0752017-04-10 16:01:20 -07002642static INLINE int bsize_to_num_blk(BLOCK_SIZE bsize) {
2643 int num_blk = 1 << (num_pels_log2_lookup[bsize] - 2 * tx_size_wide_log2[0]);
2644 return num_blk;
2645}
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002646#endif // CONFIG_TXK_SEL || CONFIG_VAR_TX
Angie Chiangf1cb0752017-04-10 16:01:20 -07002647
Urvang Joshi52648442016-10-13 17:27:51 -07002648static void choose_tx_size_type_from_rd(const AV1_COMP *const cpi,
Angie Chiang7c2b7f22016-11-07 16:00:00 -08002649 MACROBLOCK *x, RD_STATS *rd_stats,
2650 int64_t ref_best_rd, BLOCK_SIZE bs) {
Angie Chianga4fa1902017-04-05 15:26:09 -07002651 const AV1_COMMON *const cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002652 MACROBLOCKD *const xd = &x->e_mbd;
2653 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002654 int64_t rd = INT64_MAX;
Angie Chianga4fa1902017-04-05 15:26:09 -07002655 int n;
2656 int start_tx, end_tx;
2657 int64_t best_rd = INT64_MAX, last_rd = INT64_MAX;
2658 const TX_SIZE max_tx_size = max_txsize_lookup[bs];
2659 TX_SIZE best_tx_size = max_tx_size;
2660 TX_TYPE best_tx_type = DCT_DCT;
Lester Lu432012f2017-08-17 14:39:29 -07002661#if CONFIG_LGT_FROM_PRED
2662 int breakout = 0;
2663 int is_lgt_best = 0;
2664 mbmi->use_lgt = 0;
2665#endif // CONFIG_LGT_FROM_PRED
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002666#if CONFIG_TXK_SEL
Angie Chiangf1cb0752017-04-10 16:01:20 -07002667 TX_TYPE best_txk_type[MAX_SB_SQUARE / (TX_SIZE_W_MIN * TX_SIZE_H_MIN)];
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002668#endif // CONFIG_TXK_SEL
Angie Chianga4fa1902017-04-05 15:26:09 -07002669 const int tx_select = cm->tx_mode == TX_MODE_SELECT;
2670 const int is_inter = is_inter_block(mbmi);
Yushin Cho77bba8d2016-11-04 16:36:56 -07002671#if CONFIG_PVQ
2672 od_rollback_buffer buf;
Yushin Cho77bba8d2016-11-04 16:36:56 -07002673 od_encode_checkpoint(&x->daala_enc, &buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08002674#endif // CONFIG_PVQ
Angie Chianga4fa1902017-04-05 15:26:09 -07002675
2676 av1_invalid_rd_stats(rd_stats);
2677
2678#if CONFIG_EXT_TX && CONFIG_RECT_TX
2679 int evaluate_rect_tx = 0;
2680 if (tx_select) {
2681 evaluate_rect_tx = is_rect_tx_allowed(xd, mbmi);
2682 } else {
2683 const TX_SIZE chosen_tx_size =
2684 tx_size_from_tx_mode(bs, cm->tx_mode, is_inter);
2685 evaluate_rect_tx = is_rect_tx(chosen_tx_size);
2686 assert(IMPLIES(evaluate_rect_tx, is_rect_tx_allowed(xd, mbmi)));
2687 }
2688 if (evaluate_rect_tx) {
Angie Chiangf1cb0752017-04-10 16:01:20 -07002689 TX_TYPE tx_start = DCT_DCT;
2690 TX_TYPE tx_end = TX_TYPES;
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002691#if CONFIG_TXK_SEL
Angie Chiangf1cb0752017-04-10 16:01:20 -07002692 // The tx_type becomes dummy when lv_map is on. The tx_type search will be
2693 // performed in av1_search_txk_type()
2694 tx_end = DCT_DCT + 1;
2695#endif
Angie Chianga4fa1902017-04-05 15:26:09 -07002696 TX_TYPE tx_type;
Angie Chiangf1cb0752017-04-10 16:01:20 -07002697 for (tx_type = tx_start; tx_type < tx_end; ++tx_type) {
Angie Chianga4fa1902017-04-05 15:26:09 -07002698 if (mbmi->ref_mv_idx > 0 && tx_type != DCT_DCT) continue;
Angie Chianga4fa1902017-04-05 15:26:09 -07002699 const TX_SIZE rect_tx_size = max_txsize_rect_lookup[bs];
2700 RD_STATS this_rd_stats;
Hui Suddbcde22017-09-18 17:22:02 -07002701 const TxSetType tx_set_type = get_ext_tx_set_type(
2702 rect_tx_size, bs, is_inter, cm->reduced_tx_set_used);
2703 if (av1_ext_tx_used[tx_set_type][tx_type]) {
Angie Chianga4fa1902017-04-05 15:26:09 -07002704 rd = txfm_yrd(cpi, x, &this_rd_stats, ref_best_rd, bs, tx_type,
2705 rect_tx_size);
Hui Suda816a12017-08-18 14:46:02 -07002706 ref_best_rd = AOMMIN(rd, ref_best_rd);
Angie Chianga4fa1902017-04-05 15:26:09 -07002707 if (rd < best_rd) {
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002708#if CONFIG_TXK_SEL
Jingning Han19b5c8f2017-07-06 15:10:12 -07002709 memcpy(best_txk_type, mbmi->txk_type, sizeof(best_txk_type[0]) * 256);
Angie Chiangf1cb0752017-04-10 16:01:20 -07002710#endif
Angie Chianga4fa1902017-04-05 15:26:09 -07002711 best_tx_type = tx_type;
2712 best_tx_size = rect_tx_size;
2713 best_rd = rd;
2714 *rd_stats = this_rd_stats;
2715 }
2716 }
Debargha Mukherjee094c9432017-02-22 10:31:25 -08002717#if CONFIG_CB4X4 && !USE_TXTYPE_SEARCH_FOR_SUB8X8_IN_CB4X4
Angie Chianga4fa1902017-04-05 15:26:09 -07002718 const int is_inter = is_inter_block(mbmi);
2719 if (mbmi->sb_type < BLOCK_8X8 && is_inter) break;
Fergus Simpson4063a682017-02-28 16:52:22 -08002720#endif // CONFIG_CB4X4 && !USE_TXTYPE_SEARCH_FOR_SUB8X8_IN_CB4X4
Angie Chianga4fa1902017-04-05 15:26:09 -07002721 }
Lester Lu432012f2017-08-17 14:39:29 -07002722#if CONFIG_LGT_FROM_PRED
2723 const TX_SIZE rect_tx_size = max_txsize_rect_lookup[bs];
2724 if (is_lgt_allowed(mbmi->mode, rect_tx_size) && !cm->reduced_tx_set_used) {
2725 RD_STATS this_rd_stats;
2726 mbmi->use_lgt = 1;
2727 rd = txfm_yrd(cpi, x, &this_rd_stats, ref_best_rd, bs, 0, rect_tx_size);
2728 if (rd < best_rd) {
2729 is_lgt_best = 1;
2730 best_tx_size = rect_tx_size;
2731 best_rd = rd;
2732 *rd_stats = this_rd_stats;
2733 }
2734 mbmi->use_lgt = 0;
2735 }
2736#endif // CONFIG_LGT_FROM_PRED
Angie Chianga4fa1902017-04-05 15:26:09 -07002737 }
Yue Chen56e226e2017-05-02 16:21:40 -07002738
2739#if CONFIG_RECT_TX_EXT
2740 // test 1:4/4:1 tx
2741 int evaluate_quarter_tx = 0;
2742 if (is_quarter_tx_allowed(xd, mbmi, is_inter)) {
2743 if (tx_select) {
2744 evaluate_quarter_tx = 1;
2745 } else {
2746 const TX_SIZE chosen_tx_size =
2747 tx_size_from_tx_mode(bs, cm->tx_mode, is_inter);
2748 evaluate_quarter_tx = chosen_tx_size == quarter_txsize_lookup[bs];
2749 }
2750 }
2751 if (evaluate_quarter_tx) {
2752 TX_TYPE tx_start = DCT_DCT;
2753 TX_TYPE tx_end = TX_TYPES;
2754#if CONFIG_TXK_SEL
2755 // The tx_type becomes dummy when lv_map is on. The tx_type search will be
2756 // performed in av1_search_txk_type()
2757 tx_end = DCT_DCT + 1;
2758#endif
2759 TX_TYPE tx_type;
2760 for (tx_type = tx_start; tx_type < tx_end; ++tx_type) {
2761 if (mbmi->ref_mv_idx > 0 && tx_type != DCT_DCT) continue;
2762 const TX_SIZE tx_size = quarter_txsize_lookup[bs];
2763 RD_STATS this_rd_stats;
Hui Suddbcde22017-09-18 17:22:02 -07002764 const TxSetType tx_set_type =
2765 get_ext_tx_set_type(tx_size, bs, is_inter, cm->reduced_tx_set_used);
2766 if (av1_ext_tx_used[tx_set_type][tx_type]) {
Yue Chen56e226e2017-05-02 16:21:40 -07002767 rd =
2768 txfm_yrd(cpi, x, &this_rd_stats, ref_best_rd, bs, tx_type, tx_size);
2769 if (rd < best_rd) {
2770#if CONFIG_TXK_SEL
2771 memcpy(best_txk_type, mbmi->txk_type,
2772 sizeof(best_txk_type[0]) * num_blk);
2773#endif
2774 best_tx_type = tx_type;
Lester Lu432012f2017-08-17 14:39:29 -07002775#if CONFIG_LGT_FROM_PRED
2776 is_lgt_best = 0;
2777#endif
Yue Chen56e226e2017-05-02 16:21:40 -07002778 best_tx_size = tx_size;
2779 best_rd = rd;
2780 *rd_stats = this_rd_stats;
2781 }
2782 }
2783#if CONFIG_CB4X4 && !USE_TXTYPE_SEARCH_FOR_SUB8X8_IN_CB4X4
2784 const int is_inter = is_inter_block(mbmi);
2785 if (mbmi->sb_type < BLOCK_8X8 && is_inter) break;
2786#endif // CONFIG_CB4X4 && !USE_TXTYPE_SEARCH_FOR_SUB8X8_IN_CB4X4
2787 }
Lester Lu432012f2017-08-17 14:39:29 -07002788#if CONFIG_LGT_FROM_PRED
2789 if (is_lgt_allowed(mbmi->mode, tx_size) && !cm->reduced_tx_set_used) {
2790 const TX_SIZE tx_size = quarter_txsize_lookup[bs];
2791 RD_STATS this_rd_stats;
2792 mbmi->use_lgt = 1;
2793 rd = txfm_yrd(cpi, x, &this_rd_stats, ref_best_rd, bs, 0, tx_size);
2794 if (rd < best_rd) {
2795 is_lgt_best = 1;
2796 best_tx_size = tx_size;
2797 best_rd = rd;
2798 *rd_stats = this_rd_stats;
2799 }
2800 mbmi->use_lgt = 0;
2801 }
2802#endif // CONFIG_LGT_FROM_PRED
Yue Chen56e226e2017-05-02 16:21:40 -07002803 }
2804#endif // CONFIG_RECT_TX_EXT
Angie Chianga4fa1902017-04-05 15:26:09 -07002805#endif // CONFIG_EXT_TX && CONFIG_RECT_TX
2806
2807 if (tx_select) {
2808 start_tx = max_tx_size;
2809 end_tx = (max_tx_size >= TX_32X32) ? TX_8X8 : TX_4X4;
2810 } else {
2811 const TX_SIZE chosen_tx_size =
2812 tx_size_from_tx_mode(bs, cm->tx_mode, is_inter);
2813 start_tx = chosen_tx_size;
2814 end_tx = chosen_tx_size;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002815 }
2816
Angie Chianga4fa1902017-04-05 15:26:09 -07002817 last_rd = INT64_MAX;
2818 for (n = start_tx; n >= end_tx; --n) {
Sarah Parker36661922017-04-13 14:26:49 -07002819#if CONFIG_EXT_TX && CONFIG_RECT_TX
2820 if (is_rect_tx(n)) break;
2821#endif // CONFIG_EXT_TX && CONFIG_RECT_TX
Angie Chiangf1cb0752017-04-10 16:01:20 -07002822 TX_TYPE tx_start = DCT_DCT;
2823 TX_TYPE tx_end = TX_TYPES;
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002824#if CONFIG_TXK_SEL
Angie Chiangf1cb0752017-04-10 16:01:20 -07002825 // The tx_type becomes dummy when lv_map is on. The tx_type search will be
2826 // performed in av1_search_txk_type()
2827 tx_end = DCT_DCT + 1;
2828#endif
Angie Chianga4fa1902017-04-05 15:26:09 -07002829 TX_TYPE tx_type;
Angie Chiangf1cb0752017-04-10 16:01:20 -07002830 for (tx_type = tx_start; tx_type < tx_end; ++tx_type) {
Angie Chianga4fa1902017-04-05 15:26:09 -07002831 RD_STATS this_rd_stats;
2832 if (skip_txfm_search(cpi, x, bs, tx_type, n)) continue;
2833 rd = txfm_yrd(cpi, x, &this_rd_stats, ref_best_rd, bs, tx_type, n);
2834#if CONFIG_PVQ
2835 od_encode_rollback(&x->daala_enc, &buf);
2836#endif // CONFIG_PVQ
2837 // Early termination in transform size search.
2838 if (cpi->sf.tx_size_search_breakout &&
2839 (rd == INT64_MAX ||
2840 (this_rd_stats.skip == 1 && tx_type != DCT_DCT && n < start_tx) ||
Lester Lu432012f2017-08-17 14:39:29 -07002841 (n < (int)max_tx_size && rd > last_rd))) {
2842#if CONFIG_LGT_FROM_PRED
2843 breakout = 1;
2844#endif
Angie Chianga4fa1902017-04-05 15:26:09 -07002845 break;
Lester Lu432012f2017-08-17 14:39:29 -07002846 }
Angie Chianga4fa1902017-04-05 15:26:09 -07002847
2848 last_rd = rd;
Hui Suda816a12017-08-18 14:46:02 -07002849 ref_best_rd = AOMMIN(rd, ref_best_rd);
Angie Chianga4fa1902017-04-05 15:26:09 -07002850 if (rd < best_rd) {
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002851#if CONFIG_TXK_SEL
Jingning Han19b5c8f2017-07-06 15:10:12 -07002852 memcpy(best_txk_type, mbmi->txk_type, sizeof(best_txk_type[0]) * 256);
Angie Chiangf1cb0752017-04-10 16:01:20 -07002853#endif
Angie Chianga4fa1902017-04-05 15:26:09 -07002854 best_tx_type = tx_type;
Lester Lu432012f2017-08-17 14:39:29 -07002855#if CONFIG_LGT_FROM_PRED
2856 is_lgt_best = 0;
2857#endif
Angie Chianga4fa1902017-04-05 15:26:09 -07002858 best_tx_size = n;
2859 best_rd = rd;
2860 *rd_stats = this_rd_stats;
2861 }
2862#if CONFIG_CB4X4 && !USE_TXTYPE_SEARCH_FOR_SUB8X8_IN_CB4X4
2863 const int is_inter = is_inter_block(mbmi);
2864 if (mbmi->sb_type < BLOCK_8X8 && is_inter) break;
2865#endif // CONFIG_CB4X4 && !USE_TXTYPE_SEARCH_FOR_SUB8X8_IN_CB4X4
2866 }
Lester Lu432012f2017-08-17 14:39:29 -07002867#if CONFIG_LGT_FROM_PRED
2868 mbmi->use_lgt = 1;
2869 if (is_lgt_allowed(mbmi->mode, n) && !skip_txfm_search(cpi, x, bs, 0, n) &&
2870 !breakout) {
2871 RD_STATS this_rd_stats;
2872 rd = txfm_yrd(cpi, x, &this_rd_stats, ref_best_rd, bs, 0, n);
2873 if (rd < best_rd) {
2874 is_lgt_best = 1;
2875 best_tx_size = n;
2876 best_rd = rd;
2877 *rd_stats = this_rd_stats;
2878 }
2879 }
2880 mbmi->use_lgt = 0;
2881#endif // CONFIG_LGT_FROM_PRED
Angie Chianga4fa1902017-04-05 15:26:09 -07002882 }
2883 mbmi->tx_size = best_tx_size;
Yaowu Xuc27fc142016-08-22 16:08:15 -07002884 mbmi->tx_type = best_tx_type;
Lester Lu432012f2017-08-17 14:39:29 -07002885#if CONFIG_LGT_FROM_PRED
2886 mbmi->use_lgt = is_lgt_best;
2887 assert(!is_lgt_best || is_lgt_allowed(mbmi->mode, mbmi->tx_size));
2888#endif // CONFIG_LGT_FROM_PRED
Angie Chiangcd9b03f2017-04-16 13:37:13 -07002889#if CONFIG_TXK_SEL
Jingning Han19b5c8f2017-07-06 15:10:12 -07002890 memcpy(mbmi->txk_type, best_txk_type, sizeof(best_txk_type[0]) * 256);
Angie Chiangf1cb0752017-04-10 16:01:20 -07002891#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07002892
Jingning Hane67b38a2016-11-04 10:30:00 -07002893#if CONFIG_VAR_TX
2894 mbmi->min_tx_size = get_min_tx_size(mbmi->tx_size);
Fergus Simpson4063a682017-02-28 16:52:22 -08002895#endif // CONFIG_VAR_TX
Jingning Hane67b38a2016-11-04 10:30:00 -07002896
Yaowu Xuc27fc142016-08-22 16:08:15 -07002897#if !CONFIG_EXT_TX
2898 if (mbmi->tx_size >= TX_32X32) assert(mbmi->tx_type == DCT_DCT);
Fergus Simpson4063a682017-02-28 16:52:22 -08002899#endif // !CONFIG_EXT_TX
Yushin Cho77bba8d2016-11-04 16:36:56 -07002900#if CONFIG_PVQ
Yushin Cho403618e2016-11-09 10:45:32 -08002901 if (best_rd != INT64_MAX) {
Angie Chianga4fa1902017-04-05 15:26:09 -07002902 txfm_yrd(cpi, x, rd_stats, ref_best_rd, bs, best_tx_type, best_tx_size);
Yushin Cho05f540a2016-11-08 22:12:51 -08002903 }
Fergus Simpson4063a682017-02-28 16:52:22 -08002904#endif // CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -07002905}
2906
Angie Chiang0e9a2e92016-11-08 09:45:40 -08002907static void super_block_yrd(const AV1_COMP *const cpi, MACROBLOCK *x,
2908 RD_STATS *rd_stats, BLOCK_SIZE bs,
2909 int64_t ref_best_rd) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07002910 MACROBLOCKD *xd = &x->e_mbd;
Angie Chiang0e9a2e92016-11-08 09:45:40 -08002911 av1_init_rd_stats(rd_stats);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002912
2913 assert(bs == xd->mi[0]->mbmi.sb_type);
2914
Yaowu Xu1e2aae12017-02-27 16:33:14 -08002915 if (xd->lossless[xd->mi[0]->mbmi.segment_id]) {
Angie Chiang0e9a2e92016-11-08 09:45:40 -08002916 choose_smallest_tx_size(cpi, x, rd_stats, ref_best_rd, bs);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002917 } else if (cpi->sf.tx_size_search_method == USE_LARGESTALL) {
Angie Chiang0e9a2e92016-11-08 09:45:40 -08002918 choose_largest_tx_size(cpi, x, rd_stats, ref_best_rd, bs);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002919 } else {
Angie Chiang0e9a2e92016-11-08 09:45:40 -08002920 choose_tx_size_type_from_rd(cpi, x, rd_stats, ref_best_rd, bs);
Yaowu Xuc27fc142016-08-22 16:08:15 -07002921 }
2922}
2923
2924static int conditional_skipintra(PREDICTION_MODE mode,
2925 PREDICTION_MODE best_intra_mode) {
2926 if (mode == D117_PRED && best_intra_mode != V_PRED &&
2927 best_intra_mode != D135_PRED)
2928 return 1;
2929 if (mode == D63_PRED && best_intra_mode != V_PRED &&
2930 best_intra_mode != D45_PRED)
2931 return 1;
2932 if (mode == D207_PRED && best_intra_mode != H_PRED &&
2933 best_intra_mode != D45_PRED)
2934 return 1;
2935 if (mode == D153_PRED && best_intra_mode != H_PRED &&
2936 best_intra_mode != D135_PRED)
2937 return 1;
2938 return 0;
2939}
2940
hui su308a6392017-01-12 14:49:57 -08002941// Model based RD estimation for luma intra blocks.
2942static int64_t intra_model_yrd(const AV1_COMP *const cpi, MACROBLOCK *const x,
hui su9a416f52017-01-13 11:37:53 -08002943 BLOCK_SIZE bsize, int mode_cost) {
David Barker761b1ac2017-09-25 11:23:03 +01002944 const AV1_COMMON *cm = &cpi->common;
hui su308a6392017-01-12 14:49:57 -08002945 MACROBLOCKD *const xd = &x->e_mbd;
2946 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Urvang Joshi330aec82017-05-08 15:37:42 -07002947 assert(!is_inter_block(mbmi));
hui su308a6392017-01-12 14:49:57 -08002948 RD_STATS this_rd_stats;
2949 int row, col;
2950 int64_t temp_sse, this_rd;
2951 const TX_SIZE tx_size = tx_size_from_tx_mode(bsize, cpi->common.tx_mode, 0);
2952 const int stepr = tx_size_high_unit[tx_size];
2953 const int stepc = tx_size_wide_unit[tx_size];
2954 const int max_blocks_wide = max_block_wide(xd, bsize, 0);
2955 const int max_blocks_high = max_block_high(xd, bsize, 0);
2956 mbmi->tx_size = tx_size;
2957 // Prediction.
Angie Chiang3d005e42017-04-02 16:31:35 -07002958 const int step = stepr * stepc;
2959 int block = 0;
hui su308a6392017-01-12 14:49:57 -08002960 for (row = 0; row < max_blocks_high; row += stepr) {
2961 for (col = 0; col < max_blocks_wide; col += stepc) {
David Barker761b1ac2017-09-25 11:23:03 +01002962 av1_predict_intra_block_facade(cm, xd, 0, block, col, row, tx_size);
Angie Chiang3d005e42017-04-02 16:31:35 -07002963 block += step;
hui su308a6392017-01-12 14:49:57 -08002964 }
2965 }
2966 // RD estimation.
2967 model_rd_for_sb(cpi, bsize, x, xd, 0, 0, &this_rd_stats.rate,
2968 &this_rd_stats.dist, &this_rd_stats.skip, &temp_sse);
hui su9a416f52017-01-13 11:37:53 -08002969#if CONFIG_EXT_INTRA
Joe Young830d4ce2017-05-30 17:48:13 -07002970 if (av1_is_directional_mode(mbmi->mode, bsize) &&
2971 av1_use_angle_delta(bsize)) {
hui su0a6731f2017-04-26 15:23:47 -07002972 mode_cost += write_uniform_cost(2 * MAX_ANGLE_DELTA + 1,
2973 MAX_ANGLE_DELTA + mbmi->angle_delta[0]);
hui su9a416f52017-01-13 11:37:53 -08002974 }
2975#endif // CONFIG_EXT_INTRA
hui su8f4cc0a2017-01-13 15:14:49 -08002976#if CONFIG_FILTER_INTRA
2977 if (mbmi->mode == DC_PRED) {
2978 const aom_prob prob = cpi->common.fc->filter_intra_probs[0];
2979 if (mbmi->filter_intra_mode_info.use_filter_intra_mode[0]) {
2980 const int mode = mbmi->filter_intra_mode_info.filter_intra_mode[0];
2981 mode_cost += (av1_cost_bit(prob, 1) +
2982 write_uniform_cost(FILTER_INTRA_MODES, mode));
2983 } else {
2984 mode_cost += av1_cost_bit(prob, 0);
2985 }
2986 }
2987#endif // CONFIG_FILTER_INTRA
Urvang Joshi70006e42017-06-14 16:08:55 -07002988 this_rd =
2989 RDCOST(x->rdmult, this_rd_stats.rate + mode_cost, this_rd_stats.dist);
hui su308a6392017-01-12 14:49:57 -08002990 return this_rd;
2991}
2992
Urvang Joshi56ba91b2017-01-10 13:22:09 -08002993// Extends 'color_map' array from 'orig_width x orig_height' to 'new_width x
2994// new_height'. Extra rows and columns are filled in by copying last valid
2995// row/column.
2996static void extend_palette_color_map(uint8_t *const color_map, int orig_width,
2997 int orig_height, int new_width,
2998 int new_height) {
2999 int j;
3000 assert(new_width >= orig_width);
3001 assert(new_height >= orig_height);
3002 if (new_width == orig_width && new_height == orig_height) return;
3003
3004 for (j = orig_height - 1; j >= 0; --j) {
3005 memmove(color_map + j * new_width, color_map + j * orig_width, orig_width);
3006 // Copy last column to extra columns.
3007 memset(color_map + j * new_width + orig_width,
3008 color_map[j * new_width + orig_width - 1], new_width - orig_width);
3009 }
3010 // Copy last row to extra rows.
3011 for (j = orig_height; j < new_height; ++j) {
3012 memcpy(color_map + j * new_width, color_map + (orig_height - 1) * new_width,
3013 new_width);
3014 }
3015}
3016
hui su33567b22017-04-30 16:40:19 -07003017#if CONFIG_PALETTE_DELTA_ENCODING
3018// Bias toward using colors in the cache.
3019// TODO(huisu): Try other schemes to improve compression.
3020static void optimize_palette_colors(uint16_t *color_cache, int n_cache,
3021 int n_colors, int stride,
3022 float *centroids) {
3023 if (n_cache <= 0) return;
3024 for (int i = 0; i < n_colors * stride; i += stride) {
3025 float min_diff = fabsf(centroids[i] - color_cache[0]);
3026 int idx = 0;
3027 for (int j = 1; j < n_cache; ++j) {
3028 float this_diff = fabsf(centroids[i] - color_cache[j]);
3029 if (this_diff < min_diff) {
3030 min_diff = this_diff;
3031 idx = j;
3032 }
3033 }
3034 if (min_diff < 1.5) centroids[i] = color_cache[idx];
3035 }
3036}
3037#endif // CONFIG_PALETTE_DELTA_ENCODING
3038
hui sude0c70a2017-01-09 17:12:17 -08003039static int rd_pick_palette_intra_sby(const AV1_COMP *const cpi, MACROBLOCK *x,
3040 BLOCK_SIZE bsize, int palette_ctx,
3041 int dc_mode_cost, MB_MODE_INFO *best_mbmi,
3042 uint8_t *best_palette_color_map,
hui su78c611a2017-01-13 17:06:04 -08003043 int64_t *best_rd, int64_t *best_model_rd,
3044 int *rate, int *rate_tokenonly,
3045 int64_t *distortion, int *skippable) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07003046 int rate_overhead = 0;
3047 MACROBLOCKD *const xd = &x->e_mbd;
3048 MODE_INFO *const mic = xd->mi[0];
hui sude0c70a2017-01-09 17:12:17 -08003049 MB_MODE_INFO *const mbmi = &mic->mbmi;
Urvang Joshi330aec82017-05-08 15:37:42 -07003050 assert(!is_inter_block(mbmi));
Urvang Joshic9e71d42017-08-09 18:58:33 -07003051 assert(bsize >= BLOCK_8X8);
Angie Chiang0e9a2e92016-11-08 09:45:40 -08003052 int this_rate, colors, n;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003053 const int src_stride = x->plane[0].src.stride;
3054 const uint8_t *const src = x->plane[0].src.buf;
hui sude0c70a2017-01-09 17:12:17 -08003055 uint8_t *const color_map = xd->plane[0].color_index_map;
Urvang Joshi56ba91b2017-01-10 13:22:09 -08003056 int block_width, block_height, rows, cols;
3057 av1_get_block_dimensions(bsize, 0, xd, &block_width, &block_height, &rows,
3058 &cols);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003059
3060 assert(cpi->common.allow_screen_content_tools);
3061
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02003062#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07003063 if (cpi->common.use_highbitdepth)
Yaowu Xuf883b422016-08-30 14:01:10 -07003064 colors = av1_count_colors_highbd(src, src_stride, rows, cols,
3065 cpi->common.bit_depth);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003066 else
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02003067#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuf883b422016-08-30 14:01:10 -07003068 colors = av1_count_colors(src, src_stride, rows, cols);
hui su5db97432016-10-14 16:10:14 -07003069#if CONFIG_FILTER_INTRA
hui sude0c70a2017-01-09 17:12:17 -08003070 mbmi->filter_intra_mode_info.use_filter_intra_mode[0] = 0;
hui su5db97432016-10-14 16:10:14 -07003071#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07003072
3073 if (colors > 1 && colors <= 64) {
Sarah Parker9c0e4512017-08-15 16:23:53 -07003074 int r, c, i, k, palette_mode_cost;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003075 const int max_itr = 50;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003076 float *const data = x->palette_buffer->kmeans_data_buf;
3077 float centroids[PALETTE_MAX_SIZE];
Yaowu Xuc27fc142016-08-22 16:08:15 -07003078 float lb, ub, val;
hui su78c611a2017-01-13 17:06:04 -08003079 RD_STATS tokenonly_rd_stats;
3080 int64_t this_rd, this_model_rd;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003081 PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02003082#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07003083 uint16_t *src16 = CONVERT_TO_SHORTPTR(src);
3084 if (cpi->common.use_highbitdepth)
3085 lb = ub = src16[0];
3086 else
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02003087#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07003088 lb = ub = src[0];
3089
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02003090#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07003091 if (cpi->common.use_highbitdepth) {
3092 for (r = 0; r < rows; ++r) {
3093 for (c = 0; c < cols; ++c) {
3094 val = src16[r * src_stride + c];
3095 data[r * cols + c] = val;
3096 if (val < lb)
3097 lb = val;
3098 else if (val > ub)
3099 ub = val;
3100 }
3101 }
3102 } else {
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02003103#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07003104 for (r = 0; r < rows; ++r) {
3105 for (c = 0; c < cols; ++c) {
3106 val = src[r * src_stride + c];
3107 data[r * cols + c] = val;
3108 if (val < lb)
3109 lb = val;
3110 else if (val > ub)
3111 ub = val;
3112 }
3113 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02003114#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07003115 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02003116#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07003117
3118 mbmi->mode = DC_PRED;
hui su5db97432016-10-14 16:10:14 -07003119#if CONFIG_FILTER_INTRA
3120 mbmi->filter_intra_mode_info.use_filter_intra_mode[0] = 0;
3121#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07003122
3123 if (rows * cols > PALETTE_MAX_BLOCK_SIZE) return 0;
3124
hui su33567b22017-04-30 16:40:19 -07003125#if CONFIG_PALETTE_DELTA_ENCODING
hui su33567b22017-04-30 16:40:19 -07003126 uint16_t color_cache[2 * PALETTE_MAX_SIZE];
Hui Su3748bc22017-08-23 11:30:41 -07003127 const int n_cache = av1_get_palette_cache(xd, 0, color_cache);
hui su33567b22017-04-30 16:40:19 -07003128#endif // CONFIG_PALETTE_DELTA_ENCODING
3129
Yaowu Xuc27fc142016-08-22 16:08:15 -07003130 for (n = colors > PALETTE_MAX_SIZE ? PALETTE_MAX_SIZE : colors; n >= 2;
3131 --n) {
Urvang Joshi773e3542017-05-05 18:09:42 -07003132 if (colors == PALETTE_MIN_SIZE) {
3133 // Special case: These colors automatically become the centroids.
3134 assert(colors == n);
3135 assert(colors == 2);
3136 centroids[0] = lb;
3137 centroids[1] = ub;
3138 k = 2;
3139 } else {
3140 for (i = 0; i < n; ++i) {
3141 centroids[i] = lb + (2 * i + 1) * (ub - lb) / n / 2;
3142 }
3143 av1_k_means(data, centroids, color_map, rows * cols, n, 1, max_itr);
hui su33567b22017-04-30 16:40:19 -07003144#if CONFIG_PALETTE_DELTA_ENCODING
3145 optimize_palette_colors(color_cache, n_cache, n, 1, centroids);
3146#endif // CONFIG_PALETTE_DELTA_ENCODING
Urvang Joshi773e3542017-05-05 18:09:42 -07003147 k = av1_remove_duplicates(centroids, n);
3148 if (k < PALETTE_MIN_SIZE) {
3149 // Too few unique colors to create a palette. And DC_PRED will work
3150 // well for that case anyway. So skip.
3151 continue;
3152 }
Urvang Joshi5fb95f72017-05-05 17:36:16 -07003153 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07003154
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02003155#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07003156 if (cpi->common.use_highbitdepth)
3157 for (i = 0; i < k; ++i)
3158 pmi->palette_colors[i] =
3159 clip_pixel_highbd((int)centroids[i], cpi->common.bit_depth);
3160 else
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02003161#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07003162 for (i = 0; i < k; ++i)
3163 pmi->palette_colors[i] = clip_pixel((int)centroids[i]);
3164 pmi->palette_size[0] = k;
3165
Yaowu Xuf883b422016-08-30 14:01:10 -07003166 av1_calc_indices(data, centroids, color_map, rows * cols, k, 1);
Urvang Joshi56ba91b2017-01-10 13:22:09 -08003167 extend_palette_color_map(color_map, cols, rows, block_width,
3168 block_height);
hui su78c611a2017-01-13 17:06:04 -08003169 palette_mode_cost =
hui sud13c24a2017-04-07 16:13:07 -07003170 dc_mode_cost +
Yue Chenb23d00a2017-07-28 17:01:21 -07003171 x->palette_y_size_cost[bsize - BLOCK_8X8][k - PALETTE_MIN_SIZE] +
Yaowu Xuc27fc142016-08-22 16:08:15 -07003172 write_uniform_cost(k, color_map[0]) +
Yaowu Xuf883b422016-08-30 14:01:10 -07003173 av1_cost_bit(
3174 av1_default_palette_y_mode_prob[bsize - BLOCK_8X8][palette_ctx],
Yaowu Xuc27fc142016-08-22 16:08:15 -07003175 1);
hui su33567b22017-04-30 16:40:19 -07003176 palette_mode_cost += av1_palette_color_cost_y(pmi,
3177#if CONFIG_PALETTE_DELTA_ENCODING
3178 color_cache, n_cache,
3179#endif // CONFIG_PALETTE_DELTA_ENCODING
3180 cpi->common.bit_depth);
Sarah Parker99e7daa2017-08-29 10:30:13 -07003181 palette_mode_cost +=
3182 av1_cost_color_map(x, 0, 0, bsize, mbmi->tx_size, PALETTE_MAP);
hui su78c611a2017-01-13 17:06:04 -08003183 this_model_rd = intra_model_yrd(cpi, x, bsize, palette_mode_cost);
3184 if (*best_model_rd != INT64_MAX &&
3185 this_model_rd > *best_model_rd + (*best_model_rd >> 1))
3186 continue;
3187 if (this_model_rd < *best_model_rd) *best_model_rd = this_model_rd;
3188 super_block_yrd(cpi, x, &tokenonly_rd_stats, bsize, *best_rd);
3189 if (tokenonly_rd_stats.rate == INT_MAX) continue;
3190 this_rate = tokenonly_rd_stats.rate + palette_mode_cost;
Urvang Joshi70006e42017-06-14 16:08:55 -07003191 this_rd = RDCOST(x->rdmult, this_rate, tokenonly_rd_stats.dist);
Rupert Swarbrickfcff0b22017-10-05 09:26:04 +01003192 if (!xd->lossless[mbmi->segment_id] &&
3193 block_signals_txsize(mbmi->sb_type)) {
Urvang Joshifeb925f2016-12-05 10:37:29 -08003194 tokenonly_rd_stats.rate -= tx_size_cost(cpi, x, bsize, mbmi->tx_size);
hui su8a630492017-01-10 18:22:41 -08003195 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07003196 if (this_rd < *best_rd) {
3197 *best_rd = this_rd;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003198 memcpy(best_palette_color_map, color_map,
Urvang Joshi56ba91b2017-01-10 13:22:09 -08003199 block_width * block_height * sizeof(color_map[0]));
hui sude0c70a2017-01-09 17:12:17 -08003200 *best_mbmi = *mbmi;
Angie Chiang0e9a2e92016-11-08 09:45:40 -08003201 rate_overhead = this_rate - tokenonly_rd_stats.rate;
hui su8a630492017-01-10 18:22:41 -08003202 if (rate) *rate = this_rate;
3203 if (rate_tokenonly) *rate_tokenonly = tokenonly_rd_stats.rate;
3204 if (distortion) *distortion = tokenonly_rd_stats.dist;
3205 if (skippable) *skippable = tokenonly_rd_stats.skip;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003206 }
3207 }
3208 }
hui sude0c70a2017-01-09 17:12:17 -08003209
3210 if (best_mbmi->palette_mode_info.palette_size[0] > 0) {
3211 memcpy(color_map, best_palette_color_map,
Luc Trudeau0401e892017-08-31 00:37:11 -04003212 block_width * block_height * sizeof(best_palette_color_map[0]));
hui sude0c70a2017-01-09 17:12:17 -08003213 }
3214 *mbmi = *best_mbmi;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003215 return rate_overhead;
3216}
3217
Urvang Joshifeb925f2016-12-05 10:37:29 -08003218static int64_t rd_pick_intra_sub_8x8_y_subblock_mode(
Urvang Joshi52648442016-10-13 17:27:51 -07003219 const AV1_COMP *const cpi, MACROBLOCK *x, int row, int col,
3220 PREDICTION_MODE *best_mode, const int *bmode_costs, ENTROPY_CONTEXT *a,
3221 ENTROPY_CONTEXT *l, int *bestrate, int *bestratey, int64_t *bestdistortion,
Urvang Joshifeb925f2016-12-05 10:37:29 -08003222 BLOCK_SIZE bsize, TX_SIZE tx_size, int *y_skip, int64_t rd_thresh) {
Angie Chiang22ba7512016-10-20 17:10:33 -07003223 const AV1_COMMON *const cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003224 PREDICTION_MODE mode;
3225 MACROBLOCKD *const xd = &x->e_mbd;
Urvang Joshi330aec82017-05-08 15:37:42 -07003226 assert(!is_inter_block(&xd->mi[0]->mbmi));
Yaowu Xuc27fc142016-08-22 16:08:15 -07003227 int64_t best_rd = rd_thresh;
3228 struct macroblock_plane *p = &x->plane[0];
3229 struct macroblockd_plane *pd = &xd->plane[0];
3230 const int src_stride = p->src.stride;
3231 const int dst_stride = pd->dst.stride;
3232 const uint8_t *src_init = &p->src.buf[row * 4 * src_stride + col * 4];
Yushin Cho1a2df5e2017-01-09 13:36:13 -08003233 uint8_t *dst_init = &pd->dst.buf[row * 4 * dst_stride + col * 4];
Timothy B. Terriberryfe67ed62017-04-26 16:53:47 -07003234#if CONFIG_CHROMA_2X2
Jingning Han276c2942016-12-05 12:37:02 -08003235 // TODO(jingning): This is a temporal change. The whole function should be
3236 // out when cb4x4 is enabled.
3237 ENTROPY_CONTEXT ta[4], tempa[4];
3238 ENTROPY_CONTEXT tl[4], templ[4];
3239#else
Yaowu Xuc27fc142016-08-22 16:08:15 -07003240 ENTROPY_CONTEXT ta[2], tempa[2];
3241 ENTROPY_CONTEXT tl[2], templ[2];
Timothy B. Terriberryfe67ed62017-04-26 16:53:47 -07003242#endif // CONFIG_CHROMA_2X2
Urvang Joshifeb925f2016-12-05 10:37:29 -08003243
3244 const int pred_width_in_4x4_blocks = num_4x4_blocks_wide_lookup[bsize];
3245 const int pred_height_in_4x4_blocks = num_4x4_blocks_high_lookup[bsize];
3246 const int tx_width_unit = tx_size_wide_unit[tx_size];
3247 const int tx_height_unit = tx_size_high_unit[tx_size];
3248 const int pred_block_width = block_size_wide[bsize];
3249 const int pred_block_height = block_size_high[bsize];
3250 const int tx_width = tx_size_wide[tx_size];
3251 const int tx_height = tx_size_high[tx_size];
3252 const int pred_width_in_transform_blocks = pred_block_width / tx_width;
3253 const int pred_height_in_transform_blocks = pred_block_height / tx_height;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003254 int idx, idy;
Debargha Mukherjee096ae4c2016-09-07 10:08:13 -07003255 int best_can_skip = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003256 uint8_t best_dst[8 * 8];
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02003257#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07003258 uint16_t best_dst16[8 * 8];
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02003259#endif // CONFIG_HIGHBITDEPTH
Urvang Joshifeb925f2016-12-05 10:37:29 -08003260 const int is_lossless = xd->lossless[xd->mi[0]->mbmi.segment_id];
3261#if CONFIG_EXT_TX && CONFIG_RECT_TX
3262 const int sub_bsize = bsize;
3263#else
3264 const int sub_bsize = BLOCK_4X4;
3265#endif // CONFIG_EXT_TX && CONFIG_RECT_TX
Yaowu Xuc27fc142016-08-22 16:08:15 -07003266
Yushin Cho77bba8d2016-11-04 16:36:56 -07003267#if CONFIG_PVQ
3268 od_rollback_buffer pre_buf, post_buf;
3269 od_encode_checkpoint(&x->daala_enc, &pre_buf);
3270 od_encode_checkpoint(&x->daala_enc, &post_buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08003271#endif // CONFIG_PVQ
Yushin Cho77bba8d2016-11-04 16:36:56 -07003272
Urvang Joshifeb925f2016-12-05 10:37:29 -08003273 assert(bsize < BLOCK_8X8);
3274 assert(tx_width < 8 || tx_height < 8);
3275#if CONFIG_EXT_TX && CONFIG_RECT_TX
hui suff5e2092017-03-27 10:07:59 -07003276 if (is_lossless)
3277 assert(tx_width == 4 && tx_height == 4);
3278 else
3279 assert(tx_width == pred_block_width && tx_height == pred_block_height);
Urvang Joshifeb925f2016-12-05 10:37:29 -08003280#else
3281 assert(tx_width == 4 && tx_height == 4);
3282#endif // CONFIG_EXT_TX && CONFIG_RECT_TX
3283
3284 memcpy(ta, a, pred_width_in_transform_blocks * sizeof(a[0]));
3285 memcpy(tl, l, pred_height_in_transform_blocks * sizeof(l[0]));
3286
3287 xd->mi[0]->mbmi.tx_size = tx_size;
3288
Yaowu Xuc27fc142016-08-22 16:08:15 -07003289 xd->mi[0]->mbmi.palette_mode_info.palette_size[0] = 0;
3290
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02003291#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07003292 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
Thomas Daede6ff6af62017-02-03 16:29:24 -08003293#if CONFIG_PVQ
3294 od_encode_checkpoint(&x->daala_enc, &pre_buf);
3295#endif
Urvang Joshi96d1c0a2017-10-10 13:15:32 -07003296 for (mode = DC_PRED; mode <= PAETH_PRED; ++mode) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07003297 int64_t this_rd;
3298 int ratey = 0;
3299 int64_t distortion = 0;
3300 int rate = bmode_costs[mode];
Debargha Mukherjee096ae4c2016-09-07 10:08:13 -07003301 int can_skip = 1;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003302
Urvang Joshifeb925f2016-12-05 10:37:29 -08003303 if (!(cpi->sf.intra_y_mode_mask[txsize_sqr_up_map[tx_size]] &
3304 (1 << mode)))
3305 continue;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003306
3307 // Only do the oblique modes if the best so far is
3308 // one of the neighboring directional modes
3309 if (cpi->sf.mode_search_skip_flags & FLAG_SKIP_INTRA_DIRMISMATCH) {
3310 if (conditional_skipintra(mode, *best_mode)) continue;
3311 }
3312
Urvang Joshifeb925f2016-12-05 10:37:29 -08003313 memcpy(tempa, ta, pred_width_in_transform_blocks * sizeof(ta[0]));
3314 memcpy(templ, tl, pred_height_in_transform_blocks * sizeof(tl[0]));
Yaowu Xuc27fc142016-08-22 16:08:15 -07003315
Urvang Joshifeb925f2016-12-05 10:37:29 -08003316 for (idy = 0; idy < pred_height_in_transform_blocks; ++idy) {
3317 for (idx = 0; idx < pred_width_in_transform_blocks; ++idx) {
3318 const int block_raster_idx = (row + idy) * 2 + (col + idx);
3319 const int block =
3320 av1_raster_order_to_block_index(tx_size, block_raster_idx);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003321 const uint8_t *const src = &src_init[idx * 4 + idy * 4 * src_stride];
3322 uint8_t *const dst = &dst_init[idx * 4 + idy * 4 * dst_stride];
Thomas Daede6ff6af62017-02-03 16:29:24 -08003323#if !CONFIG_PVQ
Urvang Joshifeb925f2016-12-05 10:37:29 -08003324 int16_t *const src_diff = av1_raster_block_offset_int16(
3325 BLOCK_8X8, block_raster_idx, p->src_diff);
Thomas Daede6ff6af62017-02-03 16:29:24 -08003326#endif
Urvang Joshifeb925f2016-12-05 10:37:29 -08003327 int skip;
3328 assert(block < 4);
3329 assert(IMPLIES(tx_size == TX_4X8 || tx_size == TX_8X4,
3330 idx == 0 && idy == 0));
3331 assert(IMPLIES(tx_size == TX_4X8 || tx_size == TX_8X4,
3332 block == 0 || block == 2));
3333 xd->mi[0]->bmi[block_raster_idx].as_mode = mode;
David Barker839467f2017-01-19 11:06:15 +00003334 av1_predict_intra_block(
David Barker761b1ac2017-09-25 11:23:03 +01003335 cm, xd, pd->width, pd->height, txsize_to_bsize[tx_size], mode,
3336 dst, dst_stride, dst, dst_stride, col + idx, row + idy, 0);
Thomas Daede6ff6af62017-02-03 16:29:24 -08003337#if !CONFIG_PVQ
Urvang Joshifeb925f2016-12-05 10:37:29 -08003338 aom_highbd_subtract_block(tx_height, tx_width, src_diff, 8, src,
3339 src_stride, dst, dst_stride, xd->bd);
Thomas Daede6ff6af62017-02-03 16:29:24 -08003340#endif
Urvang Joshifeb925f2016-12-05 10:37:29 -08003341 if (is_lossless) {
Jingning Han19b5c8f2017-07-06 15:10:12 -07003342 TX_TYPE tx_type =
3343 av1_get_tx_type(PLANE_TYPE_Y, xd, 0, 0, block, tx_size);
Angie Chiangbd99b382017-06-20 15:11:16 -07003344 const SCAN_ORDER *scan_order =
3345 get_scan(cm, tx_size, tx_type, &xd->mi[0]->mbmi);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003346 const int coeff_ctx =
Urvang Joshifeb925f2016-12-05 10:37:29 -08003347 combine_entropy_contexts(tempa[idx], templ[idy]);
Thomas Daede6ff6af62017-02-03 16:29:24 -08003348#if !CONFIG_PVQ
Angie Chiangff6d8902016-10-21 11:02:09 -07003349 av1_xform_quant(cm, x, 0, block, row + idy, col + idx, BLOCK_8X8,
Urvang Joshifeb925f2016-12-05 10:37:29 -08003350 tx_size, coeff_ctx, AV1_XFORM_QUANT_FP);
Jingning Han7eab9ff2017-07-06 10:12:54 -07003351 ratey += av1_cost_coeffs(cpi, x, 0, 0, 0, block, tx_size,
3352 scan_order, tempa + idx, templ + idy,
Urvang Joshi03f6fdc2016-10-14 15:53:39 -07003353 cpi->sf.use_fast_coef_costing);
Urvang Joshifeb925f2016-12-05 10:37:29 -08003354 skip = (p->eobs[block] == 0);
3355 can_skip &= skip;
3356 tempa[idx] = !skip;
3357 templ[idy] = !skip;
3358#if CONFIG_EXT_TX
3359 if (tx_size == TX_8X4) {
3360 tempa[idx + 1] = tempa[idx];
3361 } else if (tx_size == TX_4X8) {
3362 templ[idy + 1] = templ[idy];
3363 }
3364#endif // CONFIG_EXT_TX
Thomas Daede6ff6af62017-02-03 16:29:24 -08003365#else
3366 (void)scan_order;
Urvang Joshifeb925f2016-12-05 10:37:29 -08003367
Thomas Daede6ff6af62017-02-03 16:29:24 -08003368 av1_xform_quant(cm, x, 0, block, row + idy, col + idx, BLOCK_8X8,
3369 tx_size, coeff_ctx, AV1_XFORM_QUANT_B);
3370
3371 ratey += x->rate;
3372 skip = x->pvq_skip[0];
3373 tempa[idx] = !skip;
3374 templ[idy] = !skip;
3375 can_skip &= skip;
3376#endif
Urvang Joshi70006e42017-06-14 16:08:55 -07003377 if (RDCOST(x->rdmult, ratey, distortion) >= best_rd)
Yaowu Xuc27fc142016-08-22 16:08:15 -07003378 goto next_highbd;
Thomas Daede6ff6af62017-02-03 16:29:24 -08003379#if CONFIG_PVQ
Yushin Cho08195cc2017-04-05 16:37:01 -07003380 if (!skip)
Thomas Daede6ff6af62017-02-03 16:29:24 -08003381#endif
Yushin Cho08195cc2017-04-05 16:37:01 -07003382 av1_inverse_transform_block(xd, BLOCK_OFFSET(pd->dqcoeff, block),
Lester Lu432012f2017-08-17 14:39:29 -07003383#if CONFIG_LGT_FROM_PRED
Lester Lu708c1ec2017-06-14 14:54:49 -07003384 mode,
3385#endif
Sarah Parker99e7daa2017-08-29 10:30:13 -07003386#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
3387 BLOCK_OFFSET(xd->mrc_mask, block),
3388#endif // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
Yushin Cho08195cc2017-04-05 16:37:01 -07003389 DCT_DCT, tx_size, dst, dst_stride,
3390 p->eobs[block]);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003391 } else {
3392 int64_t dist;
3393 unsigned int tmp;
Jingning Han19b5c8f2017-07-06 15:10:12 -07003394 TX_TYPE tx_type =
3395 av1_get_tx_type(PLANE_TYPE_Y, xd, 0, 0, block, tx_size);
Angie Chiangbd99b382017-06-20 15:11:16 -07003396 const SCAN_ORDER *scan_order =
3397 get_scan(cm, tx_size, tx_type, &xd->mi[0]->mbmi);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003398 const int coeff_ctx =
Urvang Joshifeb925f2016-12-05 10:37:29 -08003399 combine_entropy_contexts(tempa[idx], templ[idy]);
Thomas Daede6ff6af62017-02-03 16:29:24 -08003400#if !CONFIG_PVQ
Sarah Parker345366a2017-06-15 12:13:01 -07003401#if DISABLE_TRELLISQ_SEARCH
3402 av1_xform_quant(cm, x, 0, block, row + idy, col + idx, BLOCK_8X8,
3403 tx_size, coeff_ctx, AV1_XFORM_QUANT_B);
3404#else
Angie Chiangff6d8902016-10-21 11:02:09 -07003405 av1_xform_quant(cm, x, 0, block, row + idy, col + idx, BLOCK_8X8,
Urvang Joshifeb925f2016-12-05 10:37:29 -08003406 tx_size, coeff_ctx, AV1_XFORM_QUANT_FP);
Jingning Han7eab9ff2017-07-06 10:12:54 -07003407 av1_optimize_b(cm, x, 0, 0, 0, block, BLOCK_8X8, tx_size,
Angie Chiang25645b72017-09-24 14:28:49 -07003408 tempa + idx, templ + idy, 1);
Sarah Parker345366a2017-06-15 12:13:01 -07003409#endif // DISABLE_TRELLISQ_SEARCH
Jingning Han7eab9ff2017-07-06 10:12:54 -07003410 ratey += av1_cost_coeffs(cpi, x, 0, 0, 0, block, tx_size,
3411 scan_order, tempa + idx, templ + idy,
Urvang Joshi03f6fdc2016-10-14 15:53:39 -07003412 cpi->sf.use_fast_coef_costing);
Urvang Joshifeb925f2016-12-05 10:37:29 -08003413 skip = (p->eobs[block] == 0);
3414 can_skip &= skip;
3415 tempa[idx] = !skip;
3416 templ[idy] = !skip;
3417#if CONFIG_EXT_TX
3418 if (tx_size == TX_8X4) {
3419 tempa[idx + 1] = tempa[idx];
3420 } else if (tx_size == TX_4X8) {
3421 templ[idy + 1] = templ[idy];
3422 }
3423#endif // CONFIG_EXT_TX
Thomas Daede6ff6af62017-02-03 16:29:24 -08003424#else
3425 (void)scan_order;
3426
3427 av1_xform_quant(cm, x, 0, block, row + idy, col + idx, BLOCK_8X8,
3428 tx_size, coeff_ctx, AV1_XFORM_QUANT_FP);
3429 ratey += x->rate;
3430 skip = x->pvq_skip[0];
3431 tempa[idx] = !skip;
3432 templ[idy] = !skip;
3433 can_skip &= skip;
3434#endif
3435#if CONFIG_PVQ
Yushin Cho08195cc2017-04-05 16:37:01 -07003436 if (!skip)
Thomas Daede6ff6af62017-02-03 16:29:24 -08003437#endif
Yushin Cho08195cc2017-04-05 16:37:01 -07003438 av1_inverse_transform_block(xd, BLOCK_OFFSET(pd->dqcoeff, block),
Lester Lu432012f2017-08-17 14:39:29 -07003439#if CONFIG_LGT_FROM_PRED
Lester Lu708c1ec2017-06-14 14:54:49 -07003440 mode,
3441#endif
Sarah Parker99e7daa2017-08-29 10:30:13 -07003442#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
3443 BLOCK_OFFSET(xd->mrc_mask, block),
3444#endif // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
Yushin Cho08195cc2017-04-05 16:37:01 -07003445 tx_type, tx_size, dst, dst_stride,
3446 p->eobs[block]);
Urvang Joshifeb925f2016-12-05 10:37:29 -08003447 cpi->fn_ptr[sub_bsize].vf(src, src_stride, dst, dst_stride, &tmp);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003448 dist = (int64_t)tmp << 4;
3449 distortion += dist;
Urvang Joshi70006e42017-06-14 16:08:55 -07003450 if (RDCOST(x->rdmult, ratey, distortion) >= best_rd)
Yaowu Xuc27fc142016-08-22 16:08:15 -07003451 goto next_highbd;
3452 }
3453 }
3454 }
3455
3456 rate += ratey;
Urvang Joshi70006e42017-06-14 16:08:55 -07003457 this_rd = RDCOST(x->rdmult, rate, distortion);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003458
3459 if (this_rd < best_rd) {
3460 *bestrate = rate;
3461 *bestratey = ratey;
3462 *bestdistortion = distortion;
3463 best_rd = this_rd;
Debargha Mukherjee096ae4c2016-09-07 10:08:13 -07003464 best_can_skip = can_skip;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003465 *best_mode = mode;
Urvang Joshifeb925f2016-12-05 10:37:29 -08003466 memcpy(a, tempa, pred_width_in_transform_blocks * sizeof(tempa[0]));
3467 memcpy(l, templ, pred_height_in_transform_blocks * sizeof(templ[0]));
Thomas Daede6ff6af62017-02-03 16:29:24 -08003468#if CONFIG_PVQ
3469 od_encode_checkpoint(&x->daala_enc, &post_buf);
3470#endif
Urvang Joshifeb925f2016-12-05 10:37:29 -08003471 for (idy = 0; idy < pred_height_in_transform_blocks * 4; ++idy) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07003472 memcpy(best_dst16 + idy * 8,
3473 CONVERT_TO_SHORTPTR(dst_init + idy * dst_stride),
Urvang Joshifeb925f2016-12-05 10:37:29 -08003474 pred_width_in_transform_blocks * 4 * sizeof(uint16_t));
Yaowu Xuc27fc142016-08-22 16:08:15 -07003475 }
3476 }
3477 next_highbd : {}
Thomas Daede6ff6af62017-02-03 16:29:24 -08003478#if CONFIG_PVQ
3479 od_encode_rollback(&x->daala_enc, &pre_buf);
3480#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07003481 }
3482
3483 if (best_rd >= rd_thresh) return best_rd;
3484
Thomas Daede6ff6af62017-02-03 16:29:24 -08003485#if CONFIG_PVQ
3486 od_encode_rollback(&x->daala_enc, &post_buf);
3487#endif
3488
Debargha Mukherjee096ae4c2016-09-07 10:08:13 -07003489 if (y_skip) *y_skip &= best_can_skip;
3490
Urvang Joshifeb925f2016-12-05 10:37:29 -08003491 for (idy = 0; idy < pred_height_in_transform_blocks * 4; ++idy) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07003492 memcpy(CONVERT_TO_SHORTPTR(dst_init + idy * dst_stride),
Urvang Joshifeb925f2016-12-05 10:37:29 -08003493 best_dst16 + idy * 8,
3494 pred_width_in_transform_blocks * 4 * sizeof(uint16_t));
Yaowu Xuc27fc142016-08-22 16:08:15 -07003495 }
3496
3497 return best_rd;
3498 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02003499#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07003500
Yushin Cho77bba8d2016-11-04 16:36:56 -07003501#if CONFIG_PVQ
3502 od_encode_checkpoint(&x->daala_enc, &pre_buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08003503#endif // CONFIG_PVQ
Yushin Cho77bba8d2016-11-04 16:36:56 -07003504
Urvang Joshi96d1c0a2017-10-10 13:15:32 -07003505 for (mode = DC_PRED; mode <= PAETH_PRED; ++mode) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07003506 int64_t this_rd;
3507 int ratey = 0;
3508 int64_t distortion = 0;
3509 int rate = bmode_costs[mode];
Debargha Mukherjee096ae4c2016-09-07 10:08:13 -07003510 int can_skip = 1;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003511
Urvang Joshifeb925f2016-12-05 10:37:29 -08003512 if (!(cpi->sf.intra_y_mode_mask[txsize_sqr_up_map[tx_size]] &
3513 (1 << mode))) {
3514 continue;
3515 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07003516
3517 // Only do the oblique modes if the best so far is
3518 // one of the neighboring directional modes
3519 if (cpi->sf.mode_search_skip_flags & FLAG_SKIP_INTRA_DIRMISMATCH) {
3520 if (conditional_skipintra(mode, *best_mode)) continue;
3521 }
3522
Urvang Joshifeb925f2016-12-05 10:37:29 -08003523 memcpy(tempa, ta, pred_width_in_transform_blocks * sizeof(ta[0]));
3524 memcpy(templ, tl, pred_height_in_transform_blocks * sizeof(tl[0]));
Yaowu Xuc27fc142016-08-22 16:08:15 -07003525
Urvang Joshifeb925f2016-12-05 10:37:29 -08003526 for (idy = 0; idy < pred_height_in_4x4_blocks; idy += tx_height_unit) {
3527 for (idx = 0; idx < pred_width_in_4x4_blocks; idx += tx_width_unit) {
3528 const int block_raster_idx = (row + idy) * 2 + (col + idx);
3529 int block = av1_raster_order_to_block_index(tx_size, block_raster_idx);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003530 const uint8_t *const src = &src_init[idx * 4 + idy * 4 * src_stride];
3531 uint8_t *const dst = &dst_init[idx * 4 + idy * 4 * dst_stride];
Yushin Cho77bba8d2016-11-04 16:36:56 -07003532#if !CONFIG_PVQ
Urvang Joshifeb925f2016-12-05 10:37:29 -08003533 int16_t *const src_diff = av1_raster_block_offset_int16(
3534 BLOCK_8X8, block_raster_idx, p->src_diff);
Fergus Simpson4063a682017-02-28 16:52:22 -08003535#endif // !CONFIG_PVQ
Urvang Joshifeb925f2016-12-05 10:37:29 -08003536 int skip;
3537 assert(block < 4);
3538 assert(IMPLIES(tx_size == TX_4X8 || tx_size == TX_8X4,
3539 idx == 0 && idy == 0));
3540 assert(IMPLIES(tx_size == TX_4X8 || tx_size == TX_8X4,
3541 block == 0 || block == 2));
3542 xd->mi[0]->bmi[block_raster_idx].as_mode = mode;
David Barker761b1ac2017-09-25 11:23:03 +01003543 av1_predict_intra_block(cm, xd, pd->width, pd->height,
David Barker839467f2017-01-19 11:06:15 +00003544 txsize_to_bsize[tx_size], mode, dst, dst_stride,
3545 dst, dst_stride,
Jingning Hand1097fc2016-12-06 10:55:34 -08003546#if CONFIG_CB4X4
3547 2 * (col + idx), 2 * (row + idy),
3548#else
3549 col + idx, row + idy,
Fergus Simpson4063a682017-02-28 16:52:22 -08003550#endif // CONFIG_CB4X4
Jingning Hand1097fc2016-12-06 10:55:34 -08003551 0);
Yushin Cho77bba8d2016-11-04 16:36:56 -07003552#if !CONFIG_PVQ
Urvang Joshifeb925f2016-12-05 10:37:29 -08003553 aom_subtract_block(tx_height, tx_width, src_diff, 8, src, src_stride,
3554 dst, dst_stride);
Fergus Simpson4063a682017-02-28 16:52:22 -08003555#endif // !CONFIG_PVQ
Jingning Han19b5c8f2017-07-06 15:10:12 -07003556 TX_TYPE tx_type =
3557 av1_get_tx_type(PLANE_TYPE_Y, xd, 0, 0, block, tx_size);
Angie Chiangbd99b382017-06-20 15:11:16 -07003558 const SCAN_ORDER *scan_order =
3559 get_scan(cm, tx_size, tx_type, &xd->mi[0]->mbmi);
Urvang Joshi14731732017-04-27 18:40:49 -07003560 const int coeff_ctx = combine_entropy_contexts(tempa[idx], templ[idy]);
Jingning Hand1097fc2016-12-06 10:55:34 -08003561#if CONFIG_CB4X4
Urvang Joshi14731732017-04-27 18:40:49 -07003562 block = 4 * block;
Fergus Simpson4063a682017-02-28 16:52:22 -08003563#endif // CONFIG_CB4X4
Yushin Cho900243b2017-01-03 11:02:38 -08003564#if !CONFIG_PVQ
Sarah Parker345366a2017-06-15 12:13:01 -07003565#if DISABLE_TRELLISQ_SEARCH
3566 av1_xform_quant(cm, x, 0, block,
3567#if CONFIG_CB4X4
3568 2 * (row + idy), 2 * (col + idx),
3569#else
3570 row + idy, col + idx,
3571#endif // CONFIG_CB4X4
3572 BLOCK_8X8, tx_size, coeff_ctx, AV1_XFORM_QUANT_B);
3573#else
Urvang Joshi14731732017-04-27 18:40:49 -07003574 const AV1_XFORM_QUANT xform_quant =
3575 is_lossless ? AV1_XFORM_QUANT_B : AV1_XFORM_QUANT_FP;
3576 av1_xform_quant(cm, x, 0, block,
Jingning Hand1097fc2016-12-06 10:55:34 -08003577#if CONFIG_CB4X4
Urvang Joshi14731732017-04-27 18:40:49 -07003578 2 * (row + idy), 2 * (col + idx),
Jingning Hand1097fc2016-12-06 10:55:34 -08003579#else
Urvang Joshi14731732017-04-27 18:40:49 -07003580 row + idy, col + idx,
Fergus Simpson4063a682017-02-28 16:52:22 -08003581#endif // CONFIG_CB4X4
Urvang Joshi14731732017-04-27 18:40:49 -07003582 BLOCK_8X8, tx_size, coeff_ctx, xform_quant);
Yushin Cho900243b2017-01-03 11:02:38 -08003583
Jingning Han7eab9ff2017-07-06 10:12:54 -07003584 av1_optimize_b(cm, x, 0, 0, 0, block, BLOCK_8X8, tx_size, tempa + idx,
Angie Chiang25645b72017-09-24 14:28:49 -07003585 templ + idy, 1);
Sarah Parker345366a2017-06-15 12:13:01 -07003586#endif // DISABLE_TRELLISQ_SEARCH
Jingning Han7eab9ff2017-07-06 10:12:54 -07003587 ratey += av1_cost_coeffs(cpi, x, 0, 0, 0, block, tx_size, scan_order,
3588 tempa + idx, templ + idy,
3589 cpi->sf.use_fast_coef_costing);
Urvang Joshi14731732017-04-27 18:40:49 -07003590 skip = (p->eobs[block] == 0);
3591 can_skip &= skip;
3592 tempa[idx] = !skip;
3593 templ[idy] = !skip;
Urvang Joshifeb925f2016-12-05 10:37:29 -08003594#if CONFIG_EXT_TX
Urvang Joshi14731732017-04-27 18:40:49 -07003595 if (tx_size == TX_8X4) {
3596 tempa[idx + 1] = tempa[idx];
3597 } else if (tx_size == TX_4X8) {
3598 templ[idy + 1] = templ[idy];
3599 }
Urvang Joshifeb925f2016-12-05 10:37:29 -08003600#endif // CONFIG_EXT_TX
Yushin Cho77bba8d2016-11-04 16:36:56 -07003601#else
Urvang Joshi14731732017-04-27 18:40:49 -07003602 (void)scan_order;
Yushin Cho900243b2017-01-03 11:02:38 -08003603
Urvang Joshi14731732017-04-27 18:40:49 -07003604 av1_xform_quant(cm, x, 0, block,
Yushin Cho900243b2017-01-03 11:02:38 -08003605#if CONFIG_CB4X4
Urvang Joshi14731732017-04-27 18:40:49 -07003606 2 * (row + idy), 2 * (col + idx),
Yushin Cho900243b2017-01-03 11:02:38 -08003607#else
Urvang Joshi14731732017-04-27 18:40:49 -07003608 row + idy, col + idx,
Fergus Simpson4063a682017-02-28 16:52:22 -08003609#endif // CONFIG_CB4X4
Urvang Joshi14731732017-04-27 18:40:49 -07003610 BLOCK_8X8, tx_size, coeff_ctx, AV1_XFORM_QUANT_FP);
3611
3612 ratey += x->rate;
3613 skip = x->pvq_skip[0];
3614 tempa[idx] = !skip;
3615 templ[idy] = !skip;
3616 can_skip &= skip;
Fergus Simpson4063a682017-02-28 16:52:22 -08003617#endif // !CONFIG_PVQ
Urvang Joshi14731732017-04-27 18:40:49 -07003618
3619 if (!is_lossless) { // To use the pixel domain distortion, we need to
3620 // calculate inverse txfm *before* calculating RD
3621 // cost. Compared to calculating the distortion in
3622 // the frequency domain, the overhead of encoding
3623 // effort is low.
Yushin Chob27a17f2016-12-23 14:33:02 -08003624#if CONFIG_PVQ
Yushin Cho08195cc2017-04-05 16:37:01 -07003625 if (!skip)
Fergus Simpson4063a682017-02-28 16:52:22 -08003626#endif // CONFIG_PVQ
Yushin Cho08195cc2017-04-05 16:37:01 -07003627 av1_inverse_transform_block(xd, BLOCK_OFFSET(pd->dqcoeff, block),
Lester Lu432012f2017-08-17 14:39:29 -07003628#if CONFIG_LGT_FROM_PRED
Lester Lu708c1ec2017-06-14 14:54:49 -07003629 mode,
3630#endif
Sarah Parker99e7daa2017-08-29 10:30:13 -07003631#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
3632 BLOCK_OFFSET(xd->mrc_mask, block),
3633#endif // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
Yushin Cho08195cc2017-04-05 16:37:01 -07003634 tx_type, tx_size, dst, dst_stride,
3635 p->eobs[block]);
Urvang Joshi14731732017-04-27 18:40:49 -07003636 unsigned int tmp;
Urvang Joshifeb925f2016-12-05 10:37:29 -08003637 cpi->fn_ptr[sub_bsize].vf(src, src_stride, dst, dst_stride, &tmp);
Urvang Joshi14731732017-04-27 18:40:49 -07003638 const int64_t dist = (int64_t)tmp << 4;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003639 distortion += dist;
Urvang Joshi14731732017-04-27 18:40:49 -07003640 }
3641
Urvang Joshi70006e42017-06-14 16:08:55 -07003642 if (RDCOST(x->rdmult, ratey, distortion) >= best_rd) goto next;
Urvang Joshi14731732017-04-27 18:40:49 -07003643
3644 if (is_lossless) { // Calculate inverse txfm *after* RD cost.
3645#if CONFIG_PVQ
3646 if (!skip)
3647#endif // CONFIG_PVQ
3648 av1_inverse_transform_block(xd, BLOCK_OFFSET(pd->dqcoeff, block),
Lester Lu432012f2017-08-17 14:39:29 -07003649#if CONFIG_LGT_FROM_PRED
Lester Lu708c1ec2017-06-14 14:54:49 -07003650 mode,
3651#endif
Sarah Parker99e7daa2017-08-29 10:30:13 -07003652#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
3653 BLOCK_OFFSET(xd->mrc_mask, block),
3654#endif // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
Urvang Joshi14731732017-04-27 18:40:49 -07003655 DCT_DCT, tx_size, dst, dst_stride,
3656 p->eobs[block]);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003657 }
3658 }
3659 }
3660
3661 rate += ratey;
Urvang Joshi70006e42017-06-14 16:08:55 -07003662 this_rd = RDCOST(x->rdmult, rate, distortion);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003663
3664 if (this_rd < best_rd) {
3665 *bestrate = rate;
3666 *bestratey = ratey;
3667 *bestdistortion = distortion;
3668 best_rd = this_rd;
Debargha Mukherjee096ae4c2016-09-07 10:08:13 -07003669 best_can_skip = can_skip;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003670 *best_mode = mode;
Urvang Joshifeb925f2016-12-05 10:37:29 -08003671 memcpy(a, tempa, pred_width_in_transform_blocks * sizeof(tempa[0]));
3672 memcpy(l, templ, pred_height_in_transform_blocks * sizeof(templ[0]));
Yushin Cho77bba8d2016-11-04 16:36:56 -07003673#if CONFIG_PVQ
3674 od_encode_checkpoint(&x->daala_enc, &post_buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08003675#endif // CONFIG_PVQ
Urvang Joshifeb925f2016-12-05 10:37:29 -08003676 for (idy = 0; idy < pred_height_in_transform_blocks * 4; ++idy)
Yaowu Xuc27fc142016-08-22 16:08:15 -07003677 memcpy(best_dst + idy * 8, dst_init + idy * dst_stride,
Urvang Joshifeb925f2016-12-05 10:37:29 -08003678 pred_width_in_transform_blocks * 4);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003679 }
3680 next : {}
Yushin Cho77bba8d2016-11-04 16:36:56 -07003681#if CONFIG_PVQ
3682 od_encode_rollback(&x->daala_enc, &pre_buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08003683#endif // CONFIG_PVQ
3684 } // mode decision loop
Yaowu Xuc27fc142016-08-22 16:08:15 -07003685
3686 if (best_rd >= rd_thresh) return best_rd;
3687
Yushin Cho77bba8d2016-11-04 16:36:56 -07003688#if CONFIG_PVQ
3689 od_encode_rollback(&x->daala_enc, &post_buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08003690#endif // CONFIG_PVQ
Yushin Cho77bba8d2016-11-04 16:36:56 -07003691
Debargha Mukherjee096ae4c2016-09-07 10:08:13 -07003692 if (y_skip) *y_skip &= best_can_skip;
3693
Urvang Joshifeb925f2016-12-05 10:37:29 -08003694 for (idy = 0; idy < pred_height_in_transform_blocks * 4; ++idy)
Yaowu Xuc27fc142016-08-22 16:08:15 -07003695 memcpy(dst_init + idy * dst_stride, best_dst + idy * 8,
Urvang Joshifeb925f2016-12-05 10:37:29 -08003696 pred_width_in_transform_blocks * 4);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003697
3698 return best_rd;
3699}
3700
Urvang Joshi52648442016-10-13 17:27:51 -07003701static int64_t rd_pick_intra_sub_8x8_y_mode(const AV1_COMP *const cpi,
3702 MACROBLOCK *mb, int *rate,
3703 int *rate_y, int64_t *distortion,
3704 int *y_skip, int64_t best_rd) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07003705 const MACROBLOCKD *const xd = &mb->e_mbd;
3706 MODE_INFO *const mic = xd->mi[0];
3707 const MODE_INFO *above_mi = xd->above_mi;
3708 const MODE_INFO *left_mi = xd->left_mi;
Urvang Joshifeb925f2016-12-05 10:37:29 -08003709 MB_MODE_INFO *const mbmi = &mic->mbmi;
Urvang Joshi330aec82017-05-08 15:37:42 -07003710 assert(!is_inter_block(mbmi));
Urvang Joshifeb925f2016-12-05 10:37:29 -08003711 const BLOCK_SIZE bsize = mbmi->sb_type;
3712 const int pred_width_in_4x4_blocks = num_4x4_blocks_wide_lookup[bsize];
3713 const int pred_height_in_4x4_blocks = num_4x4_blocks_high_lookup[bsize];
Yaowu Xuc27fc142016-08-22 16:08:15 -07003714 int idx, idy;
3715 int cost = 0;
3716 int64_t total_distortion = 0;
3717 int tot_rate_y = 0;
3718 int64_t total_rd = 0;
Yue Chenb23d00a2017-07-28 17:01:21 -07003719 const int *bmode_costs = mb->mbmode_cost[0];
Urvang Joshifeb925f2016-12-05 10:37:29 -08003720 const int is_lossless = xd->lossless[mbmi->segment_id];
3721#if CONFIG_EXT_TX && CONFIG_RECT_TX
3722 const TX_SIZE tx_size = is_lossless ? TX_4X4 : max_txsize_rect_lookup[bsize];
3723#else
3724 const TX_SIZE tx_size = TX_4X4;
3725#endif // CONFIG_EXT_TX && CONFIG_RECT_TX
Yaowu Xuc27fc142016-08-22 16:08:15 -07003726
3727#if CONFIG_EXT_INTRA
hui sueda3d762016-12-06 16:58:23 -08003728#if CONFIG_INTRA_INTERP
Urvang Joshifeb925f2016-12-05 10:37:29 -08003729 mbmi->intra_filter = INTRA_FILTER_LINEAR;
hui sueda3d762016-12-06 16:58:23 -08003730#endif // CONFIG_INTRA_INTERP
Yaowu Xuc27fc142016-08-22 16:08:15 -07003731#endif // CONFIG_EXT_INTRA
hui su5db97432016-10-14 16:10:14 -07003732#if CONFIG_FILTER_INTRA
Urvang Joshifeb925f2016-12-05 10:37:29 -08003733 mbmi->filter_intra_mode_info.use_filter_intra_mode[0] = 0;
hui su5db97432016-10-14 16:10:14 -07003734#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07003735
3736 // TODO(any): Add search of the tx_type to improve rd performance at the
3737 // expense of speed.
Urvang Joshifeb925f2016-12-05 10:37:29 -08003738 mbmi->tx_type = DCT_DCT;
3739 mbmi->tx_size = tx_size;
Lester Lu432012f2017-08-17 14:39:29 -07003740#if CONFIG_LGT_FROM_PRED
3741 mbmi->use_lgt = 0;
3742#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07003743
Debargha Mukherjee096ae4c2016-09-07 10:08:13 -07003744 if (y_skip) *y_skip = 1;
3745
Urvang Joshifeb925f2016-12-05 10:37:29 -08003746 // Pick modes for each prediction sub-block (of size 4x4, 4x8, or 8x4) in this
3747 // 8x8 coding block.
3748 for (idy = 0; idy < 2; idy += pred_height_in_4x4_blocks) {
3749 for (idx = 0; idx < 2; idx += pred_width_in_4x4_blocks) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07003750 PREDICTION_MODE best_mode = DC_PRED;
3751 int r = INT_MAX, ry = INT_MAX;
3752 int64_t d = INT64_MAX, this_rd = INT64_MAX;
Urvang Joshifeb925f2016-12-05 10:37:29 -08003753 int j;
3754 const int pred_block_idx = idy * 2 + idx;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003755 if (cpi->common.frame_type == KEY_FRAME) {
Urvang Joshifeb925f2016-12-05 10:37:29 -08003756 const PREDICTION_MODE A =
3757 av1_above_block_mode(mic, above_mi, pred_block_idx);
3758 const PREDICTION_MODE L =
3759 av1_left_block_mode(mic, left_mi, pred_block_idx);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003760
Jingning Hana45d8422017-10-05 09:57:38 -07003761#if CONFIG_KF_CTX
3762 const int above_ctx = intra_mode_context[A];
3763 const int left_ctx = intra_mode_context[L];
3764 bmode_costs = mb->y_mode_costs[above_ctx][left_ctx];
3765#else
Yue Chenb23d00a2017-07-28 17:01:21 -07003766 bmode_costs = mb->y_mode_costs[A][L];
Jingning Hana45d8422017-10-05 09:57:38 -07003767#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07003768 }
Urvang Joshifeb925f2016-12-05 10:37:29 -08003769 this_rd = rd_pick_intra_sub_8x8_y_subblock_mode(
Yaowu Xuc27fc142016-08-22 16:08:15 -07003770 cpi, mb, idy, idx, &best_mode, bmode_costs,
3771 xd->plane[0].above_context + idx, xd->plane[0].left_context + idy, &r,
Urvang Joshifeb925f2016-12-05 10:37:29 -08003772 &ry, &d, bsize, tx_size, y_skip, best_rd - total_rd);
Yushin Cho55104332017-08-14 16:15:43 -07003773#if CONFIG_DIST_8X8
3774 if (!cpi->oxcf.using_dist_8x8)
3775#endif
3776 if (this_rd >= best_rd - total_rd) return INT64_MAX;
3777
Yaowu Xuc27fc142016-08-22 16:08:15 -07003778 total_rd += this_rd;
3779 cost += r;
3780 total_distortion += d;
3781 tot_rate_y += ry;
3782
Urvang Joshifeb925f2016-12-05 10:37:29 -08003783 mic->bmi[pred_block_idx].as_mode = best_mode;
3784 for (j = 1; j < pred_height_in_4x4_blocks; ++j)
3785 mic->bmi[pred_block_idx + j * 2].as_mode = best_mode;
3786 for (j = 1; j < pred_width_in_4x4_blocks; ++j)
3787 mic->bmi[pred_block_idx + j].as_mode = best_mode;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003788
3789 if (total_rd >= best_rd) return INT64_MAX;
3790 }
3791 }
Urvang Joshifeb925f2016-12-05 10:37:29 -08003792 mbmi->mode = mic->bmi[3].as_mode;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003793
Yushin Chob7b60c52017-07-14 16:18:52 -07003794#if CONFIG_DIST_8X8
Yushin Cho55104332017-08-14 16:15:43 -07003795 if (cpi->oxcf.using_dist_8x8) {
Yushin Cho7a428ba2017-01-12 16:28:49 -08003796 const struct macroblock_plane *p = &mb->plane[0];
3797 const struct macroblockd_plane *pd = &xd->plane[0];
3798 const int src_stride = p->src.stride;
3799 const int dst_stride = pd->dst.stride;
3800 uint8_t *src = p->src.buf;
3801 uint8_t *dst = pd->dst.buf;
Yushin Cho7a428ba2017-01-12 16:28:49 -08003802
Yushin Cho7a428ba2017-01-12 16:28:49 -08003803 // Daala-defined distortion computed for the block of 8x8 pixels
Yushin Choe30a47c2017-08-15 13:08:30 -07003804 total_distortion = av1_dist_8x8(cpi, mb, src, src_stride, dst, dst_stride,
Yushin Chob7b60c52017-07-14 16:18:52 -07003805 BLOCK_8X8, 8, 8, 8, 8, mb->qindex)
3806 << 4;
Yushin Cho7a428ba2017-01-12 16:28:49 -08003807 }
Yushin Chob7b60c52017-07-14 16:18:52 -07003808#endif // CONFIG_DIST_8X8
Yaowu Xuc27fc142016-08-22 16:08:15 -07003809 // Add in the cost of the transform type
Urvang Joshifeb925f2016-12-05 10:37:29 -08003810 if (!is_lossless) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07003811 int rate_tx_type = 0;
3812#if CONFIG_EXT_TX
Sarah Parkere68a3e42017-02-16 14:03:24 -08003813 if (get_ext_tx_types(tx_size, bsize, 0, cpi->common.reduced_tx_set_used) >
3814 1) {
3815 const int eset =
3816 get_ext_tx_set(tx_size, bsize, 0, cpi->common.reduced_tx_set_used);
Lester Lu432012f2017-08-17 14:39:29 -07003817#if CONFIG_LGT_FROM_PRED
3818 if (LGT_FROM_PRED_INTRA && is_lgt_allowed(mbmi->mode, tx_size))
3819 rate_tx_type += mb->intra_lgt_cost[txsize_sqr_map[tx_size]][mbmi->mode]
3820 [mbmi->use_lgt];
3821 if (!LGT_FROM_PRED_INTRA || !mbmi->use_lgt)
3822#endif // CONFIG_LGT_FROM_PRED
3823 rate_tx_type += mb->intra_tx_type_costs[eset][txsize_sqr_map[tx_size]]
3824 [mbmi->mode][mbmi->tx_type];
Yaowu Xuc27fc142016-08-22 16:08:15 -07003825 }
3826#else
clang-format67948d32016-09-07 22:40:40 -07003827 rate_tx_type =
Yue Chenb23d00a2017-07-28 17:01:21 -07003828 mb->intra_tx_type_costs[txsize_sqr_map[tx_size]]
3829 [intra_mode_to_tx_type_context[mbmi->mode]]
3830 [mbmi->tx_type];
Fergus Simpson4063a682017-02-28 16:52:22 -08003831#endif // CONFIG_EXT_TX
Urvang Joshifeb925f2016-12-05 10:37:29 -08003832 assert(mbmi->tx_size == tx_size);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003833 cost += rate_tx_type;
3834 tot_rate_y += rate_tx_type;
3835 }
3836
3837 *rate = cost;
3838 *rate_y = tot_rate_y;
3839 *distortion = total_distortion;
3840
Urvang Joshi70006e42017-06-14 16:08:55 -07003841 return RDCOST(mb->rdmult, cost, total_distortion);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003842}
3843
hui su5db97432016-10-14 16:10:14 -07003844#if CONFIG_FILTER_INTRA
3845// Return 1 if an filter intra mode is selected; return 0 otherwise.
3846static int rd_pick_filter_intra_sby(const AV1_COMP *const cpi, MACROBLOCK *x,
3847 int *rate, int *rate_tokenonly,
3848 int64_t *distortion, int *skippable,
3849 BLOCK_SIZE bsize, int mode_cost,
hui su8f4cc0a2017-01-13 15:14:49 -08003850 int64_t *best_rd, int64_t *best_model_rd,
3851 uint16_t skip_mask) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07003852 MACROBLOCKD *const xd = &x->e_mbd;
3853 MODE_INFO *const mic = xd->mi[0];
3854 MB_MODE_INFO *mbmi = &mic->mbmi;
hui su5db97432016-10-14 16:10:14 -07003855 int filter_intra_selected_flag = 0;
hui su5db97432016-10-14 16:10:14 -07003856 FILTER_INTRA_MODE mode;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003857 TX_SIZE best_tx_size = TX_4X4;
hui su5db97432016-10-14 16:10:14 -07003858 FILTER_INTRA_MODE_INFO filter_intra_mode_info;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003859 TX_TYPE best_tx_type;
Lester Lu432012f2017-08-17 14:39:29 -07003860#if CONFIG_LGT_FROM_PRED
3861 int use_lgt_when_selected;
3862#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07003863
hui su5db97432016-10-14 16:10:14 -07003864 av1_zero(filter_intra_mode_info);
3865 mbmi->filter_intra_mode_info.use_filter_intra_mode[0] = 1;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003866 mbmi->mode = DC_PRED;
3867 mbmi->palette_mode_info.palette_size[0] = 0;
3868
3869 for (mode = 0; mode < FILTER_INTRA_MODES; ++mode) {
hui su8f4cc0a2017-01-13 15:14:49 -08003870 int this_rate;
3871 int64_t this_rd, this_model_rd;
3872 RD_STATS tokenonly_rd_stats;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003873 if (skip_mask & (1 << mode)) continue;
hui su5db97432016-10-14 16:10:14 -07003874 mbmi->filter_intra_mode_info.filter_intra_mode[0] = mode;
hui su8f4cc0a2017-01-13 15:14:49 -08003875 this_model_rd = intra_model_yrd(cpi, x, bsize, mode_cost);
3876 if (*best_model_rd != INT64_MAX &&
3877 this_model_rd > *best_model_rd + (*best_model_rd >> 1))
3878 continue;
3879 if (this_model_rd < *best_model_rd) *best_model_rd = this_model_rd;
Angie Chiang0e9a2e92016-11-08 09:45:40 -08003880 super_block_yrd(cpi, x, &tokenonly_rd_stats, bsize, *best_rd);
3881 if (tokenonly_rd_stats.rate == INT_MAX) continue;
Angie Chiang0e9a2e92016-11-08 09:45:40 -08003882 this_rate = tokenonly_rd_stats.rate +
hui su5db97432016-10-14 16:10:14 -07003883 av1_cost_bit(cpi->common.fc->filter_intra_probs[0], 1) +
Yaowu Xuc27fc142016-08-22 16:08:15 -07003884 write_uniform_cost(FILTER_INTRA_MODES, mode) + mode_cost;
Urvang Joshi70006e42017-06-14 16:08:55 -07003885 this_rd = RDCOST(x->rdmult, this_rate, tokenonly_rd_stats.dist);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003886
3887 if (this_rd < *best_rd) {
3888 *best_rd = this_rd;
3889 best_tx_size = mic->mbmi.tx_size;
hui su5db97432016-10-14 16:10:14 -07003890 filter_intra_mode_info = mbmi->filter_intra_mode_info;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003891 best_tx_type = mic->mbmi.tx_type;
Lester Lu432012f2017-08-17 14:39:29 -07003892#if CONFIG_LGT_FROM_PRED
3893 use_lgt_when_selected = mic->mbmi.use_lgt;
3894#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07003895 *rate = this_rate;
Angie Chiang0e9a2e92016-11-08 09:45:40 -08003896 *rate_tokenonly = tokenonly_rd_stats.rate;
3897 *distortion = tokenonly_rd_stats.dist;
3898 *skippable = tokenonly_rd_stats.skip;
hui su5db97432016-10-14 16:10:14 -07003899 filter_intra_selected_flag = 1;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003900 }
3901 }
3902
hui su5db97432016-10-14 16:10:14 -07003903 if (filter_intra_selected_flag) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07003904 mbmi->mode = DC_PRED;
3905 mbmi->tx_size = best_tx_size;
Lester Lu432012f2017-08-17 14:39:29 -07003906#if CONFIG_LGT_FROM_PRED
3907 mbmi->use_lgt = use_lgt_when_selected;
3908#endif
hui su5db97432016-10-14 16:10:14 -07003909 mbmi->filter_intra_mode_info.use_filter_intra_mode[0] =
3910 filter_intra_mode_info.use_filter_intra_mode[0];
3911 mbmi->filter_intra_mode_info.filter_intra_mode[0] =
3912 filter_intra_mode_info.filter_intra_mode[0];
Yaowu Xuc27fc142016-08-22 16:08:15 -07003913 mbmi->tx_type = best_tx_type;
3914 return 1;
3915 } else {
3916 return 0;
3917 }
3918}
hui su5db97432016-10-14 16:10:14 -07003919#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07003920
hui su5db97432016-10-14 16:10:14 -07003921#if CONFIG_EXT_INTRA
hui su45dc5972016-12-08 17:42:50 -08003922// Run RD calculation with given luma intra prediction angle., and return
3923// the RD cost. Update the best mode info. if the RD cost is the best so far.
3924static int64_t calc_rd_given_intra_angle(
3925 const AV1_COMP *const cpi, MACROBLOCK *x, BLOCK_SIZE bsize, int mode_cost,
3926 int64_t best_rd_in, int8_t angle_delta, int max_angle_delta, int *rate,
3927 RD_STATS *rd_stats, int *best_angle_delta, TX_SIZE *best_tx_size,
3928 TX_TYPE *best_tx_type,
Lester Lu432012f2017-08-17 14:39:29 -07003929#if CONFIG_LGT_FROM_PRED
3930 int *use_lgt_when_selected,
3931#endif
hui sueda3d762016-12-06 16:58:23 -08003932#if CONFIG_INTRA_INTERP
3933 INTRA_FILTER *best_filter,
3934#endif // CONFIG_INTRA_INTERP
hui su9a416f52017-01-13 11:37:53 -08003935 int64_t *best_rd, int64_t *best_model_rd) {
Angie Chiang0e9a2e92016-11-08 09:45:40 -08003936 int this_rate;
3937 RD_STATS tokenonly_rd_stats;
hui su9a416f52017-01-13 11:37:53 -08003938 int64_t this_rd, this_model_rd;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003939 MB_MODE_INFO *mbmi = &x->e_mbd.mi[0]->mbmi;
Urvang Joshi330aec82017-05-08 15:37:42 -07003940 assert(!is_inter_block(mbmi));
Yaowu Xuc27fc142016-08-22 16:08:15 -07003941
hui su45dc5972016-12-08 17:42:50 -08003942 mbmi->angle_delta[0] = angle_delta;
hui su9a416f52017-01-13 11:37:53 -08003943 this_model_rd = intra_model_yrd(cpi, x, bsize, mode_cost);
3944 if (*best_model_rd != INT64_MAX &&
3945 this_model_rd > *best_model_rd + (*best_model_rd >> 1))
3946 return INT64_MAX;
3947 if (this_model_rd < *best_model_rd) *best_model_rd = this_model_rd;
hui su45dc5972016-12-08 17:42:50 -08003948 super_block_yrd(cpi, x, &tokenonly_rd_stats, bsize, best_rd_in);
3949 if (tokenonly_rd_stats.rate == INT_MAX) return INT64_MAX;
3950
3951 this_rate = tokenonly_rd_stats.rate + mode_cost +
3952 write_uniform_cost(2 * max_angle_delta + 1,
3953 mbmi->angle_delta[0] + max_angle_delta);
Urvang Joshi70006e42017-06-14 16:08:55 -07003954 this_rd = RDCOST(x->rdmult, this_rate, tokenonly_rd_stats.dist);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003955
3956 if (this_rd < *best_rd) {
3957 *best_rd = this_rd;
3958 *best_angle_delta = mbmi->angle_delta[0];
3959 *best_tx_size = mbmi->tx_size;
hui sueda3d762016-12-06 16:58:23 -08003960#if CONFIG_INTRA_INTERP
Yaowu Xuc27fc142016-08-22 16:08:15 -07003961 *best_filter = mbmi->intra_filter;
hui sueda3d762016-12-06 16:58:23 -08003962#endif // CONFIG_INTRA_INTERP
Yaowu Xuc27fc142016-08-22 16:08:15 -07003963 *best_tx_type = mbmi->tx_type;
Lester Lu432012f2017-08-17 14:39:29 -07003964#if CONFIG_LGT_FROM_PRED
3965 *use_lgt_when_selected = mbmi->use_lgt;
3966#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07003967 *rate = this_rate;
hui su45dc5972016-12-08 17:42:50 -08003968 rd_stats->rate = tokenonly_rd_stats.rate;
3969 rd_stats->dist = tokenonly_rd_stats.dist;
3970 rd_stats->skip = tokenonly_rd_stats.skip;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003971 }
hui su45dc5972016-12-08 17:42:50 -08003972 return this_rd;
Yaowu Xuc27fc142016-08-22 16:08:15 -07003973}
3974
hui su45dc5972016-12-08 17:42:50 -08003975// With given luma directional intra prediction mode, pick the best angle delta
3976// Return the RD cost corresponding to the best angle delta.
Urvang Joshi52648442016-10-13 17:27:51 -07003977static int64_t rd_pick_intra_angle_sby(const AV1_COMP *const cpi, MACROBLOCK *x,
hui su45dc5972016-12-08 17:42:50 -08003978 int *rate, RD_STATS *rd_stats,
3979 BLOCK_SIZE bsize, int mode_cost,
hui su9a416f52017-01-13 11:37:53 -08003980 int64_t best_rd,
3981 int64_t *best_model_rd) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07003982 MACROBLOCKD *const xd = &x->e_mbd;
3983 MODE_INFO *const mic = xd->mi[0];
3984 MB_MODE_INFO *mbmi = &mic->mbmi;
Urvang Joshi330aec82017-05-08 15:37:42 -07003985 assert(!is_inter_block(mbmi));
hui su45dc5972016-12-08 17:42:50 -08003986 int i, angle_delta, best_angle_delta = 0;
hui su45dc5972016-12-08 17:42:50 -08003987 int first_try = 1;
hui sueda3d762016-12-06 16:58:23 -08003988#if CONFIG_INTRA_INTERP
3989 int p_angle;
Yaowu Xuf883b422016-08-30 14:01:10 -07003990 const int intra_filter_ctx = av1_get_pred_context_intra_interp(xd);
Yaowu Xuc27fc142016-08-22 16:08:15 -07003991 INTRA_FILTER filter, best_filter = INTRA_FILTER_LINEAR;
hui sueda3d762016-12-06 16:58:23 -08003992#endif // CONFIG_INTRA_INTERP
Debargha Mukherjeedf0e0d72017-04-27 15:16:53 -07003993 int64_t this_rd, best_rd_in, rd_cost[2 * (MAX_ANGLE_DELTA + 2)];
Yaowu Xuc27fc142016-08-22 16:08:15 -07003994 TX_SIZE best_tx_size = mic->mbmi.tx_size;
3995 TX_TYPE best_tx_type = mbmi->tx_type;
Lester Lu432012f2017-08-17 14:39:29 -07003996#if CONFIG_LGT_FROM_PRED
3997 int use_lgt_when_selected = mbmi->use_lgt;
3998#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07003999
hui su0a6731f2017-04-26 15:23:47 -07004000 for (i = 0; i < 2 * (MAX_ANGLE_DELTA + 2); ++i) rd_cost[i] = INT64_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004001
hui su0a6731f2017-04-26 15:23:47 -07004002 for (angle_delta = 0; angle_delta <= MAX_ANGLE_DELTA; angle_delta += 2) {
hui sueda3d762016-12-06 16:58:23 -08004003#if CONFIG_INTRA_INTERP
hui su45dc5972016-12-08 17:42:50 -08004004 for (filter = INTRA_FILTER_LINEAR; filter < INTRA_FILTERS; ++filter) {
4005 if (FILTER_FAST_SEARCH && filter != INTRA_FILTER_LINEAR) continue;
4006 mic->mbmi.intra_filter = filter;
hui sueda3d762016-12-06 16:58:23 -08004007#endif // CONFIG_INTRA_INTERP
hui su45dc5972016-12-08 17:42:50 -08004008 for (i = 0; i < 2; ++i) {
4009 best_rd_in = (best_rd == INT64_MAX)
4010 ? INT64_MAX
4011 : (best_rd + (best_rd >> (first_try ? 3 : 5)));
4012 this_rd = calc_rd_given_intra_angle(
4013 cpi, x, bsize,
hui sueda3d762016-12-06 16:58:23 -08004014#if CONFIG_INTRA_INTERP
Yue Chenb23d00a2017-07-28 17:01:21 -07004015 mode_cost + x->intra_filter_cost[intra_filter_ctx][filter],
hui sueda3d762016-12-06 16:58:23 -08004016#else
hui su45dc5972016-12-08 17:42:50 -08004017 mode_cost,
hui sueda3d762016-12-06 16:58:23 -08004018#endif // CONFIG_INTRA_INTERP
hui su0a6731f2017-04-26 15:23:47 -07004019 best_rd_in, (1 - 2 * i) * angle_delta, MAX_ANGLE_DELTA, rate,
hui su45dc5972016-12-08 17:42:50 -08004020 rd_stats, &best_angle_delta, &best_tx_size, &best_tx_type,
Lester Lu432012f2017-08-17 14:39:29 -07004021#if CONFIG_LGT_FROM_PRED
4022 &use_lgt_when_selected,
4023#endif
hui sueda3d762016-12-06 16:58:23 -08004024#if CONFIG_INTRA_INTERP
4025 &best_filter,
4026#endif // CONFIG_INTRA_INTERP
hui su9a416f52017-01-13 11:37:53 -08004027 &best_rd, best_model_rd);
hui su45dc5972016-12-08 17:42:50 -08004028 rd_cost[2 * angle_delta + i] = this_rd;
4029 if (first_try && this_rd == INT64_MAX) return best_rd;
4030 first_try = 0;
4031 if (angle_delta == 0) {
4032 rd_cost[1] = this_rd;
4033 break;
4034 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07004035 }
hui su45dc5972016-12-08 17:42:50 -08004036#if CONFIG_INTRA_INTERP
Yaowu Xuc27fc142016-08-22 16:08:15 -07004037 }
hui su45dc5972016-12-08 17:42:50 -08004038#endif // CONFIG_INTRA_INTERP
4039 }
4040
4041 assert(best_rd != INT64_MAX);
hui su0a6731f2017-04-26 15:23:47 -07004042 for (angle_delta = 1; angle_delta <= MAX_ANGLE_DELTA; angle_delta += 2) {
hui su45dc5972016-12-08 17:42:50 -08004043 int64_t rd_thresh;
4044#if CONFIG_INTRA_INTERP
4045 for (filter = INTRA_FILTER_LINEAR; filter < INTRA_FILTERS; ++filter) {
4046 if (FILTER_FAST_SEARCH && filter != INTRA_FILTER_LINEAR) continue;
4047 mic->mbmi.intra_filter = filter;
4048#endif // CONFIG_INTRA_INTERP
4049 for (i = 0; i < 2; ++i) {
4050 int skip_search = 0;
4051 rd_thresh = best_rd + (best_rd >> 5);
4052 if (rd_cost[2 * (angle_delta + 1) + i] > rd_thresh &&
4053 rd_cost[2 * (angle_delta - 1) + i] > rd_thresh)
4054 skip_search = 1;
4055 if (!skip_search) {
Yue Chenb0f808b2017-04-26 11:55:14 -07004056 calc_rd_given_intra_angle(
hui su45dc5972016-12-08 17:42:50 -08004057 cpi, x, bsize,
4058#if CONFIG_INTRA_INTERP
Yue Chenb23d00a2017-07-28 17:01:21 -07004059 mode_cost + x->intra_filter_cost[intra_filter_ctx][filter],
hui su45dc5972016-12-08 17:42:50 -08004060#else
4061 mode_cost,
4062#endif // CONFIG_INTRA_INTERP
hui su0a6731f2017-04-26 15:23:47 -07004063 best_rd, (1 - 2 * i) * angle_delta, MAX_ANGLE_DELTA, rate,
hui su45dc5972016-12-08 17:42:50 -08004064 rd_stats, &best_angle_delta, &best_tx_size, &best_tx_type,
Lester Lu432012f2017-08-17 14:39:29 -07004065#if CONFIG_LGT_FROM_PRED
4066 &use_lgt_when_selected,
4067#endif
hui su45dc5972016-12-08 17:42:50 -08004068#if CONFIG_INTRA_INTERP
4069 &best_filter,
4070#endif // CONFIG_INTRA_INTERP
hui su9a416f52017-01-13 11:37:53 -08004071 &best_rd, best_model_rd);
hui su45dc5972016-12-08 17:42:50 -08004072 }
4073 }
4074#if CONFIG_INTRA_INTERP
4075 }
4076#endif // CONFIG_INTRA_INTERP
Yaowu Xuc27fc142016-08-22 16:08:15 -07004077 }
4078
hui sueda3d762016-12-06 16:58:23 -08004079#if CONFIG_INTRA_INTERP
hui su45dc5972016-12-08 17:42:50 -08004080 if (FILTER_FAST_SEARCH && rd_stats->rate < INT_MAX) {
hui su0a6731f2017-04-26 15:23:47 -07004081 p_angle = mode_to_angle_map[mbmi->mode] + best_angle_delta * ANGLE_STEP;
Yaowu Xuf883b422016-08-30 14:01:10 -07004082 if (av1_is_intra_filter_switchable(p_angle)) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07004083 for (filter = INTRA_FILTER_LINEAR + 1; filter < INTRA_FILTERS; ++filter) {
4084 mic->mbmi.intra_filter = filter;
hui su45dc5972016-12-08 17:42:50 -08004085 this_rd = calc_rd_given_intra_angle(
4086 cpi, x, bsize,
Yue Chenb23d00a2017-07-28 17:01:21 -07004087 mode_cost + x->intra_filter_cost[intra_filter_ctx][filter], best_rd,
4088 best_angle_delta, MAX_ANGLE_DELTA, rate, rd_stats,
Lester Lu432012f2017-08-17 14:39:29 -07004089 &best_angle_delta, &best_tx_size, &best_tx_type,
4090#if CONFIG_LGT_FROM_PRED
4091 &use_lgt_when_selected,
4092#endif
4093 &best_filter, &best_rd, best_model_rd);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004094 }
4095 }
4096 }
hui sueda3d762016-12-06 16:58:23 -08004097#endif // CONFIG_INTRA_INTERP
Yaowu Xuc27fc142016-08-22 16:08:15 -07004098
4099 mbmi->tx_size = best_tx_size;
4100 mbmi->angle_delta[0] = best_angle_delta;
hui sueda3d762016-12-06 16:58:23 -08004101#if CONFIG_INTRA_INTERP
Yaowu Xuc27fc142016-08-22 16:08:15 -07004102 mic->mbmi.intra_filter = best_filter;
hui sueda3d762016-12-06 16:58:23 -08004103#endif // CONFIG_INTRA_INTERP
Yaowu Xuc27fc142016-08-22 16:08:15 -07004104 mbmi->tx_type = best_tx_type;
Lester Lu432012f2017-08-17 14:39:29 -07004105#if CONFIG_LGT_FROM_PRED
4106 mbmi->use_lgt = use_lgt_when_selected;
4107#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07004108 return best_rd;
4109}
4110
4111// Indices are sign, integer, and fractional part of the gradient value
4112static const uint8_t gradient_to_angle_bin[2][7][16] = {
4113 {
4114 { 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0 },
4115 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1 },
4116 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
4117 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
4118 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
4119 { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
4120 { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
4121 },
4122 {
4123 { 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4 },
4124 { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3 },
4125 { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
4126 { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
4127 { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
4128 { 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
4129 { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
4130 },
4131};
4132
Yue Chen56e226e2017-05-02 16:21:40 -07004133/* clang-format off */
Yaowu Xuc27fc142016-08-22 16:08:15 -07004134static const uint8_t mode_to_angle_bin[INTRA_MODES] = {
4135 0, 2, 6, 0, 4, 3, 5, 7, 1, 0,
hui su9cc10652017-04-27 17:22:07 -07004136 0,
Yaowu Xuc27fc142016-08-22 16:08:15 -07004137};
Yue Chen56e226e2017-05-02 16:21:40 -07004138/* clang-format on */
Yaowu Xuc27fc142016-08-22 16:08:15 -07004139
4140static void angle_estimation(const uint8_t *src, int src_stride, int rows,
hui su9cc10652017-04-27 17:22:07 -07004141 int cols, BLOCK_SIZE bsize,
4142 uint8_t *directional_mode_skip_mask) {
4143 memset(directional_mode_skip_mask, 0,
4144 INTRA_MODES * sizeof(*directional_mode_skip_mask));
Joe Young830d4ce2017-05-30 17:48:13 -07004145 // Check if angle_delta is used
4146 if (!av1_use_angle_delta(bsize)) return;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004147 uint64_t hist[DIRECTIONAL_MODES];
Yaowu Xuc27fc142016-08-22 16:08:15 -07004148 memset(hist, 0, DIRECTIONAL_MODES * sizeof(hist[0]));
4149 src += src_stride;
hui su9cc10652017-04-27 17:22:07 -07004150 int r, c, dx, dy;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004151 for (r = 1; r < rows; ++r) {
4152 for (c = 1; c < cols; ++c) {
4153 dx = src[c] - src[c - 1];
4154 dy = src[c] - src[c - src_stride];
hui su9cc10652017-04-27 17:22:07 -07004155 int index;
4156 const int temp = dx * dx + dy * dy;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004157 if (dy == 0) {
4158 index = 2;
4159 } else {
hui su9cc10652017-04-27 17:22:07 -07004160 const int sn = (dx > 0) ^ (dy > 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004161 dx = abs(dx);
4162 dy = abs(dy);
hui su9cc10652017-04-27 17:22:07 -07004163 const int remd = (dx % dy) * 16 / dy;
4164 const int quot = dx / dy;
Yaowu Xuf883b422016-08-30 14:01:10 -07004165 index = gradient_to_angle_bin[sn][AOMMIN(quot, 6)][AOMMIN(remd, 15)];
Yaowu Xuc27fc142016-08-22 16:08:15 -07004166 }
4167 hist[index] += temp;
4168 }
4169 src += src_stride;
4170 }
4171
hui su9cc10652017-04-27 17:22:07 -07004172 int i;
4173 uint64_t hist_sum = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004174 for (i = 0; i < DIRECTIONAL_MODES; ++i) hist_sum += hist[i];
4175 for (i = 0; i < INTRA_MODES; ++i) {
hui su9cc10652017-04-27 17:22:07 -07004176 if (av1_is_directional_mode(i, bsize)) {
Urvang Joshida70e7b2016-10-19 11:48:54 -07004177 const uint8_t angle_bin = mode_to_angle_bin[i];
4178 uint64_t score = 2 * hist[angle_bin];
Yaowu Xuc27fc142016-08-22 16:08:15 -07004179 int weight = 2;
Urvang Joshida70e7b2016-10-19 11:48:54 -07004180 if (angle_bin > 0) {
4181 score += hist[angle_bin - 1];
4182 ++weight;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004183 }
Urvang Joshida70e7b2016-10-19 11:48:54 -07004184 if (angle_bin < DIRECTIONAL_MODES - 1) {
4185 score += hist[angle_bin + 1];
4186 ++weight;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004187 }
4188 if (score * ANGLE_SKIP_THRESH < hist_sum * weight)
4189 directional_mode_skip_mask[i] = 1;
4190 }
4191 }
4192}
4193
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02004194#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07004195static void highbd_angle_estimation(const uint8_t *src8, int src_stride,
hui su9cc10652017-04-27 17:22:07 -07004196 int rows, int cols, BLOCK_SIZE bsize,
Yaowu Xuc27fc142016-08-22 16:08:15 -07004197 uint8_t *directional_mode_skip_mask) {
hui su9cc10652017-04-27 17:22:07 -07004198 memset(directional_mode_skip_mask, 0,
4199 INTRA_MODES * sizeof(*directional_mode_skip_mask));
Joe Young830d4ce2017-05-30 17:48:13 -07004200 // Check if angle_delta is used
4201 if (!av1_use_angle_delta(bsize)) return;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004202 uint16_t *src = CONVERT_TO_SHORTPTR(src8);
hui su9cc10652017-04-27 17:22:07 -07004203 uint64_t hist[DIRECTIONAL_MODES];
Yaowu Xuc27fc142016-08-22 16:08:15 -07004204 memset(hist, 0, DIRECTIONAL_MODES * sizeof(hist[0]));
4205 src += src_stride;
hui su9cc10652017-04-27 17:22:07 -07004206 int r, c, dx, dy;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004207 for (r = 1; r < rows; ++r) {
4208 for (c = 1; c < cols; ++c) {
4209 dx = src[c] - src[c - 1];
4210 dy = src[c] - src[c - src_stride];
hui su9cc10652017-04-27 17:22:07 -07004211 int index;
4212 const int temp = dx * dx + dy * dy;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004213 if (dy == 0) {
4214 index = 2;
4215 } else {
hui su9cc10652017-04-27 17:22:07 -07004216 const int sn = (dx > 0) ^ (dy > 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004217 dx = abs(dx);
4218 dy = abs(dy);
hui su9cc10652017-04-27 17:22:07 -07004219 const int remd = (dx % dy) * 16 / dy;
4220 const int quot = dx / dy;
Yaowu Xuf883b422016-08-30 14:01:10 -07004221 index = gradient_to_angle_bin[sn][AOMMIN(quot, 6)][AOMMIN(remd, 15)];
Yaowu Xuc27fc142016-08-22 16:08:15 -07004222 }
4223 hist[index] += temp;
4224 }
4225 src += src_stride;
4226 }
4227
hui su9cc10652017-04-27 17:22:07 -07004228 int i;
4229 uint64_t hist_sum = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004230 for (i = 0; i < DIRECTIONAL_MODES; ++i) hist_sum += hist[i];
4231 for (i = 0; i < INTRA_MODES; ++i) {
hui su9cc10652017-04-27 17:22:07 -07004232 if (av1_is_directional_mode(i, bsize)) {
Urvang Joshida70e7b2016-10-19 11:48:54 -07004233 const uint8_t angle_bin = mode_to_angle_bin[i];
4234 uint64_t score = 2 * hist[angle_bin];
Yaowu Xuc27fc142016-08-22 16:08:15 -07004235 int weight = 2;
Urvang Joshida70e7b2016-10-19 11:48:54 -07004236 if (angle_bin > 0) {
4237 score += hist[angle_bin - 1];
4238 ++weight;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004239 }
Urvang Joshida70e7b2016-10-19 11:48:54 -07004240 if (angle_bin < DIRECTIONAL_MODES - 1) {
4241 score += hist[angle_bin + 1];
4242 ++weight;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004243 }
4244 if (score * ANGLE_SKIP_THRESH < hist_sum * weight)
4245 directional_mode_skip_mask[i] = 1;
4246 }
4247 }
4248}
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02004249#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07004250#endif // CONFIG_EXT_INTRA
4251
4252// This function is used only for intra_only frames
Urvang Joshi52648442016-10-13 17:27:51 -07004253static int64_t rd_pick_intra_sby_mode(const AV1_COMP *const cpi, MACROBLOCK *x,
4254 int *rate, int *rate_tokenonly,
4255 int64_t *distortion, int *skippable,
4256 BLOCK_SIZE bsize, int64_t best_rd) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07004257 MACROBLOCKD *const xd = &x->e_mbd;
4258 MODE_INFO *const mic = xd->mi[0];
hui sude0c70a2017-01-09 17:12:17 -08004259 MB_MODE_INFO *const mbmi = &mic->mbmi;
Urvang Joshi330aec82017-05-08 15:37:42 -07004260 assert(!is_inter_block(mbmi));
hui sude0c70a2017-01-09 17:12:17 -08004261 MB_MODE_INFO best_mbmi = *mbmi;
hui su308a6392017-01-12 14:49:57 -08004262 int64_t best_model_rd = INT64_MAX;
hui sude0c70a2017-01-09 17:12:17 -08004263#if CONFIG_EXT_INTRA
Jingning Hanae5cfde2016-11-30 12:01:44 -08004264 const int rows = block_size_high[bsize];
4265 const int cols = block_size_wide[bsize];
hui sueda3d762016-12-06 16:58:23 -08004266#if CONFIG_INTRA_INTERP
Yaowu Xuf883b422016-08-30 14:01:10 -07004267 const int intra_filter_ctx = av1_get_pred_context_intra_interp(xd);
hui sueda3d762016-12-06 16:58:23 -08004268#endif // CONFIG_INTRA_INTERP
hui sude0c70a2017-01-09 17:12:17 -08004269 int is_directional_mode;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004270 uint8_t directional_mode_skip_mask[INTRA_MODES];
Yaowu Xuc27fc142016-08-22 16:08:15 -07004271 const int src_stride = x->plane[0].src.stride;
4272 const uint8_t *src = x->plane[0].src.buf;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004273#endif // CONFIG_EXT_INTRA
hui su5db97432016-10-14 16:10:14 -07004274#if CONFIG_FILTER_INTRA
4275 int beat_best_rd = 0;
hui su5db97432016-10-14 16:10:14 -07004276 uint16_t filter_intra_mode_skip_mask = (1 << FILTER_INTRA_MODES) - 1;
4277#endif // CONFIG_FILTER_INTRA
Urvang Joshi52648442016-10-13 17:27:51 -07004278 const int *bmode_costs;
hui sude0c70a2017-01-09 17:12:17 -08004279 PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
Urvang Joshi23a61112017-01-30 14:59:27 -08004280 int palette_y_mode_ctx = 0;
Hui Sue87fb232017-10-05 15:00:15 -07004281 const int try_palette =
4282 av1_allow_palette(cpi->common.allow_screen_content_tools, mbmi->sb_type);
4283 uint8_t *best_palette_color_map =
4284 try_palette ? x->palette_buffer->best_palette_color_map : NULL;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004285 const MODE_INFO *above_mi = xd->above_mi;
4286 const MODE_INFO *left_mi = xd->left_mi;
Yaowu Xuf883b422016-08-30 14:01:10 -07004287 const PREDICTION_MODE A = av1_above_block_mode(mic, above_mi, 0);
4288 const PREDICTION_MODE L = av1_left_block_mode(mic, left_mi, 0);
Urvang Joshi96d1c0a2017-10-10 13:15:32 -07004289 const PREDICTION_MODE FINAL_MODE_SEARCH = PAETH_PRED + 1;
Yushin Cho77bba8d2016-11-04 16:36:56 -07004290#if CONFIG_PVQ
4291 od_rollback_buffer pre_buf, post_buf;
4292
4293 od_encode_checkpoint(&x->daala_enc, &pre_buf);
4294 od_encode_checkpoint(&x->daala_enc, &post_buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08004295#endif // CONFIG_PVQ
Jingning Hana45d8422017-10-05 09:57:38 -07004296
4297#if CONFIG_KF_CTX
4298 const int above_ctx = intra_mode_context[A];
4299 const int left_ctx = intra_mode_context[L];
4300 bmode_costs = x->y_mode_costs[above_ctx][left_ctx];
4301#else
Yue Chenb23d00a2017-07-28 17:01:21 -07004302 bmode_costs = x->y_mode_costs[A][L];
Jingning Hana45d8422017-10-05 09:57:38 -07004303#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07004304
4305#if CONFIG_EXT_INTRA
hui sude0c70a2017-01-09 17:12:17 -08004306 mbmi->angle_delta[0] = 0;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02004307#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07004308 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
hui su9cc10652017-04-27 17:22:07 -07004309 highbd_angle_estimation(src, src_stride, rows, cols, bsize,
Yaowu Xuc27fc142016-08-22 16:08:15 -07004310 directional_mode_skip_mask);
4311 else
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02004312#endif // CONFIG_HIGHBITDEPTH
hui su9cc10652017-04-27 17:22:07 -07004313 angle_estimation(src, src_stride, rows, cols, bsize,
4314 directional_mode_skip_mask);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004315#endif // CONFIG_EXT_INTRA
hui su5db97432016-10-14 16:10:14 -07004316#if CONFIG_FILTER_INTRA
hui sude0c70a2017-01-09 17:12:17 -08004317 mbmi->filter_intra_mode_info.use_filter_intra_mode[0] = 0;
hui su5db97432016-10-14 16:10:14 -07004318#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07004319 pmi->palette_size[0] = 0;
Hui Sue87fb232017-10-05 15:00:15 -07004320 if (try_palette) {
4321 if (above_mi) {
4322 palette_y_mode_ctx +=
4323 (above_mi->mbmi.palette_mode_info.palette_size[0] > 0);
4324 }
4325 if (left_mi) {
4326 palette_y_mode_ctx +=
4327 (left_mi->mbmi.palette_mode_info.palette_size[0] > 0);
4328 }
4329 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07004330
4331 if (cpi->sf.tx_type_search.fast_intra_tx_type_search)
4332 x->use_default_intra_tx_type = 1;
4333 else
4334 x->use_default_intra_tx_type = 0;
4335
4336 /* Y Search for intra prediction mode */
hui su8a516a82017-07-06 10:00:36 -07004337 for (int mode_idx = DC_PRED; mode_idx <= FINAL_MODE_SEARCH; ++mode_idx) {
Angie Chiang0e9a2e92016-11-08 09:45:40 -08004338 RD_STATS this_rd_stats;
hui su308a6392017-01-12 14:49:57 -08004339 int this_rate, this_rate_tokenonly, s;
4340 int64_t this_distortion, this_rd, this_model_rd;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004341 if (mode_idx == FINAL_MODE_SEARCH) {
4342 if (x->use_default_intra_tx_type == 0) break;
hui sude0c70a2017-01-09 17:12:17 -08004343 mbmi->mode = best_mbmi.mode;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004344 x->use_default_intra_tx_type = 0;
4345 } else {
hui su8a516a82017-07-06 10:00:36 -07004346 assert(mode_idx < INTRA_MODES);
4347 mbmi->mode = intra_rd_search_mode_order[mode_idx];
Yaowu Xuc27fc142016-08-22 16:08:15 -07004348 }
Yushin Cho77bba8d2016-11-04 16:36:56 -07004349#if CONFIG_PVQ
4350 od_encode_rollback(&x->daala_enc, &pre_buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08004351#endif // CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -07004352#if CONFIG_EXT_INTRA
hui su308a6392017-01-12 14:49:57 -08004353 mbmi->angle_delta[0] = 0;
4354#endif // CONFIG_EXT_INTRA
hui su9a416f52017-01-13 11:37:53 -08004355 this_model_rd = intra_model_yrd(cpi, x, bsize, bmode_costs[mbmi->mode]);
hui su308a6392017-01-12 14:49:57 -08004356 if (best_model_rd != INT64_MAX &&
4357 this_model_rd > best_model_rd + (best_model_rd >> 1))
4358 continue;
4359 if (this_model_rd < best_model_rd) best_model_rd = this_model_rd;
4360#if CONFIG_EXT_INTRA
hui sude0c70a2017-01-09 17:12:17 -08004361 is_directional_mode = av1_is_directional_mode(mbmi->mode, bsize);
4362 if (is_directional_mode && directional_mode_skip_mask[mbmi->mode]) continue;
Joe Young830d4ce2017-05-30 17:48:13 -07004363 if (is_directional_mode && av1_use_angle_delta(bsize)) {
hui su45dc5972016-12-08 17:42:50 -08004364 this_rd_stats.rate = INT_MAX;
Yue Chenb0f808b2017-04-26 11:55:14 -07004365 rd_pick_intra_angle_sby(cpi, x, &this_rate, &this_rd_stats, bsize,
4366 bmode_costs[mbmi->mode], best_rd, &best_model_rd);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004367 } else {
Angie Chiang0e9a2e92016-11-08 09:45:40 -08004368 super_block_yrd(cpi, x, &this_rd_stats, bsize, best_rd);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004369 }
4370#else
Angie Chiang0e9a2e92016-11-08 09:45:40 -08004371 super_block_yrd(cpi, x, &this_rd_stats, bsize, best_rd);
hui su45dc5972016-12-08 17:42:50 -08004372#endif // CONFIG_EXT_INTRA
Angie Chiang0e9a2e92016-11-08 09:45:40 -08004373 this_rate_tokenonly = this_rd_stats.rate;
4374 this_distortion = this_rd_stats.dist;
4375 s = this_rd_stats.skip;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004376
4377 if (this_rate_tokenonly == INT_MAX) continue;
4378
hui sude0c70a2017-01-09 17:12:17 -08004379 this_rate = this_rate_tokenonly + bmode_costs[mbmi->mode];
Yaowu Xuc27fc142016-08-22 16:08:15 -07004380
Rupert Swarbrickfcff0b22017-10-05 09:26:04 +01004381 if (!xd->lossless[mbmi->segment_id] &&
4382 block_signals_txsize(mbmi->sb_type)) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07004383 // super_block_yrd above includes the cost of the tx_size in the
4384 // tokenonly rate, but for intra blocks, tx_size is always coded
4385 // (prediction granularity), so we account for it in the full rate,
4386 // not the tokenonly rate.
Urvang Joshifeb925f2016-12-05 10:37:29 -08004387 this_rate_tokenonly -= tx_size_cost(cpi, x, bsize, mbmi->tx_size);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004388 }
hui su9bc1d8d2017-03-24 12:36:03 -07004389 if (try_palette && mbmi->mode == DC_PRED) {
Urvang Joshi23a61112017-01-30 14:59:27 -08004390 this_rate +=
4391 av1_cost_bit(av1_default_palette_y_mode_prob[bsize - BLOCK_8X8]
4392 [palette_y_mode_ctx],
4393 0);
hui su9bc1d8d2017-03-24 12:36:03 -07004394 }
hui su5db97432016-10-14 16:10:14 -07004395#if CONFIG_FILTER_INTRA
hui sude0c70a2017-01-09 17:12:17 -08004396 if (mbmi->mode == DC_PRED)
hui su5db97432016-10-14 16:10:14 -07004397 this_rate += av1_cost_bit(cpi->common.fc->filter_intra_probs[0], 0);
4398#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07004399#if CONFIG_EXT_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07004400 if (is_directional_mode) {
hui sueda3d762016-12-06 16:58:23 -08004401#if CONFIG_INTRA_INTERP
hui su0a6731f2017-04-26 15:23:47 -07004402 const int p_angle =
4403 mode_to_angle_map[mbmi->mode] + mbmi->angle_delta[0] * ANGLE_STEP;
Yaowu Xuf883b422016-08-30 14:01:10 -07004404 if (av1_is_intra_filter_switchable(p_angle))
Yue Chenb23d00a2017-07-28 17:01:21 -07004405 this_rate += x->intra_filter_cost[intra_filter_ctx][mbmi->intra_filter];
hui sueda3d762016-12-06 16:58:23 -08004406#endif // CONFIG_INTRA_INTERP
Joe Young830d4ce2017-05-30 17:48:13 -07004407 if (av1_use_angle_delta(bsize)) {
4408 this_rate += write_uniform_cost(2 * MAX_ANGLE_DELTA + 1,
4409 MAX_ANGLE_DELTA + mbmi->angle_delta[0]);
4410 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07004411 }
4412#endif // CONFIG_EXT_INTRA
Hui Su8dc00922017-09-14 16:15:55 -07004413#if CONFIG_INTRABC
4414 if (bsize >= BLOCK_8X8 && cpi->common.allow_screen_content_tools)
4415 this_rate += x->intrabc_cost[0];
4416#endif // CONFIG_INTRABC
Urvang Joshi70006e42017-06-14 16:08:55 -07004417 this_rd = RDCOST(x->rdmult, this_rate, this_distortion);
hui su5db97432016-10-14 16:10:14 -07004418#if CONFIG_FILTER_INTRA
Debargha Mukherjee1ae9f2c2016-10-04 14:30:16 -07004419 if (best_rd == INT64_MAX || this_rd - best_rd < (best_rd >> 4)) {
hui sude0c70a2017-01-09 17:12:17 -08004420 filter_intra_mode_skip_mask ^= (1 << mbmi->mode);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004421 }
hui su5db97432016-10-14 16:10:14 -07004422#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07004423
4424 if (this_rd < best_rd) {
hui sude0c70a2017-01-09 17:12:17 -08004425 best_mbmi = *mbmi;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004426 best_rd = this_rd;
hui su5db97432016-10-14 16:10:14 -07004427#if CONFIG_FILTER_INTRA
4428 beat_best_rd = 1;
4429#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07004430 *rate = this_rate;
4431 *rate_tokenonly = this_rate_tokenonly;
4432 *distortion = this_distortion;
4433 *skippable = s;
Yushin Cho77bba8d2016-11-04 16:36:56 -07004434#if CONFIG_PVQ
4435 od_encode_checkpoint(&x->daala_enc, &post_buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08004436#endif // CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -07004437 }
4438 }
4439
Yushin Cho77bba8d2016-11-04 16:36:56 -07004440#if CONFIG_PVQ
4441 od_encode_rollback(&x->daala_enc, &post_buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08004442#endif // CONFIG_PVQ
Yushin Cho77bba8d2016-11-04 16:36:56 -07004443
hui su9bc1d8d2017-03-24 12:36:03 -07004444 if (try_palette) {
Urvang Joshi23a61112017-01-30 14:59:27 -08004445 rd_pick_palette_intra_sby(cpi, x, bsize, palette_y_mode_ctx,
4446 bmode_costs[DC_PRED], &best_mbmi,
4447 best_palette_color_map, &best_rd, &best_model_rd,
4448 rate, rate_tokenonly, distortion, skippable);
hui sude0c70a2017-01-09 17:12:17 -08004449 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07004450
hui su5db97432016-10-14 16:10:14 -07004451#if CONFIG_FILTER_INTRA
4452 if (beat_best_rd) {
4453 if (rd_pick_filter_intra_sby(cpi, x, rate, rate_tokenonly, distortion,
4454 skippable, bsize, bmode_costs[DC_PRED],
hui su8f4cc0a2017-01-13 15:14:49 -08004455 &best_rd, &best_model_rd,
4456 filter_intra_mode_skip_mask)) {
hui sude0c70a2017-01-09 17:12:17 -08004457 best_mbmi = *mbmi;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004458 }
4459 }
hui su5db97432016-10-14 16:10:14 -07004460#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07004461
hui sude0c70a2017-01-09 17:12:17 -08004462 *mbmi = best_mbmi;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004463 return best_rd;
4464}
4465
Yue Chena1e48dc2016-08-29 17:29:33 -07004466// Return value 0: early termination triggered, no valid rd cost available;
4467// 1: rd cost values are valid.
Angie Chiang284d7772016-11-08 11:06:45 -08004468static int super_block_uvrd(const AV1_COMP *const cpi, MACROBLOCK *x,
4469 RD_STATS *rd_stats, BLOCK_SIZE bsize,
4470 int64_t ref_best_rd) {
Yue Chena1e48dc2016-08-29 17:29:33 -07004471 MACROBLOCKD *const xd = &x->e_mbd;
4472 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
hui su0c6244b2017-07-12 17:11:43 -07004473 const TX_SIZE uv_tx_size = av1_get_uv_tx_size(mbmi, &xd->plane[1]);
Yue Chena1e48dc2016-08-29 17:29:33 -07004474 int plane;
Yue Chena1e48dc2016-08-29 17:29:33 -07004475 int is_cost_valid = 1;
Angie Chiang284d7772016-11-08 11:06:45 -08004476 av1_init_rd_stats(rd_stats);
Yue Chena1e48dc2016-08-29 17:29:33 -07004477
4478 if (ref_best_rd < 0) is_cost_valid = 0;
Jingning Han9ce464c2017-02-20 15:36:30 -08004479
Jingning Han31b6a4f2017-02-23 11:05:53 -08004480#if CONFIG_CB4X4 && !CONFIG_CHROMA_2X2
Jingning Han9ce464c2017-02-20 15:36:30 -08004481 if (x->skip_chroma_rd) return is_cost_valid;
Jingning Han2d2dac22017-04-11 09:41:10 -07004482
4483 bsize = scale_chroma_bsize(bsize, xd->plane[1].subsampling_x,
4484 xd->plane[1].subsampling_y);
Fergus Simpson4063a682017-02-28 16:52:22 -08004485#endif // CONFIG_CB4X4 && !CONFIG_CHROMA_2X2
Jingning Han9ce464c2017-02-20 15:36:30 -08004486
Yushin Cho77bba8d2016-11-04 16:36:56 -07004487#if !CONFIG_PVQ
Yue Chena1e48dc2016-08-29 17:29:33 -07004488 if (is_inter_block(mbmi) && is_cost_valid) {
Yue Chena1e48dc2016-08-29 17:29:33 -07004489 for (plane = 1; plane < MAX_MB_PLANE; ++plane)
4490 av1_subtract_plane(x, bsize, plane);
4491 }
Fergus Simpson4063a682017-02-28 16:52:22 -08004492#endif // !CONFIG_PVQ
Yue Chena1e48dc2016-08-29 17:29:33 -07004493
Yushin Cho09de28b2016-06-21 14:51:23 -07004494 if (is_cost_valid) {
4495 for (plane = 1; plane < MAX_MB_PLANE; ++plane) {
Angie Chiang7c2b7f22016-11-07 16:00:00 -08004496 RD_STATS pn_rd_stats;
4497 txfm_rd_in_plane(x, cpi, &pn_rd_stats, ref_best_rd, plane, bsize,
4498 uv_tx_size, cpi->sf.use_fast_coef_costing);
4499 if (pn_rd_stats.rate == INT_MAX) {
Yushin Cho09de28b2016-06-21 14:51:23 -07004500 is_cost_valid = 0;
4501 break;
4502 }
Angie Chiang284d7772016-11-08 11:06:45 -08004503 av1_merge_rd_stats(rd_stats, &pn_rd_stats);
Urvang Joshi70006e42017-06-14 16:08:55 -07004504 if (RDCOST(x->rdmult, rd_stats->rate, rd_stats->dist) > ref_best_rd &&
4505 RDCOST(x->rdmult, 0, rd_stats->sse) > ref_best_rd) {
Yushin Cho09de28b2016-06-21 14:51:23 -07004506 is_cost_valid = 0;
4507 break;
4508 }
Yue Chena1e48dc2016-08-29 17:29:33 -07004509 }
4510 }
4511
4512 if (!is_cost_valid) {
4513 // reset cost value
Angie Chiang284d7772016-11-08 11:06:45 -08004514 av1_invalid_rd_stats(rd_stats);
Yue Chena1e48dc2016-08-29 17:29:33 -07004515 }
4516
4517 return is_cost_valid;
4518}
4519
Yaowu Xuc27fc142016-08-22 16:08:15 -07004520#if CONFIG_VAR_TX
Yaowu Xuf883b422016-08-30 14:01:10 -07004521void av1_tx_block_rd_b(const AV1_COMP *cpi, MACROBLOCK *x, TX_SIZE tx_size,
4522 int blk_row, int blk_col, int plane, int block,
Angie Chiang77368af2017-03-23 16:22:07 -07004523 int plane_bsize, const ENTROPY_CONTEXT *a,
4524 const ENTROPY_CONTEXT *l, RD_STATS *rd_stats) {
Angie Chiang22ba7512016-10-20 17:10:33 -07004525 const AV1_COMMON *const cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004526 MACROBLOCKD *xd = &x->e_mbd;
4527 const struct macroblock_plane *const p = &x->plane[plane];
4528 struct macroblockd_plane *const pd = &xd->plane[plane];
Jingning Han243b66b2017-06-23 12:11:47 -07004529
4530#if CONFIG_TXK_SEL
4531 av1_search_txk_type(cpi, x, plane, block, blk_row, blk_col, plane_bsize,
4532 tx_size, a, l, 0, rd_stats);
4533 return;
4534#endif
4535
Yaowu Xuc27fc142016-08-22 16:08:15 -07004536 int64_t tmp;
4537 tran_low_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
Sarah Parker99e7daa2017-08-29 10:30:13 -07004538#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
4539 uint8_t *mrc_mask = BLOCK_OFFSET(xd->mrc_mask, block);
4540#endif // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
Luc Trudeau005feb62017-02-22 13:34:01 -05004541 PLANE_TYPE plane_type = get_plane_type(plane);
Jingning Han19b5c8f2017-07-06 15:10:12 -07004542 TX_TYPE tx_type =
4543 av1_get_tx_type(plane_type, xd, blk_row, blk_col, block, tx_size);
Urvang Joshi03f6fdc2016-10-14 15:53:39 -07004544 const SCAN_ORDER *const scan_order =
Angie Chiangbd99b382017-06-20 15:11:16 -07004545 get_scan(cm, tx_size, tx_type, &xd->mi[0]->mbmi);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004546 BLOCK_SIZE txm_bsize = txsize_to_bsize[tx_size];
Jingning Han9fdc4222016-10-27 21:32:19 -07004547 int bh = block_size_high[txm_bsize];
4548 int bw = block_size_wide[txm_bsize];
Yaowu Xuc27fc142016-08-22 16:08:15 -07004549 int src_stride = p->src.stride;
Jingning Han9ca05b72017-01-03 14:41:36 -08004550 uint8_t *src =
4551 &p->src.buf[(blk_row * src_stride + blk_col) << tx_size_wide_log2[0]];
4552 uint8_t *dst =
4553 &pd->dst
4554 .buf[(blk_row * pd->dst.stride + blk_col) << tx_size_wide_log2[0]];
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02004555#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07004556 DECLARE_ALIGNED(16, uint16_t, rec_buffer16[MAX_TX_SQUARE]);
4557 uint8_t *rec_buffer;
4558#else
4559 DECLARE_ALIGNED(16, uint8_t, rec_buffer[MAX_TX_SQUARE]);
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02004560#endif // CONFIG_HIGHBITDEPTH
Timothy B. Terriberryd62e2a32017-06-10 16:04:21 -07004561 const int diff_stride = block_size_wide[plane_bsize];
Jingning Han9ca05b72017-01-03 14:41:36 -08004562 const int16_t *diff =
4563 &p->src_diff[(blk_row * diff_stride + blk_col) << tx_size_wide_log2[0]];
Angie Chiangd81fdb42016-11-03 12:20:58 -07004564 int txb_coeff_cost;
Jingning Hand3fada82016-11-22 10:46:55 -08004565
4566 assert(tx_size < TX_SIZES_ALL);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004567
Angie Chiang77368af2017-03-23 16:22:07 -07004568 int coeff_ctx = get_entropy_context(tx_size, a, l);
4569
Jingning Han1a7f0a82017-07-27 09:48:05 -07004570 tmp = pixel_diff_dist(x, plane, diff, diff_stride, blk_row, blk_col,
4571 plane_bsize, txm_bsize);
4572
4573#if CONFIG_HIGHBITDEPTH
4574 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
4575 tmp = ROUND_POWER_OF_TWO(tmp, (xd->bd - 8) * 2);
4576#endif // CONFIG_HIGHBITDEPTH
4577 rd_stats->sse += tmp << 4;
4578
4579 if (rd_stats->invalid_rate) {
4580 rd_stats->dist += tmp << 4;
4581 rd_stats->rate += rd_stats->zero_rate;
4582 rd_stats->skip = 1;
4583 return;
4584 }
4585
Angie Chiang808d8592017-04-06 18:36:55 -07004586// TODO(any): Use av1_dist_block to compute distortion
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02004587#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07004588 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
4589 rec_buffer = CONVERT_TO_BYTEPTR(rec_buffer16);
Yaowu Xuf883b422016-08-30 14:01:10 -07004590 aom_highbd_convolve_copy(dst, pd->dst.stride, rec_buffer, MAX_TX_SIZE, NULL,
Jingning Han9fdc4222016-10-27 21:32:19 -07004591 0, NULL, 0, bw, bh, xd->bd);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004592 } else {
4593 rec_buffer = (uint8_t *)rec_buffer16;
Yaowu Xuf883b422016-08-30 14:01:10 -07004594 aom_convolve_copy(dst, pd->dst.stride, rec_buffer, MAX_TX_SIZE, NULL, 0,
Jingning Han9fdc4222016-10-27 21:32:19 -07004595 NULL, 0, bw, bh);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004596 }
4597#else
Yaowu Xuf883b422016-08-30 14:01:10 -07004598 aom_convolve_copy(dst, pd->dst.stride, rec_buffer, MAX_TX_SIZE, NULL, 0, NULL,
Jingning Han9fdc4222016-10-27 21:32:19 -07004599 0, bw, bh);
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02004600#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07004601
Jingning Han3bce7542017-07-25 10:53:57 -07004602#if DISABLE_TRELLISQ_SEARCH
4603 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
4604 coeff_ctx, AV1_XFORM_QUANT_B);
4605
4606#else
4607 av1_xform_quant(cm, x, plane, block, blk_row, blk_col, plane_bsize, tx_size,
4608 coeff_ctx, AV1_XFORM_QUANT_FP);
4609
4610 const int shift = (MAX_TX_SCALE - av1_get_tx_scale(tx_size)) * 2;
4611 tran_low_t *const coeff = BLOCK_OFFSET(p->coeff, block);
4612 const int buffer_length = tx_size_2d[tx_size];
Jingning Han1a7f0a82017-07-27 09:48:05 -07004613 int64_t tmp_dist, tmp_sse;
Yunqing Wang24d2d5d2017-09-20 09:45:13 -07004614#if CONFIG_DIST_8X8
Yushin Choc00769a2017-09-14 14:44:30 -07004615 int disable_early_skip =
4616 x->using_dist_8x8 && plane == 0 && plane_bsize >= BLOCK_8X8 &&
4617 (tx_size == TX_4X4 || tx_size == TX_4X8 || tx_size == TX_8X4) &&
4618 x->tune_metric != AOM_TUNE_PSNR;
Yunqing Wang24d2d5d2017-09-20 09:45:13 -07004619#endif // CONFIG_DIST_8X8
4620
Jingning Han3bce7542017-07-25 10:53:57 -07004621#if CONFIG_HIGHBITDEPTH
4622 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
Debargha Mukherjeeb02d2f32017-10-03 11:06:40 -07004623 tmp_dist =
4624 av1_highbd_block_error(coeff, dqcoeff, buffer_length, &tmp_sse, xd->bd);
Jingning Han3bce7542017-07-25 10:53:57 -07004625 else
4626#endif
Debargha Mukherjeeb02d2f32017-10-03 11:06:40 -07004627 tmp_dist = av1_block_error(coeff, dqcoeff, buffer_length, &tmp_sse);
4628
4629 tmp_dist = RIGHT_SIGNED_SHIFT(tmp_dist, shift);
Jingning Han3bce7542017-07-25 10:53:57 -07004630
Sarah Parkerde6f0722017-08-07 20:23:46 -07004631#if CONFIG_MRC_TX
4632 if (tx_type == MRC_DCT && !xd->mi[0]->mbmi.valid_mrc_mask) {
4633 av1_invalid_rd_stats(rd_stats);
4634 return;
4635 }
4636#endif // CONFIG_MRC_TX
Yushin Choa4817a62017-07-27 13:09:43 -07004637 if (
4638#if CONFIG_DIST_8X8
Yushin Choc00769a2017-09-14 14:44:30 -07004639 disable_early_skip ||
Yushin Choa4817a62017-07-27 13:09:43 -07004640#endif
4641 RDCOST(x->rdmult, 0, tmp_dist) < rd_stats->ref_rdcost) {
Jingning Han3bce7542017-07-25 10:53:57 -07004642 av1_optimize_b(cm, x, plane, blk_row, blk_col, block, plane_bsize, tx_size,
Angie Chiang25645b72017-09-24 14:28:49 -07004643 a, l, 1);
Jingning Han1a7f0a82017-07-27 09:48:05 -07004644 } else {
4645 rd_stats->rate += rd_stats->zero_rate;
Yushin Cho952eae22017-10-03 16:21:06 -07004646 rd_stats->dist += tmp << 4;
Jingning Han1a7f0a82017-07-27 09:48:05 -07004647 rd_stats->skip = 1;
4648 rd_stats->invalid_rate = 1;
4649 return;
Jingning Han3bce7542017-07-25 10:53:57 -07004650 }
4651#endif // DISABLE_TRELLISQ_SEARCH
4652
Angie Chiang41fffae2017-04-03 10:33:18 -07004653 const int eob = p->eobs[block];
Yaowu Xuc27fc142016-08-22 16:08:15 -07004654
Lester Lu918fe692017-08-17 14:39:29 -07004655 av1_inverse_transform_block(xd, dqcoeff,
Lester Lu432012f2017-08-17 14:39:29 -07004656#if CONFIG_LGT_FROM_PRED
Lester Lu918fe692017-08-17 14:39:29 -07004657 xd->mi[0]->mbmi.mode,
Lester Lu708c1ec2017-06-14 14:54:49 -07004658#endif
Sarah Parker99e7daa2017-08-29 10:30:13 -07004659#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
4660 mrc_mask,
4661#endif // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
Lester Lu918fe692017-08-17 14:39:29 -07004662 tx_type, tx_size, rec_buffer, MAX_TX_SIZE, eob);
Angie Chiang41fffae2017-04-03 10:33:18 -07004663 if (eob > 0) {
Yushin Chob7b60c52017-07-14 16:18:52 -07004664#if CONFIG_DIST_8X8
Yushin Cho55104332017-08-14 16:15:43 -07004665 if (x->using_dist_8x8 && plane == 0 && (bw < 8 && bh < 8)) {
Yushin Cho04749122017-05-25 14:19:07 -07004666 // Save sub8x8 luma decoded pixels
4667 // since 8x8 luma decoded pixels are not available for daala-dist
4668 // after recursive split of BLOCK_8x8 is done.
4669 const int pred_stride = block_size_wide[plane_bsize];
4670 const int pred_idx = (blk_row * pred_stride + blk_col)
4671 << tx_size_wide_log2[0];
4672 int16_t *decoded = &pd->pred[pred_idx];
4673 int i, j;
4674
Yushin Cho8ab875d2017-06-23 14:47:21 -07004675#if CONFIG_HIGHBITDEPTH
4676 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
4677 for (j = 0; j < bh; j++)
4678 for (i = 0; i < bw; i++)
4679 decoded[j * pred_stride + i] =
4680 CONVERT_TO_SHORTPTR(rec_buffer)[j * MAX_TX_SIZE + i];
4681 } else {
4682#endif
4683 for (j = 0; j < bh; j++)
4684 for (i = 0; i < bw; i++)
4685 decoded[j * pred_stride + i] = rec_buffer[j * MAX_TX_SIZE + i];
4686#if CONFIG_HIGHBITDEPTH
4687 }
4688#endif // CONFIG_HIGHBITDEPTH
Yushin Cho04749122017-05-25 14:19:07 -07004689 }
Yushin Chob7b60c52017-07-14 16:18:52 -07004690#endif // CONFIG_DIST_8X8
Yushin Cho75b01002017-06-21 13:43:57 -07004691 tmp = pixel_dist(cpi, x, plane, src, src_stride, rec_buffer, MAX_TX_SIZE,
4692 blk_row, blk_col, plane_bsize, txm_bsize);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004693 }
Angie Chiangb5dda482016-11-02 16:19:58 -07004694 rd_stats->dist += tmp * 16;
Jingning Han7eab9ff2017-07-06 10:12:54 -07004695 txb_coeff_cost = av1_cost_coeffs(cpi, x, plane, blk_row, blk_col, block,
4696 tx_size, scan_order, a, l, 0);
Angie Chiangd81fdb42016-11-03 12:20:58 -07004697 rd_stats->rate += txb_coeff_cost;
Angie Chiang41fffae2017-04-03 10:33:18 -07004698 rd_stats->skip &= (eob == 0);
Jingning Han63cbf342016-11-09 15:37:48 -08004699
Angie Chiangd81fdb42016-11-03 12:20:58 -07004700#if CONFIG_RD_DEBUG
Angie Chiange94556b2016-11-09 10:59:30 -08004701 av1_update_txb_coeff_cost(rd_stats, plane, tx_size, blk_row, blk_col,
4702 txb_coeff_cost);
Fergus Simpson4063a682017-02-28 16:52:22 -08004703#endif // CONFIG_RD_DEBUG
Yaowu Xuc27fc142016-08-22 16:08:15 -07004704}
4705
Yaowu Xuf883b422016-08-30 14:01:10 -07004706static void select_tx_block(const AV1_COMP *cpi, MACROBLOCK *x, int blk_row,
Debargha Mukherjee9245d892017-10-06 13:54:31 -07004707 int blk_col, int plane, int block, TX_SIZE tx_size,
4708 int depth, BLOCK_SIZE plane_bsize,
Jingning Han94d5bfc2016-10-21 10:14:36 -07004709 ENTROPY_CONTEXT *ta, ENTROPY_CONTEXT *tl,
4710 TXFM_CONTEXT *tx_above, TXFM_CONTEXT *tx_left,
Angie Chiangb5dda482016-11-02 16:19:58 -07004711 RD_STATS *rd_stats, int64_t ref_best_rd,
Debargha Mukherjee9245d892017-10-06 13:54:31 -07004712 int *is_cost_valid) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07004713 MACROBLOCKD *const xd = &x->e_mbd;
4714 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
4715 struct macroblock_plane *const p = &x->plane[plane];
4716 struct macroblockd_plane *const pd = &xd->plane[plane];
4717 const int tx_row = blk_row >> (1 - pd->subsampling_y);
4718 const int tx_col = blk_col >> (1 - pd->subsampling_x);
clang-format67948d32016-09-07 22:40:40 -07004719 TX_SIZE(*const inter_tx_size)
Yaowu Xuc27fc142016-08-22 16:08:15 -07004720 [MAX_MIB_SIZE] =
4721 (TX_SIZE(*)[MAX_MIB_SIZE]) & mbmi->inter_tx_size[tx_row][tx_col];
Jingning Hanf65b8702016-10-31 12:13:20 -07004722 const int max_blocks_high = max_block_high(xd, plane_bsize, plane);
4723 const int max_blocks_wide = max_block_wide(xd, plane_bsize, plane);
Jingning Han58224042016-10-27 16:35:32 -07004724 const int bw = block_size_wide[plane_bsize] >> tx_size_wide_log2[0];
Yaowu Xuc27fc142016-08-22 16:08:15 -07004725 int64_t this_rd = INT64_MAX;
4726 ENTROPY_CONTEXT *pta = ta + blk_col;
4727 ENTROPY_CONTEXT *ptl = tl + blk_row;
Jingning Han5a995d72017-07-02 15:20:54 -07004728 int i;
Jingning Han331662e2017-05-30 17:03:32 -07004729 int ctx = txfm_partition_context(tx_above + blk_col, tx_left + blk_row,
4730 mbmi->sb_type, tx_size);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004731 int64_t sum_rd = INT64_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004732 int tmp_eob = 0;
4733 int zero_blk_rate;
Angie Chiangd7246172016-11-03 11:49:15 -07004734 RD_STATS sum_rd_stats;
Jingning Hane3b81bc2017-06-23 11:43:52 -07004735#if CONFIG_TXK_SEL
4736 TX_TYPE best_tx_type = TX_TYPES;
Jingning Han19b5c8f2017-07-06 15:10:12 -07004737 int txk_idx = (blk_row << 4) + blk_col;
Jingning Hane3b81bc2017-06-23 11:43:52 -07004738#endif
Yue Chend6bdd462017-07-19 16:05:43 -07004739#if CONFIG_RECT_TX_EXT
4740 TX_SIZE quarter_txsize = quarter_txsize_lookup[mbmi->sb_type];
4741 int check_qttx = is_quarter_tx_allowed(xd, mbmi, is_inter_block(mbmi)) &&
4742 tx_size == max_txsize_rect_lookup[mbmi->sb_type] &&
4743 quarter_txsize != tx_size;
4744 int is_qttx_picked = 0;
4745 int eobs_qttx[2] = { 0, 0 };
4746 int skip_qttx[2] = { 0, 0 };
4747 int block_offset_qttx = check_qttx
4748 ? tx_size_wide_unit[quarter_txsize] *
4749 tx_size_high_unit[quarter_txsize]
4750 : 0;
4751 int blk_row_offset, blk_col_offset;
4752 int is_wide_qttx =
4753 tx_size_wide_unit[quarter_txsize] > tx_size_high_unit[quarter_txsize];
4754 blk_row_offset = is_wide_qttx ? tx_size_high_unit[quarter_txsize] : 0;
4755 blk_col_offset = is_wide_qttx ? 0 : tx_size_wide_unit[quarter_txsize];
4756#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07004757
Jingning Han63cbf342016-11-09 15:37:48 -08004758 av1_init_rd_stats(&sum_rd_stats);
Jingning Hanfe45b212016-11-22 10:30:23 -08004759
Jingning Hand3fada82016-11-22 10:46:55 -08004760 assert(tx_size < TX_SIZES_ALL);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004761
4762 if (ref_best_rd < 0) {
4763 *is_cost_valid = 0;
4764 return;
4765 }
4766
Angie Chiangc0feea82016-11-03 15:36:18 -07004767 av1_init_rd_stats(rd_stats);
Yaowu Xuc27fc142016-08-22 16:08:15 -07004768
4769 if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return;
4770
Jingning Han5a995d72017-07-02 15:20:54 -07004771#if CONFIG_LV_MAP
4772 TX_SIZE txs_ctx = get_txsize_context(tx_size);
4773 TXB_CTX txb_ctx;
4774 get_txb_ctx(plane_bsize, tx_size, plane, pta, ptl, &txb_ctx);
Jingning Hane9814912017-08-31 16:38:59 -07004775
4776#if LV_MAP_PROB
4777 zero_blk_rate = x->coeff_costs[txs_ctx][get_plane_type(plane)]
4778 .txb_skip_cost[txb_ctx.txb_skip_ctx][1];
4779#else
Jingning Han5a995d72017-07-02 15:20:54 -07004780 zero_blk_rate =
4781 av1_cost_bit(xd->fc->txb_skip[txs_ctx][txb_ctx.txb_skip_ctx], 1);
Jingning Hane9814912017-08-31 16:38:59 -07004782#endif // LV_MAP_PROB
Jingning Han5a995d72017-07-02 15:20:54 -07004783#else
Urvang Joshi9752a2e2017-10-02 17:32:27 -07004784 TX_SIZE tx_size_ctx = txsize_sqr_map[tx_size];
Jingning Han5a995d72017-07-02 15:20:54 -07004785 int coeff_ctx = get_entropy_context(tx_size, pta, ptl);
hui suc0cf71d2017-07-20 16:38:50 -07004786 zero_blk_rate =
4787 x->token_head_costs[tx_size_ctx][pd->plane_type][1][0][coeff_ctx][0];
Jingning Han5a995d72017-07-02 15:20:54 -07004788#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07004789
Jingning Han3bce7542017-07-25 10:53:57 -07004790 rd_stats->ref_rdcost = ref_best_rd;
4791 rd_stats->zero_rate = zero_blk_rate;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004792 if (cpi->common.tx_mode == TX_MODE_SELECT || tx_size == TX_4X4) {
4793 inter_tx_size[0][0] = tx_size;
Debargha Mukherjee9245d892017-10-06 13:54:31 -07004794 av1_tx_block_rd_b(cpi, x, tx_size, blk_row, blk_col, plane, block,
4795 plane_bsize, pta, ptl, rd_stats);
Sarah Parkerde6f0722017-08-07 20:23:46 -07004796 if (rd_stats->rate == INT_MAX) return;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004797
Urvang Joshi70006e42017-06-14 16:08:55 -07004798 if ((RDCOST(x->rdmult, rd_stats->rate, rd_stats->dist) >=
4799 RDCOST(x->rdmult, zero_blk_rate, rd_stats->sse) ||
Angie Chiangb5dda482016-11-02 16:19:58 -07004800 rd_stats->skip == 1) &&
Yaowu Xuc27fc142016-08-22 16:08:15 -07004801 !xd->lossless[mbmi->segment_id]) {
Jingning Hanc7ea7612017-01-11 15:01:30 -08004802#if CONFIG_RD_DEBUG
4803 av1_update_txb_coeff_cost(rd_stats, plane, tx_size, blk_row, blk_col,
4804 zero_blk_rate - rd_stats->rate);
Fergus Simpson4063a682017-02-28 16:52:22 -08004805#endif // CONFIG_RD_DEBUG
Angie Chiangb5dda482016-11-02 16:19:58 -07004806 rd_stats->rate = zero_blk_rate;
4807 rd_stats->dist = rd_stats->sse;
4808 rd_stats->skip = 1;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004809 x->blk_skip[plane][blk_row * bw + blk_col] = 1;
4810 p->eobs[block] = 0;
Jingning Han19b5c8f2017-07-06 15:10:12 -07004811#if CONFIG_TXK_SEL
4812 mbmi->txk_type[txk_idx] = DCT_DCT;
4813#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07004814 } else {
4815 x->blk_skip[plane][blk_row * bw + blk_col] = 0;
Angie Chiangb5dda482016-11-02 16:19:58 -07004816 rd_stats->skip = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004817 }
4818
Jingning Han571189c2016-10-24 10:38:43 -07004819 if (tx_size > TX_4X4 && depth < MAX_VARTX_DEPTH)
Angie Chiangb5dda482016-11-02 16:19:58 -07004820 rd_stats->rate +=
4821 av1_cost_bit(cpi->common.fc->txfm_partition_prob[ctx], 0);
Yue Chend6bdd462017-07-19 16:05:43 -07004822#if CONFIG_RECT_TX_EXT
4823 if (check_qttx) {
4824 assert(blk_row == 0 && blk_col == 0);
4825 rd_stats->rate += av1_cost_bit(cpi->common.fc->quarter_tx_size_prob, 0);
4826 }
4827#endif
Urvang Joshi70006e42017-06-14 16:08:55 -07004828 this_rd = RDCOST(x->rdmult, rd_stats->rate, rd_stats->dist);
Jingning Han2f42d772017-07-05 16:28:18 -07004829#if CONFIG_LV_MAP
4830 tmp_eob = p->txb_entropy_ctx[block];
4831#else
Yaowu Xuc27fc142016-08-22 16:08:15 -07004832 tmp_eob = p->eobs[block];
Jingning Han2f42d772017-07-05 16:28:18 -07004833#endif
4834
Jingning Hane3b81bc2017-06-23 11:43:52 -07004835#if CONFIG_TXK_SEL
4836 best_tx_type = mbmi->txk_type[txk_idx];
4837#endif
Yue Chend6bdd462017-07-19 16:05:43 -07004838
4839#if CONFIG_RECT_TX_EXT
4840 if (check_qttx) {
4841 assert(blk_row == 0 && blk_col == 0 && block == 0 && plane == 0);
4842
4843 RD_STATS rd_stats_tmp, rd_stats_qttx;
4844 int64_t rd_qttx;
4845
4846 av1_init_rd_stats(&rd_stats_qttx);
4847 av1_init_rd_stats(&rd_stats_tmp);
4848
4849 av1_tx_block_rd_b(cpi, x, quarter_txsize, 0, 0, plane, 0, plane_bsize,
4850 pta, ptl, &rd_stats_qttx);
Sarah Parkerde6f0722017-08-07 20:23:46 -07004851 if (rd_stats->rate == INT_MAX) return;
Yue Chend6bdd462017-07-19 16:05:43 -07004852
4853 tx_size_ctx = txsize_sqr_map[quarter_txsize];
4854 coeff_ctx = get_entropy_context(quarter_txsize, pta, ptl);
hui suc0cf71d2017-07-20 16:38:50 -07004855 zero_blk_rate =
4856 x->token_head_costs[tx_size_ctx][pd->plane_type][1][0][coeff_ctx][0];
Yue Chend6bdd462017-07-19 16:05:43 -07004857 if ((RDCOST(x->rdmult, rd_stats_qttx.rate, rd_stats_qttx.dist) >=
4858 RDCOST(x->rdmult, zero_blk_rate, rd_stats_qttx.sse) ||
4859 rd_stats_qttx.skip == 1) &&
4860 !xd->lossless[mbmi->segment_id]) {
4861#if CONFIG_RD_DEBUG
4862 av1_update_txb_coeff_cost(&rd_stats_qttx, plane, quarter_txsize, 0, 0,
4863 zero_blk_rate - rd_stats_qttx.rate);
4864#endif // CONFIG_RD_DEBUG
4865 rd_stats_qttx.rate = zero_blk_rate;
4866 rd_stats_qttx.dist = rd_stats_qttx.sse;
4867 rd_stats_qttx.skip = 1;
4868 x->blk_skip[plane][blk_row * bw + blk_col] = 1;
4869 skip_qttx[0] = 1;
4870 p->eobs[block] = 0;
4871 } else {
4872 x->blk_skip[plane][blk_row * bw + blk_col] = 0;
4873 skip_qttx[0] = 0;
4874 rd_stats->skip = 0;
4875 }
4876
4877 // Second tx block
4878 av1_tx_block_rd_b(cpi, x, quarter_txsize, blk_row_offset, blk_col_offset,
4879 plane, block_offset_qttx, plane_bsize, pta, ptl,
4880 &rd_stats_tmp);
4881
Sarah Parkerde6f0722017-08-07 20:23:46 -07004882 if (rd_stats->rate == INT_MAX) return;
4883
Tom Fineganac870492017-08-15 16:19:13 -07004884#if !CONFIG_PVQ
Yue Chend6bdd462017-07-19 16:05:43 -07004885 av1_set_txb_context(x, plane, 0, quarter_txsize, pta, ptl);
Tom Fineganac870492017-08-15 16:19:13 -07004886#endif // !CONFIG_PVQ
Yue Chend6bdd462017-07-19 16:05:43 -07004887 coeff_ctx = get_entropy_context(quarter_txsize, pta + blk_col_offset,
4888 ptl + blk_row_offset);
hui suc0cf71d2017-07-20 16:38:50 -07004889 zero_blk_rate =
4890 x->token_head_costs[tx_size_ctx][pd->plane_type][1][0][coeff_ctx][0];
Yue Chend6bdd462017-07-19 16:05:43 -07004891 if ((RDCOST(x->rdmult, rd_stats_tmp.rate, rd_stats_tmp.dist) >=
4892 RDCOST(x->rdmult, zero_blk_rate, rd_stats_tmp.sse) ||
4893 rd_stats_tmp.skip == 1) &&
4894 !xd->lossless[mbmi->segment_id]) {
4895#if CONFIG_RD_DEBUG
4896 av1_update_txb_coeff_cost(&rd_stats_tmp, plane, quarter_txsize, 0, 0,
4897 zero_blk_rate - rd_stats_tmp.rate);
4898#endif // CONFIG_RD_DEBUG
4899 rd_stats_tmp.rate = zero_blk_rate;
4900 rd_stats_tmp.dist = rd_stats_tmp.sse;
4901 rd_stats_tmp.skip = 1;
4902 x->blk_skip[plane][blk_row_offset * bw + blk_col_offset] = 1;
4903 skip_qttx[1] = 1;
4904 p->eobs[block_offset_qttx] = 0;
4905 } else {
4906 x->blk_skip[plane][blk_row_offset * bw + blk_col_offset] = 0;
4907 skip_qttx[1] = 0;
4908 rd_stats_tmp.skip = 0;
4909 }
4910
4911 av1_merge_rd_stats(&rd_stats_qttx, &rd_stats_tmp);
4912
4913 if (tx_size > TX_4X4 && depth < MAX_VARTX_DEPTH) {
4914 rd_stats_qttx.rate +=
4915 av1_cost_bit(cpi->common.fc->txfm_partition_prob[ctx], 0);
4916 }
4917 rd_stats_qttx.rate +=
4918 av1_cost_bit(cpi->common.fc->quarter_tx_size_prob, 1);
4919 rd_qttx = RDCOST(x->rdmult, rd_stats_qttx.rate, rd_stats_qttx.dist);
4920#if CONFIG_LV_MAP
4921 eobs_qttx[0] = p->txb_entropy_ctx[0];
4922 eobs_qttx[1] = p->txb_entropy_ctx[block_offset_qttx];
4923#else
4924 eobs_qttx[0] = p->eobs[0];
4925 eobs_qttx[1] = p->eobs[block_offset_qttx];
4926#endif
4927 if (rd_qttx < this_rd) {
4928 is_qttx_picked = 1;
4929 this_rd = rd_qttx;
4930 rd_stats->rate = rd_stats_qttx.rate;
4931 rd_stats->dist = rd_stats_qttx.dist;
4932 rd_stats->sse = rd_stats_qttx.sse;
4933 rd_stats->skip = rd_stats_qttx.skip;
4934 rd_stats->rdcost = rd_stats_qttx.rdcost;
4935 }
4936 av1_get_entropy_contexts(plane_bsize, 0, pd, ta, tl);
4937 }
4938#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07004939 }
4940
Yushin Choc5a1f262017-10-02 17:17:19 -07004941 if (tx_size > TX_4X4 && depth < MAX_VARTX_DEPTH
Sarah Parker53f93db2017-07-11 17:20:04 -07004942#if CONFIG_MRC_TX
Yushin Choc5a1f262017-10-02 17:17:19 -07004943 // If the tx type we are trying is MRC_DCT, we cannot partition the
4944 // transform into anything smaller than TX_32X32
4945 && mbmi->tx_type != MRC_DCT
4946#endif // CONFIG_MRC_TX
4947 ) {
Jingning Han18482fe2016-11-02 17:01:58 -07004948 const TX_SIZE sub_txs = sub_tx_size_map[tx_size];
4949 const int bsl = tx_size_wide_unit[sub_txs];
Jingning Han58224042016-10-27 16:35:32 -07004950 int sub_step = tx_size_wide_unit[sub_txs] * tx_size_high_unit[sub_txs];
Angie Chiangb5dda482016-11-02 16:19:58 -07004951 RD_STATS this_rd_stats;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004952 int this_cost_valid = 1;
4953 int64_t tmp_rd = 0;
Yushin Chob7b60c52017-07-14 16:18:52 -07004954#if CONFIG_DIST_8X8
Yushin Cho04749122017-05-25 14:19:07 -07004955 int sub8x8_eob[4];
4956#endif
Angie Chiangd7246172016-11-03 11:49:15 -07004957 sum_rd_stats.rate =
4958 av1_cost_bit(cpi->common.fc->txfm_partition_prob[ctx], 1);
Jingning Hand3fada82016-11-22 10:46:55 -08004959
4960 assert(tx_size < TX_SIZES_ALL);
4961
Jingning Han16a9df72017-07-26 15:27:43 -07004962 ref_best_rd = AOMMIN(this_rd, ref_best_rd);
4963
Yaowu Xuc27fc142016-08-22 16:08:15 -07004964 for (i = 0; i < 4 && this_cost_valid; ++i) {
Jingning Han98d6a1f2016-11-03 12:47:47 -07004965 int offsetr = blk_row + (i >> 1) * bsl;
4966 int offsetc = blk_col + (i & 0x01) * bsl;
4967
4968 if (offsetr >= max_blocks_high || offsetc >= max_blocks_wide) continue;
4969
Debargha Mukherjee9245d892017-10-06 13:54:31 -07004970 select_tx_block(cpi, x, offsetr, offsetc, plane, block, sub_txs,
Jingning Han98d6a1f2016-11-03 12:47:47 -07004971 depth + 1, plane_bsize, ta, tl, tx_above, tx_left,
Debargha Mukherjee9245d892017-10-06 13:54:31 -07004972 &this_rd_stats, ref_best_rd - tmp_rd, &this_cost_valid);
Yushin Chob7b60c52017-07-14 16:18:52 -07004973#if CONFIG_DIST_8X8
Yushin Cho55104332017-08-14 16:15:43 -07004974 if (x->using_dist_8x8 && plane == 0 && tx_size == TX_8X8) {
Yushin Cho04749122017-05-25 14:19:07 -07004975 sub8x8_eob[i] = p->eobs[block];
4976 }
Yushin Chob7b60c52017-07-14 16:18:52 -07004977#endif // CONFIG_DIST_8X8
Angie Chiangc0feea82016-11-03 15:36:18 -07004978 av1_merge_rd_stats(&sum_rd_stats, &this_rd_stats);
Jingning Han98d6a1f2016-11-03 12:47:47 -07004979
Urvang Joshi70006e42017-06-14 16:08:55 -07004980 tmp_rd = RDCOST(x->rdmult, sum_rd_stats.rate, sum_rd_stats.dist);
Yushin Cho55104332017-08-14 16:15:43 -07004981#if CONFIG_DIST_8X8
4982 if (!x->using_dist_8x8)
Yushin Cho04749122017-05-25 14:19:07 -07004983#endif
Yushin Cho55104332017-08-14 16:15:43 -07004984 if (this_rd < tmp_rd) break;
Jingning Han98d6a1f2016-11-03 12:47:47 -07004985 block += sub_step;
Yaowu Xuc27fc142016-08-22 16:08:15 -07004986 }
Yushin Chob7b60c52017-07-14 16:18:52 -07004987#if CONFIG_DIST_8X8
Yushin Cho55104332017-08-14 16:15:43 -07004988 if (x->using_dist_8x8 && this_cost_valid && plane == 0 &&
4989 tx_size == TX_8X8) {
Yushin Cho04749122017-05-25 14:19:07 -07004990 const int src_stride = p->src.stride;
4991 const int dst_stride = pd->dst.stride;
4992
4993 const uint8_t *src =
4994 &p->src.buf[(blk_row * src_stride + blk_col) << tx_size_wide_log2[0]];
4995 const uint8_t *dst =
4996 &pd->dst
4997 .buf[(blk_row * dst_stride + blk_col) << tx_size_wide_log2[0]];
4998
Yushin Chob7b60c52017-07-14 16:18:52 -07004999 int64_t dist_8x8;
Yushin Cho04749122017-05-25 14:19:07 -07005000 int qindex = x->qindex;
5001 const int pred_stride = block_size_wide[plane_bsize];
5002 const int pred_idx = (blk_row * pred_stride + blk_col)
5003 << tx_size_wide_log2[0];
5004 int16_t *pred = &pd->pred[pred_idx];
5005 int j;
Yushin Cho04749122017-05-25 14:19:07 -07005006 int row, col;
5007
Yushin Cho8ab875d2017-06-23 14:47:21 -07005008#if CONFIG_HIGHBITDEPTH
5009 uint8_t *pred8;
5010 DECLARE_ALIGNED(16, uint16_t, pred8_16[8 * 8]);
5011#else
Yushin Cho04749122017-05-25 14:19:07 -07005012 DECLARE_ALIGNED(16, uint8_t, pred8[8 * 8]);
Yushin Cho8ab875d2017-06-23 14:47:21 -07005013#endif // CONFIG_HIGHBITDEPTH
Yushin Cho04749122017-05-25 14:19:07 -07005014
Yushin Choe30a47c2017-08-15 13:08:30 -07005015 dist_8x8 = av1_dist_8x8(cpi, x, src, src_stride, dst, dst_stride,
Yushin Chob7b60c52017-07-14 16:18:52 -07005016 BLOCK_8X8, 8, 8, 8, 8, qindex) *
5017 16;
5018 sum_rd_stats.sse = dist_8x8;
Yushin Cho04749122017-05-25 14:19:07 -07005019
Yushin Cho8ab875d2017-06-23 14:47:21 -07005020#if CONFIG_HIGHBITDEPTH
5021 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
5022 pred8 = CONVERT_TO_BYTEPTR(pred8_16);
5023 else
5024 pred8 = (uint8_t *)pred8_16;
5025#endif
Yushin Cho04749122017-05-25 14:19:07 -07005026
Yushin Cho8ab875d2017-06-23 14:47:21 -07005027#if CONFIG_HIGHBITDEPTH
5028 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
5029 for (row = 0; row < 2; ++row) {
5030 for (col = 0; col < 2; ++col) {
5031 int idx = row * 2 + col;
5032 int eob = sub8x8_eob[idx];
5033
5034 if (eob > 0) {
5035 for (j = 0; j < 4; j++)
5036 for (i = 0; i < 4; i++)
5037 CONVERT_TO_SHORTPTR(pred8)
5038 [(row * 4 + j) * 8 + 4 * col + i] =
5039 pred[(row * 4 + j) * pred_stride + 4 * col + i];
5040 } else {
5041 for (j = 0; j < 4; j++)
5042 for (i = 0; i < 4; i++)
5043 CONVERT_TO_SHORTPTR(pred8)
5044 [(row * 4 + j) * 8 + 4 * col + i] = CONVERT_TO_SHORTPTR(
5045 dst)[(row * 4 + j) * dst_stride + 4 * col + i];
5046 }
Yushin Cho04749122017-05-25 14:19:07 -07005047 }
5048 }
Yushin Cho8ab875d2017-06-23 14:47:21 -07005049 } else {
5050#endif
5051 for (row = 0; row < 2; ++row) {
5052 for (col = 0; col < 2; ++col) {
5053 int idx = row * 2 + col;
5054 int eob = sub8x8_eob[idx];
5055
5056 if (eob > 0) {
5057 for (j = 0; j < 4; j++)
5058 for (i = 0; i < 4; i++)
5059 pred8[(row * 4 + j) * 8 + 4 * col + i] =
Yaowu Xu7a471702017-09-29 08:38:37 -07005060 (uint8_t)pred[(row * 4 + j) * pred_stride + 4 * col + i];
Yushin Cho8ab875d2017-06-23 14:47:21 -07005061 } else {
5062 for (j = 0; j < 4; j++)
5063 for (i = 0; i < 4; i++)
5064 pred8[(row * 4 + j) * 8 + 4 * col + i] =
5065 dst[(row * 4 + j) * dst_stride + 4 * col + i];
5066 }
5067 }
5068 }
5069#if CONFIG_HIGHBITDEPTH
Yushin Cho04749122017-05-25 14:19:07 -07005070 }
Yushin Cho8ab875d2017-06-23 14:47:21 -07005071#endif // CONFIG_HIGHBITDEPTH
Yushin Choe30a47c2017-08-15 13:08:30 -07005072 dist_8x8 = av1_dist_8x8(cpi, x, src, src_stride, pred8, 8, BLOCK_8X8, 8,
Yushin Chob7b60c52017-07-14 16:18:52 -07005073 8, 8, 8, qindex) *
5074 16;
5075 sum_rd_stats.dist = dist_8x8;
Yushin Cho04749122017-05-25 14:19:07 -07005076 tmp_rd = RDCOST(x->rdmult, sum_rd_stats.rate, sum_rd_stats.dist);
5077 }
Yushin Chob7b60c52017-07-14 16:18:52 -07005078#endif // CONFIG_DIST_8X8
Yaowu Xuc27fc142016-08-22 16:08:15 -07005079 if (this_cost_valid) sum_rd = tmp_rd;
5080 }
5081
5082 if (this_rd < sum_rd) {
5083 int idx, idy;
Yue Chend6bdd462017-07-19 16:05:43 -07005084#if CONFIG_RECT_TX_EXT
5085 TX_SIZE tx_size_selected = is_qttx_picked ? quarter_txsize : tx_size;
5086#else
5087 TX_SIZE tx_size_selected = tx_size;
5088#endif
Jingning Han2f42d772017-07-05 16:28:18 -07005089
Yue Chend6bdd462017-07-19 16:05:43 -07005090#if CONFIG_RECT_TX_EXT
5091 if (is_qttx_picked) {
5092 assert(blk_row == 0 && blk_col == 0 && plane == 0);
Jingning Han2f42d772017-07-05 16:28:18 -07005093#if CONFIG_LV_MAP
Yue Chend6bdd462017-07-19 16:05:43 -07005094 p->txb_entropy_ctx[0] = eobs_qttx[0];
5095 p->txb_entropy_ctx[block_offset_qttx] = eobs_qttx[1];
5096#else
5097 p->eobs[0] = eobs_qttx[0];
5098 p->eobs[block_offset_qttx] = eobs_qttx[1];
5099#endif
5100 } else {
5101#endif
5102#if CONFIG_LV_MAP
5103 p->txb_entropy_ctx[block] = tmp_eob;
Jingning Han2f42d772017-07-05 16:28:18 -07005104#else
5105 p->eobs[block] = tmp_eob;
5106#endif
Yue Chend6bdd462017-07-19 16:05:43 -07005107#if CONFIG_RECT_TX_EXT
5108 }
5109#endif
Jingning Han2f42d772017-07-05 16:28:18 -07005110
Tom Fineganac870492017-08-15 16:19:13 -07005111#if !CONFIG_PVQ
Yue Chend6bdd462017-07-19 16:05:43 -07005112 av1_set_txb_context(x, plane, block, tx_size_selected, pta, ptl);
5113#if CONFIG_RECT_TX_EXT
5114 if (is_qttx_picked)
5115 av1_set_txb_context(x, plane, block_offset_qttx, tx_size_selected,
5116 pta + blk_col_offset, ptl + blk_row_offset);
Tom Fineganac870492017-08-15 16:19:13 -07005117#endif // CONFIG_RECT_TX_EXT
5118#endif // !CONFIG_PVQ
Jingning Han2f42d772017-07-05 16:28:18 -07005119
Jingning Han331662e2017-05-30 17:03:32 -07005120 txfm_partition_update(tx_above + blk_col, tx_left + blk_row, tx_size,
5121 tx_size);
Yue Chend6bdd462017-07-19 16:05:43 -07005122 inter_tx_size[0][0] = tx_size_selected;
Jingning Han58224042016-10-27 16:35:32 -07005123 for (idy = 0; idy < tx_size_high_unit[tx_size] / 2; ++idy)
5124 for (idx = 0; idx < tx_size_wide_unit[tx_size] / 2; ++idx)
Yue Chend6bdd462017-07-19 16:05:43 -07005125 inter_tx_size[idy][idx] = tx_size_selected;
5126 mbmi->tx_size = tx_size_selected;
Jingning Hane3b81bc2017-06-23 11:43:52 -07005127#if CONFIG_TXK_SEL
5128 mbmi->txk_type[txk_idx] = best_tx_type;
5129#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07005130 if (this_rd == INT64_MAX) *is_cost_valid = 0;
Yue Chend6bdd462017-07-19 16:05:43 -07005131#if CONFIG_RECT_TX_EXT
5132 if (is_qttx_picked) {
5133 x->blk_skip[plane][0] = skip_qttx[0];
5134 x->blk_skip[plane][blk_row_offset * bw + blk_col_offset] = skip_qttx[1];
5135 } else {
5136#endif
5137 x->blk_skip[plane][blk_row * bw + blk_col] = rd_stats->skip;
5138#if CONFIG_RECT_TX_EXT
5139 }
5140#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07005141 } else {
Angie Chiangd7246172016-11-03 11:49:15 -07005142 *rd_stats = sum_rd_stats;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005143 if (sum_rd == INT64_MAX) *is_cost_valid = 0;
5144 }
5145}
5146
Angie Chiangb5dda482016-11-02 16:19:58 -07005147static void inter_block_yrd(const AV1_COMP *cpi, MACROBLOCK *x,
5148 RD_STATS *rd_stats, BLOCK_SIZE bsize,
Debargha Mukherjee9245d892017-10-06 13:54:31 -07005149 int64_t ref_best_rd) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07005150 MACROBLOCKD *const xd = &x->e_mbd;
5151 int is_cost_valid = 1;
5152 int64_t this_rd = 0;
5153
5154 if (ref_best_rd < 0) is_cost_valid = 0;
5155
Angie Chiangc0feea82016-11-03 15:36:18 -07005156 av1_init_rd_stats(rd_stats);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005157
5158 if (is_cost_valid) {
5159 const struct macroblockd_plane *const pd = &xd->plane[0];
5160 const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd);
Jingning Han9ca05b72017-01-03 14:41:36 -08005161 const int mi_width = block_size_wide[plane_bsize] >> tx_size_wide_log2[0];
5162 const int mi_height = block_size_high[plane_bsize] >> tx_size_high_log2[0];
Jingning Han70e5f3f2016-11-09 17:03:07 -08005163 const TX_SIZE max_tx_size = max_txsize_rect_lookup[plane_bsize];
Jingning Han18482fe2016-11-02 17:01:58 -07005164 const int bh = tx_size_high_unit[max_tx_size];
5165 const int bw = tx_size_wide_unit[max_tx_size];
Yaowu Xuc27fc142016-08-22 16:08:15 -07005166 int idx, idy;
5167 int block = 0;
Sarah Parkerd25ef8c2017-10-06 12:17:30 -07005168 int init_depth =
5169 (mi_height != mi_width) ? RECT_VARTX_DEPTH_INIT : SQR_VARTX_DEPTH_INIT;
Jingning Han18482fe2016-11-02 17:01:58 -07005170 int step = tx_size_wide_unit[max_tx_size] * tx_size_high_unit[max_tx_size];
Yaowu Xuc27fc142016-08-22 16:08:15 -07005171 ENTROPY_CONTEXT ctxa[2 * MAX_MIB_SIZE];
5172 ENTROPY_CONTEXT ctxl[2 * MAX_MIB_SIZE];
Jingning Han331662e2017-05-30 17:03:32 -07005173 TXFM_CONTEXT tx_above[MAX_MIB_SIZE * 2];
5174 TXFM_CONTEXT tx_left[MAX_MIB_SIZE * 2];
Yaowu Xuc27fc142016-08-22 16:08:15 -07005175
Angie Chiangb5dda482016-11-02 16:19:58 -07005176 RD_STATS pn_rd_stats;
Angie Chiangc0feea82016-11-03 15:36:18 -07005177 av1_init_rd_stats(&pn_rd_stats);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005178
Jingning Han9ca05b72017-01-03 14:41:36 -08005179 av1_get_entropy_contexts(bsize, 0, pd, ctxa, ctxl);
Jingning Han331662e2017-05-30 17:03:32 -07005180 memcpy(tx_above, xd->above_txfm_context, sizeof(TXFM_CONTEXT) * mi_width);
5181 memcpy(tx_left, xd->left_txfm_context, sizeof(TXFM_CONTEXT) * mi_height);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005182
5183 for (idy = 0; idy < mi_height; idy += bh) {
Jingning Han18482fe2016-11-02 17:01:58 -07005184 for (idx = 0; idx < mi_width; idx += bw) {
Sarah Parkerd25ef8c2017-10-06 12:17:30 -07005185 select_tx_block(cpi, x, idy, idx, 0, block, max_tx_size, init_depth,
5186 plane_bsize, ctxa, ctxl, tx_above, tx_left,
5187 &pn_rd_stats, ref_best_rd - this_rd, &is_cost_valid);
Sarah Parkerde6f0722017-08-07 20:23:46 -07005188 if (pn_rd_stats.rate == INT_MAX) {
5189 av1_invalid_rd_stats(rd_stats);
5190 return;
5191 }
Angie Chiangc0feea82016-11-03 15:36:18 -07005192 av1_merge_rd_stats(rd_stats, &pn_rd_stats);
Urvang Joshi70006e42017-06-14 16:08:55 -07005193 this_rd += AOMMIN(RDCOST(x->rdmult, pn_rd_stats.rate, pn_rd_stats.dist),
5194 RDCOST(x->rdmult, 0, pn_rd_stats.sse));
Yaowu Xuc27fc142016-08-22 16:08:15 -07005195 block += step;
5196 }
5197 }
5198 }
5199
Urvang Joshi70006e42017-06-14 16:08:55 -07005200 this_rd = AOMMIN(RDCOST(x->rdmult, rd_stats->rate, rd_stats->dist),
5201 RDCOST(x->rdmult, 0, rd_stats->sse));
Yaowu Xuc27fc142016-08-22 16:08:15 -07005202 if (this_rd > ref_best_rd) is_cost_valid = 0;
5203
5204 if (!is_cost_valid) {
5205 // reset cost value
Angie Chiangc0feea82016-11-03 15:36:18 -07005206 av1_invalid_rd_stats(rd_stats);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005207 }
5208}
5209
Yaowu Xuf883b422016-08-30 14:01:10 -07005210static int64_t select_tx_size_fix_type(const AV1_COMP *cpi, MACROBLOCK *x,
Angie Chiangb5dda482016-11-02 16:19:58 -07005211 RD_STATS *rd_stats, BLOCK_SIZE bsize,
Debargha Mukherjee9245d892017-10-06 13:54:31 -07005212 int64_t ref_best_rd, TX_TYPE tx_type) {
Yaowu Xuf883b422016-08-30 14:01:10 -07005213 const AV1_COMMON *const cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005214 MACROBLOCKD *const xd = &x->e_mbd;
5215 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005216 const int is_inter = is_inter_block(mbmi);
Yaowu Xuf883b422016-08-30 14:01:10 -07005217 aom_prob skip_prob = av1_get_skip_prob(cm, xd);
5218 int s0 = av1_cost_bit(skip_prob, 0);
5219 int s1 = av1_cost_bit(skip_prob, 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005220 int64_t rd;
Jingning Hane67b38a2016-11-04 10:30:00 -07005221 int row, col;
5222 const int max_blocks_high = max_block_high(xd, bsize, 0);
5223 const int max_blocks_wide = max_block_wide(xd, bsize, 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005224
5225 mbmi->tx_type = tx_type;
Debargha Mukherjee9245d892017-10-06 13:54:31 -07005226 inter_block_yrd(cpi, x, rd_stats, bsize, ref_best_rd);
Jingning Han70bd76e2017-05-30 10:53:00 -07005227 mbmi->min_tx_size = get_min_tx_size(mbmi->inter_tx_size[0][0]);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005228
Angie Chiangb5dda482016-11-02 16:19:58 -07005229 if (rd_stats->rate == INT_MAX) return INT64_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005230
Jingning Hane67b38a2016-11-04 10:30:00 -07005231 for (row = 0; row < max_blocks_high / 2; ++row)
5232 for (col = 0; col < max_blocks_wide / 2; ++col)
5233 mbmi->min_tx_size = AOMMIN(
5234 mbmi->min_tx_size, get_min_tx_size(mbmi->inter_tx_size[row][col]));
5235
Jingning Han1643a0a2017-07-05 15:48:25 -07005236#if !CONFIG_TXK_SEL
Yaowu Xuc27fc142016-08-22 16:08:15 -07005237#if CONFIG_EXT_TX
Sarah Parkere68a3e42017-02-16 14:03:24 -08005238 if (get_ext_tx_types(mbmi->min_tx_size, bsize, is_inter,
5239 cm->reduced_tx_set_used) > 1 &&
Yaowu Xuc27fc142016-08-22 16:08:15 -07005240 !xd->lossless[xd->mi[0]->mbmi.segment_id]) {
Sarah Parkere68a3e42017-02-16 14:03:24 -08005241 const int ext_tx_set = get_ext_tx_set(mbmi->min_tx_size, bsize, is_inter,
5242 cm->reduced_tx_set_used);
Lester Lu432012f2017-08-17 14:39:29 -07005243#if CONFIG_LGT_FROM_PRED
5244 if (is_lgt_allowed(mbmi->mode, mbmi->min_tx_size)) {
5245 if (LGT_FROM_PRED_INTRA && !is_inter && ext_tx_set > 0 &&
5246 ALLOW_INTRA_EXT_TX)
5247 rd_stats->rate += x->intra_lgt_cost[txsize_sqr_map[mbmi->min_tx_size]]
5248 [mbmi->mode][mbmi->use_lgt];
5249 if (LGT_FROM_PRED_INTER && is_inter && ext_tx_set > 0)
Angie Chiangb5dda482016-11-02 16:19:58 -07005250 rd_stats->rate +=
Lester Lu432012f2017-08-17 14:39:29 -07005251 x->inter_lgt_cost[txsize_sqr_map[mbmi->min_tx_size]][mbmi->use_lgt];
Yaowu Xuc27fc142016-08-22 16:08:15 -07005252 }
Lester Lu432012f2017-08-17 14:39:29 -07005253 if (!mbmi->use_lgt) {
5254#endif // CONFIG_LGT_FROM_PRED
5255 if (is_inter) {
5256 if (ext_tx_set > 0)
5257 rd_stats->rate +=
5258 x->inter_tx_type_costs[ext_tx_set]
5259 [txsize_sqr_map[mbmi->min_tx_size]]
5260 [mbmi->tx_type];
5261 } else {
5262 if (ext_tx_set > 0 && ALLOW_INTRA_EXT_TX)
5263 rd_stats->rate +=
5264 x->intra_tx_type_costs[ext_tx_set][mbmi->min_tx_size][mbmi->mode]
5265 [mbmi->tx_type];
5266 }
5267 }
5268#if CONFIG_LGT_FROM_PRED
Yaowu Xuc27fc142016-08-22 16:08:15 -07005269 }
Lester Lu432012f2017-08-17 14:39:29 -07005270#endif
Jingning Han1643a0a2017-07-05 15:48:25 -07005271#else
Jingning Hane67b38a2016-11-04 10:30:00 -07005272 if (mbmi->min_tx_size < TX_32X32 && !xd->lossless[xd->mi[0]->mbmi.segment_id])
Zoe Liu4508d882017-07-31 15:36:55 -07005273 rd_stats->rate += x->inter_tx_type_costs[mbmi->min_tx_size][mbmi->tx_type];
Yaowu Xuc27fc142016-08-22 16:08:15 -07005274#endif // CONFIG_EXT_TX
Jingning Han1643a0a2017-07-05 15:48:25 -07005275#endif // CONFIG_TXK_SEL
Yaowu Xuc27fc142016-08-22 16:08:15 -07005276
Angie Chiangb5dda482016-11-02 16:19:58 -07005277 if (rd_stats->skip)
Urvang Joshi70006e42017-06-14 16:08:55 -07005278 rd = RDCOST(x->rdmult, s1, rd_stats->sse);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005279 else
Urvang Joshi70006e42017-06-14 16:08:55 -07005280 rd = RDCOST(x->rdmult, rd_stats->rate + s0, rd_stats->dist);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005281
Angie Chiangb5dda482016-11-02 16:19:58 -07005282 if (is_inter && !xd->lossless[xd->mi[0]->mbmi.segment_id] &&
5283 !(rd_stats->skip))
Urvang Joshi70006e42017-06-14 16:08:55 -07005284 rd = AOMMIN(rd, RDCOST(x->rdmult, s1, rd_stats->sse));
Yaowu Xuc27fc142016-08-22 16:08:15 -07005285
5286 return rd;
5287}
5288
Hui Su1ddf2312017-08-19 15:21:34 -07005289static uint32_t get_block_residue_hash(MACROBLOCK *x, BLOCK_SIZE bsize) {
5290 const int rows = block_size_high[bsize];
5291 const int cols = block_size_wide[bsize];
5292 const int diff_stride = cols;
5293 const struct macroblock_plane *const p = &x->plane[0];
5294 const int16_t *diff = &p->src_diff[0];
5295 uint8_t hash_data[MAX_SB_SQUARE];
5296 for (int r = 0; r < rows; ++r) {
5297 for (int c = 0; c < cols; ++c) {
5298 hash_data[cols * r + c] = clip_pixel(diff[c] + 128);
5299 }
5300 diff += diff_stride;
5301 }
5302 return (av1_get_crc_value(&x->tx_rd_record.crc_calculator, hash_data,
5303 rows * cols)
5304 << 7) +
5305 bsize;
5306}
5307
5308static void save_tx_rd_info(int n4, uint32_t hash, const MACROBLOCK *const x,
5309 const RD_STATS *const rd_stats,
5310 TX_RD_INFO *const tx_rd_info) {
5311 const MACROBLOCKD *const xd = &x->e_mbd;
5312 const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
5313 tx_rd_info->hash_value = hash;
5314 tx_rd_info->tx_type = mbmi->tx_type;
5315 tx_rd_info->tx_size = mbmi->tx_size;
5316#if CONFIG_VAR_TX
5317 tx_rd_info->min_tx_size = mbmi->min_tx_size;
5318 memcpy(tx_rd_info->blk_skip, x->blk_skip[0],
5319 sizeof(tx_rd_info->blk_skip[0]) * n4);
5320 for (int idy = 0; idy < xd->n8_h; ++idy)
5321 for (int idx = 0; idx < xd->n8_w; ++idx)
5322 tx_rd_info->inter_tx_size[idy][idx] = mbmi->inter_tx_size[idy][idx];
5323#endif // CONFIG_VAR_TX
5324#if CONFIG_TXK_SEL
5325 av1_copy(tx_rd_info->txk_type, mbmi->txk_type);
5326#endif // CONFIG_TXK_SEL
5327 tx_rd_info->rd_stats = *rd_stats;
5328}
5329
5330static void fetch_tx_rd_info(int n4, const TX_RD_INFO *const tx_rd_info,
5331 RD_STATS *const rd_stats, MACROBLOCK *const x) {
5332 MACROBLOCKD *const xd = &x->e_mbd;
5333 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
5334 mbmi->tx_type = tx_rd_info->tx_type;
5335 mbmi->tx_size = tx_rd_info->tx_size;
5336#if CONFIG_VAR_TX
5337 mbmi->min_tx_size = tx_rd_info->min_tx_size;
5338 memcpy(x->blk_skip[0], tx_rd_info->blk_skip,
5339 sizeof(tx_rd_info->blk_skip[0]) * n4);
5340 for (int idy = 0; idy < xd->n8_h; ++idy)
5341 for (int idx = 0; idx < xd->n8_w; ++idx)
5342 mbmi->inter_tx_size[idy][idx] = tx_rd_info->inter_tx_size[idy][idx];
5343#endif // CONFIG_VAR_TX
5344#if CONFIG_TXK_SEL
5345 av1_copy(mbmi->txk_type, tx_rd_info->txk_type);
5346#endif // CONFIG_TXK_SEL
5347 *rd_stats = tx_rd_info->rd_stats;
5348}
5349
Alexander Bokov8829a242017-08-31 18:07:05 -07005350// Uses simple features on top of DCT coefficients to quickly predict
5351// whether optimal RD decision is to skip encoding the residual.
5352static int predict_skip_flag_8bit(const MACROBLOCK *x, BLOCK_SIZE bsize) {
5353 if (bsize > BLOCK_16X16) return 0;
5354 // Tuned for target false-positive rate of 5% for all block sizes:
5355 const uint32_t threshold_table[] = { 50, 50, 50, 55, 47, 47, 53, 22, 22, 37 };
5356 const struct macroblock_plane *const p = &x->plane[0];
5357 const int bw = block_size_wide[bsize];
5358 const int bh = block_size_high[bsize];
5359 tran_low_t DCT_coefs[32 * 32];
5360 TxfmParam param;
5361 param.tx_type = DCT_DCT;
5362#if CONFIG_RECT_TX && (CONFIG_EXT_TX || CONFIG_VAR_TX)
5363 param.tx_size = max_txsize_rect_lookup[bsize];
5364#else
5365 param.tx_size = max_txsize_lookup[bsize];
5366#endif
5367 param.bd = 8;
5368 param.lossless = 0;
5369 av1_fwd_txfm(p->src_diff, DCT_coefs, bw, &param);
5370
5371 uint32_t dc = (uint32_t)av1_dc_quant(x->qindex, 0, AOM_BITS_8);
5372 uint32_t ac = (uint32_t)av1_ac_quant(x->qindex, 0, AOM_BITS_8);
5373 uint32_t max_quantized_coef = (100 * (uint32_t)abs(DCT_coefs[0])) / dc;
5374 for (int i = 1; i < bw * bh; i++) {
5375 uint32_t cur_quantized_coef = (100 * (uint32_t)abs(DCT_coefs[i])) / ac;
5376 if (cur_quantized_coef > max_quantized_coef)
5377 max_quantized_coef = cur_quantized_coef;
5378 }
5379
5380 return max_quantized_coef < threshold_table[AOMMAX(bsize - BLOCK_4X4, 0)];
5381}
5382
5383// Used to set proper context for early termination with skip = 1.
5384static void set_skip_flag(const AV1_COMP *cpi, MACROBLOCK *x,
5385 RD_STATS *rd_stats, int bsize) {
5386 MACROBLOCKD *const xd = &x->e_mbd;
5387 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
5388 const int n4 = bsize_to_num_blk(bsize);
5389#if CONFIG_RECT_TX && (CONFIG_EXT_TX || CONFIG_VAR_TX)
5390 const TX_SIZE tx_size = max_txsize_rect_lookup[bsize];
5391#else
5392 const TX_SIZE tx_size = max_txsize_lookup[bsize];
5393#endif
5394 mbmi->tx_type = DCT_DCT;
5395 for (int idy = 0; idy < xd->n8_h; ++idy)
5396 for (int idx = 0; idx < xd->n8_w; ++idx)
5397 mbmi->inter_tx_size[idy][idx] = tx_size;
5398 mbmi->tx_size = tx_size;
5399 mbmi->min_tx_size = get_min_tx_size(tx_size);
5400 memset(x->blk_skip[0], 1, sizeof(uint8_t) * n4);
5401 rd_stats->skip = 1;
5402
5403 // Rate.
5404 const int tx_size_ctx = txsize_sqr_map[tx_size];
5405 ENTROPY_CONTEXT ctxa[2 * MAX_MIB_SIZE];
5406 ENTROPY_CONTEXT ctxl[2 * MAX_MIB_SIZE];
5407 av1_get_entropy_contexts(bsize, 0, &xd->plane[0], ctxa, ctxl);
5408 int coeff_ctx = get_entropy_context(tx_size, ctxa, ctxl);
5409 int rate = x->token_head_costs[tx_size_ctx][PLANE_TYPE_Y][1][0][coeff_ctx][0];
5410 if (tx_size > TX_4X4) {
5411 int ctx = txfm_partition_context(
5412 xd->above_txfm_context, xd->left_txfm_context, mbmi->sb_type, tx_size);
5413 rate += av1_cost_bit(cpi->common.fc->txfm_partition_prob[ctx], 0);
5414 }
5415#if !CONFIG_TXK_SEL
5416#if CONFIG_EXT_TX
5417 const AV1_COMMON *cm = &cpi->common;
5418 const int ext_tx_set = get_ext_tx_set(max_txsize_lookup[bsize], bsize, 1,
5419 cm->reduced_tx_set_used);
5420 if (get_ext_tx_types(mbmi->min_tx_size, bsize, 1, cm->reduced_tx_set_used) >
5421 1 &&
5422 !xd->lossless[xd->mi[0]->mbmi.segment_id]) {
5423 if (ext_tx_set > 0)
5424 rate +=
5425 x->inter_tx_type_costs[ext_tx_set][txsize_sqr_map[mbmi->min_tx_size]]
5426 [mbmi->tx_type];
5427 }
5428#else
5429 if (mbmi->min_tx_size < TX_32X32 && !xd->lossless[xd->mi[0]->mbmi.segment_id])
5430 rd_stats->rate += x->inter_tx_type_costs[mbmi->min_tx_size][mbmi->tx_type];
5431#endif // CONFIG_EXT_TX
5432#endif // CONFIG_TXK_SEL
5433 rd_stats->rate = rate;
5434
5435 // Distortion.
5436 int64_t tmp = pixel_diff_dist(x, 0, x->plane[0].src_diff,
5437 block_size_wide[bsize], 0, 0, bsize, bsize);
5438#if CONFIG_HIGHBITDEPTH
5439 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
5440 tmp = ROUND_POWER_OF_TWO(tmp, (xd->bd - 8) * 2);
5441#endif // CONFIG_HIGHBITDEPTH
5442 rd_stats->dist = rd_stats->sse = (tmp << 4);
5443}
5444
Angie Chiangb5dda482016-11-02 16:19:58 -07005445static void select_tx_type_yrd(const AV1_COMP *cpi, MACROBLOCK *x,
5446 RD_STATS *rd_stats, BLOCK_SIZE bsize,
Yaowu Xuc27fc142016-08-22 16:08:15 -07005447 int64_t ref_best_rd) {
Jingning Han2b0eeb12017-02-23 15:55:37 -08005448 const AV1_COMMON *cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005449 const TX_SIZE max_tx_size = max_txsize_lookup[bsize];
5450 MACROBLOCKD *const xd = &x->e_mbd;
5451 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
5452 int64_t rd = INT64_MAX;
5453 int64_t best_rd = INT64_MAX;
5454 TX_TYPE tx_type, best_tx_type = DCT_DCT;
5455 const int is_inter = is_inter_block(mbmi);
5456 TX_SIZE best_tx_size[MAX_MIB_SIZE][MAX_MIB_SIZE];
Debargha Mukherjee28d924b2016-10-05 00:48:28 -07005457 TX_SIZE best_tx = max_txsize_lookup[bsize];
Jingning Hane67b38a2016-11-04 10:30:00 -07005458 TX_SIZE best_min_tx_size = TX_SIZES_ALL;
Jingning Han9ca05b72017-01-03 14:41:36 -08005459 uint8_t best_blk_skip[MAX_MIB_SIZE * MAX_MIB_SIZE * 8];
Jingning Hane3b81bc2017-06-23 11:43:52 -07005460 TX_TYPE txk_start = DCT_DCT;
5461#if CONFIG_TXK_SEL
5462 TX_TYPE txk_end = DCT_DCT + 1;
5463#else
5464 TX_TYPE txk_end = TX_TYPES;
5465#endif
Angie Chiangf1cb0752017-04-10 16:01:20 -07005466 const int n4 = bsize_to_num_blk(bsize);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005467 int idx, idy;
5468 int prune = 0;
5469#if CONFIG_EXT_TX
Hui Suddbcde22017-09-18 17:22:02 -07005470 const TxSetType tx_set_type = get_ext_tx_set_type(
5471 max_tx_size, bsize, is_inter, cm->reduced_tx_set_used);
Sarah Parkere68a3e42017-02-16 14:03:24 -08005472 const int ext_tx_set =
5473 get_ext_tx_set(max_tx_size, bsize, is_inter, cm->reduced_tx_set_used);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005474#endif // CONFIG_EXT_TX
5475
Angie Chiangc0feea82016-11-03 15:36:18 -07005476 av1_invalid_rd_stats(rd_stats);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005477
Lester Lu432012f2017-08-17 14:39:29 -07005478#if CONFIG_LGT_FROM_PRED
5479 mbmi->use_lgt = 0;
5480 int search_lgt = is_inter
5481 ? LGT_FROM_PRED_INTER &&
5482 (!cpi->sf.tx_type_search.prune_mode > NO_PRUNE)
5483 : LGT_FROM_PRED_INTRA && ALLOW_INTRA_EXT_TX;
5484#endif // CONFIG_LGT_FROM_PRED
5485
Hui Su1ddf2312017-08-19 15:21:34 -07005486 const uint32_t hash = get_block_residue_hash(x, bsize);
5487 TX_RD_RECORD *tx_rd_record = &x->tx_rd_record;
5488
5489 if (ref_best_rd != INT64_MAX) {
5490 for (int i = 0; i < tx_rd_record->num; ++i) {
5491 const int index = (tx_rd_record->index_start + i) % RD_RECORD_BUFFER_LEN;
5492 // If there is a match in the tx_rd_record, fetch the RD decision and
5493 // terminate early.
5494 if (tx_rd_record->tx_rd_info[index].hash_value == hash) {
5495 TX_RD_INFO *tx_rd_info = &tx_rd_record->tx_rd_info[index];
5496 fetch_tx_rd_info(n4, tx_rd_info, rd_stats, x);
5497 return;
5498 }
5499 }
5500 }
5501
Alexander Bokov8829a242017-08-31 18:07:05 -07005502// If we predict that skip is the optimal RD decision - set the respective
5503// context and terminate early.
5504#if CONFIG_HIGHBITDEPTH
5505 if (!(xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH))
5506#endif // CONFIG_HIGHBITDEPTH
5507 {
5508 if (is_inter && cpi->sf.tx_type_search.use_skip_flag_prediction &&
5509 predict_skip_flag_8bit(x, bsize)) {
5510 set_skip_flag(cpi, x, rd_stats, bsize);
5511 return;
5512 }
5513 }
5514
5515 if (is_inter && cpi->sf.tx_type_search.prune_mode > NO_PRUNE)
5516#if CONFIG_EXT_TX
5517 prune = prune_tx_types(cpi, bsize, x, xd, ext_tx_set);
5518#else
5519 prune = prune_tx_types(cpi, bsize, x, xd, 0);
5520#endif // CONFIG_EXT_TX
5521
Rupert Swarbrickde2ea942017-10-09 15:21:21 +01005522 int found = 0;
5523
Jingning Hane3b81bc2017-06-23 11:43:52 -07005524 for (tx_type = txk_start; tx_type < txk_end; ++tx_type) {
Angie Chiangb5dda482016-11-02 16:19:58 -07005525 RD_STATS this_rd_stats;
Angie Chiangc0feea82016-11-03 15:36:18 -07005526 av1_init_rd_stats(&this_rd_stats);
Sarah Parker53f93db2017-07-11 17:20:04 -07005527#if CONFIG_MRC_TX
5528 // MRC_DCT only implemented for TX_32X32 so only include this tx in
5529 // the search for TX_32X32
Sarah Parker2e08d962017-08-01 19:51:20 -07005530 if (tx_type == MRC_DCT &&
5531 (max_tx_size != TX_32X32 || (is_inter && !USE_MRC_INTER) ||
5532 (!is_inter && !USE_MRC_INTRA)))
5533 continue;
Sarah Parker53f93db2017-07-11 17:20:04 -07005534#endif // CONFIG_MRC_TX
Yaowu Xuc27fc142016-08-22 16:08:15 -07005535#if CONFIG_EXT_TX
Hui Suddbcde22017-09-18 17:22:02 -07005536 if (!av1_ext_tx_used[tx_set_type][tx_type]) continue;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005537 if (is_inter) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07005538 if (cpi->sf.tx_type_search.prune_mode > NO_PRUNE) {
5539 if (!do_tx_type_search(tx_type, prune)) continue;
5540 }
5541 } else {
5542 if (!ALLOW_INTRA_EXT_TX && bsize >= BLOCK_8X8) {
5543 if (tx_type != intra_mode_to_tx_type_context[mbmi->mode]) continue;
5544 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07005545 }
5546#else // CONFIG_EXT_TX
Yaowu Xuc27fc142016-08-22 16:08:15 -07005547 if (is_inter && cpi->sf.tx_type_search.prune_mode > NO_PRUNE &&
5548 !do_tx_type_search(tx_type, prune))
5549 continue;
5550#endif // CONFIG_EXT_TX
5551 if (is_inter && x->use_default_inter_tx_type &&
5552 tx_type != get_default_tx_type(0, xd, 0, max_tx_size))
5553 continue;
5554
Jingning Hane67b38a2016-11-04 10:30:00 -07005555 if (xd->lossless[mbmi->segment_id])
5556 if (tx_type != DCT_DCT) continue;
5557
Angie Chiangb5dda482016-11-02 16:19:58 -07005558 rd = select_tx_size_fix_type(cpi, x, &this_rd_stats, bsize, ref_best_rd,
Debargha Mukherjee9245d892017-10-06 13:54:31 -07005559 tx_type);
Hui Suda816a12017-08-18 14:46:02 -07005560 ref_best_rd = AOMMIN(rd, ref_best_rd);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005561 if (rd < best_rd) {
5562 best_rd = rd;
Angie Chiangb5dda482016-11-02 16:19:58 -07005563 *rd_stats = this_rd_stats;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005564 best_tx_type = mbmi->tx_type;
5565 best_tx = mbmi->tx_size;
Jingning Hane67b38a2016-11-04 10:30:00 -07005566 best_min_tx_size = mbmi->min_tx_size;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005567 memcpy(best_blk_skip, x->blk_skip[0], sizeof(best_blk_skip[0]) * n4);
Rupert Swarbrickde2ea942017-10-09 15:21:21 +01005568 found = 1;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005569 for (idy = 0; idy < xd->n8_h; ++idy)
5570 for (idx = 0; idx < xd->n8_w; ++idx)
5571 best_tx_size[idy][idx] = mbmi->inter_tx_size[idy][idx];
5572 }
5573 }
5574
Rupert Swarbrickde2ea942017-10-09 15:21:21 +01005575 // We should always find at least one candidate unless ref_best_rd is less
5576 // than INT64_MAX (in which case, all the calls to select_tx_size_fix_type
5577 // might have failed to find something better)
5578 assert(IMPLIES(!found, ref_best_rd != INT64_MAX));
5579 if (!found) return;
5580
Lester Lu432012f2017-08-17 14:39:29 -07005581#if CONFIG_LGT_FROM_PRED
5582 if (search_lgt && is_lgt_allowed(mbmi->mode, max_tx_size) &&
5583 !cm->reduced_tx_set_used) {
5584 RD_STATS this_rd_stats;
5585 mbmi->use_lgt = 1;
5586 rd = select_tx_size_fix_type(cpi, x, &this_rd_stats, bsize, ref_best_rd, 0);
5587 if (rd < best_rd) {
5588 best_rd = rd;
5589 *rd_stats = this_rd_stats;
5590 best_tx = mbmi->tx_size;
5591 best_min_tx_size = mbmi->min_tx_size;
5592 memcpy(best_blk_skip, x->blk_skip[0], sizeof(best_blk_skip[0]) * n4);
5593 for (idy = 0; idy < xd->n8_h; ++idy)
5594 for (idx = 0; idx < xd->n8_w; ++idx)
5595 best_tx_size[idy][idx] = mbmi->inter_tx_size[idy][idx];
5596 } else {
5597 mbmi->use_lgt = 0;
5598 }
5599 }
5600#endif // CONFIG_LGT_FROM_PRED
Rupert Swarbrickde2ea942017-10-09 15:21:21 +01005601 // We found a candidate transform to use. Copy our results from the "best"
5602 // array into mbmi.
Yaowu Xuc27fc142016-08-22 16:08:15 -07005603 mbmi->tx_type = best_tx_type;
5604 for (idy = 0; idy < xd->n8_h; ++idy)
5605 for (idx = 0; idx < xd->n8_w; ++idx)
5606 mbmi->inter_tx_size[idy][idx] = best_tx_size[idy][idx];
5607 mbmi->tx_size = best_tx;
Jingning Hane67b38a2016-11-04 10:30:00 -07005608 mbmi->min_tx_size = best_min_tx_size;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005609 memcpy(x->blk_skip[0], best_blk_skip, sizeof(best_blk_skip[0]) * n4);
Hui Su1ddf2312017-08-19 15:21:34 -07005610
5611 // Save the RD search results into tx_rd_record.
5612 int index;
5613 if (tx_rd_record->num < RD_RECORD_BUFFER_LEN) {
5614 index =
5615 (tx_rd_record->index_start + tx_rd_record->num) % RD_RECORD_BUFFER_LEN;
5616 ++tx_rd_record->num;
5617 } else {
5618 index = tx_rd_record->index_start;
5619 tx_rd_record->index_start =
5620 (tx_rd_record->index_start + 1) % RD_RECORD_BUFFER_LEN;
5621 }
5622 save_tx_rd_info(n4, hash, x, rd_stats, &tx_rd_record->tx_rd_info[index]);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005623}
5624
Yaowu Xuf883b422016-08-30 14:01:10 -07005625static void tx_block_rd(const AV1_COMP *cpi, MACROBLOCK *x, int blk_row,
Yaowu Xuc27fc142016-08-22 16:08:15 -07005626 int blk_col, int plane, int block, TX_SIZE tx_size,
5627 BLOCK_SIZE plane_bsize, ENTROPY_CONTEXT *above_ctx,
Angie Chiangb5dda482016-11-02 16:19:58 -07005628 ENTROPY_CONTEXT *left_ctx, RD_STATS *rd_stats) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07005629 MACROBLOCKD *const xd = &x->e_mbd;
5630 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005631 struct macroblockd_plane *const pd = &xd->plane[plane];
5632 BLOCK_SIZE bsize = txsize_to_bsize[tx_size];
5633 const int tx_row = blk_row >> (1 - pd->subsampling_y);
5634 const int tx_col = blk_col >> (1 - pd->subsampling_x);
5635 TX_SIZE plane_tx_size;
Jingning Han18482fe2016-11-02 17:01:58 -07005636 const int max_blocks_high = max_block_high(xd, plane_bsize, plane);
5637 const int max_blocks_wide = max_block_wide(xd, plane_bsize, plane);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005638
Jingning Hand3fada82016-11-22 10:46:55 -08005639 assert(tx_size < TX_SIZES_ALL);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005640
Yaowu Xuc27fc142016-08-22 16:08:15 -07005641 if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return;
5642
Debargha Mukherjee2f123402016-08-30 17:43:38 -07005643 plane_tx_size =
5644 plane ? uv_txsize_lookup[bsize][mbmi->inter_tx_size[tx_row][tx_col]][0][0]
5645 : mbmi->inter_tx_size[tx_row][tx_col];
Yaowu Xuc27fc142016-08-22 16:08:15 -07005646
5647 if (tx_size == plane_tx_size) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07005648 ENTROPY_CONTEXT *ta = above_ctx + blk_col;
5649 ENTROPY_CONTEXT *tl = left_ctx + blk_row;
Yaowu Xuf883b422016-08-30 14:01:10 -07005650 av1_tx_block_rd_b(cpi, x, tx_size, blk_row, blk_col, plane, block,
Angie Chiang77368af2017-03-23 16:22:07 -07005651 plane_bsize, ta, tl, rd_stats);
Tom Fineganac870492017-08-15 16:19:13 -07005652#if !CONFIG_PVQ
Jingning Han328d57b2017-07-07 14:40:17 -07005653 av1_set_txb_context(x, plane, block, tx_size, ta, tl);
Tom Fineganac870492017-08-15 16:19:13 -07005654#endif // !CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -07005655 } else {
Jingning Han18482fe2016-11-02 17:01:58 -07005656 const TX_SIZE sub_txs = sub_tx_size_map[tx_size];
5657 const int bsl = tx_size_wide_unit[sub_txs];
Jingning Han58224042016-10-27 16:35:32 -07005658 int step = tx_size_wide_unit[sub_txs] * tx_size_high_unit[sub_txs];
Yaowu Xuc27fc142016-08-22 16:08:15 -07005659 int i;
5660
5661 assert(bsl > 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005662
5663 for (i = 0; i < 4; ++i) {
Jingning Han98d6a1f2016-11-03 12:47:47 -07005664 int offsetr = blk_row + (i >> 1) * bsl;
5665 int offsetc = blk_col + (i & 0x01) * bsl;
5666
5667 if (offsetr >= max_blocks_high || offsetc >= max_blocks_wide) continue;
5668
5669 tx_block_rd(cpi, x, offsetr, offsetc, plane, block, sub_txs, plane_bsize,
5670 above_ctx, left_ctx, rd_stats);
5671 block += step;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005672 }
5673 }
5674}
5675
5676// Return value 0: early termination triggered, no valid rd cost available;
5677// 1: rd cost values are valid.
Angie Chiangb5dda482016-11-02 16:19:58 -07005678static int inter_block_uvrd(const AV1_COMP *cpi, MACROBLOCK *x,
5679 RD_STATS *rd_stats, BLOCK_SIZE bsize,
5680 int64_t ref_best_rd) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07005681 MACROBLOCKD *const xd = &x->e_mbd;
5682 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
5683 int plane;
5684 int is_cost_valid = 1;
5685 int64_t this_rd;
5686
5687 if (ref_best_rd < 0) is_cost_valid = 0;
5688
Angie Chiangc0feea82016-11-03 15:36:18 -07005689 av1_init_rd_stats(rd_stats);
Yue Chena1e48dc2016-08-29 17:29:33 -07005690
Jingning Han31b6a4f2017-02-23 11:05:53 -08005691#if CONFIG_CB4X4 && !CONFIG_CHROMA_2X2
Jingning Han9ce464c2017-02-20 15:36:30 -08005692 if (x->skip_chroma_rd) return is_cost_valid;
Jingning Han52d2b402017-05-19 09:31:17 -07005693 bsize = scale_chroma_bsize(mbmi->sb_type, xd->plane[1].subsampling_x,
5694 xd->plane[1].subsampling_y);
Fergus Simpson4063a682017-02-28 16:52:22 -08005695#endif // CONFIG_CB4X4 && !CONFIG_CHROMA_2X2
Jingning Han9ce464c2017-02-20 15:36:30 -08005696
Yue Chena1e48dc2016-08-29 17:29:33 -07005697#if CONFIG_EXT_TX && CONFIG_RECT_TX
5698 if (is_rect_tx(mbmi->tx_size)) {
Angie Chiang284d7772016-11-08 11:06:45 -08005699 return super_block_uvrd(cpi, x, rd_stats, bsize, ref_best_rd);
Yue Chena1e48dc2016-08-29 17:29:33 -07005700 }
5701#endif // CONFIG_EXT_TX && CONFIG_RECT_TX
5702
Yaowu Xuc27fc142016-08-22 16:08:15 -07005703 if (is_inter_block(mbmi) && is_cost_valid) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07005704 for (plane = 1; plane < MAX_MB_PLANE; ++plane)
Yaowu Xuf883b422016-08-30 14:01:10 -07005705 av1_subtract_plane(x, bsize, plane);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005706 }
5707
Yaowu Xuc27fc142016-08-22 16:08:15 -07005708 for (plane = 1; plane < MAX_MB_PLANE; ++plane) {
5709 const struct macroblockd_plane *const pd = &xd->plane[plane];
5710 const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd);
Jingning Han9ca05b72017-01-03 14:41:36 -08005711 const int mi_width = block_size_wide[plane_bsize] >> tx_size_wide_log2[0];
5712 const int mi_height = block_size_high[plane_bsize] >> tx_size_high_log2[0];
Jingning Han70e5f3f2016-11-09 17:03:07 -08005713 const TX_SIZE max_tx_size = max_txsize_rect_lookup[plane_bsize];
Jingning Han18482fe2016-11-02 17:01:58 -07005714 const int bh = tx_size_high_unit[max_tx_size];
5715 const int bw = tx_size_wide_unit[max_tx_size];
Yaowu Xuc27fc142016-08-22 16:08:15 -07005716 int idx, idy;
5717 int block = 0;
Jingning Han18482fe2016-11-02 17:01:58 -07005718 const int step = bh * bw;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005719 ENTROPY_CONTEXT ta[2 * MAX_MIB_SIZE];
5720 ENTROPY_CONTEXT tl[2 * MAX_MIB_SIZE];
Angie Chiangb5dda482016-11-02 16:19:58 -07005721 RD_STATS pn_rd_stats;
Angie Chiangc0feea82016-11-03 15:36:18 -07005722 av1_init_rd_stats(&pn_rd_stats);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005723
Jingning Han9ca05b72017-01-03 14:41:36 -08005724 av1_get_entropy_contexts(bsize, 0, pd, ta, tl);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005725
5726 for (idy = 0; idy < mi_height; idy += bh) {
Jingning Han18482fe2016-11-02 17:01:58 -07005727 for (idx = 0; idx < mi_width; idx += bw) {
5728 tx_block_rd(cpi, x, idy, idx, plane, block, max_tx_size, plane_bsize,
Angie Chiangb5dda482016-11-02 16:19:58 -07005729 ta, tl, &pn_rd_stats);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005730 block += step;
5731 }
5732 }
5733
Angie Chiangb5dda482016-11-02 16:19:58 -07005734 if (pn_rd_stats.rate == INT_MAX) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07005735 is_cost_valid = 0;
5736 break;
5737 }
5738
Angie Chiang628d7c92016-11-03 16:24:56 -07005739 av1_merge_rd_stats(rd_stats, &pn_rd_stats);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005740
Urvang Joshi70006e42017-06-14 16:08:55 -07005741 this_rd = AOMMIN(RDCOST(x->rdmult, rd_stats->rate, rd_stats->dist),
5742 RDCOST(x->rdmult, 0, rd_stats->sse));
Yaowu Xuc27fc142016-08-22 16:08:15 -07005743
5744 if (this_rd > ref_best_rd) {
5745 is_cost_valid = 0;
5746 break;
5747 }
5748 }
5749
5750 if (!is_cost_valid) {
5751 // reset cost value
Angie Chiangc0feea82016-11-03 15:36:18 -07005752 av1_invalid_rd_stats(rd_stats);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005753 }
5754
5755 return is_cost_valid;
5756}
5757#endif // CONFIG_VAR_TX
5758
hui su83c26632017-01-24 17:19:06 -08005759static void rd_pick_palette_intra_sbuv(const AV1_COMP *const cpi, MACROBLOCK *x,
5760 int dc_mode_cost,
5761 uint8_t *best_palette_color_map,
5762 MB_MODE_INFO *const best_mbmi,
5763 int64_t *best_rd, int *rate,
5764 int *rate_tokenonly, int64_t *distortion,
5765 int *skippable) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07005766 MACROBLOCKD *const xd = &x->e_mbd;
5767 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Urvang Joshi330aec82017-05-08 15:37:42 -07005768 assert(!is_inter_block(mbmi));
hui sude0c70a2017-01-09 17:12:17 -08005769 PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005770 const BLOCK_SIZE bsize = mbmi->sb_type;
Urvang Joshic9e71d42017-08-09 18:58:33 -07005771 assert(bsize >= BLOCK_8X8);
Angie Chiang284d7772016-11-08 11:06:45 -08005772 int this_rate;
5773 int64_t this_rd;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005774 int colors_u, colors_v, colors;
5775 const int src_stride = x->plane[1].src.stride;
5776 const uint8_t *const src_u = x->plane[1].src.buf;
5777 const uint8_t *const src_v = x->plane[2].src.buf;
hui sude0c70a2017-01-09 17:12:17 -08005778 uint8_t *const color_map = xd->plane[1].color_index_map;
Angie Chiang284d7772016-11-08 11:06:45 -08005779 RD_STATS tokenonly_rd_stats;
Urvang Joshi56ba91b2017-01-10 13:22:09 -08005780 int plane_block_width, plane_block_height, rows, cols;
5781 av1_get_block_dimensions(bsize, 1, xd, &plane_block_width,
5782 &plane_block_height, &rows, &cols);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005783 if (rows * cols > PALETTE_MAX_BLOCK_SIZE) return;
5784
Luc Trudeaud6d9eee2017-07-12 12:36:50 -04005785 mbmi->uv_mode = UV_DC_PRED;
hui su5db97432016-10-14 16:10:14 -07005786#if CONFIG_FILTER_INTRA
5787 mbmi->filter_intra_mode_info.use_filter_intra_mode[1] = 0;
5788#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07005789
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02005790#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07005791 if (cpi->common.use_highbitdepth) {
Yaowu Xuf883b422016-08-30 14:01:10 -07005792 colors_u = av1_count_colors_highbd(src_u, src_stride, rows, cols,
5793 cpi->common.bit_depth);
5794 colors_v = av1_count_colors_highbd(src_v, src_stride, rows, cols,
5795 cpi->common.bit_depth);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005796 } else {
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02005797#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuf883b422016-08-30 14:01:10 -07005798 colors_u = av1_count_colors(src_u, src_stride, rows, cols);
5799 colors_v = av1_count_colors(src_v, src_stride, rows, cols);
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02005800#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07005801 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02005802#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07005803
hui su33567b22017-04-30 16:40:19 -07005804#if CONFIG_PALETTE_DELTA_ENCODING
hui su33567b22017-04-30 16:40:19 -07005805 uint16_t color_cache[2 * PALETTE_MAX_SIZE];
Hui Su3748bc22017-08-23 11:30:41 -07005806 const int n_cache = av1_get_palette_cache(xd, 1, color_cache);
hui su33567b22017-04-30 16:40:19 -07005807#endif // CONFIG_PALETTE_DELTA_ENCODING
5808
Yaowu Xuc27fc142016-08-22 16:08:15 -07005809 colors = colors_u > colors_v ? colors_u : colors_v;
5810 if (colors > 1 && colors <= 64) {
5811 int r, c, n, i, j;
5812 const int max_itr = 50;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005813 float lb_u, ub_u, val_u;
5814 float lb_v, ub_v, val_v;
5815 float *const data = x->palette_buffer->kmeans_data_buf;
5816 float centroids[2 * PALETTE_MAX_SIZE];
Yaowu Xuc27fc142016-08-22 16:08:15 -07005817
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02005818#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07005819 uint16_t *src_u16 = CONVERT_TO_SHORTPTR(src_u);
5820 uint16_t *src_v16 = CONVERT_TO_SHORTPTR(src_v);
5821 if (cpi->common.use_highbitdepth) {
5822 lb_u = src_u16[0];
5823 ub_u = src_u16[0];
5824 lb_v = src_v16[0];
5825 ub_v = src_v16[0];
5826 } else {
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02005827#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07005828 lb_u = src_u[0];
5829 ub_u = src_u[0];
5830 lb_v = src_v[0];
5831 ub_v = src_v[0];
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02005832#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07005833 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02005834#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07005835
Yaowu Xuc27fc142016-08-22 16:08:15 -07005836 for (r = 0; r < rows; ++r) {
5837 for (c = 0; c < cols; ++c) {
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02005838#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07005839 if (cpi->common.use_highbitdepth) {
5840 val_u = src_u16[r * src_stride + c];
5841 val_v = src_v16[r * src_stride + c];
5842 data[(r * cols + c) * 2] = val_u;
5843 data[(r * cols + c) * 2 + 1] = val_v;
5844 } else {
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02005845#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07005846 val_u = src_u[r * src_stride + c];
5847 val_v = src_v[r * src_stride + c];
5848 data[(r * cols + c) * 2] = val_u;
5849 data[(r * cols + c) * 2 + 1] = val_v;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02005850#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07005851 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02005852#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07005853 if (val_u < lb_u)
5854 lb_u = val_u;
5855 else if (val_u > ub_u)
5856 ub_u = val_u;
5857 if (val_v < lb_v)
5858 lb_v = val_v;
5859 else if (val_v > ub_v)
5860 ub_v = val_v;
5861 }
5862 }
5863
5864 for (n = colors > PALETTE_MAX_SIZE ? PALETTE_MAX_SIZE : colors; n >= 2;
5865 --n) {
5866 for (i = 0; i < n; ++i) {
5867 centroids[i * 2] = lb_u + (2 * i + 1) * (ub_u - lb_u) / n / 2;
5868 centroids[i * 2 + 1] = lb_v + (2 * i + 1) * (ub_v - lb_v) / n / 2;
5869 }
Yaowu Xuf883b422016-08-30 14:01:10 -07005870 av1_k_means(data, centroids, color_map, rows * cols, n, 2, max_itr);
hui sud13c24a2017-04-07 16:13:07 -07005871#if CONFIG_PALETTE_DELTA_ENCODING
hui su33567b22017-04-30 16:40:19 -07005872 optimize_palette_colors(color_cache, n_cache, n, 2, centroids);
hui sud13c24a2017-04-07 16:13:07 -07005873 // Sort the U channel colors in ascending order.
5874 for (i = 0; i < 2 * (n - 1); i += 2) {
5875 int min_idx = i;
5876 float min_val = centroids[i];
5877 for (j = i + 2; j < 2 * n; j += 2)
5878 if (centroids[j] < min_val) min_val = centroids[j], min_idx = j;
5879 if (min_idx != i) {
5880 float temp_u = centroids[i], temp_v = centroids[i + 1];
5881 centroids[i] = centroids[min_idx];
5882 centroids[i + 1] = centroids[min_idx + 1];
5883 centroids[min_idx] = temp_u, centroids[min_idx + 1] = temp_v;
5884 }
5885 }
5886 av1_calc_indices(data, centroids, color_map, rows * cols, n, 2);
5887#endif // CONFIG_PALETTE_DELTA_ENCODING
Urvang Joshi56ba91b2017-01-10 13:22:09 -08005888 extend_palette_color_map(color_map, cols, rows, plane_block_width,
5889 plane_block_height);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005890 pmi->palette_size[1] = n;
5891 for (i = 1; i < 3; ++i) {
5892 for (j = 0; j < n; ++j) {
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02005893#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07005894 if (cpi->common.use_highbitdepth)
5895 pmi->palette_colors[i * PALETTE_MAX_SIZE + j] = clip_pixel_highbd(
5896 (int)centroids[j * 2 + i - 1], cpi->common.bit_depth);
5897 else
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02005898#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07005899 pmi->palette_colors[i * PALETTE_MAX_SIZE + j] =
5900 clip_pixel((int)centroids[j * 2 + i - 1]);
5901 }
5902 }
5903
Angie Chiang284d7772016-11-08 11:06:45 -08005904 super_block_uvrd(cpi, x, &tokenonly_rd_stats, bsize, *best_rd);
5905 if (tokenonly_rd_stats.rate == INT_MAX) continue;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005906 this_rate =
Angie Chiang284d7772016-11-08 11:06:45 -08005907 tokenonly_rd_stats.rate + dc_mode_cost +
Yue Chenb23d00a2017-07-28 17:01:21 -07005908 x->palette_uv_size_cost[bsize - BLOCK_8X8][n - PALETTE_MIN_SIZE] +
Yaowu Xuc27fc142016-08-22 16:08:15 -07005909 write_uniform_cost(n, color_map[0]) +
Yaowu Xuf883b422016-08-30 14:01:10 -07005910 av1_cost_bit(
5911 av1_default_palette_uv_mode_prob[pmi->palette_size[0] > 0], 1);
hui su33567b22017-04-30 16:40:19 -07005912 this_rate += av1_palette_color_cost_uv(pmi,
5913#if CONFIG_PALETTE_DELTA_ENCODING
5914 color_cache, n_cache,
5915#endif // CONFIG_PALETTE_DELTA_ENCODING
5916 cpi->common.bit_depth);
Sarah Parker99e7daa2017-08-29 10:30:13 -07005917 this_rate +=
5918 av1_cost_color_map(x, 1, 0, bsize, mbmi->tx_size, PALETTE_MAP);
Urvang Joshi70006e42017-06-14 16:08:55 -07005919 this_rd = RDCOST(x->rdmult, this_rate, tokenonly_rd_stats.dist);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005920 if (this_rd < *best_rd) {
5921 *best_rd = this_rd;
hui su83c26632017-01-24 17:19:06 -08005922 *best_mbmi = *mbmi;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005923 memcpy(best_palette_color_map, color_map,
Urvang Joshi56ba91b2017-01-10 13:22:09 -08005924 plane_block_width * plane_block_height *
5925 sizeof(best_palette_color_map[0]));
Yaowu Xuc27fc142016-08-22 16:08:15 -07005926 *rate = this_rate;
Angie Chiang284d7772016-11-08 11:06:45 -08005927 *distortion = tokenonly_rd_stats.dist;
5928 *rate_tokenonly = tokenonly_rd_stats.rate;
5929 *skippable = tokenonly_rd_stats.skip;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005930 }
5931 }
5932 }
hui su83c26632017-01-24 17:19:06 -08005933 if (best_mbmi->palette_mode_info.palette_size[1] > 0) {
hui sude0c70a2017-01-09 17:12:17 -08005934 memcpy(color_map, best_palette_color_map,
Luc Trudeau0401e892017-08-31 00:37:11 -04005935 plane_block_width * plane_block_height *
5936 sizeof(best_palette_color_map[0]));
hui sude0c70a2017-01-09 17:12:17 -08005937 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07005938}
5939
hui su5db97432016-10-14 16:10:14 -07005940#if CONFIG_FILTER_INTRA
5941// Return 1 if an filter intra mode is selected; return 0 otherwise.
5942static int rd_pick_filter_intra_sbuv(const AV1_COMP *const cpi, MACROBLOCK *x,
5943 int *rate, int *rate_tokenonly,
5944 int64_t *distortion, int *skippable,
5945 BLOCK_SIZE bsize, int64_t *best_rd) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07005946 MACROBLOCKD *const xd = &x->e_mbd;
5947 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
hui su5db97432016-10-14 16:10:14 -07005948 int filter_intra_selected_flag = 0;
Angie Chiang284d7772016-11-08 11:06:45 -08005949 int this_rate;
5950 int64_t this_rd;
hui su5db97432016-10-14 16:10:14 -07005951 FILTER_INTRA_MODE mode;
5952 FILTER_INTRA_MODE_INFO filter_intra_mode_info;
Angie Chiang284d7772016-11-08 11:06:45 -08005953 RD_STATS tokenonly_rd_stats;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005954
hui su5db97432016-10-14 16:10:14 -07005955 av1_zero(filter_intra_mode_info);
5956 mbmi->filter_intra_mode_info.use_filter_intra_mode[1] = 1;
Luc Trudeaud6d9eee2017-07-12 12:36:50 -04005957 mbmi->uv_mode = UV_DC_PRED;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005958 mbmi->palette_mode_info.palette_size[1] = 0;
5959
5960 for (mode = 0; mode < FILTER_INTRA_MODES; ++mode) {
hui su5db97432016-10-14 16:10:14 -07005961 mbmi->filter_intra_mode_info.filter_intra_mode[1] = mode;
Angie Chiang284d7772016-11-08 11:06:45 -08005962 if (!super_block_uvrd(cpi, x, &tokenonly_rd_stats, bsize, *best_rd))
Yaowu Xuc27fc142016-08-22 16:08:15 -07005963 continue;
5964
Angie Chiang284d7772016-11-08 11:06:45 -08005965 this_rate = tokenonly_rd_stats.rate +
hui su5db97432016-10-14 16:10:14 -07005966 av1_cost_bit(cpi->common.fc->filter_intra_probs[1], 1) +
Yue Chenb23d00a2017-07-28 17:01:21 -07005967 x->intra_uv_mode_cost[mbmi->mode][mbmi->uv_mode] +
Yaowu Xuc27fc142016-08-22 16:08:15 -07005968 write_uniform_cost(FILTER_INTRA_MODES, mode);
Urvang Joshi70006e42017-06-14 16:08:55 -07005969 this_rd = RDCOST(x->rdmult, this_rate, tokenonly_rd_stats.dist);
Yaowu Xuc27fc142016-08-22 16:08:15 -07005970 if (this_rd < *best_rd) {
5971 *best_rd = this_rd;
5972 *rate = this_rate;
Angie Chiang284d7772016-11-08 11:06:45 -08005973 *rate_tokenonly = tokenonly_rd_stats.rate;
5974 *distortion = tokenonly_rd_stats.dist;
5975 *skippable = tokenonly_rd_stats.skip;
hui su5db97432016-10-14 16:10:14 -07005976 filter_intra_mode_info = mbmi->filter_intra_mode_info;
5977 filter_intra_selected_flag = 1;
Yaowu Xuc27fc142016-08-22 16:08:15 -07005978 }
5979 }
5980
hui su5db97432016-10-14 16:10:14 -07005981 if (filter_intra_selected_flag) {
Luc Trudeaud6d9eee2017-07-12 12:36:50 -04005982 mbmi->uv_mode = UV_DC_PRED;
hui su5db97432016-10-14 16:10:14 -07005983 mbmi->filter_intra_mode_info.use_filter_intra_mode[1] =
5984 filter_intra_mode_info.use_filter_intra_mode[1];
5985 mbmi->filter_intra_mode_info.filter_intra_mode[1] =
5986 filter_intra_mode_info.filter_intra_mode[1];
Yaowu Xuc27fc142016-08-22 16:08:15 -07005987 return 1;
5988 } else {
5989 return 0;
5990 }
5991}
hui su5db97432016-10-14 16:10:14 -07005992#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07005993
hui su5db97432016-10-14 16:10:14 -07005994#if CONFIG_EXT_INTRA
hui su45dc5972016-12-08 17:42:50 -08005995// Run RD calculation with given chroma intra prediction angle., and return
5996// the RD cost. Update the best mode info. if the RD cost is the best so far.
5997static int64_t pick_intra_angle_routine_sbuv(
5998 const AV1_COMP *const cpi, MACROBLOCK *x, BLOCK_SIZE bsize,
5999 int rate_overhead, int64_t best_rd_in, int *rate, RD_STATS *rd_stats,
6000 int *best_angle_delta, int64_t *best_rd) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07006001 MB_MODE_INFO *mbmi = &x->e_mbd.mi[0]->mbmi;
Urvang Joshi330aec82017-05-08 15:37:42 -07006002 assert(!is_inter_block(mbmi));
Angie Chiang284d7772016-11-08 11:06:45 -08006003 int this_rate;
6004 int64_t this_rd;
6005 RD_STATS tokenonly_rd_stats;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006006
hui su45dc5972016-12-08 17:42:50 -08006007 if (!super_block_uvrd(cpi, x, &tokenonly_rd_stats, bsize, best_rd_in))
6008 return INT64_MAX;
Angie Chiang284d7772016-11-08 11:06:45 -08006009 this_rate = tokenonly_rd_stats.rate + rate_overhead;
Urvang Joshi70006e42017-06-14 16:08:55 -07006010 this_rd = RDCOST(x->rdmult, this_rate, tokenonly_rd_stats.dist);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006011 if (this_rd < *best_rd) {
6012 *best_rd = this_rd;
6013 *best_angle_delta = mbmi->angle_delta[1];
6014 *rate = this_rate;
hui su45dc5972016-12-08 17:42:50 -08006015 rd_stats->rate = tokenonly_rd_stats.rate;
6016 rd_stats->dist = tokenonly_rd_stats.dist;
6017 rd_stats->skip = tokenonly_rd_stats.skip;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006018 }
hui su45dc5972016-12-08 17:42:50 -08006019 return this_rd;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006020}
6021
hui su45dc5972016-12-08 17:42:50 -08006022// With given chroma directional intra prediction mode, pick the best angle
6023// delta. Return true if a RD cost that is smaller than the input one is found.
Urvang Joshi52648442016-10-13 17:27:51 -07006024static int rd_pick_intra_angle_sbuv(const AV1_COMP *const cpi, MACROBLOCK *x,
Urvang Joshi52648442016-10-13 17:27:51 -07006025 BLOCK_SIZE bsize, int rate_overhead,
hui su45dc5972016-12-08 17:42:50 -08006026 int64_t best_rd, int *rate,
6027 RD_STATS *rd_stats) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07006028 MACROBLOCKD *const xd = &x->e_mbd;
6029 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Urvang Joshi330aec82017-05-08 15:37:42 -07006030 assert(!is_inter_block(mbmi));
hui su45dc5972016-12-08 17:42:50 -08006031 int i, angle_delta, best_angle_delta = 0;
hui su0a6731f2017-04-26 15:23:47 -07006032 int64_t this_rd, best_rd_in, rd_cost[2 * (MAX_ANGLE_DELTA + 2)];
Yaowu Xuc27fc142016-08-22 16:08:15 -07006033
hui su45dc5972016-12-08 17:42:50 -08006034 rd_stats->rate = INT_MAX;
6035 rd_stats->skip = 0;
6036 rd_stats->dist = INT64_MAX;
hui su0a6731f2017-04-26 15:23:47 -07006037 for (i = 0; i < 2 * (MAX_ANGLE_DELTA + 2); ++i) rd_cost[i] = INT64_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006038
hui su0a6731f2017-04-26 15:23:47 -07006039 for (angle_delta = 0; angle_delta <= MAX_ANGLE_DELTA; angle_delta += 2) {
hui su45dc5972016-12-08 17:42:50 -08006040 for (i = 0; i < 2; ++i) {
6041 best_rd_in = (best_rd == INT64_MAX)
6042 ? INT64_MAX
6043 : (best_rd + (best_rd >> ((angle_delta == 0) ? 3 : 5)));
6044 mbmi->angle_delta[1] = (1 - 2 * i) * angle_delta;
6045 this_rd = pick_intra_angle_routine_sbuv(cpi, x, bsize, rate_overhead,
6046 best_rd_in, rate, rd_stats,
6047 &best_angle_delta, &best_rd);
6048 rd_cost[2 * angle_delta + i] = this_rd;
6049 if (angle_delta == 0) {
6050 if (this_rd == INT64_MAX) return 0;
6051 rd_cost[1] = this_rd;
6052 break;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006053 }
6054 }
hui su45dc5972016-12-08 17:42:50 -08006055 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07006056
hui su45dc5972016-12-08 17:42:50 -08006057 assert(best_rd != INT64_MAX);
hui su0a6731f2017-04-26 15:23:47 -07006058 for (angle_delta = 1; angle_delta <= MAX_ANGLE_DELTA; angle_delta += 2) {
hui su45dc5972016-12-08 17:42:50 -08006059 int64_t rd_thresh;
6060 for (i = 0; i < 2; ++i) {
6061 int skip_search = 0;
6062 rd_thresh = best_rd + (best_rd >> 5);
6063 if (rd_cost[2 * (angle_delta + 1) + i] > rd_thresh &&
6064 rd_cost[2 * (angle_delta - 1) + i] > rd_thresh)
6065 skip_search = 1;
6066 if (!skip_search) {
6067 mbmi->angle_delta[1] = (1 - 2 * i) * angle_delta;
Yue Chenb0f808b2017-04-26 11:55:14 -07006068 pick_intra_angle_routine_sbuv(cpi, x, bsize, rate_overhead, best_rd,
6069 rate, rd_stats, &best_angle_delta,
6070 &best_rd);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006071 }
6072 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07006073 }
6074
6075 mbmi->angle_delta[1] = best_angle_delta;
hui su45dc5972016-12-08 17:42:50 -08006076 return rd_stats->rate != INT_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006077}
6078#endif // CONFIG_EXT_INTRA
6079
David Michael Barr2510f642017-07-11 23:39:20 +09006080#if CONFIG_CFL
Luc Trudeau056d1f42017-09-15 17:38:14 -04006081static int64_t cfl_alpha_dist_lbd(const int16_t *pred_buf_q3,
6082 const uint8_t *src, int src_stride, int width,
6083 int height, int dc_pred, int alpha_q3,
6084 int64_t *dist_neg_out) {
Luc Trudeau4c5df102017-07-08 14:43:27 -04006085 int64_t dist = 0;
David Michael Barr2510f642017-07-11 23:39:20 +09006086 int diff;
6087
6088 if (alpha_q3 == 0) {
6089 for (int j = 0; j < height; j++) {
6090 for (int i = 0; i < width; i++) {
6091 diff = src[i] - dc_pred;
6092 dist += diff * diff;
6093 }
6094 src += src_stride;
6095 }
6096
6097 if (dist_neg_out) *dist_neg_out = dist;
6098
6099 return dist;
6100 }
6101
Luc Trudeau4c5df102017-07-08 14:43:27 -04006102 int64_t dist_neg = 0;
Luc Trudeau593d02c2017-09-08 11:29:37 -04006103 for (int j = 0; j < height; j++) {
6104 for (int i = 0; i < width; i++) {
6105 const int uv = src[i];
Luc Trudeau4e26d662017-09-11 13:08:40 -04006106 const int scaled_luma = get_scaled_luma_q0(alpha_q3, pred_buf_q3[i]);
David Michael Barr2510f642017-07-11 23:39:20 +09006107
Luc Trudeau60669132017-09-28 16:49:49 -04006108 diff = uv - clip_pixel(scaled_luma + dc_pred);
Luc Trudeau593d02c2017-09-08 11:29:37 -04006109 dist += diff * diff;
David Michael Barr2510f642017-07-11 23:39:20 +09006110
Luc Trudeau60669132017-09-28 16:49:49 -04006111 diff = uv - clip_pixel(-scaled_luma + dc_pred);
Luc Trudeau593d02c2017-09-08 11:29:37 -04006112 dist_neg += diff * diff;
David Michael Barr2510f642017-07-11 23:39:20 +09006113 }
Luc Trudeau4e26d662017-09-11 13:08:40 -04006114 pred_buf_q3 += MAX_SB_SIZE;
Luc Trudeau593d02c2017-09-08 11:29:37 -04006115 src += src_stride;
David Michael Barr2510f642017-07-11 23:39:20 +09006116 }
6117
6118 if (dist_neg_out) *dist_neg_out = dist_neg;
6119
6120 return dist;
6121}
Luc Trudeau056d1f42017-09-15 17:38:14 -04006122#if CONFIG_HIGHBITDEPTH
6123static int64_t cfl_alpha_dist_hbd(const int16_t *pred_buf_q3,
6124 const uint16_t *src, int src_stride,
6125 int width, int height, int dc_pred,
6126 int alpha_q3, int bit_depth,
6127 int64_t *dist_neg_out) {
6128 const int shift = 2 * (bit_depth - 8);
6129 const int rounding = shift > 0 ? (1 << shift) >> 1 : 0;
6130 int64_t dist = 0;
6131 int diff;
6132
6133 if (alpha_q3 == 0) {
6134 for (int j = 0; j < height; j++) {
6135 for (int i = 0; i < width; i++) {
6136 diff = src[i] - dc_pred;
6137 dist += diff * diff;
6138 }
6139 src += src_stride;
6140 }
6141 dist = (dist + rounding) >> shift;
6142
6143 if (dist_neg_out) *dist_neg_out = dist;
6144
6145 return dist;
6146 }
6147
6148 int64_t dist_neg = 0;
6149 for (int j = 0; j < height; j++) {
6150 for (int i = 0; i < width; i++) {
6151 const int uv = src[i];
6152 const int scaled_luma = get_scaled_luma_q0(alpha_q3, pred_buf_q3[i]);
6153
6154 diff = uv - clip_pixel_highbd(scaled_luma + dc_pred, bit_depth);
6155 dist += diff * diff;
6156
6157 diff = uv - clip_pixel_highbd(-scaled_luma + dc_pred, bit_depth);
6158 dist_neg += diff * diff;
6159 }
6160 pred_buf_q3 += MAX_SB_SIZE;
6161 src += src_stride;
6162 }
6163
6164 if (dist_neg_out) *dist_neg_out = (dist_neg + rounding) >> shift;
6165
6166 return (dist + rounding) >> shift;
6167}
6168#endif // CONFIG_HIGHBITDEPTH
6169static int64_t cfl_alpha_dist(const int16_t *pred_buf_q3, const uint8_t *src,
6170 int src_stride, int width, int height,
6171 int dc_pred, int alpha_q3, int use_hbd,
6172 int bit_depth, int64_t *dist_neg_out) {
6173#if CONFIG_HIGHBITDEPTH
6174 if (use_hbd) {
6175 const uint16_t *src_16 = CONVERT_TO_SHORTPTR(src);
6176 return cfl_alpha_dist_hbd(pred_buf_q3, src_16, src_stride, width, height,
6177 dc_pred, alpha_q3, bit_depth, dist_neg_out);
6178 }
6179#endif // CONFIG_HIGHBITDEPTH
6180 (void)use_hbd;
6181 (void)bit_depth;
6182 return cfl_alpha_dist_lbd(pred_buf_q3, src, src_stride, width, height,
6183 dc_pred, alpha_q3, dist_neg_out);
6184}
David Michael Barr2510f642017-07-11 23:39:20 +09006185
David Michael Barr2510f642017-07-11 23:39:20 +09006186static int cfl_rd_pick_alpha(MACROBLOCK *const x, TX_SIZE tx_size) {
6187 const struct macroblock_plane *const p_u = &x->plane[AOM_PLANE_U];
6188 const struct macroblock_plane *const p_v = &x->plane[AOM_PLANE_V];
6189 const uint8_t *const src_u = p_u->src.buf;
6190 const uint8_t *const src_v = p_v->src.buf;
6191 const int src_stride_u = p_u->src.stride;
6192 const int src_stride_v = p_v->src.stride;
6193
6194 MACROBLOCKD *const xd = &x->e_mbd;
David Michael Barr2510f642017-07-11 23:39:20 +09006195 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
6196
6197 CFL_CTX *const cfl = xd->cfl;
6198 cfl_compute_parameters(xd, tx_size);
6199 const int width = cfl->uv_width;
6200 const int height = cfl->uv_height;
6201 const int dc_pred_u = cfl->dc_pred[CFL_PRED_U];
6202 const int dc_pred_v = cfl->dc_pred[CFL_PRED_V];
Luc Trudeau4e26d662017-09-11 13:08:40 -04006203 const int16_t *pred_buf_q3 = cfl->pred_buf_q3;
Luc Trudeau056d1f42017-09-15 17:38:14 -04006204 const int use_hbd = get_bitdepth_data_path_index(xd);
David Michael Barr2510f642017-07-11 23:39:20 +09006205
Luc Trudeau4c5df102017-07-08 14:43:27 -04006206 int64_t sse[CFL_PRED_PLANES][CFL_MAGS_SIZE];
Luc Trudeau056d1f42017-09-15 17:38:14 -04006207 sse[CFL_PRED_U][0] =
6208 cfl_alpha_dist(pred_buf_q3, src_u, src_stride_u, width, height, dc_pred_u,
6209 0, use_hbd, xd->bd, NULL);
6210 sse[CFL_PRED_V][0] =
6211 cfl_alpha_dist(pred_buf_q3, src_v, src_stride_v, width, height, dc_pred_v,
6212 0, use_hbd, xd->bd, NULL);
David Michael Barr2510f642017-07-11 23:39:20 +09006213
David Michael Barrf6eaa152017-07-19 19:42:28 +09006214 for (int c = 0; c < CFL_ALPHABET_SIZE; c++) {
6215 const int m = c * 2 + 1;
6216 const int abs_alpha_q3 = c + 1;
Luc Trudeau056d1f42017-09-15 17:38:14 -04006217 sse[CFL_PRED_U][m] = cfl_alpha_dist(
6218 pred_buf_q3, src_u, src_stride_u, width, height, dc_pred_u,
6219 abs_alpha_q3, use_hbd, xd->bd, &sse[CFL_PRED_U][m + 1]);
6220 sse[CFL_PRED_V][m] = cfl_alpha_dist(
6221 pred_buf_q3, src_v, src_stride_v, width, height, dc_pred_v,
6222 abs_alpha_q3, use_hbd, xd->bd, &sse[CFL_PRED_V][m + 1]);
David Michael Barr2510f642017-07-11 23:39:20 +09006223 }
6224
Luc Trudeau4c5df102017-07-08 14:43:27 -04006225 int64_t dist;
David Michael Barr2510f642017-07-11 23:39:20 +09006226 int64_t cost;
David Michael Barrf6eaa152017-07-19 19:42:28 +09006227 int64_t best_cost = INT64_MAX;
6228 int best_rate = 0;
David Michael Barr2510f642017-07-11 23:39:20 +09006229
6230 // Compute least squares parameter of the entire block
David Michael Barr2510f642017-07-11 23:39:20 +09006231 int ind = 0;
David Michael Barrf6eaa152017-07-19 19:42:28 +09006232 int signs = 0;
David Michael Barr2510f642017-07-11 23:39:20 +09006233
David Michael Barrf6eaa152017-07-19 19:42:28 +09006234 for (int joint_sign = 0; joint_sign < CFL_JOINT_SIGNS; joint_sign++) {
6235 const int sign_u = CFL_SIGN_U(joint_sign);
6236 const int sign_v = CFL_SIGN_V(joint_sign);
6237 const int size_u = (sign_u == CFL_SIGN_ZERO) ? 1 : CFL_ALPHABET_SIZE;
6238 const int size_v = (sign_v == CFL_SIGN_ZERO) ? 1 : CFL_ALPHABET_SIZE;
6239 for (int u = 0; u < size_u; u++) {
6240 const int idx_u = (sign_u == CFL_SIGN_ZERO) ? 0 : u * 2 + 1;
6241 for (int v = 0; v < size_v; v++) {
6242 const int idx_v = (sign_v == CFL_SIGN_ZERO) ? 0 : v * 2 + 1;
David Michael Barr2510f642017-07-11 23:39:20 +09006243 dist = sse[CFL_PRED_U][idx_u + (sign_u == CFL_SIGN_NEG)] +
6244 sse[CFL_PRED_V][idx_v + (sign_v == CFL_SIGN_NEG)];
6245 dist *= 16;
David Michael Barr38e560c2017-08-16 21:46:37 +09006246 const int rate = x->cfl_cost[joint_sign][CFL_PRED_U][u] +
6247 x->cfl_cost[joint_sign][CFL_PRED_V][v];
David Michael Barrf6eaa152017-07-19 19:42:28 +09006248 cost = RDCOST(x->rdmult, rate, dist);
David Michael Barr2510f642017-07-11 23:39:20 +09006249 if (cost < best_cost) {
6250 best_cost = cost;
David Michael Barrf6eaa152017-07-19 19:42:28 +09006251 best_rate = rate;
6252 ind = (u << CFL_ALPHABET_SIZE_LOG2) + v;
6253 signs = joint_sign;
David Michael Barr2510f642017-07-11 23:39:20 +09006254 }
6255 }
6256 }
6257 }
6258
6259 mbmi->cfl_alpha_idx = ind;
David Michael Barrf6eaa152017-07-19 19:42:28 +09006260 mbmi->cfl_alpha_signs = signs;
6261 return best_rate;
David Michael Barr2510f642017-07-11 23:39:20 +09006262}
6263#endif // CONFIG_CFL
6264
hui sueaddeee2017-05-30 12:19:38 -07006265static void init_sbuv_mode(MB_MODE_INFO *const mbmi) {
Luc Trudeaud6d9eee2017-07-12 12:36:50 -04006266 mbmi->uv_mode = UV_DC_PRED;
hui sueaddeee2017-05-30 12:19:38 -07006267 mbmi->palette_mode_info.palette_size[1] = 0;
hui sueaddeee2017-05-30 12:19:38 -07006268#if CONFIG_FILTER_INTRA
6269 mbmi->filter_intra_mode_info.use_filter_intra_mode[1] = 0;
6270#endif // CONFIG_FILTER_INTRA
6271}
6272
Urvang Joshi52648442016-10-13 17:27:51 -07006273static int64_t rd_pick_intra_sbuv_mode(const AV1_COMP *const cpi, MACROBLOCK *x,
6274 int *rate, int *rate_tokenonly,
6275 int64_t *distortion, int *skippable,
6276 BLOCK_SIZE bsize, TX_SIZE max_tx_size) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07006277 MACROBLOCKD *xd = &x->e_mbd;
6278 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Urvang Joshi330aec82017-05-08 15:37:42 -07006279 assert(!is_inter_block(mbmi));
hui su83c26632017-01-24 17:19:06 -08006280 MB_MODE_INFO best_mbmi = *mbmi;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006281 int64_t best_rd = INT64_MAX, this_rd;
Yushin Cho77bba8d2016-11-04 16:36:56 -07006282#if CONFIG_PVQ
6283 od_rollback_buffer buf;
Yushin Cho77bba8d2016-11-04 16:36:56 -07006284 od_encode_checkpoint(&x->daala_enc, &buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08006285#endif // CONFIG_PVQ
hui sude0c70a2017-01-09 17:12:17 -08006286 PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
Hui Sue87fb232017-10-05 15:00:15 -07006287 const int try_palette =
6288 av1_allow_palette(cpi->common.allow_screen_content_tools, mbmi->sb_type);
hui su5db97432016-10-14 16:10:14 -07006289
Luc Trudeaud6d9eee2017-07-12 12:36:50 -04006290 for (int mode_idx = 0; mode_idx < UV_INTRA_MODES; ++mode_idx) {
hui su8a516a82017-07-06 10:00:36 -07006291 int this_rate;
6292 RD_STATS tokenonly_rd_stats;
Luc Trudeaud6d9eee2017-07-12 12:36:50 -04006293 UV_PREDICTION_MODE mode = uv_rd_search_mode_order[mode_idx];
hui su83c26632017-01-24 17:19:06 -08006294#if CONFIG_EXT_INTRA
6295 const int is_directional_mode =
Luc Trudeau6e1cd782017-06-21 13:52:36 -04006296 av1_is_directional_mode(get_uv_mode(mode), mbmi->sb_type);
hui su83c26632017-01-24 17:19:06 -08006297#endif // CONFIG_EXT_INTRA
Urvang Joshifeb925f2016-12-05 10:37:29 -08006298 if (!(cpi->sf.intra_uv_mode_mask[txsize_sqr_up_map[max_tx_size]] &
6299 (1 << mode)))
6300 continue;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006301
6302 mbmi->uv_mode = mode;
David Michael Barr2510f642017-07-11 23:39:20 +09006303#if CONFIG_CFL
6304 int cfl_alpha_rate = 0;
Luc Trudeau6e1cd782017-06-21 13:52:36 -04006305 if (mode == UV_CFL_PRED) {
6306 assert(!is_directional_mode);
Luc Trudeaub05eeae2017-08-18 15:14:30 -04006307 const TX_SIZE uv_tx_size = av1_get_uv_tx_size(mbmi, &xd->plane[1]);
6308 cfl_alpha_rate = cfl_rd_pick_alpha(x, uv_tx_size);
David Michael Barr2510f642017-07-11 23:39:20 +09006309 }
6310#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07006311#if CONFIG_EXT_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07006312 mbmi->angle_delta[1] = 0;
Joe Young830d4ce2017-05-30 17:48:13 -07006313 if (is_directional_mode && av1_use_angle_delta(mbmi->sb_type)) {
Yue Chenb23d00a2017-07-28 17:01:21 -07006314 const int rate_overhead = x->intra_uv_mode_cost[mbmi->mode][mode] +
hui su0a6731f2017-04-26 15:23:47 -07006315 write_uniform_cost(2 * MAX_ANGLE_DELTA + 1, 0);
hui su45dc5972016-12-08 17:42:50 -08006316 if (!rd_pick_intra_angle_sbuv(cpi, x, bsize, rate_overhead, best_rd,
6317 &this_rate, &tokenonly_rd_stats))
Yaowu Xuc27fc142016-08-22 16:08:15 -07006318 continue;
6319 } else {
hui su83c26632017-01-24 17:19:06 -08006320#endif // CONFIG_EXT_INTRA
Angie Chiang284d7772016-11-08 11:06:45 -08006321 if (!super_block_uvrd(cpi, x, &tokenonly_rd_stats, bsize, best_rd)) {
Yushin Cho77bba8d2016-11-04 16:36:56 -07006322#if CONFIG_PVQ
6323 od_encode_rollback(&x->daala_enc, &buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08006324#endif // CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -07006325 continue;
Yushin Cho77bba8d2016-11-04 16:36:56 -07006326 }
hui su83c26632017-01-24 17:19:06 -08006327#if CONFIG_EXT_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07006328 }
hui su83c26632017-01-24 17:19:06 -08006329#endif // CONFIG_EXT_INTRA
Angie Chiang284d7772016-11-08 11:06:45 -08006330 this_rate =
Yue Chenb23d00a2017-07-28 17:01:21 -07006331 tokenonly_rd_stats.rate + x->intra_uv_mode_cost[mbmi->mode][mode];
hui su83c26632017-01-24 17:19:06 -08006332
Luc Trudeaudff41922017-07-07 09:47:58 -04006333#if CONFIG_CFL
Luc Trudeau6e1cd782017-06-21 13:52:36 -04006334 if (mode == UV_CFL_PRED) {
David Michael Barr2510f642017-07-11 23:39:20 +09006335 this_rate += cfl_alpha_rate;
Luc Trudeaudff41922017-07-07 09:47:58 -04006336 }
6337#endif
hui su83c26632017-01-24 17:19:06 -08006338#if CONFIG_EXT_INTRA
Joe Young830d4ce2017-05-30 17:48:13 -07006339 if (is_directional_mode && av1_use_angle_delta(mbmi->sb_type)) {
hui su0a6731f2017-04-26 15:23:47 -07006340 this_rate += write_uniform_cost(2 * MAX_ANGLE_DELTA + 1,
6341 MAX_ANGLE_DELTA + mbmi->angle_delta[1]);
hui su45dc5972016-12-08 17:42:50 -08006342 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07006343#endif // CONFIG_EXT_INTRA
hui su5db97432016-10-14 16:10:14 -07006344#if CONFIG_FILTER_INTRA
Luc Trudeau91357ee2017-09-27 13:40:37 -04006345 if (mbmi->sb_type >= BLOCK_8X8 && mode == UV_DC_PRED)
hui su5db97432016-10-14 16:10:14 -07006346 this_rate += av1_cost_bit(cpi->common.fc->filter_intra_probs[1], 0);
6347#endif // CONFIG_FILTER_INTRA
Rupert Swarbrick6f9cd942017-08-02 15:57:18 +01006348 if (try_palette && mode == UV_DC_PRED)
Yaowu Xuf883b422016-08-30 14:01:10 -07006349 this_rate += av1_cost_bit(
6350 av1_default_palette_uv_mode_prob[pmi->palette_size[0] > 0], 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006351
Yushin Cho77bba8d2016-11-04 16:36:56 -07006352#if CONFIG_PVQ
Yushin Cho77bba8d2016-11-04 16:36:56 -07006353 od_encode_rollback(&x->daala_enc, &buf);
Fergus Simpson4063a682017-02-28 16:52:22 -08006354#endif // CONFIG_PVQ
Urvang Joshi70006e42017-06-14 16:08:55 -07006355 this_rd = RDCOST(x->rdmult, this_rate, tokenonly_rd_stats.dist);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006356
6357 if (this_rd < best_rd) {
hui su83c26632017-01-24 17:19:06 -08006358 best_mbmi = *mbmi;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006359 best_rd = this_rd;
6360 *rate = this_rate;
Angie Chiang284d7772016-11-08 11:06:45 -08006361 *rate_tokenonly = tokenonly_rd_stats.rate;
6362 *distortion = tokenonly_rd_stats.dist;
6363 *skippable = tokenonly_rd_stats.skip;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006364 }
6365 }
6366
Rupert Swarbrick6f9cd942017-08-02 15:57:18 +01006367 if (try_palette) {
hui su8a516a82017-07-06 10:00:36 -07006368 uint8_t *best_palette_color_map = x->palette_buffer->best_palette_color_map;
hui su83c26632017-01-24 17:19:06 -08006369 rd_pick_palette_intra_sbuv(cpi, x,
Yue Chenb23d00a2017-07-28 17:01:21 -07006370 x->intra_uv_mode_cost[mbmi->mode][UV_DC_PRED],
hui su83c26632017-01-24 17:19:06 -08006371 best_palette_color_map, &best_mbmi, &best_rd,
6372 rate, rate_tokenonly, distortion, skippable);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006373 }
6374
hui su5db97432016-10-14 16:10:14 -07006375#if CONFIG_FILTER_INTRA
6376 if (mbmi->sb_type >= BLOCK_8X8) {
6377 if (rd_pick_filter_intra_sbuv(cpi, x, rate, rate_tokenonly, distortion,
hui su83c26632017-01-24 17:19:06 -08006378 skippable, bsize, &best_rd))
6379 best_mbmi = *mbmi;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006380 }
hui su5db97432016-10-14 16:10:14 -07006381#endif // CONFIG_FILTER_INTRA
6382
hui su83c26632017-01-24 17:19:06 -08006383 *mbmi = best_mbmi;
Urvang Joshifeb925f2016-12-05 10:37:29 -08006384 // Make sure we actually chose a mode
6385 assert(best_rd < INT64_MAX);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006386 return best_rd;
6387}
6388
Urvang Joshi52648442016-10-13 17:27:51 -07006389static void choose_intra_uv_mode(const AV1_COMP *const cpi, MACROBLOCK *const x,
Luc Trudeau9d4cbb82017-07-27 17:01:32 -04006390 BLOCK_SIZE bsize, TX_SIZE max_tx_size,
6391 int *rate_uv, int *rate_uv_tokenonly,
6392 int64_t *dist_uv, int *skip_uv,
6393 UV_PREDICTION_MODE *mode_uv) {
Luc Trudeaub05eeae2017-08-18 15:14:30 -04006394 MACROBLOCKD *xd = &x->e_mbd;
6395 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006396 // Use an estimated rd for uv_intra based on DC_PRED if the
6397 // appropriate speed flag is set.
Luc Trudeaub05eeae2017-08-18 15:14:30 -04006398 init_sbuv_mode(mbmi);
Jingning Han271bb2c2016-12-14 12:34:46 -08006399#if CONFIG_CB4X4
Luc Trudeau9d4cbb82017-07-27 17:01:32 -04006400#if !CONFIG_CHROMA_2X2
Jingning Han9ce464c2017-02-20 15:36:30 -08006401 if (x->skip_chroma_rd) {
6402 *rate_uv = 0;
6403 *rate_uv_tokenonly = 0;
6404 *dist_uv = 0;
6405 *skip_uv = 1;
Luc Trudeaud6d9eee2017-07-12 12:36:50 -04006406 *mode_uv = UV_DC_PRED;
Jingning Han9ce464c2017-02-20 15:36:30 -08006407 return;
6408 }
Luc Trudeaub05eeae2017-08-18 15:14:30 -04006409 bsize = scale_chroma_bsize(bsize, xd->plane[AOM_PLANE_U].subsampling_x,
6410 xd->plane[AOM_PLANE_U].subsampling_y);
Luc Trudeau9d4cbb82017-07-27 17:01:32 -04006411#endif // !CONFIG_CHROMA_2X2
Luc Trudeaub05eeae2017-08-18 15:14:30 -04006412#if CONFIG_CFL
6413 // Only store reconstructed luma when there's chroma RDO. When there's no
6414 // chroma RDO, the reconstructed luma will be stored in encode_superblock().
6415 xd->cfl->store_y = !x->skip_chroma_rd;
6416#endif // CONFIG_CFL
Jingning Han31b6a4f2017-02-23 11:05:53 -08006417#else
Luc Trudeau9d4cbb82017-07-27 17:01:32 -04006418 bsize = bsize < BLOCK_8X8 ? BLOCK_8X8 : bsize;
Luc Trudeaub05eeae2017-08-18 15:14:30 -04006419#if CONFIG_CFL
6420 xd->cfl->store_y = 1;
6421#endif // CONFIG_CFL
Jingning Han31b6a4f2017-02-23 11:05:53 -08006422#endif // CONFIG_CB4X4
Luc Trudeaub05eeae2017-08-18 15:14:30 -04006423#if CONFIG_CFL
6424 if (xd->cfl->store_y) {
6425 // Perform one extra call to txfm_rd_in_plane(), with the values chosen
6426 // during luma RDO, so we can store reconstructed luma values
6427 RD_STATS this_rd_stats;
6428 txfm_rd_in_plane(x, cpi, &this_rd_stats, INT64_MAX, AOM_PLANE_Y,
6429 mbmi->sb_type, mbmi->tx_size,
6430 cpi->sf.use_fast_coef_costing);
6431 xd->cfl->store_y = 0;
6432 }
6433#endif // CONFIG_CFL
Luc Trudeau9d4cbb82017-07-27 17:01:32 -04006434 rd_pick_intra_sbuv_mode(cpi, x, rate_uv, rate_uv_tokenonly, dist_uv, skip_uv,
6435 bsize, max_tx_size);
Luc Trudeaub05eeae2017-08-18 15:14:30 -04006436 *mode_uv = mbmi->uv_mode;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006437}
6438
Yue Chenb23d00a2017-07-28 17:01:21 -07006439static int cost_mv_ref(const MACROBLOCK *const x, PREDICTION_MODE mode,
Yaowu Xuc27fc142016-08-22 16:08:15 -07006440 int16_t mode_context) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07006441 if (is_inter_compound_mode(mode)) {
Yue Chenb23d00a2017-07-28 17:01:21 -07006442 return x
clang-format55ce9e02017-02-15 22:27:12 -08006443 ->inter_compound_mode_cost[mode_context][INTER_COMPOUND_OFFSET(mode)];
Zoe Liu85b66462017-04-20 14:28:19 -07006444#if CONFIG_COMPOUND_SINGLEREF
6445 } else if (is_inter_singleref_comp_mode(mode)) {
Yue Chenb23d00a2017-07-28 17:01:21 -07006446 return x->inter_singleref_comp_mode_cost[mode_context]
6447 [INTER_SINGLEREF_COMP_OFFSET(mode)];
Zoe Liu85b66462017-04-20 14:28:19 -07006448#endif // CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -07006449 }
David Barkercb03dc32017-04-07 13:05:09 +01006450
David Barkercb03dc32017-04-07 13:05:09 +01006451 int mode_cost = 0;
6452 int16_t mode_ctx = mode_context & NEWMV_CTX_MASK;
6453 int16_t is_all_zero_mv = mode_context & (1 << ALL_ZERO_FLAG_OFFSET);
6454
6455 assert(is_inter_mode(mode));
6456
6457 if (mode == NEWMV) {
Yue Chenb23d00a2017-07-28 17:01:21 -07006458 mode_cost = x->newmv_mode_cost[mode_ctx][0];
David Barkercb03dc32017-04-07 13:05:09 +01006459 return mode_cost;
6460 } else {
Yue Chenb23d00a2017-07-28 17:01:21 -07006461 mode_cost = x->newmv_mode_cost[mode_ctx][1];
David Barkercb03dc32017-04-07 13:05:09 +01006462 mode_ctx = (mode_context >> ZEROMV_OFFSET) & ZEROMV_CTX_MASK;
6463
6464 if (is_all_zero_mv) return mode_cost;
6465
6466 if (mode == ZEROMV) {
Yue Chenb23d00a2017-07-28 17:01:21 -07006467 mode_cost += x->zeromv_mode_cost[mode_ctx][0];
David Barkercb03dc32017-04-07 13:05:09 +01006468 return mode_cost;
6469 } else {
Yue Chenb23d00a2017-07-28 17:01:21 -07006470 mode_cost += x->zeromv_mode_cost[mode_ctx][1];
David Barkercb03dc32017-04-07 13:05:09 +01006471 mode_ctx = (mode_context >> REFMV_OFFSET) & REFMV_CTX_MASK;
6472
6473 if (mode_context & (1 << SKIP_NEARESTMV_OFFSET)) mode_ctx = 6;
6474 if (mode_context & (1 << SKIP_NEARMV_OFFSET)) mode_ctx = 7;
6475 if (mode_context & (1 << SKIP_NEARESTMV_SUB8X8_OFFSET)) mode_ctx = 8;
6476
Yue Chenb23d00a2017-07-28 17:01:21 -07006477 mode_cost += x->refmv_mode_cost[mode_ctx][mode != NEARESTMV];
David Barkercb03dc32017-04-07 13:05:09 +01006478 return mode_cost;
6479 }
6480 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07006481}
6482
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006483#if (CONFIG_WEDGE || CONFIG_COMPOUND_SEGMENT)
Sarah Parker6fdc8532016-11-16 17:47:13 -08006484static int get_interinter_compound_type_bits(BLOCK_SIZE bsize,
6485 COMPOUND_TYPE comp_type) {
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00006486 (void)bsize;
Sarah Parker6fdc8532016-11-16 17:47:13 -08006487 switch (comp_type) {
6488 case COMPOUND_AVERAGE: return 0;
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00006489#if CONFIG_WEDGE
Sarah Parker6fdc8532016-11-16 17:47:13 -08006490 case COMPOUND_WEDGE: return get_interinter_wedge_bits(bsize);
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00006491#endif // CONFIG_WEDGE
Sarah Parker2f6ce752016-12-08 15:26:46 -08006492#if CONFIG_COMPOUND_SEGMENT
Sarah Parker569edda2016-12-14 14:57:38 -08006493 case COMPOUND_SEG: return 1;
Sarah Parker2f6ce752016-12-08 15:26:46 -08006494#endif // CONFIG_COMPOUND_SEGMENT
Sarah Parker6fdc8532016-11-16 17:47:13 -08006495 default: assert(0); return 0;
6496 }
6497}
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006498#endif // (CONFIG_WEDGE || CONFIG_COMPOUND_SEGMENT)
Sarah Parker6fdc8532016-11-16 17:47:13 -08006499
Yaowu Xuc27fc142016-08-22 16:08:15 -07006500typedef struct {
6501 int eobs;
6502 int brate;
6503 int byrate;
6504 int64_t bdist;
6505 int64_t bsse;
6506 int64_t brdcost;
6507 int_mv mvs[2];
Yaowu Xuc27fc142016-08-22 16:08:15 -07006508 int_mv pred_mv[2];
Yaowu Xuc27fc142016-08-22 16:08:15 -07006509 int_mv ref_mv[2];
Jingning Han276c2942016-12-05 12:37:02 -08006510
Timothy B. Terriberryfe67ed62017-04-26 16:53:47 -07006511#if CONFIG_CHROMA_2X2
Jingning Han276c2942016-12-05 12:37:02 -08006512 ENTROPY_CONTEXT ta[4];
6513 ENTROPY_CONTEXT tl[4];
6514#else
Yaowu Xuc27fc142016-08-22 16:08:15 -07006515 ENTROPY_CONTEXT ta[2];
6516 ENTROPY_CONTEXT tl[2];
Timothy B. Terriberryfe67ed62017-04-26 16:53:47 -07006517#endif // CONFIG_CHROMA_2X2
Yaowu Xuc27fc142016-08-22 16:08:15 -07006518} SEG_RDSTAT;
6519
6520typedef struct {
6521 int_mv *ref_mv[2];
6522 int_mv mvp;
6523
6524 int64_t segment_rd;
6525 int r;
6526 int64_t d;
6527 int64_t sse;
6528 int segment_yrate;
6529 PREDICTION_MODE modes[4];
Zoe Liu85b66462017-04-20 14:28:19 -07006530#if CONFIG_COMPOUND_SINGLEREF
6531 SEG_RDSTAT rdstat[4][INTER_MODES + INTER_SINGLEREF_COMP_MODES +
6532 INTER_COMPOUND_MODES];
6533#else // !CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -07006534 SEG_RDSTAT rdstat[4][INTER_MODES + INTER_COMPOUND_MODES];
Zoe Liu85b66462017-04-20 14:28:19 -07006535#endif // CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -07006536 int mvthresh;
6537} BEST_SEG_INFO;
6538
Alex Converse0fa0f422017-04-24 12:51:14 -07006539static INLINE int mv_check_bounds(const MvLimits *mv_limits, const MV *mv) {
6540 return (mv->row >> 3) < mv_limits->row_min ||
6541 (mv->row >> 3) > mv_limits->row_max ||
6542 (mv->col >> 3) < mv_limits->col_min ||
6543 (mv->col >> 3) > mv_limits->col_max;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006544}
6545
Yaowu Xuc27fc142016-08-22 16:08:15 -07006546// Check if NEARESTMV/NEARMV/ZEROMV is the cheapest way encode zero motion.
6547// TODO(aconverse): Find out if this is still productive then clean up or remove
6548static int check_best_zero_mv(
Yue Chenb23d00a2017-07-28 17:01:21 -07006549 const AV1_COMP *const cpi, const MACROBLOCK *const x,
6550 const int16_t mode_context[TOTAL_REFS_PER_FRAME],
Yaowu Xuc27fc142016-08-22 16:08:15 -07006551 const int16_t compound_mode_context[TOTAL_REFS_PER_FRAME],
Yaowu Xuc27fc142016-08-22 16:08:15 -07006552 int_mv frame_mv[MB_MODE_COUNT][TOTAL_REFS_PER_FRAME], int this_mode,
David Barker45390c12017-02-20 14:44:40 +00006553 const MV_REFERENCE_FRAME ref_frames[2], const BLOCK_SIZE bsize, int block,
6554 int mi_row, int mi_col) {
Luc Trudeaud28e91d2017-06-05 14:42:26 -04006555 int_mv zeromv[2] = { {.as_int = 0 } };
Yushin Choc9751c52017-06-12 10:38:29 -07006556#if CONFIG_GLOBAL_MOTION
Sarah Parkerc2d38712017-01-24 15:15:41 -08006557 int comp_pred_mode = ref_frames[1] > INTRA_FRAME;
Yushin Choc9751c52017-06-12 10:38:29 -07006558#endif
David Barker45390c12017-02-20 14:44:40 +00006559 (void)mi_row;
6560 (void)mi_col;
Zoe Liubc030ee2017-07-31 15:20:46 -07006561 (void)cpi;
Sarah Parkerc2d38712017-01-24 15:15:41 -08006562#if CONFIG_GLOBAL_MOTION
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006563 if (this_mode == ZEROMV || this_mode == ZERO_ZEROMV) {
Luc Trudeaud28e91d2017-06-05 14:42:26 -04006564 for (int cur_frm = 0; cur_frm < 1 + comp_pred_mode; cur_frm++) {
Sarah Parkerc2d38712017-01-24 15:15:41 -08006565 zeromv[cur_frm].as_int =
6566 gm_get_motion_vector(&cpi->common.global_motion[ref_frames[cur_frm]],
Sarah Parkerae7c4582017-02-28 16:30:30 -08006567 cpi->common.allow_high_precision_mv, bsize,
RogerZhou3b635242017-09-19 10:06:46 -07006568 mi_col, mi_row, block
6569#if CONFIG_AMVR
6570 ,
6571 cpi->common.cur_frame_mv_precision_level
6572#endif
6573 )
Sarah Parkerc2d38712017-01-24 15:15:41 -08006574 .as_int;
Luc Trudeaud28e91d2017-06-05 14:42:26 -04006575 }
Sarah Parkerc2d38712017-01-24 15:15:41 -08006576 }
Luc Trudeaud28e91d2017-06-05 14:42:26 -04006577#endif // CONFIG_GLOBAL_MOTION
6578
Yaowu Xuc27fc142016-08-22 16:08:15 -07006579 if ((this_mode == NEARMV || this_mode == NEARESTMV || this_mode == ZEROMV) &&
Sarah Parkerc2d38712017-01-24 15:15:41 -08006580 frame_mv[this_mode][ref_frames[0]].as_int == zeromv[0].as_int &&
Yaowu Xuc27fc142016-08-22 16:08:15 -07006581 (ref_frames[1] <= INTRA_FRAME ||
Sarah Parkerc2d38712017-01-24 15:15:41 -08006582 frame_mv[this_mode][ref_frames[1]].as_int == zeromv[1].as_int)) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07006583 int16_t rfc =
Yaowu Xuf883b422016-08-30 14:01:10 -07006584 av1_mode_context_analyzer(mode_context, ref_frames, bsize, block);
Yue Chenb23d00a2017-07-28 17:01:21 -07006585 int c1 = cost_mv_ref(x, NEARMV, rfc);
6586 int c2 = cost_mv_ref(x, NEARESTMV, rfc);
6587 int c3 = cost_mv_ref(x, ZEROMV, rfc);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006588
Yaowu Xuc27fc142016-08-22 16:08:15 -07006589 if (this_mode == NEARMV) {
6590 if (c1 > c3) return 0;
6591 } else if (this_mode == NEARESTMV) {
6592 if (c2 > c3) return 0;
6593 } else {
6594 assert(this_mode == ZEROMV);
6595 if (ref_frames[1] <= INTRA_FRAME) {
6596 if ((c3 >= c2 && frame_mv[NEARESTMV][ref_frames[0]].as_int == 0) ||
6597 (c3 >= c1 && frame_mv[NEARMV][ref_frames[0]].as_int == 0))
6598 return 0;
6599 } else {
6600 if ((c3 >= c2 && frame_mv[NEARESTMV][ref_frames[0]].as_int == 0 &&
6601 frame_mv[NEARESTMV][ref_frames[1]].as_int == 0) ||
6602 (c3 >= c1 && frame_mv[NEARMV][ref_frames[0]].as_int == 0 &&
6603 frame_mv[NEARMV][ref_frames[1]].as_int == 0))
6604 return 0;
6605 }
6606 }
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006607 } else if ((this_mode == NEAREST_NEARESTMV || this_mode == NEAR_NEARMV ||
6608 this_mode == ZERO_ZEROMV) &&
6609 frame_mv[this_mode][ref_frames[0]].as_int == zeromv[0].as_int &&
6610 frame_mv[this_mode][ref_frames[1]].as_int == zeromv[1].as_int) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07006611 int16_t rfc = compound_mode_context[ref_frames[0]];
Yue Chenb23d00a2017-07-28 17:01:21 -07006612 int c2 = cost_mv_ref(x, NEAREST_NEARESTMV, rfc);
6613 int c3 = cost_mv_ref(x, ZERO_ZEROMV, rfc);
6614 int c5 = cost_mv_ref(x, NEAR_NEARMV, rfc);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006615
Debargha Mukherjeebb6e1342017-04-17 16:05:04 -07006616 if (this_mode == NEAREST_NEARESTMV) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07006617 if (c2 > c3) return 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006618 } else if (this_mode == NEAR_NEARMV) {
6619 if (c5 > c3) return 0;
6620 } else {
6621 assert(this_mode == ZERO_ZEROMV);
6622 if ((c3 >= c2 && frame_mv[NEAREST_NEARESTMV][ref_frames[0]].as_int == 0 &&
6623 frame_mv[NEAREST_NEARESTMV][ref_frames[1]].as_int == 0) ||
Yaowu Xuc27fc142016-08-22 16:08:15 -07006624 (c3 >= c5 && frame_mv[NEAR_NEARMV][ref_frames[0]].as_int == 0 &&
Debargha Mukherjeebb6e1342017-04-17 16:05:04 -07006625 frame_mv[NEAR_NEARMV][ref_frames[1]].as_int == 0))
Yaowu Xuc27fc142016-08-22 16:08:15 -07006626 return 0;
6627 }
6628 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07006629 return 1;
6630}
6631
Urvang Joshi52648442016-10-13 17:27:51 -07006632static void joint_motion_search(const AV1_COMP *cpi, MACROBLOCK *x,
Zoe Liu85b66462017-04-20 14:28:19 -07006633 BLOCK_SIZE bsize, int_mv *frame_mv,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006634#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006635 int_mv *frame_comp_mv,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006636#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006637 int mi_row, int mi_col,
David Barkerc155e012017-05-11 13:54:54 +01006638 int_mv *ref_mv_sub8x8[2], const uint8_t *mask,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006639 int mask_stride, int *rate_mv,
6640 const int block) {
Yaowu Xuf883b422016-08-30 14:01:10 -07006641 const AV1_COMMON *const cm = &cpi->common;
Jingning Hanae5cfde2016-11-30 12:01:44 -08006642 const int pw = block_size_wide[bsize];
6643 const int ph = block_size_high[bsize];
Yaowu Xuc27fc142016-08-22 16:08:15 -07006644 MACROBLOCKD *xd = &x->e_mbd;
6645 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Zoe Liu85b66462017-04-20 14:28:19 -07006646// This function should only ever be called for compound modes
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006647#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006648 if (!has_second_ref(mbmi)) {
6649 assert(is_inter_singleref_comp_mode(mbmi->mode));
6650 assert(frame_comp_mv);
6651 }
6652 assert(has_second_ref(mbmi) || is_inter_singleref_comp_mode(mbmi->mode));
clang-format4eafefe2017-09-04 12:51:20 -07006653 const int refs[2] = { mbmi->ref_frame[0],
6654 has_second_ref(mbmi) ? mbmi->ref_frame[1]
6655 : mbmi->ref_frame[0] };
Zoe Liu85b66462017-04-20 14:28:19 -07006656#else
Sarah Parkerb3ebed12017-03-09 10:52:03 -08006657 assert(has_second_ref(mbmi));
Zoe Liu122f3942017-04-25 11:18:38 -07006658 const int refs[2] = { mbmi->ref_frame[0], mbmi->ref_frame[1] };
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006659#endif // CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -07006660 int_mv ref_mv[2];
6661 int ite, ref;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006662 struct scale_factors sf;
Sarah Parker4c10a3c2017-04-10 19:37:59 -07006663#if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
James Zern89a015b2017-08-08 12:39:00 -04006664 // ic and ir are the 4x4 coordinates of the sub8x8 at index "block"
Sarah Parkerb3ebed12017-03-09 10:52:03 -08006665 const int ic = block & 1;
6666 const int ir = (block - ic) >> 1;
Jingning Hancb637672017-06-22 09:14:40 -07006667 struct macroblockd_plane *const pd = &xd->plane[0];
Sarah Parkerb3ebed12017-03-09 10:52:03 -08006668 const int p_col = ((mi_col * MI_SIZE) >> pd->subsampling_x) + 4 * ic;
6669 const int p_row = ((mi_row * MI_SIZE) >> pd->subsampling_y) + 4 * ir;
Sarah Parker4c10a3c2017-04-10 19:37:59 -07006670#if CONFIG_GLOBAL_MOTION
Sarah Parkerb3ebed12017-03-09 10:52:03 -08006671 int is_global[2];
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006672#if CONFIG_COMPOUND_SINGLEREF
Cheng Chen1483a712017-10-08 13:07:02 -07006673 for (ref = 0; ref < 1 + has_second_ref(mbmi); ++ref)
Zoe Liu85b66462017-04-20 14:28:19 -07006674#else
Cheng Chen1483a712017-10-08 13:07:02 -07006675 for (ref = 0; ref < 2; ++ref)
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006676#endif // CONFIG_COMPOUND_SINGLEREF
Cheng Chen1483a712017-10-08 13:07:02 -07006677 {
Sarah Parkerb3ebed12017-03-09 10:52:03 -08006678 WarpedMotionParams *const wm =
6679 &xd->global_motion[xd->mi[0]->mbmi.ref_frame[ref]];
6680 is_global[ref] = is_global_mv_block(xd->mi[0], block, wm->wmtype);
6681 }
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006682#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006683 if (!has_second_ref(mbmi)) is_global[1] = is_global[0];
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006684#endif // CONFIG_COMPOUND_SINGLEREF
Sarah Parkerb3ebed12017-03-09 10:52:03 -08006685#endif // CONFIG_GLOBAL_MOTION
Timothy B. Terriberry5d24b6f2017-06-15 13:39:35 -07006686#else // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
6687 (void)block;
Sarah Parker4c10a3c2017-04-10 19:37:59 -07006688#endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -07006689
6690 // Do joint motion search in compound mode to get more accurate mv.
6691 struct buf_2d backup_yv12[2][MAX_MB_PLANE];
6692 int last_besterr[2] = { INT_MAX, INT_MAX };
6693 const YV12_BUFFER_CONFIG *const scaled_ref_frame[2] = {
Zoe Liu122f3942017-04-25 11:18:38 -07006694 av1_get_scaled_ref_frame(cpi, refs[0]),
6695 av1_get_scaled_ref_frame(cpi, refs[1])
Yaowu Xuc27fc142016-08-22 16:08:15 -07006696 };
6697
6698// Prediction buffer from second frame.
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02006699#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07006700 DECLARE_ALIGNED(16, uint16_t, second_pred_alloc_16[MAX_SB_SQUARE]);
6701 uint8_t *second_pred;
6702#else
6703 DECLARE_ALIGNED(16, uint8_t, second_pred[MAX_SB_SQUARE]);
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02006704#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07006705
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006706#if CONFIG_CB4X4
Jingning Han61418bb2017-01-23 17:12:48 -08006707 (void)ref_mv_sub8x8;
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006708#endif // CONFIG_CB4X4
Jingning Han61418bb2017-01-23 17:12:48 -08006709
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006710#if CONFIG_COMPOUND_SINGLEREF
Cheng Chen1483a712017-10-08 13:07:02 -07006711 for (ref = 0; ref < 1 + has_second_ref(mbmi); ++ref)
Zoe Liu85b66462017-04-20 14:28:19 -07006712#else
Cheng Chen1483a712017-10-08 13:07:02 -07006713 for (ref = 0; ref < 2; ++ref)
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006714#endif // CONFIG_COMPOUND_SINGLEREF
Cheng Chen1483a712017-10-08 13:07:02 -07006715 {
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006716#if !CONFIG_CB4X4
Yaowu Xuc27fc142016-08-22 16:08:15 -07006717 if (bsize < BLOCK_8X8 && ref_mv_sub8x8 != NULL)
6718 ref_mv[ref].as_int = ref_mv_sub8x8[ref]->as_int;
6719 else
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006720#endif // !CONFIG_CB4X4
Yaowu Xuc27fc142016-08-22 16:08:15 -07006721 ref_mv[ref] = x->mbmi_ext->ref_mvs[refs[ref]][0];
6722
6723 if (scaled_ref_frame[ref]) {
6724 int i;
6725 // Swap out the reference frame for a version that's been scaled to
6726 // match the resolution of the current frame, allowing the existing
6727 // motion search code to be used without additional modifications.
6728 for (i = 0; i < MAX_MB_PLANE; i++)
6729 backup_yv12[ref][i] = xd->plane[i].pre[ref];
Yaowu Xuf883b422016-08-30 14:01:10 -07006730 av1_setup_pre_planes(xd, ref, scaled_ref_frame[ref], mi_row, mi_col,
6731 NULL);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006732 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07006733 }
6734
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006735#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006736 if (!has_second_ref(mbmi)) {
6737 assert(is_inter_singleref_comp_mode(mbmi->mode));
6738 // NOTE: For single ref comp mode, set up the 2nd set of ref_mv/pre_planes
6739 // all from the 1st reference frame, i.e. refs[0].
6740 ref_mv[1] = x->mbmi_ext->ref_mvs[refs[0]][0];
6741 if (scaled_ref_frame[0]) {
6742 int i;
6743 // Swap out the reference frame for a version that's been scaled to
6744 // match the resolution of the current frame, allowing the existing
6745 // motion search code to be used without additional modifications.
6746 for (i = 0; i < MAX_MB_PLANE; i++)
6747 backup_yv12[1][i] = xd->plane[i].pre[1];
6748 av1_setup_pre_planes(xd, 1, scaled_ref_frame[0], mi_row, mi_col, NULL);
6749 }
6750 }
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006751#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006752
Yaowu Xuc27fc142016-08-22 16:08:15 -07006753// Since we have scaled the reference frames to match the size of the current
6754// frame we must use a unit scaling factor during mode selection.
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02006755#if CONFIG_HIGHBITDEPTH
Yaowu Xuf883b422016-08-30 14:01:10 -07006756 av1_setup_scale_factors_for_frame(&sf, cm->width, cm->height, cm->width,
6757 cm->height, cm->use_highbitdepth);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006758#else
Yaowu Xuf883b422016-08-30 14:01:10 -07006759 av1_setup_scale_factors_for_frame(&sf, cm->width, cm->height, cm->width,
6760 cm->height);
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02006761#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07006762
Zoe Liu85b66462017-04-20 14:28:19 -07006763// Allow joint search multiple times iteratively for each reference frame
6764// and break out of the search loop if it couldn't find a better mv.
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006765#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006766 const int num_ites =
6767 (has_second_ref(mbmi) || mbmi->mode == SR_NEW_NEWMV) ? 4 : 1;
6768 const int start_ite = has_second_ref(mbmi) ? 0 : 1;
Cheng Chen1483a712017-10-08 13:07:02 -07006769 for (ite = start_ite; ite < (start_ite + num_ites); ite++)
Zoe Liu85b66462017-04-20 14:28:19 -07006770#else
Cheng Chen1483a712017-10-08 13:07:02 -07006771 for (ite = 0; ite < 4; ite++)
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006772#endif // CONFIG_COMPOUND_SINGLEREF
Cheng Chen1483a712017-10-08 13:07:02 -07006773 {
Yaowu Xuc27fc142016-08-22 16:08:15 -07006774 struct buf_2d ref_yv12[2];
6775 int bestsme = INT_MAX;
6776 int sadpb = x->sadperbit16;
6777 MV *const best_mv = &x->best_mv.as_mv;
6778 int search_range = 3;
6779
Alex Converse0fa0f422017-04-24 12:51:14 -07006780 MvLimits tmp_mv_limits = x->mv_limits;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006781 int id = ite % 2; // Even iterations search in the first reference frame,
6782 // odd iterations search in the second. The predictor
6783 // found for the 'other' reference frame is factored in.
Angie Chiange3a4c1c2017-02-10 16:26:49 -08006784 const int plane = 0;
David Barkere64d51a2017-06-09 14:52:42 +01006785 ConvolveParams conv_params = get_conv_params(!id, 0, plane);
Sarah Parker4c10a3c2017-04-10 19:37:59 -07006786#if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
6787 WarpTypesAllowed warp_types;
6788#if CONFIG_GLOBAL_MOTION
6789 warp_types.global_warp_allowed = is_global[!id];
6790#endif // CONFIG_GLOBAL_MOTION
6791#if CONFIG_WARPED_MOTION
6792 warp_types.local_warp_allowed = mbmi->motion_mode == WARPED_CAUSAL;
6793#endif // CONFIG_WARPED_MOTION
6794#endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -07006795
6796 // Initialized here because of compiler problem in Visual Studio.
Angie Chiange3a4c1c2017-02-10 16:26:49 -08006797 ref_yv12[0] = xd->plane[plane].pre[0];
6798 ref_yv12[1] = xd->plane[plane].pre[1];
Yaowu Xuc27fc142016-08-22 16:08:15 -07006799
Yaowu Xuc27fc142016-08-22 16:08:15 -07006800// Get the prediction block from the 'other' reference frame.
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006801#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006802 MV *const the_other_mv = (has_second_ref(mbmi) || id)
6803 ? &frame_mv[refs[!id]].as_mv
6804 : &frame_comp_mv[refs[0]].as_mv;
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006805#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006806
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02006807#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07006808 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
6809 second_pred = CONVERT_TO_BYTEPTR(second_pred_alloc_16);
Yaowu Xuf883b422016-08-30 14:01:10 -07006810 av1_highbd_build_inter_predictor(
Yaowu Xuc27fc142016-08-22 16:08:15 -07006811 ref_yv12[!id].buf, ref_yv12[!id].stride, second_pred, pw,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006812#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006813 the_other_mv,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006814#else // !(CONFIG_COMPOUND_SINGLEREF)
Zoe Liu85b66462017-04-20 14:28:19 -07006815 &frame_mv[refs[!id]].as_mv,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006816#endif // CONFIG_COMPOUND_SINGLEREF
Rupert Swarbrick27e90292017-09-28 17:46:50 +01006817 &sf, pw, ph, 0, mbmi->interp_filters,
Sarah Parker4c10a3c2017-04-10 19:37:59 -07006818#if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
6819 &warp_types, p_col, p_row,
6820#endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
Sarah Parkerb3ebed12017-03-09 10:52:03 -08006821 plane, MV_PRECISION_Q3, mi_col * MI_SIZE, mi_row * MI_SIZE, xd);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006822 } else {
6823 second_pred = (uint8_t *)second_pred_alloc_16;
Zoe Liu76fcff72017-04-24 17:50:53 -07006824#endif // CONFIG_HIGHBITDEPTH
Zoe Liu85b66462017-04-20 14:28:19 -07006825 av1_build_inter_predictor(
6826 ref_yv12[!id].buf, ref_yv12[!id].stride, second_pred, pw,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006827#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006828 the_other_mv,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006829#else // !(CONFIG_COMPOUND_SINGLEREF)
Zoe Liu85b66462017-04-20 14:28:19 -07006830 &frame_mv[refs[!id]].as_mv,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006831#endif // CONFIG_COMPOUND_SINGLEREF
Rupert Swarbrick27e90292017-09-28 17:46:50 +01006832 &sf, pw, ph, &conv_params, mbmi->interp_filters,
Sarah Parker4c10a3c2017-04-10 19:37:59 -07006833#if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
Zoe Liu85b66462017-04-20 14:28:19 -07006834 &warp_types, p_col, p_row, plane, !id,
Sarah Parker4c10a3c2017-04-10 19:37:59 -07006835#endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
Zoe Liu85b66462017-04-20 14:28:19 -07006836 MV_PRECISION_Q3, mi_col * MI_SIZE, mi_row * MI_SIZE, xd);
Zoe Liu76fcff72017-04-24 17:50:53 -07006837#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07006838 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02006839#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07006840
6841 // Do compound motion search on the current reference frame.
Angie Chiange3a4c1c2017-02-10 16:26:49 -08006842 if (id) xd->plane[plane].pre[0] = ref_yv12[id];
Alex Converse0fa0f422017-04-24 12:51:14 -07006843 av1_set_mv_search_range(&x->mv_limits, &ref_mv[id].as_mv);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006844
Zoe Liu85b66462017-04-20 14:28:19 -07006845// Use the mv result from the single mode as mv predictor.
6846// Use the mv result from the single mode as mv predictor.
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006847#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006848 if (!has_second_ref(mbmi) && id)
6849 *best_mv = frame_comp_mv[refs[0]].as_mv;
6850 else
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006851#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006852 *best_mv = frame_mv[refs[id]].as_mv;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006853
6854 best_mv->col >>= 3;
6855 best_mv->row >>= 3;
6856
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006857#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006858 if (!has_second_ref(mbmi))
6859 av1_set_mvcost(x, refs[0], 0, mbmi->ref_mv_idx);
6860 else
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006861#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006862 av1_set_mvcost(x, refs[id], id, mbmi->ref_mv_idx);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006863
6864 // Small-range full-pixel motion search.
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006865 bestsme = av1_refining_search_8p_c(x, sadpb, search_range,
6866 &cpi->fn_ptr[bsize], mask, mask_stride,
6867 id, &ref_mv[id].as_mv, second_pred);
David Barkerc155e012017-05-11 13:54:54 +01006868 if (bestsme < INT_MAX) {
David Barkerc155e012017-05-11 13:54:54 +01006869 if (mask)
6870 bestsme = av1_get_mvpred_mask_var(x, best_mv, &ref_mv[id].as_mv,
6871 second_pred, mask, mask_stride, id,
6872 &cpi->fn_ptr[bsize], 1);
6873 else
David Barkerc155e012017-05-11 13:54:54 +01006874 bestsme = av1_get_mvpred_av_var(x, best_mv, &ref_mv[id].as_mv,
6875 second_pred, &cpi->fn_ptr[bsize], 1);
6876 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07006877
Alex Converse0fa0f422017-04-24 12:51:14 -07006878 x->mv_limits = tmp_mv_limits;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006879
RogerZhou3b635242017-09-19 10:06:46 -07006880#if CONFIG_AMVR
6881 if (cpi->common.cur_frame_mv_precision_level) {
6882 x->best_mv.as_mv.row *= 8;
6883 x->best_mv.as_mv.col *= 8;
6884 }
Cheng Chen1483a712017-10-08 13:07:02 -07006885 if (bestsme < INT_MAX && cpi->common.cur_frame_mv_precision_level == 0)
RogerZhou3b635242017-09-19 10:06:46 -07006886#else
Cheng Chen1483a712017-10-08 13:07:02 -07006887 if (bestsme < INT_MAX)
RogerZhou3b635242017-09-19 10:06:46 -07006888#endif
Cheng Chen1483a712017-10-08 13:07:02 -07006889 {
Yaowu Xuc27fc142016-08-22 16:08:15 -07006890 int dis; /* TODO: use dis in distortion calculation later. */
6891 unsigned int sse;
Timothy B. Terriberry5d24b6f2017-06-15 13:39:35 -07006892 bestsme = cpi->find_fractional_mv_step(
6893 x, &ref_mv[id].as_mv, cpi->common.allow_high_precision_mv,
6894 x->errorperbit, &cpi->fn_ptr[bsize], 0,
6895 cpi->sf.mv.subpel_iters_per_step, NULL, x->nmvjointcost, x->mvcost,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006896 &dis, &sse, second_pred, mask, mask_stride, id, pw, ph,
6897 cpi->sf.use_upsampled_references);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006898 }
6899
6900 // Restore the pointer to the first (possibly scaled) prediction buffer.
Angie Chiange3a4c1c2017-02-10 16:26:49 -08006901 if (id) xd->plane[plane].pre[0] = ref_yv12[0];
Yaowu Xuc27fc142016-08-22 16:08:15 -07006902
6903 if (bestsme < last_besterr[id]) {
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006904#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006905 // NOTE: For single ref comp mode, frame_mv stores the first mv and
6906 // frame_comp_mv stores the second mv.
6907 if (!has_second_ref(mbmi) && id)
6908 frame_comp_mv[refs[0]].as_mv = *best_mv;
6909 else
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006910#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006911 frame_mv[refs[id]].as_mv = *best_mv;
Yaowu Xuc27fc142016-08-22 16:08:15 -07006912 last_besterr[id] = bestsme;
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006913#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006914 if (!has_second_ref(mbmi)) last_besterr[!id] = last_besterr[id];
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006915#endif // CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -07006916 } else {
6917 break;
6918 }
6919 }
6920
6921 *rate_mv = 0;
6922
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006923#if CONFIG_COMPOUND_SINGLEREF
Cheng Chen1483a712017-10-08 13:07:02 -07006924 for (ref = 0; ref < 1 + has_second_ref(mbmi); ++ref)
Zoe Liu85b66462017-04-20 14:28:19 -07006925#else
Cheng Chen1483a712017-10-08 13:07:02 -07006926 for (ref = 0; ref < 2; ++ref)
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006927#endif // CONFIG_COMPOUND_SINGLEREF
Cheng Chen1483a712017-10-08 13:07:02 -07006928 {
Yaowu Xuc27fc142016-08-22 16:08:15 -07006929 if (scaled_ref_frame[ref]) {
6930 // Restore the prediction frame pointers to their unscaled versions.
6931 int i;
6932 for (i = 0; i < MAX_MB_PLANE; i++)
6933 xd->plane[i].pre[ref] = backup_yv12[ref][i];
6934 }
Zoe Liu85b66462017-04-20 14:28:19 -07006935
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006936#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006937 if (!has_second_ref(mbmi))
6938 av1_set_mvcost(x, refs[0], 0, mbmi->ref_mv_idx);
Yaowu Xuc27fc142016-08-22 16:08:15 -07006939 else
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006940#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006941 av1_set_mvcost(x, refs[ref], ref, mbmi->ref_mv_idx);
6942
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006943#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006944 if (!has_second_ref(mbmi)) {
6945 // NOTE: For single ref comp mode, i.e. !has_second_ref(mbmi) is true, the
6946 // first mv is stored in frame_mv[] and the second mv is stored in
6947 // frame_comp_mv[].
6948 if (compound_ref0_mode(mbmi->mode) == NEWMV) // SR_NEW_NEWMV
6949 *rate_mv += av1_mv_bit_cost(&frame_mv[refs[0]].as_mv,
6950 &x->mbmi_ext->ref_mvs[refs[0]][0].as_mv,
6951 x->nmvjointcost, x->mvcost, MV_COST_WEIGHT);
6952 assert(compound_ref1_mode(mbmi->mode) == NEWMV);
6953 *rate_mv += av1_mv_bit_cost(&frame_comp_mv[refs[0]].as_mv,
6954 &x->mbmi_ext->ref_mvs[refs[0]][0].as_mv,
6955 x->nmvjointcost, x->mvcost, MV_COST_WEIGHT);
6956 } else {
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006957#endif // CONFIG_COMPOUND_SINGLEREF
6958#if !CONFIG_CB4X4
Zoe Liu85b66462017-04-20 14:28:19 -07006959 if (bsize >= BLOCK_8X8)
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006960#endif // !CONFIG_CB4X4
Zoe Liu85b66462017-04-20 14:28:19 -07006961 *rate_mv += av1_mv_bit_cost(&frame_mv[refs[ref]].as_mv,
6962 &x->mbmi_ext->ref_mvs[refs[ref]][0].as_mv,
6963 x->nmvjointcost, x->mvcost, MV_COST_WEIGHT);
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006964#if !CONFIG_CB4X4
Zoe Liu85b66462017-04-20 14:28:19 -07006965 else
6966 *rate_mv += av1_mv_bit_cost(&frame_mv[refs[ref]].as_mv,
6967 &ref_mv_sub8x8[ref]->as_mv, x->nmvjointcost,
6968 x->mvcost, MV_COST_WEIGHT);
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006969#endif // !CONFIG_CB4X4
6970#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006971 }
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006972#endif // CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -07006973 }
Zoe Liu85b66462017-04-20 14:28:19 -07006974
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006975#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07006976 if (!has_second_ref(mbmi)) {
6977 if (scaled_ref_frame[0]) {
6978 // Restore the prediction frame pointers to their unscaled versions.
6979 int i;
6980 for (i = 0; i < MAX_MB_PLANE; i++)
6981 xd->plane[i].pre[1] = backup_yv12[1][i];
6982 }
6983 }
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02006984#endif // CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -07006985}
6986
Zoe Liuc082bbc2017-05-17 13:31:37 -07006987static void estimate_ref_frame_costs(
6988 const AV1_COMMON *cm, const MACROBLOCKD *xd, int segment_id,
6989 unsigned int *ref_costs_single,
6990#if CONFIG_EXT_COMP_REFS
6991 unsigned int (*ref_costs_comp)[TOTAL_REFS_PER_FRAME],
6992#else
6993 unsigned int *ref_costs_comp,
6994#endif // CONFIG_EXT_COMP_REFS
6995 aom_prob *comp_mode_p) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07006996 int seg_ref_active =
6997 segfeature_active(&cm->seg, segment_id, SEG_LVL_REF_FRAME);
6998 if (seg_ref_active) {
6999 memset(ref_costs_single, 0,
7000 TOTAL_REFS_PER_FRAME * sizeof(*ref_costs_single));
Zoe Liuc082bbc2017-05-17 13:31:37 -07007001#if CONFIG_EXT_COMP_REFS
7002 int ref_frame;
7003 for (ref_frame = 0; ref_frame < TOTAL_REFS_PER_FRAME; ++ref_frame)
7004 memset(ref_costs_comp[ref_frame], 0,
7005 TOTAL_REFS_PER_FRAME * sizeof((*ref_costs_comp)[0]));
7006#else
Yaowu Xuc27fc142016-08-22 16:08:15 -07007007 memset(ref_costs_comp, 0, TOTAL_REFS_PER_FRAME * sizeof(*ref_costs_comp));
Zoe Liuc082bbc2017-05-17 13:31:37 -07007008#endif // CONFIG_EXT_COMP_REFS
7009
Yaowu Xuc27fc142016-08-22 16:08:15 -07007010 *comp_mode_p = 128;
7011 } else {
Yaowu Xuf883b422016-08-30 14:01:10 -07007012 aom_prob intra_inter_p = av1_get_intra_inter_prob(cm, xd);
7013 aom_prob comp_inter_p = 128;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007014
7015 if (cm->reference_mode == REFERENCE_MODE_SELECT) {
Yaowu Xuf883b422016-08-30 14:01:10 -07007016 comp_inter_p = av1_get_reference_mode_prob(cm, xd);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007017 *comp_mode_p = comp_inter_p;
7018 } else {
7019 *comp_mode_p = 128;
7020 }
7021
Yaowu Xuf883b422016-08-30 14:01:10 -07007022 ref_costs_single[INTRA_FRAME] = av1_cost_bit(intra_inter_p, 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007023
7024 if (cm->reference_mode != COMPOUND_REFERENCE) {
Yaowu Xuf883b422016-08-30 14:01:10 -07007025 aom_prob ref_single_p1 = av1_get_pred_prob_single_ref_p1(cm, xd);
7026 aom_prob ref_single_p2 = av1_get_pred_prob_single_ref_p2(cm, xd);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007027#if CONFIG_EXT_REFS
Yaowu Xuf883b422016-08-30 14:01:10 -07007028 aom_prob ref_single_p3 = av1_get_pred_prob_single_ref_p3(cm, xd);
7029 aom_prob ref_single_p4 = av1_get_pred_prob_single_ref_p4(cm, xd);
7030 aom_prob ref_single_p5 = av1_get_pred_prob_single_ref_p5(cm, xd);
Zoe Liue9b15e22017-07-19 15:53:01 -07007031 aom_prob ref_single_p6 = av1_get_pred_prob_single_ref_p6(cm, xd);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007032#endif // CONFIG_EXT_REFS
7033
Yaowu Xuf883b422016-08-30 14:01:10 -07007034 unsigned int base_cost = av1_cost_bit(intra_inter_p, 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007035
7036 ref_costs_single[LAST_FRAME] =
7037#if CONFIG_EXT_REFS
7038 ref_costs_single[LAST2_FRAME] = ref_costs_single[LAST3_FRAME] =
Zoe Liu3ac20932017-08-30 16:35:55 -07007039 ref_costs_single[BWDREF_FRAME] = ref_costs_single[ALTREF2_FRAME] =
Yaowu Xuc27fc142016-08-22 16:08:15 -07007040#endif // CONFIG_EXT_REFS
Zoe Liu3ac20932017-08-30 16:35:55 -07007041 ref_costs_single[GOLDEN_FRAME] =
7042 ref_costs_single[ALTREF_FRAME] = base_cost;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007043
7044#if CONFIG_EXT_REFS
Zoe Liufcf5fa22017-06-26 16:00:38 -07007045 ref_costs_single[LAST_FRAME] += av1_cost_bit(ref_single_p1, 0);
7046 ref_costs_single[LAST2_FRAME] += av1_cost_bit(ref_single_p1, 0);
7047 ref_costs_single[LAST3_FRAME] += av1_cost_bit(ref_single_p1, 0);
7048 ref_costs_single[GOLDEN_FRAME] += av1_cost_bit(ref_single_p1, 0);
7049 ref_costs_single[BWDREF_FRAME] += av1_cost_bit(ref_single_p1, 1);
Zoe Liue9b15e22017-07-19 15:53:01 -07007050 ref_costs_single[ALTREF2_FRAME] += av1_cost_bit(ref_single_p1, 1);
Zoe Liufcf5fa22017-06-26 16:00:38 -07007051 ref_costs_single[ALTREF_FRAME] += av1_cost_bit(ref_single_p1, 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007052
Zoe Liufcf5fa22017-06-26 16:00:38 -07007053 ref_costs_single[LAST_FRAME] += av1_cost_bit(ref_single_p3, 0);
7054 ref_costs_single[LAST2_FRAME] += av1_cost_bit(ref_single_p3, 0);
7055 ref_costs_single[LAST3_FRAME] += av1_cost_bit(ref_single_p3, 1);
7056 ref_costs_single[GOLDEN_FRAME] += av1_cost_bit(ref_single_p3, 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007057
Zoe Liufcf5fa22017-06-26 16:00:38 -07007058 ref_costs_single[BWDREF_FRAME] += av1_cost_bit(ref_single_p2, 0);
Zoe Liue9b15e22017-07-19 15:53:01 -07007059 ref_costs_single[ALTREF2_FRAME] += av1_cost_bit(ref_single_p2, 0);
Zoe Liufcf5fa22017-06-26 16:00:38 -07007060 ref_costs_single[ALTREF_FRAME] += av1_cost_bit(ref_single_p2, 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007061
Zoe Liufcf5fa22017-06-26 16:00:38 -07007062 ref_costs_single[LAST_FRAME] += av1_cost_bit(ref_single_p4, 0);
7063 ref_costs_single[LAST2_FRAME] += av1_cost_bit(ref_single_p4, 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007064
Zoe Liufcf5fa22017-06-26 16:00:38 -07007065 ref_costs_single[LAST3_FRAME] += av1_cost_bit(ref_single_p5, 0);
7066 ref_costs_single[GOLDEN_FRAME] += av1_cost_bit(ref_single_p5, 1);
Zoe Liue9b15e22017-07-19 15:53:01 -07007067
Zoe Liue9b15e22017-07-19 15:53:01 -07007068 ref_costs_single[BWDREF_FRAME] += av1_cost_bit(ref_single_p6, 0);
7069 ref_costs_single[ALTREF2_FRAME] += av1_cost_bit(ref_single_p6, 1);
Zoe Liu7b1ec7a2017-05-24 22:28:24 -07007070#else // !CONFIG_EXT_REFS
Yaowu Xuf883b422016-08-30 14:01:10 -07007071 ref_costs_single[LAST_FRAME] += av1_cost_bit(ref_single_p1, 0);
7072 ref_costs_single[GOLDEN_FRAME] += av1_cost_bit(ref_single_p1, 1);
7073 ref_costs_single[ALTREF_FRAME] += av1_cost_bit(ref_single_p1, 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007074
Yaowu Xuf883b422016-08-30 14:01:10 -07007075 ref_costs_single[GOLDEN_FRAME] += av1_cost_bit(ref_single_p2, 0);
7076 ref_costs_single[ALTREF_FRAME] += av1_cost_bit(ref_single_p2, 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007077#endif // CONFIG_EXT_REFS
7078 } else {
7079 ref_costs_single[LAST_FRAME] = 512;
7080#if CONFIG_EXT_REFS
7081 ref_costs_single[LAST2_FRAME] = 512;
7082 ref_costs_single[LAST3_FRAME] = 512;
7083 ref_costs_single[BWDREF_FRAME] = 512;
Zoe Liue9b15e22017-07-19 15:53:01 -07007084 ref_costs_single[ALTREF2_FRAME] = 512;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007085#endif // CONFIG_EXT_REFS
7086 ref_costs_single[GOLDEN_FRAME] = 512;
7087 ref_costs_single[ALTREF_FRAME] = 512;
7088 }
7089
7090 if (cm->reference_mode != SINGLE_REFERENCE) {
Yaowu Xuf883b422016-08-30 14:01:10 -07007091 aom_prob ref_comp_p = av1_get_pred_prob_comp_ref_p(cm, xd);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007092#if CONFIG_EXT_REFS
Yaowu Xuf883b422016-08-30 14:01:10 -07007093 aom_prob ref_comp_p1 = av1_get_pred_prob_comp_ref_p1(cm, xd);
7094 aom_prob ref_comp_p2 = av1_get_pred_prob_comp_ref_p2(cm, xd);
7095 aom_prob bwdref_comp_p = av1_get_pred_prob_comp_bwdref_p(cm, xd);
Zoe Liue9b15e22017-07-19 15:53:01 -07007096 aom_prob bwdref_comp_p1 = av1_get_pred_prob_comp_bwdref_p1(cm, xd);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007097#endif // CONFIG_EXT_REFS
7098
Yaowu Xuf883b422016-08-30 14:01:10 -07007099 unsigned int base_cost = av1_cost_bit(intra_inter_p, 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007100
Zoe Liuc082bbc2017-05-17 13:31:37 -07007101#if CONFIG_EXT_COMP_REFS
7102 aom_prob comp_ref_type_p = av1_get_comp_reference_type_prob(cm, xd);
7103 unsigned int ref_bicomp_costs[TOTAL_REFS_PER_FRAME] = { 0 };
7104
7105 ref_bicomp_costs[LAST_FRAME] = ref_bicomp_costs[LAST2_FRAME] =
7106 ref_bicomp_costs[LAST3_FRAME] = ref_bicomp_costs[GOLDEN_FRAME] =
7107#if USE_UNI_COMP_REFS
7108 base_cost + av1_cost_bit(comp_ref_type_p, 1);
7109#else
7110 base_cost;
7111#endif // USE_UNI_COMP_REFS
Zoe Liu3ac20932017-08-30 16:35:55 -07007112 ref_bicomp_costs[BWDREF_FRAME] = ref_bicomp_costs[ALTREF2_FRAME] = 0;
Zoe Liuac889702017-08-23 14:22:58 -07007113 ref_bicomp_costs[ALTREF_FRAME] = 0;
Zoe Liuc082bbc2017-05-17 13:31:37 -07007114
7115 ref_bicomp_costs[LAST_FRAME] += av1_cost_bit(ref_comp_p, 0);
7116 ref_bicomp_costs[LAST2_FRAME] += av1_cost_bit(ref_comp_p, 0);
7117 ref_bicomp_costs[LAST3_FRAME] += av1_cost_bit(ref_comp_p, 1);
7118 ref_bicomp_costs[GOLDEN_FRAME] += av1_cost_bit(ref_comp_p, 1);
7119
7120 ref_bicomp_costs[LAST_FRAME] += av1_cost_bit(ref_comp_p1, 1);
7121 ref_bicomp_costs[LAST2_FRAME] += av1_cost_bit(ref_comp_p1, 0);
7122
7123 ref_bicomp_costs[LAST3_FRAME] += av1_cost_bit(ref_comp_p2, 0);
7124 ref_bicomp_costs[GOLDEN_FRAME] += av1_cost_bit(ref_comp_p2, 1);
7125
7126 ref_bicomp_costs[BWDREF_FRAME] += av1_cost_bit(bwdref_comp_p, 0);
Zoe Liuac889702017-08-23 14:22:58 -07007127 ref_bicomp_costs[ALTREF2_FRAME] += av1_cost_bit(bwdref_comp_p, 0);
Zoe Liuc082bbc2017-05-17 13:31:37 -07007128 ref_bicomp_costs[ALTREF_FRAME] += av1_cost_bit(bwdref_comp_p, 1);
7129
Zoe Liuac889702017-08-23 14:22:58 -07007130 ref_bicomp_costs[BWDREF_FRAME] += av1_cost_bit(bwdref_comp_p1, 0);
7131 ref_bicomp_costs[ALTREF2_FRAME] += av1_cost_bit(bwdref_comp_p1, 1);
Zoe Liuac889702017-08-23 14:22:58 -07007132
7133 int ref0, ref1;
Zoe Liuc082bbc2017-05-17 13:31:37 -07007134 for (ref0 = LAST_FRAME; ref0 <= GOLDEN_FRAME; ++ref0) {
Zoe Liuac889702017-08-23 14:22:58 -07007135 for (ref1 = BWDREF_FRAME; ref1 <= ALTREF_FRAME; ++ref1) {
7136 ref_costs_comp[ref0][ref1] =
7137 ref_bicomp_costs[ref0] + ref_bicomp_costs[ref1];
7138 }
Zoe Liuc082bbc2017-05-17 13:31:37 -07007139 }
7140
7141 aom_prob uni_comp_ref_p = av1_get_pred_prob_uni_comp_ref_p(cm, xd);
7142 aom_prob uni_comp_ref_p1 = av1_get_pred_prob_uni_comp_ref_p1(cm, xd);
Zoe Liufcf5fa22017-06-26 16:00:38 -07007143 aom_prob uni_comp_ref_p2 = av1_get_pred_prob_uni_comp_ref_p2(cm, xd);
Zoe Liuc082bbc2017-05-17 13:31:37 -07007144
7145 ref_costs_comp[LAST_FRAME][LAST2_FRAME] =
7146 base_cost + av1_cost_bit(comp_ref_type_p, 0) +
7147 av1_cost_bit(uni_comp_ref_p, 0) + av1_cost_bit(uni_comp_ref_p1, 0);
Zoe Liufcf5fa22017-06-26 16:00:38 -07007148 ref_costs_comp[LAST_FRAME][LAST3_FRAME] =
7149 base_cost + av1_cost_bit(comp_ref_type_p, 0) +
7150 av1_cost_bit(uni_comp_ref_p, 0) + av1_cost_bit(uni_comp_ref_p1, 1) +
7151 av1_cost_bit(uni_comp_ref_p2, 0);
Zoe Liuc082bbc2017-05-17 13:31:37 -07007152 ref_costs_comp[LAST_FRAME][GOLDEN_FRAME] =
7153 base_cost + av1_cost_bit(comp_ref_type_p, 0) +
Zoe Liufcf5fa22017-06-26 16:00:38 -07007154 av1_cost_bit(uni_comp_ref_p, 0) + av1_cost_bit(uni_comp_ref_p1, 1) +
7155 av1_cost_bit(uni_comp_ref_p2, 1);
Zoe Liuc082bbc2017-05-17 13:31:37 -07007156
7157 ref_costs_comp[BWDREF_FRAME][ALTREF_FRAME] =
7158 base_cost + av1_cost_bit(comp_ref_type_p, 0) +
7159 av1_cost_bit(uni_comp_ref_p, 1);
7160
7161#else // !CONFIG_EXT_COMP_REFS
7162
Yaowu Xuc27fc142016-08-22 16:08:15 -07007163 ref_costs_comp[LAST_FRAME] =
7164#if CONFIG_EXT_REFS
7165 ref_costs_comp[LAST2_FRAME] = ref_costs_comp[LAST3_FRAME] =
7166#endif // CONFIG_EXT_REFS
7167 ref_costs_comp[GOLDEN_FRAME] = base_cost;
7168
7169#if CONFIG_EXT_REFS
Zoe Liu3ac20932017-08-30 16:35:55 -07007170 ref_costs_comp[BWDREF_FRAME] = ref_costs_comp[ALTREF2_FRAME] =
7171 ref_costs_comp[ALTREF_FRAME] = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007172#endif // CONFIG_EXT_REFS
7173
7174#if CONFIG_EXT_REFS
Zoe Liufcf5fa22017-06-26 16:00:38 -07007175 ref_costs_comp[LAST_FRAME] += av1_cost_bit(ref_comp_p, 0);
7176 ref_costs_comp[LAST2_FRAME] += av1_cost_bit(ref_comp_p, 0);
7177 ref_costs_comp[LAST3_FRAME] += av1_cost_bit(ref_comp_p, 1);
7178 ref_costs_comp[GOLDEN_FRAME] += av1_cost_bit(ref_comp_p, 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007179
Zoe Liufcf5fa22017-06-26 16:00:38 -07007180 ref_costs_comp[LAST_FRAME] += av1_cost_bit(ref_comp_p1, 1);
7181 ref_costs_comp[LAST2_FRAME] += av1_cost_bit(ref_comp_p1, 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007182
Zoe Liufcf5fa22017-06-26 16:00:38 -07007183 ref_costs_comp[LAST3_FRAME] += av1_cost_bit(ref_comp_p2, 0);
7184 ref_costs_comp[GOLDEN_FRAME] += av1_cost_bit(ref_comp_p2, 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007185
Zoe Liufcf5fa22017-06-26 16:00:38 -07007186 // NOTE(zoeliu): BWDREF and ALTREF each add an extra cost by coding 1
7187 // more bit.
7188 ref_costs_comp[BWDREF_FRAME] += av1_cost_bit(bwdref_comp_p, 0);
Zoe Liue9b15e22017-07-19 15:53:01 -07007189 ref_costs_comp[ALTREF2_FRAME] += av1_cost_bit(bwdref_comp_p, 0);
Zoe Liufcf5fa22017-06-26 16:00:38 -07007190 ref_costs_comp[ALTREF_FRAME] += av1_cost_bit(bwdref_comp_p, 1);
Zoe Liue9b15e22017-07-19 15:53:01 -07007191
Zoe Liue9b15e22017-07-19 15:53:01 -07007192 ref_costs_comp[BWDREF_FRAME] += av1_cost_bit(bwdref_comp_p1, 0);
7193 ref_costs_comp[ALTREF2_FRAME] += av1_cost_bit(bwdref_comp_p1, 1);
Zoe Liu7b1ec7a2017-05-24 22:28:24 -07007194#else // !CONFIG_EXT_REFS
Yaowu Xuf883b422016-08-30 14:01:10 -07007195 ref_costs_comp[LAST_FRAME] += av1_cost_bit(ref_comp_p, 0);
7196 ref_costs_comp[GOLDEN_FRAME] += av1_cost_bit(ref_comp_p, 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007197#endif // CONFIG_EXT_REFS
Zoe Liuc082bbc2017-05-17 13:31:37 -07007198#endif // CONFIG_EXT_COMP_REFS
Yaowu Xuc27fc142016-08-22 16:08:15 -07007199 } else {
Zoe Liuc082bbc2017-05-17 13:31:37 -07007200#if CONFIG_EXT_COMP_REFS
Zoe Liuac889702017-08-23 14:22:58 -07007201 int ref0, ref1;
Zoe Liuc082bbc2017-05-17 13:31:37 -07007202 for (ref0 = LAST_FRAME; ref0 <= GOLDEN_FRAME; ++ref0) {
Zoe Liuac889702017-08-23 14:22:58 -07007203 for (ref1 = BWDREF_FRAME; ref1 <= ALTREF_FRAME; ++ref1)
7204 ref_costs_comp[ref0][ref1] = 512;
Zoe Liuc082bbc2017-05-17 13:31:37 -07007205 }
7206 ref_costs_comp[LAST_FRAME][LAST2_FRAME] = 512;
Zoe Liufcf5fa22017-06-26 16:00:38 -07007207 ref_costs_comp[LAST_FRAME][LAST3_FRAME] = 512;
Zoe Liuc082bbc2017-05-17 13:31:37 -07007208 ref_costs_comp[LAST_FRAME][GOLDEN_FRAME] = 512;
7209 ref_costs_comp[BWDREF_FRAME][ALTREF_FRAME] = 512;
7210#else // !CONFIG_EXT_COMP_REFS
Yaowu Xuc27fc142016-08-22 16:08:15 -07007211 ref_costs_comp[LAST_FRAME] = 512;
7212#if CONFIG_EXT_REFS
7213 ref_costs_comp[LAST2_FRAME] = 512;
7214 ref_costs_comp[LAST3_FRAME] = 512;
7215 ref_costs_comp[BWDREF_FRAME] = 512;
Zoe Liue9b15e22017-07-19 15:53:01 -07007216 ref_costs_comp[ALTREF2_FRAME] = 512;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007217 ref_costs_comp[ALTREF_FRAME] = 512;
7218#endif // CONFIG_EXT_REFS
7219 ref_costs_comp[GOLDEN_FRAME] = 512;
Zoe Liuc082bbc2017-05-17 13:31:37 -07007220#endif // CONFIG_EXT_COMP_REFS
Yaowu Xuc27fc142016-08-22 16:08:15 -07007221 }
7222 }
7223}
7224
7225static void store_coding_context(MACROBLOCK *x, PICK_MODE_CONTEXT *ctx,
7226 int mode_index,
7227 int64_t comp_pred_diff[REFERENCE_MODES],
7228 int skippable) {
7229 MACROBLOCKD *const xd = &x->e_mbd;
7230
7231 // Take a snapshot of the coding context so it can be
7232 // restored if we decide to encode this way
7233 ctx->skip = x->skip;
7234 ctx->skippable = skippable;
7235 ctx->best_mode_index = mode_index;
7236 ctx->mic = *xd->mi[0];
7237 ctx->mbmi_ext = *x->mbmi_ext;
7238 ctx->single_pred_diff = (int)comp_pred_diff[SINGLE_REFERENCE];
7239 ctx->comp_pred_diff = (int)comp_pred_diff[COMPOUND_REFERENCE];
7240 ctx->hybrid_pred_diff = (int)comp_pred_diff[REFERENCE_MODE_SELECT];
7241}
7242
clang-format55ce9e02017-02-15 22:27:12 -08007243static void setup_buffer_inter(
7244 const AV1_COMP *const cpi, MACROBLOCK *x, MV_REFERENCE_FRAME ref_frame,
7245 BLOCK_SIZE block_size, int mi_row, int mi_col,
7246 int_mv frame_nearest_mv[TOTAL_REFS_PER_FRAME],
7247 int_mv frame_near_mv[TOTAL_REFS_PER_FRAME],
7248 struct buf_2d yv12_mb[TOTAL_REFS_PER_FRAME][MAX_MB_PLANE]) {
Yaowu Xuf883b422016-08-30 14:01:10 -07007249 const AV1_COMMON *cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007250 const YV12_BUFFER_CONFIG *yv12 = get_ref_frame_buffer(cpi, ref_frame);
7251 MACROBLOCKD *const xd = &x->e_mbd;
7252 MODE_INFO *const mi = xd->mi[0];
7253 int_mv *const candidates = x->mbmi_ext->ref_mvs[ref_frame];
7254 const struct scale_factors *const sf = &cm->frame_refs[ref_frame - 1].sf;
7255 MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
7256
7257 assert(yv12 != NULL);
7258
7259 // TODO(jkoleszar): Is the UV buffer ever used here? If so, need to make this
7260 // use the UV scaling factors.
Yaowu Xuf883b422016-08-30 14:01:10 -07007261 av1_setup_pred_block(xd, yv12_mb[ref_frame], yv12, mi_row, mi_col, sf, sf);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007262
7263 // Gets an initial list of candidate vectors from neighbours and orders them
Sebastien Alaiwane140c502017-04-27 09:52:34 +02007264 av1_find_mv_refs(cm, xd, mi, ref_frame, &mbmi_ext->ref_mv_count[ref_frame],
7265 mbmi_ext->ref_mv_stack[ref_frame],
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02007266 mbmi_ext->compound_mode_context, candidates, mi_row, mi_col,
7267 NULL, NULL, mbmi_ext->mode_context);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007268
RogerZhou3b635242017-09-19 10:06:46 -07007269// Candidate refinement carried out at encoder and decoder
7270#if CONFIG_AMVR
7271 av1_find_best_ref_mvs(cm->allow_high_precision_mv, candidates,
7272 &frame_nearest_mv[ref_frame], &frame_near_mv[ref_frame],
7273 cm->cur_frame_mv_precision_level);
7274#else
Yaowu Xuf883b422016-08-30 14:01:10 -07007275 av1_find_best_ref_mvs(cm->allow_high_precision_mv, candidates,
7276 &frame_nearest_mv[ref_frame],
7277 &frame_near_mv[ref_frame]);
RogerZhou3b635242017-09-19 10:06:46 -07007278#endif
Jingning Han271bb2c2016-12-14 12:34:46 -08007279// Further refinement that is encode side only to test the top few candidates
7280// in full and choose the best as the centre point for subsequent searches.
7281// The current implementation doesn't support scaling.
7282#if CONFIG_CB4X4
7283 av1_mv_pred(cpi, x, yv12_mb[ref_frame][0].buf, yv12->y_stride, ref_frame,
7284 block_size);
7285#else
Yaowu Xuf883b422016-08-30 14:01:10 -07007286 if (!av1_is_scaled(sf) && block_size >= BLOCK_8X8)
7287 av1_mv_pred(cpi, x, yv12_mb[ref_frame][0].buf, yv12->y_stride, ref_frame,
7288 block_size);
Fergus Simpson4063a682017-02-28 16:52:22 -08007289#endif // CONFIG_CB4X4
Yaowu Xuc27fc142016-08-22 16:08:15 -07007290}
7291
Urvang Joshi52648442016-10-13 17:27:51 -07007292static void single_motion_search(const AV1_COMP *const cpi, MACROBLOCK *x,
7293 BLOCK_SIZE bsize, int mi_row, int mi_col,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02007294 int ref_idx, int *rate_mv) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07007295 MACROBLOCKD *xd = &x->e_mbd;
Yaowu Xuf883b422016-08-30 14:01:10 -07007296 const AV1_COMMON *cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007297 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
7298 struct buf_2d backup_yv12[MAX_MB_PLANE] = { { 0, 0, 0, 0, 0 } };
7299 int bestsme = INT_MAX;
7300 int step_param;
7301 int sadpb = x->sadperbit16;
7302 MV mvp_full;
Zoe Liu85b66462017-04-20 14:28:19 -07007303#if CONFIG_COMPOUND_SINGLEREF
7304 int ref =
7305 has_second_ref(mbmi) ? mbmi->ref_frame[ref_idx] : mbmi->ref_frame[0];
7306#else // !CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -07007307 int ref = mbmi->ref_frame[ref_idx];
Zoe Liu85b66462017-04-20 14:28:19 -07007308#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu7f24e1b2017-03-17 17:42:05 -07007309 MV ref_mv = x->mbmi_ext->ref_mvs[ref][0].as_mv;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007310
Alex Converse0fa0f422017-04-24 12:51:14 -07007311 MvLimits tmp_mv_limits = x->mv_limits;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007312 int cost_list[5];
7313
7314 const YV12_BUFFER_CONFIG *scaled_ref_frame =
Yaowu Xuf883b422016-08-30 14:01:10 -07007315 av1_get_scaled_ref_frame(cpi, ref);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007316
7317 MV pred_mv[3];
7318 pred_mv[0] = x->mbmi_ext->ref_mvs[ref][0].as_mv;
7319 pred_mv[1] = x->mbmi_ext->ref_mvs[ref][1].as_mv;
7320 pred_mv[2] = x->pred_mv[ref];
7321
Yaowu Xuc27fc142016-08-22 16:08:15 -07007322 if (scaled_ref_frame) {
7323 int i;
7324 // Swap out the reference frame for a version that's been scaled to
7325 // match the resolution of the current frame, allowing the existing
7326 // motion search code to be used without additional modifications.
7327 for (i = 0; i < MAX_MB_PLANE; i++)
7328 backup_yv12[i] = xd->plane[i].pre[ref_idx];
7329
Yaowu Xuf883b422016-08-30 14:01:10 -07007330 av1_setup_pre_planes(xd, ref_idx, scaled_ref_frame, mi_row, mi_col, NULL);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007331 }
7332
Alex Converse0fa0f422017-04-24 12:51:14 -07007333 av1_set_mv_search_range(&x->mv_limits, &ref_mv);
Yaowu Xu4306b6e2016-09-27 12:55:32 -07007334
Yaowu Xu4306b6e2016-09-27 12:55:32 -07007335 av1_set_mvcost(x, ref, ref_idx, mbmi->ref_mv_idx);
Yaowu Xu4306b6e2016-09-27 12:55:32 -07007336
Yaowu Xuc27fc142016-08-22 16:08:15 -07007337 // Work out the size of the first step in the mv step search.
Yaowu Xuf883b422016-08-30 14:01:10 -07007338 // 0 here is maximum length first step. 1 is AOMMAX >> 1 etc.
Yaowu Xuc27fc142016-08-22 16:08:15 -07007339 if (cpi->sf.mv.auto_mv_step_size && cm->show_frame) {
James Zern89a015b2017-08-08 12:39:00 -04007340 // Take the weighted average of the step_params based on the last frame's
Yaowu Xuc27fc142016-08-22 16:08:15 -07007341 // max mv magnitude and that based on the best ref mvs of the current
7342 // block for the given reference.
7343 step_param =
Yaowu Xuf883b422016-08-30 14:01:10 -07007344 (av1_init_search_range(x->max_mv_context[ref]) + cpi->mv_step_param) /
Yaowu Xuc27fc142016-08-22 16:08:15 -07007345 2;
7346 } else {
7347 step_param = cpi->mv_step_param;
7348 }
7349
7350 if (cpi->sf.adaptive_motion_search && bsize < cm->sb_size) {
7351 int boffset =
7352 2 * (b_width_log2_lookup[cm->sb_size] -
Yaowu Xuf883b422016-08-30 14:01:10 -07007353 AOMMIN(b_height_log2_lookup[bsize], b_width_log2_lookup[bsize]));
7354 step_param = AOMMAX(step_param, boffset);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007355 }
7356
7357 if (cpi->sf.adaptive_motion_search) {
7358 int bwl = b_width_log2_lookup[bsize];
7359 int bhl = b_height_log2_lookup[bsize];
7360 int tlevel = x->pred_mv_sad[ref] >> (bwl + bhl + 4);
7361
Debargha Mukherjee27be8742017-10-07 23:51:10 -07007362 if (tlevel < 5) {
7363 step_param += 2;
7364 step_param = AOMMIN(step_param, MAX_MVSEARCH_STEPS - 1);
7365 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07007366
7367 // prev_mv_sad is not setup for dynamically scaled frames.
Debargha Mukherjee7166f222017-09-05 21:32:42 -07007368 if (cpi->oxcf.resize_mode != RESIZE_RANDOM) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07007369 int i;
7370 for (i = LAST_FRAME; i <= ALTREF_FRAME && cm->show_frame; ++i) {
7371 if ((x->pred_mv_sad[ref] >> 3) > x->pred_mv_sad[i]) {
7372 x->pred_mv[ref].row = 0;
7373 x->pred_mv[ref].col = 0;
7374 x->best_mv.as_int = INVALID_MV;
7375
7376 if (scaled_ref_frame) {
Urvang Joshi454280d2016-10-14 16:51:44 -07007377 int j;
7378 for (j = 0; j < MAX_MB_PLANE; ++j)
7379 xd->plane[j].pre[ref_idx] = backup_yv12[j];
Yaowu Xuc27fc142016-08-22 16:08:15 -07007380 }
7381 return;
7382 }
7383 }
7384 }
7385 }
7386
Alex Converse0fa0f422017-04-24 12:51:14 -07007387 av1_set_mv_search_range(&x->mv_limits, &ref_mv);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007388
Yue Chene9638cc2016-10-10 12:37:54 -07007389#if CONFIG_MOTION_VAR
7390 if (mbmi->motion_mode != SIMPLE_TRANSLATION)
7391 mvp_full = mbmi->mv[0].as_mv;
7392 else
7393#endif // CONFIG_MOTION_VAR
7394 mvp_full = pred_mv[x->mv_best_ref_index[ref]];
Yaowu Xuc27fc142016-08-22 16:08:15 -07007395
7396 mvp_full.col >>= 3;
7397 mvp_full.row >>= 3;
7398
7399 x->best_mv.as_int = x->second_best_mv.as_int = INVALID_MV;
7400
Yue Chene9638cc2016-10-10 12:37:54 -07007401#if CONFIG_MOTION_VAR
7402 switch (mbmi->motion_mode) {
7403 case SIMPLE_TRANSLATION:
7404#endif // CONFIG_MOTION_VAR
RogerZhoucc5d35d2017-08-07 22:20:15 -07007405#if CONFIG_HASH_ME
Yue Chene9638cc2016-10-10 12:37:54 -07007406 bestsme = av1_full_pixel_search(cpi, x, bsize, &mvp_full, step_param,
7407 sadpb, cond_cost_list(cpi, cost_list),
RogerZhoucc5d35d2017-08-07 22:20:15 -07007408 &ref_mv, INT_MAX, 1, (MI_SIZE * mi_col),
RogerZhoud15e7c12017-09-26 08:49:28 -07007409 (MI_SIZE * mi_row), 0);
RogerZhoucc5d35d2017-08-07 22:20:15 -07007410#else
7411 bestsme = av1_full_pixel_search(cpi, x, bsize, &mvp_full, step_param, sadpb,
7412 cond_cost_list(cpi, cost_list), &ref_mv,
7413 INT_MAX, 1);
7414#endif
Yue Chene9638cc2016-10-10 12:37:54 -07007415#if CONFIG_MOTION_VAR
7416 break;
7417 case OBMC_CAUSAL:
7418 bestsme = av1_obmc_full_pixel_diamond(
7419 cpi, x, &mvp_full, step_param, sadpb,
7420 MAX_MVSEARCH_STEPS - 1 - step_param, 1, &cpi->fn_ptr[bsize], &ref_mv,
7421 &(x->best_mv.as_mv), 0);
7422 break;
James Zern88896732017-06-23 15:55:09 -07007423 default: assert(0 && "Invalid motion mode!\n");
Yue Chene9638cc2016-10-10 12:37:54 -07007424 }
7425#endif // CONFIG_MOTION_VAR
Yaowu Xuc27fc142016-08-22 16:08:15 -07007426
Alex Converse0fa0f422017-04-24 12:51:14 -07007427 x->mv_limits = tmp_mv_limits;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007428
RogerZhou3b635242017-09-19 10:06:46 -07007429#if CONFIG_AMVR
7430 if (cpi->common.cur_frame_mv_precision_level) {
7431 x->best_mv.as_mv.row *= 8;
7432 x->best_mv.as_mv.col *= 8;
7433 }
7434 if (bestsme < INT_MAX && cpi->common.cur_frame_mv_precision_level == 0) {
7435#else
Yaowu Xuc27fc142016-08-22 16:08:15 -07007436 if (bestsme < INT_MAX) {
RogerZhou3b635242017-09-19 10:06:46 -07007437#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07007438 int dis; /* TODO: use dis in distortion calculation later. */
Yue Chene9638cc2016-10-10 12:37:54 -07007439#if CONFIG_MOTION_VAR
7440 switch (mbmi->motion_mode) {
7441 case SIMPLE_TRANSLATION:
7442#endif // CONFIG_MOTION_VAR
7443 if (cpi->sf.use_upsampled_references) {
7444 int best_mv_var;
7445 const int try_second = x->second_best_mv.as_int != INVALID_MV &&
7446 x->second_best_mv.as_int != x->best_mv.as_int;
Jingning Hanae5cfde2016-11-30 12:01:44 -08007447 const int pw = block_size_wide[bsize];
7448 const int ph = block_size_high[bsize];
Yaowu Xuc27fc142016-08-22 16:08:15 -07007449
Yue Chene9638cc2016-10-10 12:37:54 -07007450 best_mv_var = cpi->find_fractional_mv_step(
Yaowu Xuc27fc142016-08-22 16:08:15 -07007451 x, &ref_mv, cm->allow_high_precision_mv, x->errorperbit,
7452 &cpi->fn_ptr[bsize], cpi->sf.mv.subpel_force_stop,
7453 cpi->sf.mv.subpel_iters_per_step, cond_cost_list(cpi, cost_list),
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02007454 x->nmvjointcost, x->mvcost, &dis, &x->pred_sse[ref], NULL, NULL,
7455 0, 0, pw, ph, 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007456
Yue Chene9638cc2016-10-10 12:37:54 -07007457 if (try_second) {
Alex Converse0fa0f422017-04-24 12:51:14 -07007458 const int minc =
7459 AOMMAX(x->mv_limits.col_min * 8, ref_mv.col - MV_MAX);
7460 const int maxc =
7461 AOMMIN(x->mv_limits.col_max * 8, ref_mv.col + MV_MAX);
7462 const int minr =
7463 AOMMAX(x->mv_limits.row_min * 8, ref_mv.row - MV_MAX);
7464 const int maxr =
7465 AOMMIN(x->mv_limits.row_max * 8, ref_mv.row + MV_MAX);
Yue Chene9638cc2016-10-10 12:37:54 -07007466 int this_var;
7467 MV best_mv = x->best_mv.as_mv;
7468
7469 x->best_mv = x->second_best_mv;
7470 if (x->best_mv.as_mv.row * 8 <= maxr &&
7471 x->best_mv.as_mv.row * 8 >= minr &&
7472 x->best_mv.as_mv.col * 8 <= maxc &&
7473 x->best_mv.as_mv.col * 8 >= minc) {
7474 this_var = cpi->find_fractional_mv_step(
7475 x, &ref_mv, cm->allow_high_precision_mv, x->errorperbit,
7476 &cpi->fn_ptr[bsize], cpi->sf.mv.subpel_force_stop,
7477 cpi->sf.mv.subpel_iters_per_step,
7478 cond_cost_list(cpi, cost_list), x->nmvjointcost, x->mvcost,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02007479 &dis, &x->pred_sse[ref], NULL, NULL, 0, 0, pw, ph, 1);
Yue Chene9638cc2016-10-10 12:37:54 -07007480 if (this_var < best_mv_var) best_mv = x->best_mv.as_mv;
7481 x->best_mv.as_mv = best_mv;
7482 }
7483 }
Yue Chene9638cc2016-10-10 12:37:54 -07007484 } else {
7485 cpi->find_fractional_mv_step(
7486 x, &ref_mv, cm->allow_high_precision_mv, x->errorperbit,
7487 &cpi->fn_ptr[bsize], cpi->sf.mv.subpel_force_stop,
7488 cpi->sf.mv.subpel_iters_per_step, cond_cost_list(cpi, cost_list),
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02007489 x->nmvjointcost, x->mvcost, &dis, &x->pred_sse[ref], NULL, NULL,
7490 0, 0, 0, 0, 0);
Yue Chene9638cc2016-10-10 12:37:54 -07007491 }
7492#if CONFIG_MOTION_VAR
7493 break;
7494 case OBMC_CAUSAL:
7495 av1_find_best_obmc_sub_pixel_tree_up(
Timothy B. Terriberry5d24b6f2017-06-15 13:39:35 -07007496 x, &x->best_mv.as_mv, &ref_mv, cm->allow_high_precision_mv,
7497 x->errorperbit, &cpi->fn_ptr[bsize], cpi->sf.mv.subpel_force_stop,
7498 cpi->sf.mv.subpel_iters_per_step, x->nmvjointcost, x->mvcost, &dis,
7499 &x->pred_sse[ref], 0, cpi->sf.use_upsampled_references);
Yue Chene9638cc2016-10-10 12:37:54 -07007500 break;
James Zern88896732017-06-23 15:55:09 -07007501 default: assert(0 && "Invalid motion mode!\n");
Yaowu Xuc27fc142016-08-22 16:08:15 -07007502 }
Yue Chene9638cc2016-10-10 12:37:54 -07007503#endif // CONFIG_MOTION_VAR
Yaowu Xuc27fc142016-08-22 16:08:15 -07007504 }
Yaowu Xuf883b422016-08-30 14:01:10 -07007505 *rate_mv = av1_mv_bit_cost(&x->best_mv.as_mv, &ref_mv, x->nmvjointcost,
7506 x->mvcost, MV_COST_WEIGHT);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007507
Yue Chene9638cc2016-10-10 12:37:54 -07007508#if CONFIG_MOTION_VAR
7509 if (cpi->sf.adaptive_motion_search && mbmi->motion_mode == SIMPLE_TRANSLATION)
7510#else
7511 if (cpi->sf.adaptive_motion_search)
7512#endif // CONFIG_MOTION_VAR
7513 x->pred_mv[ref] = x->best_mv.as_mv;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007514
7515 if (scaled_ref_frame) {
7516 int i;
7517 for (i = 0; i < MAX_MB_PLANE; i++)
7518 xd->plane[i].pre[ref_idx] = backup_yv12[i];
7519 }
7520}
7521
David Barkerac37fa32016-12-02 12:30:21 +00007522static INLINE void restore_dst_buf(MACROBLOCKD *xd, BUFFER_SET dst) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07007523 int i;
7524 for (i = 0; i < MAX_MB_PLANE; i++) {
David Barkerac37fa32016-12-02 12:30:21 +00007525 xd->plane[i].dst.buf = dst.plane[i];
7526 xd->plane[i].dst.stride = dst.stride[i];
Yaowu Xuc27fc142016-08-22 16:08:15 -07007527 }
7528}
7529
David Barker8dd9b572017-05-12 16:31:38 +01007530static void build_second_inter_pred(const AV1_COMP *cpi, MACROBLOCK *x,
David Barkerf19f35f2017-05-22 16:33:22 +01007531 BLOCK_SIZE bsize, const MV *other_mv,
David Barker8dd9b572017-05-12 16:31:38 +01007532 int mi_row, int mi_col, const int block,
7533 int ref_idx, uint8_t *second_pred) {
7534 const AV1_COMMON *const cm = &cpi->common;
7535 const int pw = block_size_wide[bsize];
7536 const int ph = block_size_high[bsize];
Yaowu Xuc27fc142016-08-22 16:08:15 -07007537 MACROBLOCKD *xd = &x->e_mbd;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007538 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Zoe Liu85b66462017-04-20 14:28:19 -07007539#if CONFIG_COMPOUND_SINGLEREF
7540 const int other_ref =
7541 has_second_ref(mbmi) ? mbmi->ref_frame[!ref_idx] : mbmi->ref_frame[0];
7542#else // !CONFIG_COMPOUND_SINGLEREF
David Barker8dd9b572017-05-12 16:31:38 +01007543 const int other_ref = mbmi->ref_frame[!ref_idx];
Zoe Liu85b66462017-04-20 14:28:19 -07007544#endif // CONFIG_COMPOUND_SINGLEREF
David Barker8dd9b572017-05-12 16:31:38 +01007545 struct scale_factors sf;
7546#if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
7547 struct macroblockd_plane *const pd = &xd->plane[0];
James Zern89a015b2017-08-08 12:39:00 -04007548 // ic and ir are the 4x4 coordinates of the sub8x8 at index "block"
David Barker8dd9b572017-05-12 16:31:38 +01007549 const int ic = block & 1;
7550 const int ir = (block - ic) >> 1;
7551 const int p_col = ((mi_col * MI_SIZE) >> pd->subsampling_x) + 4 * ic;
7552 const int p_row = ((mi_row * MI_SIZE) >> pd->subsampling_y) + 4 * ir;
7553#if CONFIG_GLOBAL_MOTION
7554 WarpedMotionParams *const wm = &xd->global_motion[other_ref];
7555 int is_global = is_global_mv_block(xd->mi[0], block, wm->wmtype);
7556#endif // CONFIG_GLOBAL_MOTION
7557#else
7558 (void)block;
7559#endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -07007560
Zoe Liu85b66462017-04-20 14:28:19 -07007561// This function should only ever be called for compound modes
7562#if CONFIG_COMPOUND_SINGLEREF
7563 assert(has_second_ref(mbmi) || is_inter_singleref_comp_mode(mbmi->mode));
7564#else // !CONFIG_COMPOUND_SINGLEREF
David Barker8dd9b572017-05-12 16:31:38 +01007565 assert(has_second_ref(mbmi));
Zoe Liu85b66462017-04-20 14:28:19 -07007566#endif // CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -07007567
David Barker8dd9b572017-05-12 16:31:38 +01007568 struct buf_2d backup_yv12[MAX_MB_PLANE];
7569 const YV12_BUFFER_CONFIG *const scaled_ref_frame =
7570 av1_get_scaled_ref_frame(cpi, other_ref);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007571
7572 if (scaled_ref_frame) {
David Barker8dd9b572017-05-12 16:31:38 +01007573 int i;
7574 // Swap out the reference frame for a version that's been scaled to
7575 // match the resolution of the current frame, allowing the existing
7576 // motion search code to be used without additional modifications.
7577 for (i = 0; i < MAX_MB_PLANE; i++)
7578 backup_yv12[i] = xd->plane[i].pre[!ref_idx];
7579 av1_setup_pre_planes(xd, !ref_idx, scaled_ref_frame, mi_row, mi_col, NULL);
7580 }
7581
7582// Since we have scaled the reference frames to match the size of the current
7583// frame we must use a unit scaling factor during mode selection.
7584#if CONFIG_HIGHBITDEPTH
7585 av1_setup_scale_factors_for_frame(&sf, cm->width, cm->height, cm->width,
7586 cm->height, cm->use_highbitdepth);
7587#else
7588 av1_setup_scale_factors_for_frame(&sf, cm->width, cm->height, cm->width,
7589 cm->height);
7590#endif // CONFIG_HIGHBITDEPTH
7591
7592 struct buf_2d ref_yv12;
7593
7594 const int plane = 0;
David Barkere64d51a2017-06-09 14:52:42 +01007595 ConvolveParams conv_params = get_conv_params(!ref_idx, 0, plane);
David Barker8dd9b572017-05-12 16:31:38 +01007596#if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
7597 WarpTypesAllowed warp_types;
7598#if CONFIG_GLOBAL_MOTION
7599 warp_types.global_warp_allowed = is_global;
7600#endif // CONFIG_GLOBAL_MOTION
7601#if CONFIG_WARPED_MOTION
7602 warp_types.local_warp_allowed = mbmi->motion_mode == WARPED_CAUSAL;
7603#endif // CONFIG_WARPED_MOTION
7604#endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
7605
7606 // Initialized here because of compiler problem in Visual Studio.
7607 ref_yv12 = xd->plane[plane].pre[!ref_idx];
7608
7609// Get the prediction block from the 'other' reference frame.
7610#if CONFIG_HIGHBITDEPTH
7611 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
7612 av1_highbd_build_inter_predictor(
David Barkerf19f35f2017-05-22 16:33:22 +01007613 ref_yv12.buf, ref_yv12.stride, second_pred, pw, other_mv, &sf, pw, ph,
Rupert Swarbrick27e90292017-09-28 17:46:50 +01007614 0, mbmi->interp_filters,
David Barker8dd9b572017-05-12 16:31:38 +01007615#if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
7616 &warp_types, p_col, p_row,
7617#endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
7618 plane, MV_PRECISION_Q3, mi_col * MI_SIZE, mi_row * MI_SIZE, xd);
7619 } else {
7620#endif // CONFIG_HIGHBITDEPTH
7621 av1_build_inter_predictor(
David Barkerf19f35f2017-05-22 16:33:22 +01007622 ref_yv12.buf, ref_yv12.stride, second_pred, pw, other_mv, &sf, pw, ph,
Rupert Swarbrick27e90292017-09-28 17:46:50 +01007623 &conv_params, mbmi->interp_filters,
David Barker8dd9b572017-05-12 16:31:38 +01007624#if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
7625 &warp_types, p_col, p_row, plane, !ref_idx,
7626#endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
7627 MV_PRECISION_Q3, mi_col * MI_SIZE, mi_row * MI_SIZE, xd);
7628#if CONFIG_HIGHBITDEPTH
7629 }
7630#endif // CONFIG_HIGHBITDEPTH
7631
7632 if (scaled_ref_frame) {
7633 // Restore the prediction frame pointers to their unscaled versions.
7634 int i;
7635 for (i = 0; i < MAX_MB_PLANE; i++)
7636 xd->plane[i].pre[!ref_idx] = backup_yv12[i];
7637 }
7638}
7639
7640// Search for the best mv for one component of a compound,
7641// given that the other component is fixed.
Timothy B. Terriberry5d24b6f2017-06-15 13:39:35 -07007642static void compound_single_motion_search(const AV1_COMP *cpi, MACROBLOCK *x,
7643 BLOCK_SIZE bsize, MV *this_mv,
7644 int mi_row, int mi_col,
7645 const uint8_t *second_pred,
7646 const uint8_t *mask, int mask_stride,
7647 int *rate_mv, int ref_idx) {
David Barker8dd9b572017-05-12 16:31:38 +01007648 const int pw = block_size_wide[bsize];
7649 const int ph = block_size_high[bsize];
7650 MACROBLOCKD *xd = &x->e_mbd;
7651 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Zoe Liu85b66462017-04-20 14:28:19 -07007652#if CONFIG_COMPOUND_SINGLEREF
7653 const int ref =
7654 has_second_ref(mbmi) ? mbmi->ref_frame[ref_idx] : mbmi->ref_frame[0];
7655#else
David Barker8dd9b572017-05-12 16:31:38 +01007656 const int ref = mbmi->ref_frame[ref_idx];
Zoe Liu85b66462017-04-20 14:28:19 -07007657#endif // CONFIG_COMPOUND_SINGLEREF
David Barkerf19f35f2017-05-22 16:33:22 +01007658 int_mv ref_mv = x->mbmi_ext->ref_mvs[ref][0];
David Barker8dd9b572017-05-12 16:31:38 +01007659 struct macroblockd_plane *const pd = &xd->plane[0];
7660
7661 struct buf_2d backup_yv12[MAX_MB_PLANE];
David Barker8dd9b572017-05-12 16:31:38 +01007662 const YV12_BUFFER_CONFIG *const scaled_ref_frame =
7663 av1_get_scaled_ref_frame(cpi, ref);
7664
Ryan Lei1d1df182017-06-15 11:38:59 -07007665// Check that this is either an interinter or an interintra block
Zoe Liu85b66462017-04-20 14:28:19 -07007666#if CONFIG_COMPOUND_SINGLEREF
Ryan Lei1d1df182017-06-15 11:38:59 -07007667 assert(has_second_ref(mbmi) ||
Zoe Liu85b66462017-04-20 14:28:19 -07007668 // or a single ref comp pred mode
7669 is_inter_singleref_comp_mode(mbmi->mode) ||
David Barker8dd9b572017-05-12 16:31:38 +01007670 (ref_idx == 0 && mbmi->ref_frame[1] == INTRA_FRAME));
Ryan Lei1d1df182017-06-15 11:38:59 -07007671#else
7672 assert(has_second_ref(mbmi) ||
7673 (ref_idx == 0 && mbmi->ref_frame[1] == INTRA_FRAME));
7674#endif // CONFIG_COMPOUND_SINGLEREF
David Barker8dd9b572017-05-12 16:31:38 +01007675
David Barker8dd9b572017-05-12 16:31:38 +01007676 if (scaled_ref_frame) {
7677 int i;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007678 // Swap out the reference frame for a version that's been scaled to
7679 // match the resolution of the current frame, allowing the existing
7680 // motion search code to be used without additional modifications.
7681 for (i = 0; i < MAX_MB_PLANE; i++)
7682 backup_yv12[i] = xd->plane[i].pre[ref_idx];
Yaowu Xuf883b422016-08-30 14:01:10 -07007683 av1_setup_pre_planes(xd, ref_idx, scaled_ref_frame, mi_row, mi_col, NULL);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007684 }
7685
David Barker8dd9b572017-05-12 16:31:38 +01007686 struct buf_2d orig_yv12;
7687 int bestsme = INT_MAX;
7688 int sadpb = x->sadperbit16;
7689 MV *const best_mv = &x->best_mv.as_mv;
7690 int search_range = 3;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007691
David Barker8dd9b572017-05-12 16:31:38 +01007692 MvLimits tmp_mv_limits = x->mv_limits;
David Barker8dd9b572017-05-12 16:31:38 +01007693
7694 // Initialized here because of compiler problem in Visual Studio.
7695 if (ref_idx) {
David Barkerf19f35f2017-05-22 16:33:22 +01007696 orig_yv12 = pd->pre[0];
7697 pd->pre[0] = pd->pre[ref_idx];
Yaowu Xuc27fc142016-08-22 16:08:15 -07007698 }
7699
David Barker8dd9b572017-05-12 16:31:38 +01007700 // Do compound motion search on the current reference frame.
7701 av1_set_mv_search_range(&x->mv_limits, &ref_mv.as_mv);
7702
7703 // Use the mv result from the single mode as mv predictor.
David Barkerf19f35f2017-05-22 16:33:22 +01007704 *best_mv = *this_mv;
David Barker8dd9b572017-05-12 16:31:38 +01007705
7706 best_mv->col >>= 3;
7707 best_mv->row >>= 3;
7708
Zoe Liu85b66462017-04-20 14:28:19 -07007709#if CONFIG_COMPOUND_SINGLEREF
7710 if (!has_second_ref(mbmi))
7711 av1_set_mvcost(x, ref, 0, mbmi->ref_mv_idx);
7712 else
7713#endif // CONFIG_COMPOUND_SINGLEREF
7714 av1_set_mvcost(x, ref, ref_idx, mbmi->ref_mv_idx);
David Barker8dd9b572017-05-12 16:31:38 +01007715
7716 // Small-range full-pixel motion search.
7717 bestsme = av1_refining_search_8p_c(x, sadpb, search_range,
7718 &cpi->fn_ptr[bsize], mask, mask_stride,
7719 ref_idx, &ref_mv.as_mv, second_pred);
7720 if (bestsme < INT_MAX) {
7721 if (mask)
7722 bestsme =
7723 av1_get_mvpred_mask_var(x, best_mv, &ref_mv.as_mv, second_pred, mask,
7724 mask_stride, ref_idx, &cpi->fn_ptr[bsize], 1);
7725 else
7726 bestsme = av1_get_mvpred_av_var(x, best_mv, &ref_mv.as_mv, second_pred,
7727 &cpi->fn_ptr[bsize], 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007728 }
7729
Alex Converse0fa0f422017-04-24 12:51:14 -07007730 x->mv_limits = tmp_mv_limits;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007731
RogerZhou3b635242017-09-19 10:06:46 -07007732#if CONFIG_AMVR
7733 if (cpi->common.cur_frame_mv_precision_level) {
7734 x->best_mv.as_mv.row *= 8;
7735 x->best_mv.as_mv.col *= 8;
7736 }
7737 if (bestsme < INT_MAX && cpi->common.cur_frame_mv_precision_level == 0) {
7738#else
Yaowu Xuc27fc142016-08-22 16:08:15 -07007739 if (bestsme < INT_MAX) {
RogerZhou3b635242017-09-19 10:06:46 -07007740#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07007741 int dis; /* TODO: use dis in distortion calculation later. */
David Barker8dd9b572017-05-12 16:31:38 +01007742 unsigned int sse;
Timothy B. Terriberry5d24b6f2017-06-15 13:39:35 -07007743 bestsme = cpi->find_fractional_mv_step(
7744 x, &ref_mv.as_mv, cpi->common.allow_high_precision_mv, x->errorperbit,
7745 &cpi->fn_ptr[bsize], 0, cpi->sf.mv.subpel_iters_per_step, NULL,
7746 x->nmvjointcost, x->mvcost, &dis, &sse, second_pred, mask, mask_stride,
7747 ref_idx, pw, ph, cpi->sf.use_upsampled_references);
David Barker8dd9b572017-05-12 16:31:38 +01007748 }
7749
7750 // Restore the pointer to the first (possibly scaled) prediction buffer.
David Barkerf19f35f2017-05-22 16:33:22 +01007751 if (ref_idx) pd->pre[0] = orig_yv12;
David Barker8dd9b572017-05-12 16:31:38 +01007752
Yue Chenf03907a2017-05-31 12:04:04 -07007753 if (bestsme < INT_MAX) *this_mv = *best_mv;
David Barker8dd9b572017-05-12 16:31:38 +01007754
7755 *rate_mv = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007756
7757 if (scaled_ref_frame) {
David Barker8dd9b572017-05-12 16:31:38 +01007758 // Restore the prediction frame pointers to their unscaled versions.
7759 int i;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007760 for (i = 0; i < MAX_MB_PLANE; i++)
7761 xd->plane[i].pre[ref_idx] = backup_yv12[i];
7762 }
David Barker8dd9b572017-05-12 16:31:38 +01007763
Zoe Liu85b66462017-04-20 14:28:19 -07007764#if CONFIG_COMPOUND_SINGLEREF
7765 if (!has_second_ref(mbmi))
7766 av1_set_mvcost(x, ref, 0, mbmi->ref_mv_idx);
7767 else
7768#endif // CONFIG_COMPOUND_SINGLEREF
7769 av1_set_mvcost(x, ref, ref_idx, mbmi->ref_mv_idx);
David Barkerf19f35f2017-05-22 16:33:22 +01007770 *rate_mv += av1_mv_bit_cost(this_mv, &ref_mv.as_mv, x->nmvjointcost,
7771 x->mvcost, MV_COST_WEIGHT);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007772}
7773
David Barker8dd9b572017-05-12 16:31:38 +01007774// Wrapper for compound_single_motion_search, for the common case
7775// where the second prediction is also an inter mode.
7776static void compound_single_motion_search_interinter(
7777 const AV1_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bsize, int_mv *frame_mv,
Zoe Liu85b66462017-04-20 14:28:19 -07007778#if CONFIG_COMPOUND_SINGLEREF
7779 int_mv *frame_comp_mv,
7780#endif // CONFIG_COMPOUND_SINGLEREF
David Barkerf19f35f2017-05-22 16:33:22 +01007781 int mi_row, int mi_col, const uint8_t *mask, int mask_stride, int *rate_mv,
7782 const int block, int ref_idx) {
7783 MACROBLOCKD *xd = &x->e_mbd;
7784 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
7785
Zoe Liu85b66462017-04-20 14:28:19 -07007786// This function should only ever be called for compound modes
7787#if CONFIG_COMPOUND_SINGLEREF
7788 int is_singleref_comp_mode =
7789 !has_second_ref(mbmi) && is_inter_singleref_comp_mode(mbmi->mode);
7790 assert(has_second_ref(mbmi) || is_singleref_comp_mode);
7791 if (is_singleref_comp_mode && ref_idx) assert(frame_comp_mv);
7792#else // !CONFIG_COMPOUND_SINGLEREF
David Barkerf19f35f2017-05-22 16:33:22 +01007793 assert(has_second_ref(mbmi));
Zoe Liu85b66462017-04-20 14:28:19 -07007794#endif // CONFIG_COMPOUND_SINGLEREF
David Barker8dd9b572017-05-12 16:31:38 +01007795
7796// Prediction buffer from second frame.
7797#if CONFIG_HIGHBITDEPTH
David Barker8dd9b572017-05-12 16:31:38 +01007798 DECLARE_ALIGNED(16, uint16_t, second_pred_alloc_16[MAX_SB_SQUARE]);
7799 uint8_t *second_pred;
7800 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
7801 second_pred = CONVERT_TO_BYTEPTR(second_pred_alloc_16);
7802 else
7803 second_pred = (uint8_t *)second_pred_alloc_16;
7804#else
7805 DECLARE_ALIGNED(16, uint8_t, second_pred[MAX_SB_SQUARE]);
7806#endif // CONFIG_HIGHBITDEPTH
7807
Zoe Liu85b66462017-04-20 14:28:19 -07007808#if CONFIG_COMPOUND_SINGLEREF
7809 MV *this_mv = has_second_ref(mbmi)
7810 ? &frame_mv[mbmi->ref_frame[ref_idx]].as_mv
7811 : (ref_idx ? &frame_comp_mv[mbmi->ref_frame[0]].as_mv
7812 : &frame_mv[mbmi->ref_frame[0]].as_mv);
7813 const MV *other_mv =
7814 has_second_ref(mbmi)
7815 ? &frame_mv[mbmi->ref_frame[!ref_idx]].as_mv
7816 : (ref_idx ? &frame_mv[mbmi->ref_frame[0]].as_mv
7817 : &frame_comp_mv[mbmi->ref_frame[0]].as_mv);
7818#else // !CONFIG_COMPOUND_SINGLEREF
David Barkerf19f35f2017-05-22 16:33:22 +01007819 MV *this_mv = &frame_mv[mbmi->ref_frame[ref_idx]].as_mv;
7820 const MV *other_mv = &frame_mv[mbmi->ref_frame[!ref_idx]].as_mv;
Zoe Liu85b66462017-04-20 14:28:19 -07007821#endif // CONFIG_COMPOUND_SINGLEREF
David Barkerf19f35f2017-05-22 16:33:22 +01007822
7823 build_second_inter_pred(cpi, x, bsize, other_mv, mi_row, mi_col, block,
David Barker8dd9b572017-05-12 16:31:38 +01007824 ref_idx, second_pred);
7825
David Barkerf19f35f2017-05-22 16:33:22 +01007826 compound_single_motion_search(cpi, x, bsize, this_mv, mi_row, mi_col,
Timothy B. Terriberry5d24b6f2017-06-15 13:39:35 -07007827 second_pred, mask, mask_stride, rate_mv,
David Barkerf19f35f2017-05-22 16:33:22 +01007828 ref_idx);
David Barker8dd9b572017-05-12 16:31:38 +01007829}
7830
7831#if CONFIG_COMPOUND_SEGMENT || CONFIG_WEDGE
Sarah Parker6fdc8532016-11-16 17:47:13 -08007832static void do_masked_motion_search_indexed(
David Barkerc155e012017-05-11 13:54:54 +01007833 const AV1_COMP *const cpi, MACROBLOCK *x, const int_mv *const cur_mv,
Sarah Parkerb9f757c2017-01-06 17:12:24 -08007834 const INTERINTER_COMPOUND_DATA *const comp_data, BLOCK_SIZE bsize,
Zoe Liu7f24e1b2017-03-17 17:42:05 -07007835 int mi_row, int mi_col, int_mv *tmp_mv, int *rate_mv, int which) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07007836 // NOTE: which values: 0 - 0 only, 1 - 1 only, 2 - both
7837 MACROBLOCKD *xd = &x->e_mbd;
7838 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
7839 BLOCK_SIZE sb_type = mbmi->sb_type;
7840 const uint8_t *mask;
Jingning Hanae5cfde2016-11-30 12:01:44 -08007841 const int mask_stride = block_size_wide[bsize];
Sarah Parker569edda2016-12-14 14:57:38 -08007842
Sarah Parkerb9f757c2017-01-06 17:12:24 -08007843 mask = av1_get_compound_type_mask(comp_data, sb_type);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007844
David Barker8dd9b572017-05-12 16:31:38 +01007845 int_mv frame_mv[TOTAL_REFS_PER_FRAME];
Zoe Liu85b66462017-04-20 14:28:19 -07007846#if CONFIG_COMPOUND_SINGLEREF
7847 int_mv frame_comp_mv[TOTAL_REFS_PER_FRAME];
7848#endif // CONFIG_COMPOUND_SINGLEREF
David Barker8dd9b572017-05-12 16:31:38 +01007849 MV_REFERENCE_FRAME rf[2] = { mbmi->ref_frame[0], mbmi->ref_frame[1] };
7850 assert(bsize >= BLOCK_8X8 || CONFIG_CB4X4);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007851
David Barker8dd9b572017-05-12 16:31:38 +01007852 frame_mv[rf[0]].as_int = cur_mv[0].as_int;
Zoe Liu85b66462017-04-20 14:28:19 -07007853#if CONFIG_COMPOUND_SINGLEREF
7854 if (!has_second_ref(mbmi))
7855 frame_comp_mv[rf[0]].as_int = cur_mv[1].as_int;
7856 else
7857#endif // CONFIG_COMPOUND_SINGLEREF
7858 frame_mv[rf[1]].as_int = cur_mv[1].as_int;
David Barkerf19f35f2017-05-22 16:33:22 +01007859 if (which == 0 || which == 1) {
Zoe Liu85b66462017-04-20 14:28:19 -07007860 compound_single_motion_search_interinter(
7861 cpi, x, bsize, frame_mv,
7862#if CONFIG_COMPOUND_SINGLEREF
7863 has_second_ref(mbmi) ? NULL : frame_comp_mv,
7864#endif // CONFIG_COMPOUND_SINGLEREF
7865 mi_row, mi_col, mask, mask_stride, rate_mv, 0, which);
David Barkerf19f35f2017-05-22 16:33:22 +01007866 } else if (which == 2) {
Zoe Liu85b66462017-04-20 14:28:19 -07007867 joint_motion_search(cpi, x, bsize, frame_mv,
7868#if CONFIG_COMPOUND_SINGLEREF
7869 has_second_ref(mbmi) ? NULL : frame_comp_mv,
7870#endif // CONFIG_COMPOUND_SINGLEREF
7871 mi_row, mi_col, NULL, mask, mask_stride, rate_mv, 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007872 }
David Barker8dd9b572017-05-12 16:31:38 +01007873 tmp_mv[0].as_int = frame_mv[rf[0]].as_int;
Zoe Liu85b66462017-04-20 14:28:19 -07007874#if CONFIG_COMPOUND_SINGLEREF
7875 if (!has_second_ref(mbmi))
7876 tmp_mv[1].as_int = frame_comp_mv[rf[0]].as_int;
7877 else // comp ref
7878#endif // CONFIG_COMPOUND_SINGLEREF
7879 tmp_mv[1].as_int = frame_mv[rf[1]].as_int;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007880}
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00007881#endif // CONFIG_COMPOUND_SEGMENT || CONFIG_WEDGE
Yaowu Xuc27fc142016-08-22 16:08:15 -07007882
James Zern89a015b2017-08-08 12:39:00 -04007883// In some situations we want to discount the apparent cost of a new motion
Yaowu Xuc27fc142016-08-22 16:08:15 -07007884// vector. Where there is a subtle motion field and especially where there is
7885// low spatial complexity then it can be hard to cover the cost of a new motion
7886// vector in a single block, even if that motion vector reduces distortion.
7887// However, once established that vector may be usable through the nearest and
7888// near mv modes to reduce distortion in subsequent blocks and also improve
7889// visual quality.
Urvang Joshi52648442016-10-13 17:27:51 -07007890static int discount_newmv_test(const AV1_COMP *const cpi, int this_mode,
Yaowu Xuc27fc142016-08-22 16:08:15 -07007891 int_mv this_mv,
7892 int_mv (*mode_mv)[TOTAL_REFS_PER_FRAME],
7893 int ref_frame) {
7894 return (!cpi->rc.is_src_frame_alt_ref && (this_mode == NEWMV) &&
7895 (this_mv.as_int != 0) &&
7896 ((mode_mv[NEARESTMV][ref_frame].as_int == 0) ||
7897 (mode_mv[NEARESTMV][ref_frame].as_int == INVALID_MV)) &&
7898 ((mode_mv[NEARMV][ref_frame].as_int == 0) ||
7899 (mode_mv[NEARMV][ref_frame].as_int == INVALID_MV)));
7900}
7901
Yaowu Xu671f2bd2016-09-30 15:07:57 -07007902#define LEFT_TOP_MARGIN ((AOM_BORDER_IN_PIXELS - AOM_INTERP_EXTEND) << 3)
7903#define RIGHT_BOTTOM_MARGIN ((AOM_BORDER_IN_PIXELS - AOM_INTERP_EXTEND) << 3)
Yaowu Xuc27fc142016-08-22 16:08:15 -07007904
7905// TODO(jingning): this mv clamping function should be block size dependent.
7906static INLINE void clamp_mv2(MV *mv, const MACROBLOCKD *xd) {
7907 clamp_mv(mv, xd->mb_to_left_edge - LEFT_TOP_MARGIN,
7908 xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN,
7909 xd->mb_to_top_edge - LEFT_TOP_MARGIN,
7910 xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN);
7911}
7912
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00007913#if CONFIG_WEDGE
Yaowu Xuf883b422016-08-30 14:01:10 -07007914static int estimate_wedge_sign(const AV1_COMP *cpi, const MACROBLOCK *x,
Yaowu Xuc27fc142016-08-22 16:08:15 -07007915 const BLOCK_SIZE bsize, const uint8_t *pred0,
7916 int stride0, const uint8_t *pred1, int stride1) {
7917 const struct macroblock_plane *const p = &x->plane[0];
7918 const uint8_t *src = p->src.buf;
7919 int src_stride = p->src.stride;
7920 const int f_index = bsize - BLOCK_8X8;
Jingning Han61418bb2017-01-23 17:12:48 -08007921 const int bw = block_size_wide[bsize];
7922 const int bh = block_size_high[bsize];
Yue Chenf03907a2017-05-31 12:04:04 -07007923 uint32_t esq[2][4];
Yaowu Xuc27fc142016-08-22 16:08:15 -07007924 int64_t tl, br;
7925
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02007926#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07007927 if (x->e_mbd.cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
7928 pred0 = CONVERT_TO_BYTEPTR(pred0);
7929 pred1 = CONVERT_TO_BYTEPTR(pred1);
7930 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02007931#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07007932
Yue Chenf03907a2017-05-31 12:04:04 -07007933 cpi->fn_ptr[f_index].vf(src, src_stride, pred0, stride0, &esq[0][0]);
7934 cpi->fn_ptr[f_index].vf(src + bw / 2, src_stride, pred0 + bw / 2, stride0,
7935 &esq[0][1]);
7936 cpi->fn_ptr[f_index].vf(src + bh / 2 * src_stride, src_stride,
7937 pred0 + bh / 2 * stride0, stride0, &esq[0][2]);
7938 cpi->fn_ptr[f_index].vf(src + bh / 2 * src_stride + bw / 2, src_stride,
7939 pred0 + bh / 2 * stride0 + bw / 2, stride0,
7940 &esq[0][3]);
7941 cpi->fn_ptr[f_index].vf(src, src_stride, pred1, stride1, &esq[1][0]);
7942 cpi->fn_ptr[f_index].vf(src + bw / 2, src_stride, pred1 + bw / 2, stride1,
7943 &esq[1][1]);
7944 cpi->fn_ptr[f_index].vf(src + bh / 2 * src_stride, src_stride,
7945 pred1 + bh / 2 * stride1, stride0, &esq[1][2]);
7946 cpi->fn_ptr[f_index].vf(src + bh / 2 * src_stride + bw / 2, src_stride,
7947 pred1 + bh / 2 * stride1 + bw / 2, stride0,
7948 &esq[1][3]);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007949
7950 tl = (int64_t)(esq[0][0] + esq[0][1] + esq[0][2]) -
7951 (int64_t)(esq[1][0] + esq[1][1] + esq[1][2]);
7952 br = (int64_t)(esq[1][3] + esq[1][1] + esq[1][2]) -
7953 (int64_t)(esq[0][3] + esq[0][1] + esq[0][2]);
7954 return (tl + br > 0);
7955}
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00007956#endif // CONFIG_WEDGE
Yaowu Xuc27fc142016-08-22 16:08:15 -07007957
7958#if !CONFIG_DUAL_FILTER
James Zern7b9407a2016-05-18 23:48:05 -07007959static InterpFilter predict_interp_filter(
Yaowu Xuf883b422016-08-30 14:01:10 -07007960 const AV1_COMP *cpi, const MACROBLOCK *x, const BLOCK_SIZE bsize,
Yaowu Xuc27fc142016-08-22 16:08:15 -07007961 const int mi_row, const int mi_col,
James Zern7b9407a2016-05-18 23:48:05 -07007962 InterpFilter (*single_filter)[TOTAL_REFS_PER_FRAME]) {
7963 InterpFilter best_filter = SWITCHABLE;
Yaowu Xuf883b422016-08-30 14:01:10 -07007964 const AV1_COMMON *cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007965 const MACROBLOCKD *xd = &x->e_mbd;
7966 int bsl = mi_width_log2_lookup[bsize];
7967 int pred_filter_search =
7968 cpi->sf.cb_pred_filter_search
7969 ? (((mi_row + mi_col) >> bsl) +
7970 get_chessboard_index(cm->current_video_frame)) &
7971 0x1
7972 : 0;
7973 MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
7974 const int is_comp_pred = has_second_ref(mbmi);
7975 const int this_mode = mbmi->mode;
7976 int refs[2] = { mbmi->ref_frame[0],
7977 (mbmi->ref_frame[1] < 0 ? 0 : mbmi->ref_frame[1]) };
Yaowu Xuc27fc142016-08-22 16:08:15 -07007978 if (pred_filter_search) {
James Zern7b9407a2016-05-18 23:48:05 -07007979 InterpFilter af = SWITCHABLE, lf = SWITCHABLE;
Rupert Swarbrick27e90292017-09-28 17:46:50 +01007980 if (xd->up_available)
7981 af = av1_extract_interp_filter(
7982 xd->mi[-xd->mi_stride]->mbmi.interp_filters, 0);
7983 if (xd->left_available)
7984 lf = av1_extract_interp_filter(xd->mi[-1]->mbmi.interp_filters, 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07007985
Zoe Liu7f24e1b2017-03-17 17:42:05 -07007986 if ((this_mode != NEWMV && this_mode != NEW_NEWMV) || (af == lf))
Yaowu Xuc27fc142016-08-22 16:08:15 -07007987 best_filter = af;
7988 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07007989 if (is_comp_pred) {
7990 if (cpi->sf.adaptive_mode_search) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07007991 switch (this_mode) {
7992 case NEAREST_NEARESTMV:
7993 if (single_filter[NEARESTMV][refs[0]] ==
7994 single_filter[NEARESTMV][refs[1]])
7995 best_filter = single_filter[NEARESTMV][refs[0]];
7996 break;
Yaowu Xuc27fc142016-08-22 16:08:15 -07007997 case NEAR_NEARMV:
7998 if (single_filter[NEARMV][refs[0]] == single_filter[NEARMV][refs[1]])
7999 best_filter = single_filter[NEARMV][refs[0]];
8000 break;
8001 case ZERO_ZEROMV:
8002 if (single_filter[ZEROMV][refs[0]] == single_filter[ZEROMV][refs[1]])
8003 best_filter = single_filter[ZEROMV][refs[0]];
8004 break;
8005 case NEW_NEWMV:
8006 if (single_filter[NEWMV][refs[0]] == single_filter[NEWMV][refs[1]])
8007 best_filter = single_filter[NEWMV][refs[0]];
8008 break;
8009 case NEAREST_NEWMV:
8010 if (single_filter[NEARESTMV][refs[0]] ==
8011 single_filter[NEWMV][refs[1]])
8012 best_filter = single_filter[NEARESTMV][refs[0]];
8013 break;
8014 case NEAR_NEWMV:
8015 if (single_filter[NEARMV][refs[0]] == single_filter[NEWMV][refs[1]])
8016 best_filter = single_filter[NEARMV][refs[0]];
8017 break;
8018 case NEW_NEARESTMV:
8019 if (single_filter[NEWMV][refs[0]] ==
8020 single_filter[NEARESTMV][refs[1]])
8021 best_filter = single_filter[NEWMV][refs[0]];
8022 break;
8023 case NEW_NEARMV:
8024 if (single_filter[NEWMV][refs[0]] == single_filter[NEARMV][refs[1]])
8025 best_filter = single_filter[NEWMV][refs[0]];
8026 break;
8027 default:
8028 if (single_filter[this_mode][refs[0]] ==
8029 single_filter[this_mode][refs[1]])
8030 best_filter = single_filter[this_mode][refs[0]];
8031 break;
8032 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07008033 }
8034 }
Angie Chiang75c22092016-10-25 12:19:16 -07008035 if (x->source_variance < cpi->sf.disable_filter_search_var_thresh) {
8036 best_filter = EIGHTTAP_REGULAR;
Yaowu Xuc27fc142016-08-22 16:08:15 -07008037 }
8038 return best_filter;
8039}
Fergus Simpson4063a682017-02-28 16:52:22 -08008040#endif // !CONFIG_DUAL_FILTER
Yaowu Xuc27fc142016-08-22 16:08:15 -07008041
Yaowu Xuc27fc142016-08-22 16:08:15 -07008042// Choose the best wedge index and sign
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00008043#if CONFIG_WEDGE
Yaowu Xuf883b422016-08-30 14:01:10 -07008044static int64_t pick_wedge(const AV1_COMP *const cpi, const MACROBLOCK *const x,
Yaowu Xuc27fc142016-08-22 16:08:15 -07008045 const BLOCK_SIZE bsize, const uint8_t *const p0,
8046 const uint8_t *const p1, int *const best_wedge_sign,
8047 int *const best_wedge_index) {
8048 const MACROBLOCKD *const xd = &x->e_mbd;
8049 const struct buf_2d *const src = &x->plane[0].src;
Jingning Hanae5cfde2016-11-30 12:01:44 -08008050 const int bw = block_size_wide[bsize];
8051 const int bh = block_size_high[bsize];
Yaowu Xuc27fc142016-08-22 16:08:15 -07008052 const int N = bw * bh;
8053 int rate;
8054 int64_t dist;
8055 int64_t rd, best_rd = INT64_MAX;
8056 int wedge_index;
8057 int wedge_sign;
8058 int wedge_types = (1 << get_wedge_bits_lookup(bsize));
8059 const uint8_t *mask;
8060 uint64_t sse;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02008061#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07008062 const int hbd = xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH;
8063 const int bd_round = hbd ? (xd->bd - 8) * 2 : 0;
8064#else
8065 const int bd_round = 0;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02008066#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07008067
8068 DECLARE_ALIGNED(32, int16_t, r0[MAX_SB_SQUARE]);
8069 DECLARE_ALIGNED(32, int16_t, r1[MAX_SB_SQUARE]);
8070 DECLARE_ALIGNED(32, int16_t, d10[MAX_SB_SQUARE]);
8071 DECLARE_ALIGNED(32, int16_t, ds[MAX_SB_SQUARE]);
8072
8073 int64_t sign_limit;
8074
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02008075#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07008076 if (hbd) {
Yaowu Xuf883b422016-08-30 14:01:10 -07008077 aom_highbd_subtract_block(bh, bw, r0, bw, src->buf, src->stride,
Yaowu Xuc27fc142016-08-22 16:08:15 -07008078 CONVERT_TO_BYTEPTR(p0), bw, xd->bd);
Yaowu Xuf883b422016-08-30 14:01:10 -07008079 aom_highbd_subtract_block(bh, bw, r1, bw, src->buf, src->stride,
Yaowu Xuc27fc142016-08-22 16:08:15 -07008080 CONVERT_TO_BYTEPTR(p1), bw, xd->bd);
Yaowu Xuf883b422016-08-30 14:01:10 -07008081 aom_highbd_subtract_block(bh, bw, d10, bw, CONVERT_TO_BYTEPTR(p1), bw,
Yaowu Xuc27fc142016-08-22 16:08:15 -07008082 CONVERT_TO_BYTEPTR(p0), bw, xd->bd);
8083 } else // NOLINT
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02008084#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07008085 {
Yaowu Xuf883b422016-08-30 14:01:10 -07008086 aom_subtract_block(bh, bw, r0, bw, src->buf, src->stride, p0, bw);
8087 aom_subtract_block(bh, bw, r1, bw, src->buf, src->stride, p1, bw);
8088 aom_subtract_block(bh, bw, d10, bw, p1, bw, p0, bw);
Yaowu Xuc27fc142016-08-22 16:08:15 -07008089 }
8090
Yaowu Xuf883b422016-08-30 14:01:10 -07008091 sign_limit = ((int64_t)aom_sum_squares_i16(r0, N) -
8092 (int64_t)aom_sum_squares_i16(r1, N)) *
Yaowu Xuc27fc142016-08-22 16:08:15 -07008093 (1 << WEDGE_WEIGHT_BITS) / 2;
8094
Jingning Han61418bb2017-01-23 17:12:48 -08008095 if (N < 64)
8096 av1_wedge_compute_delta_squares_c(ds, r0, r1, N);
8097 else
8098 av1_wedge_compute_delta_squares(ds, r0, r1, N);
Yaowu Xuc27fc142016-08-22 16:08:15 -07008099
8100 for (wedge_index = 0; wedge_index < wedge_types; ++wedge_index) {
Yaowu Xuf883b422016-08-30 14:01:10 -07008101 mask = av1_get_contiguous_soft_mask(wedge_index, 0, bsize);
Jingning Han61418bb2017-01-23 17:12:48 -08008102
8103 // TODO(jingning): Make sse2 functions support N = 16 case
8104 if (N < 64)
8105 wedge_sign = av1_wedge_sign_from_residuals_c(ds, mask, N, sign_limit);
8106 else
8107 wedge_sign = av1_wedge_sign_from_residuals(ds, mask, N, sign_limit);
Yaowu Xuc27fc142016-08-22 16:08:15 -07008108
Yaowu Xuf883b422016-08-30 14:01:10 -07008109 mask = av1_get_contiguous_soft_mask(wedge_index, wedge_sign, bsize);
Jingning Han61418bb2017-01-23 17:12:48 -08008110 if (N < 64)
8111 sse = av1_wedge_sse_from_residuals_c(r1, d10, mask, N);
8112 else
8113 sse = av1_wedge_sse_from_residuals(r1, d10, mask, N);
Yaowu Xuc27fc142016-08-22 16:08:15 -07008114 sse = ROUND_POWER_OF_TWO(sse, bd_round);
8115
8116 model_rd_from_sse(cpi, xd, bsize, 0, sse, &rate, &dist);
Urvang Joshi70006e42017-06-14 16:08:55 -07008117 rd = RDCOST(x->rdmult, rate, dist);
Yaowu Xuc27fc142016-08-22 16:08:15 -07008118
8119 if (rd < best_rd) {
8120 *best_wedge_index = wedge_index;
8121 *best_wedge_sign = wedge_sign;
8122 best_rd = rd;
8123 }
8124 }
8125
8126 return best_rd;
8127}
8128
8129// Choose the best wedge index the specified sign
8130static int64_t pick_wedge_fixed_sign(
Yaowu Xuf883b422016-08-30 14:01:10 -07008131 const AV1_COMP *const cpi, const MACROBLOCK *const x,
Yaowu Xuc27fc142016-08-22 16:08:15 -07008132 const BLOCK_SIZE bsize, const uint8_t *const p0, const uint8_t *const p1,
8133 const int wedge_sign, int *const best_wedge_index) {
8134 const MACROBLOCKD *const xd = &x->e_mbd;
8135 const struct buf_2d *const src = &x->plane[0].src;
Jingning Hanae5cfde2016-11-30 12:01:44 -08008136 const int bw = block_size_wide[bsize];
8137 const int bh = block_size_high[bsize];
Yaowu Xuc27fc142016-08-22 16:08:15 -07008138 const int N = bw * bh;
8139 int rate;
8140 int64_t dist;
8141 int64_t rd, best_rd = INT64_MAX;
8142 int wedge_index;
8143 int wedge_types = (1 << get_wedge_bits_lookup(bsize));
8144 const uint8_t *mask;
8145 uint64_t sse;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02008146#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07008147 const int hbd = xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH;
8148 const int bd_round = hbd ? (xd->bd - 8) * 2 : 0;
8149#else
8150 const int bd_round = 0;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02008151#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07008152
8153 DECLARE_ALIGNED(32, int16_t, r1[MAX_SB_SQUARE]);
8154 DECLARE_ALIGNED(32, int16_t, d10[MAX_SB_SQUARE]);
8155
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02008156#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07008157 if (hbd) {
Yaowu Xuf883b422016-08-30 14:01:10 -07008158 aom_highbd_subtract_block(bh, bw, r1, bw, src->buf, src->stride,
Yaowu Xuc27fc142016-08-22 16:08:15 -07008159 CONVERT_TO_BYTEPTR(p1), bw, xd->bd);
Yaowu Xuf883b422016-08-30 14:01:10 -07008160 aom_highbd_subtract_block(bh, bw, d10, bw, CONVERT_TO_BYTEPTR(p1), bw,
Yaowu Xuc27fc142016-08-22 16:08:15 -07008161 CONVERT_TO_BYTEPTR(p0), bw, xd->bd);
8162 } else // NOLINT
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02008163#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07008164 {
Yaowu Xuf883b422016-08-30 14:01:10 -07008165 aom_subtract_block(bh, bw, r1, bw, src->buf, src->stride, p1, bw);
8166 aom_subtract_block(bh, bw, d10, bw, p1, bw, p0, bw);
Yaowu Xuc27fc142016-08-22 16:08:15 -07008167 }
8168
8169 for (wedge_index = 0; wedge_index < wedge_types; ++wedge_index) {
Yaowu Xuf883b422016-08-30 14:01:10 -07008170 mask = av1_get_contiguous_soft_mask(wedge_index, wedge_sign, bsize);
Jingning Han61418bb2017-01-23 17:12:48 -08008171 if (N < 64)
8172 sse = av1_wedge_sse_from_residuals_c(r1, d10, mask, N);
8173 else
8174 sse = av1_wedge_sse_from_residuals(r1, d10, mask, N);
Yaowu Xuc27fc142016-08-22 16:08:15 -07008175 sse = ROUND_POWER_OF_TWO(sse, bd_round);
8176
8177 model_rd_from_sse(cpi, xd, bsize, 0, sse, &rate, &dist);
Urvang Joshi70006e42017-06-14 16:08:55 -07008178 rd = RDCOST(x->rdmult, rate, dist);
Yaowu Xuc27fc142016-08-22 16:08:15 -07008179
8180 if (rd < best_rd) {
8181 *best_wedge_index = wedge_index;
8182 best_rd = rd;
8183 }
8184 }
8185
8186 return best_rd;
8187}
8188
Yaowu Xuf883b422016-08-30 14:01:10 -07008189static int64_t pick_interinter_wedge(const AV1_COMP *const cpi,
Sarah Parker2d0e9b72017-05-04 01:34:16 +00008190 MACROBLOCK *const x,
Yaowu Xuc27fc142016-08-22 16:08:15 -07008191 const BLOCK_SIZE bsize,
8192 const uint8_t *const p0,
8193 const uint8_t *const p1) {
Sarah Parker2d0e9b72017-05-04 01:34:16 +00008194 MACROBLOCKD *const xd = &x->e_mbd;
Yaowu Xuc27fc142016-08-22 16:08:15 -07008195 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Jingning Hanae5cfde2016-11-30 12:01:44 -08008196 const int bw = block_size_wide[bsize];
Yaowu Xuc27fc142016-08-22 16:08:15 -07008197
8198 int64_t rd;
8199 int wedge_index = -1;
8200 int wedge_sign = 0;
8201
Sarah Parker42d96102017-01-31 21:05:27 -08008202 assert(is_interinter_compound_used(COMPOUND_WEDGE, bsize));
Debargha Mukherjee9e2c7a62017-05-23 21:18:42 -07008203 assert(cpi->common.allow_masked_compound);
Yaowu Xuc27fc142016-08-22 16:08:15 -07008204
8205 if (cpi->sf.fast_wedge_sign_estimate) {
8206 wedge_sign = estimate_wedge_sign(cpi, x, bsize, p0, bw, p1, bw);
8207 rd = pick_wedge_fixed_sign(cpi, x, bsize, p0, p1, wedge_sign, &wedge_index);
8208 } else {
8209 rd = pick_wedge(cpi, x, bsize, p0, p1, &wedge_sign, &wedge_index);
8210 }
8211
Sarah Parker2d0e9b72017-05-04 01:34:16 +00008212 mbmi->wedge_sign = wedge_sign;
8213 mbmi->wedge_index = wedge_index;
Yaowu Xuc27fc142016-08-22 16:08:15 -07008214 return rd;
8215}
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00008216#endif // CONFIG_WEDGE
Yaowu Xuc27fc142016-08-22 16:08:15 -07008217
Sarah Parker569edda2016-12-14 14:57:38 -08008218#if CONFIG_COMPOUND_SEGMENT
Sarah Parkerddcea392017-04-25 15:57:22 -07008219static int64_t pick_interinter_seg(const AV1_COMP *const cpi,
Sarah Parker2d0e9b72017-05-04 01:34:16 +00008220 MACROBLOCK *const x, const BLOCK_SIZE bsize,
Sarah Parkerddcea392017-04-25 15:57:22 -07008221 const uint8_t *const p0,
8222 const uint8_t *const p1) {
Sarah Parker2d0e9b72017-05-04 01:34:16 +00008223 MACROBLOCKD *const xd = &x->e_mbd;
Sarah Parker569edda2016-12-14 14:57:38 -08008224 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
8225 const struct buf_2d *const src = &x->plane[0].src;
8226 const int bw = block_size_wide[bsize];
8227 const int bh = block_size_high[bsize];
8228 const int N = bw * bh;
8229 int rate;
8230 uint64_t sse;
8231 int64_t dist;
Debargha Mukherjeec30934b2017-04-25 01:23:51 -07008232 int64_t rd0;
Sarah Parkerb9f757c2017-01-06 17:12:24 -08008233 SEG_MASK_TYPE cur_mask_type;
8234 int64_t best_rd = INT64_MAX;
8235 SEG_MASK_TYPE best_mask_type = 0;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02008236#if CONFIG_HIGHBITDEPTH
Sarah Parker569edda2016-12-14 14:57:38 -08008237 const int hbd = xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH;
8238 const int bd_round = hbd ? (xd->bd - 8) * 2 : 0;
8239#else
8240 const int bd_round = 0;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02008241#endif // CONFIG_HIGHBITDEPTH
Sarah Parker569edda2016-12-14 14:57:38 -08008242 DECLARE_ALIGNED(32, int16_t, r0[MAX_SB_SQUARE]);
8243 DECLARE_ALIGNED(32, int16_t, r1[MAX_SB_SQUARE]);
8244 DECLARE_ALIGNED(32, int16_t, d10[MAX_SB_SQUARE]);
8245
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02008246#if CONFIG_HIGHBITDEPTH
Sarah Parker569edda2016-12-14 14:57:38 -08008247 if (hbd) {
8248 aom_highbd_subtract_block(bh, bw, r0, bw, src->buf, src->stride,
8249 CONVERT_TO_BYTEPTR(p0), bw, xd->bd);
8250 aom_highbd_subtract_block(bh, bw, r1, bw, src->buf, src->stride,
8251 CONVERT_TO_BYTEPTR(p1), bw, xd->bd);
8252 aom_highbd_subtract_block(bh, bw, d10, bw, CONVERT_TO_BYTEPTR(p1), bw,
8253 CONVERT_TO_BYTEPTR(p0), bw, xd->bd);
8254 } else // NOLINT
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02008255#endif // CONFIG_HIGHBITDEPTH
Sarah Parker569edda2016-12-14 14:57:38 -08008256 {
8257 aom_subtract_block(bh, bw, r0, bw, src->buf, src->stride, p0, bw);
8258 aom_subtract_block(bh, bw, r1, bw, src->buf, src->stride, p1, bw);
8259 aom_subtract_block(bh, bw, d10, bw, p1, bw, p0, bw);
8260 }
8261
Sarah Parkerb9f757c2017-01-06 17:12:24 -08008262 // try each mask type and its inverse
8263 for (cur_mask_type = 0; cur_mask_type < SEG_MASK_TYPES; cur_mask_type++) {
Debargha Mukherjee1edf9a32017-01-07 18:54:20 -08008264// build mask and inverse
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02008265#if CONFIG_HIGHBITDEPTH
Debargha Mukherjee1edf9a32017-01-07 18:54:20 -08008266 if (hbd)
8267 build_compound_seg_mask_highbd(
Sarah Parker2d0e9b72017-05-04 01:34:16 +00008268 xd->seg_mask, cur_mask_type, CONVERT_TO_BYTEPTR(p0), bw,
Debargha Mukherjee1edf9a32017-01-07 18:54:20 -08008269 CONVERT_TO_BYTEPTR(p1), bw, bsize, bh, bw, xd->bd);
8270 else
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02008271#endif // CONFIG_HIGHBITDEPTH
Sarah Parker2d0e9b72017-05-04 01:34:16 +00008272 build_compound_seg_mask(xd->seg_mask, cur_mask_type, p0, bw, p1, bw,
8273 bsize, bh, bw);
Sarah Parker569edda2016-12-14 14:57:38 -08008274
Sarah Parkerb9f757c2017-01-06 17:12:24 -08008275 // compute rd for mask
Sarah Parker2d0e9b72017-05-04 01:34:16 +00008276 sse = av1_wedge_sse_from_residuals(r1, d10, xd->seg_mask, N);
Sarah Parkerb9f757c2017-01-06 17:12:24 -08008277 sse = ROUND_POWER_OF_TWO(sse, bd_round);
Sarah Parker569edda2016-12-14 14:57:38 -08008278
Sarah Parkerb9f757c2017-01-06 17:12:24 -08008279 model_rd_from_sse(cpi, xd, bsize, 0, sse, &rate, &dist);
Urvang Joshi70006e42017-06-14 16:08:55 -07008280 rd0 = RDCOST(x->rdmult, rate, dist);
Sarah Parker569edda2016-12-14 14:57:38 -08008281
Sarah Parkerb9f757c2017-01-06 17:12:24 -08008282 if (rd0 < best_rd) {
8283 best_mask_type = cur_mask_type;
8284 best_rd = rd0;
8285 }
8286 }
Sarah Parker569edda2016-12-14 14:57:38 -08008287
Sarah Parkerb9f757c2017-01-06 17:12:24 -08008288 // make final mask
Sarah Parker2d0e9b72017-05-04 01:34:16 +00008289 mbmi->mask_type = best_mask_type;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02008290#if CONFIG_HIGHBITDEPTH
Debargha Mukherjee1edf9a32017-01-07 18:54:20 -08008291 if (hbd)
8292 build_compound_seg_mask_highbd(
Sarah Parker2d0e9b72017-05-04 01:34:16 +00008293 xd->seg_mask, mbmi->mask_type, CONVERT_TO_BYTEPTR(p0), bw,
Debargha Mukherjee1edf9a32017-01-07 18:54:20 -08008294 CONVERT_TO_BYTEPTR(p1), bw, bsize, bh, bw, xd->bd);
8295 else
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02008296#endif // CONFIG_HIGHBITDEPTH
Sarah Parker2d0e9b72017-05-04 01:34:16 +00008297 build_compound_seg_mask(xd->seg_mask, mbmi->mask_type, p0, bw, p1, bw,
8298 bsize, bh, bw);
Sarah Parker569edda2016-12-14 14:57:38 -08008299
Sarah Parkerb9f757c2017-01-06 17:12:24 -08008300 return best_rd;
Sarah Parker569edda2016-12-14 14:57:38 -08008301}
8302#endif // CONFIG_COMPOUND_SEGMENT
8303
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00008304#if CONFIG_WEDGE && CONFIG_INTERINTRA
Yaowu Xuf883b422016-08-30 14:01:10 -07008305static int64_t pick_interintra_wedge(const AV1_COMP *const cpi,
Yaowu Xuc27fc142016-08-22 16:08:15 -07008306 const MACROBLOCK *const x,
8307 const BLOCK_SIZE bsize,
8308 const uint8_t *const p0,
8309 const uint8_t *const p1) {
8310 const MACROBLOCKD *const xd = &x->e_mbd;
8311 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
8312
8313 int64_t rd;
8314 int wedge_index = -1;
8315
8316 assert(is_interintra_wedge_used(bsize));
Debargha Mukherjee9e2c7a62017-05-23 21:18:42 -07008317 assert(cpi->common.allow_interintra_compound);
Yaowu Xuc27fc142016-08-22 16:08:15 -07008318
8319 rd = pick_wedge_fixed_sign(cpi, x, bsize, p0, p1, 0, &wedge_index);
8320
8321 mbmi->interintra_wedge_sign = 0;
8322 mbmi->interintra_wedge_index = wedge_index;
8323 return rd;
8324}
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00008325#endif // CONFIG_WEDGE && CONFIG_INTERINTRA
Sarah Parker6fdc8532016-11-16 17:47:13 -08008326
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00008327#if CONFIG_COMPOUND_SEGMENT || CONFIG_WEDGE
Sarah Parker2d0e9b72017-05-04 01:34:16 +00008328static int64_t pick_interinter_mask(const AV1_COMP *const cpi, MACROBLOCK *x,
Sarah Parkerddcea392017-04-25 15:57:22 -07008329 const BLOCK_SIZE bsize,
8330 const uint8_t *const p0,
8331 const uint8_t *const p1) {
8332 const COMPOUND_TYPE compound_type =
Sarah Parker2d0e9b72017-05-04 01:34:16 +00008333 x->e_mbd.mi[0]->mbmi.interinter_compound_type;
Sarah Parkerddcea392017-04-25 15:57:22 -07008334 switch (compound_type) {
8335#if CONFIG_WEDGE
8336 case COMPOUND_WEDGE: return pick_interinter_wedge(cpi, x, bsize, p0, p1);
8337#endif // CONFIG_WEDGE
8338#if CONFIG_COMPOUND_SEGMENT
8339 case COMPOUND_SEG: return pick_interinter_seg(cpi, x, bsize, p0, p1);
8340#endif // CONFIG_COMPOUND_SEGMENT
8341 default: assert(0); return 0;
8342 }
8343}
8344
David Barkerc155e012017-05-11 13:54:54 +01008345static int interinter_compound_motion_search(
8346 const AV1_COMP *const cpi, MACROBLOCK *x, const int_mv *const cur_mv,
8347 const BLOCK_SIZE bsize, const int this_mode, int mi_row, int mi_col) {
Sarah Parker2d0e9b72017-05-04 01:34:16 +00008348 MACROBLOCKD *const xd = &x->e_mbd;
Sarah Parker6fdc8532016-11-16 17:47:13 -08008349 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
8350 int_mv tmp_mv[2];
David Barkerc155e012017-05-11 13:54:54 +01008351 int tmp_rate_mv = 0;
Sarah Parker2d0e9b72017-05-04 01:34:16 +00008352 const INTERINTER_COMPOUND_DATA compound_data = {
8353#if CONFIG_WEDGE
8354 mbmi->wedge_index,
8355 mbmi->wedge_sign,
8356#endif // CONFIG_WEDGE
8357#if CONFIG_COMPOUND_SEGMENT
8358 mbmi->mask_type,
8359 xd->seg_mask,
8360#endif // CONFIG_COMPOUND_SEGMENT
8361 mbmi->interinter_compound_type
8362 };
Zoe Liu85b66462017-04-20 14:28:19 -07008363#if CONFIG_COMPOUND_SINGLEREF
8364 // NOTE: Mode is needed to identify the compound mode prediction, regardless
8365 // of comp refs or single ref.
8366 mbmi->mode = this_mode;
8367#endif // CONFIG_COMPOUND_SINGLEREF
8368
8369 if (this_mode == NEW_NEWMV
8370#if CONFIG_COMPOUND_SINGLEREF
8371 || this_mode == SR_NEW_NEWMV
8372#endif // CONFIG_COMPOUND_SINGLEREF
8373 ) {
David Barkerc155e012017-05-11 13:54:54 +01008374 do_masked_motion_search_indexed(cpi, x, cur_mv, &compound_data, bsize,
8375 mi_row, mi_col, tmp_mv, &tmp_rate_mv, 2);
Sarah Parker6fdc8532016-11-16 17:47:13 -08008376 mbmi->mv[0].as_int = tmp_mv[0].as_int;
8377 mbmi->mv[1].as_int = tmp_mv[1].as_int;
8378 } else if (this_mode == NEW_NEARESTMV || this_mode == NEW_NEARMV) {
David Barkerc155e012017-05-11 13:54:54 +01008379 do_masked_motion_search_indexed(cpi, x, cur_mv, &compound_data, bsize,
8380 mi_row, mi_col, tmp_mv, &tmp_rate_mv, 0);
Sarah Parker6fdc8532016-11-16 17:47:13 -08008381 mbmi->mv[0].as_int = tmp_mv[0].as_int;
Zoe Liu85b66462017-04-20 14:28:19 -07008382 } else if (this_mode == NEAREST_NEWMV || this_mode == NEAR_NEWMV
8383#if CONFIG_COMPOUND_SINGLEREF
8384 // || this_mode == SR_NEAREST_NEWMV
8385 || this_mode == SR_NEAR_NEWMV || this_mode == SR_ZERO_NEWMV
8386#endif // CONFIG_COMPOUND_SINGLEREF
8387 ) {
David Barkerc155e012017-05-11 13:54:54 +01008388 do_masked_motion_search_indexed(cpi, x, cur_mv, &compound_data, bsize,
8389 mi_row, mi_col, tmp_mv, &tmp_rate_mv, 1);
Sarah Parker6fdc8532016-11-16 17:47:13 -08008390 mbmi->mv[1].as_int = tmp_mv[1].as_int;
8391 }
8392 return tmp_rate_mv;
8393}
8394
Sarah Parkerddcea392017-04-25 15:57:22 -07008395static int64_t build_and_cost_compound_type(
Sarah Parker569edda2016-12-14 14:57:38 -08008396 const AV1_COMP *const cpi, MACROBLOCK *x, const int_mv *const cur_mv,
8397 const BLOCK_SIZE bsize, const int this_mode, int rs2, int rate_mv,
8398 BUFFER_SET *ctx, int *out_rate_mv, uint8_t **preds0, uint8_t **preds1,
8399 int *strides, int mi_row, int mi_col) {
Debargha Mukherjeead8be032017-05-09 15:28:45 -07008400 const AV1_COMMON *const cm = &cpi->common;
Sarah Parker569edda2016-12-14 14:57:38 -08008401 MACROBLOCKD *xd = &x->e_mbd;
8402 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
8403 int rate_sum;
8404 int64_t dist_sum;
8405 int64_t best_rd_cur = INT64_MAX;
8406 int64_t rd = INT64_MAX;
8407 int tmp_skip_txfm_sb;
8408 int64_t tmp_skip_sse_sb;
Sarah Parker2d0e9b72017-05-04 01:34:16 +00008409 const COMPOUND_TYPE compound_type = mbmi->interinter_compound_type;
Sarah Parker569edda2016-12-14 14:57:38 -08008410
Sarah Parkerddcea392017-04-25 15:57:22 -07008411 best_rd_cur = pick_interinter_mask(cpi, x, bsize, *preds0, *preds1);
Urvang Joshi70006e42017-06-14 16:08:55 -07008412 best_rd_cur += RDCOST(x->rdmult, rs2 + rate_mv, 0);
Sarah Parker569edda2016-12-14 14:57:38 -08008413
Sarah Parker2e604882017-01-17 17:31:25 -08008414 if (have_newmv_in_inter_mode(this_mode) &&
Sarah Parkerddcea392017-04-25 15:57:22 -07008415 use_masked_motion_search(compound_type)) {
David Barkerc155e012017-05-11 13:54:54 +01008416 *out_rate_mv = interinter_compound_motion_search(cpi, x, cur_mv, bsize,
8417 this_mode, mi_row, mi_col);
Debargha Mukherjeead8be032017-05-09 15:28:45 -07008418 av1_build_inter_predictors_sby(cm, xd, mi_row, mi_col, ctx, bsize);
Sarah Parker6fdc8532016-11-16 17:47:13 -08008419 model_rd_for_sb(cpi, bsize, x, xd, 0, 0, &rate_sum, &dist_sum,
8420 &tmp_skip_txfm_sb, &tmp_skip_sse_sb);
Urvang Joshi70006e42017-06-14 16:08:55 -07008421 rd = RDCOST(x->rdmult, rs2 + *out_rate_mv + rate_sum, dist_sum);
Zoe Liu4d44f5a2016-12-14 17:46:19 -08008422 if (rd >= best_rd_cur) {
Sarah Parker6fdc8532016-11-16 17:47:13 -08008423 mbmi->mv[0].as_int = cur_mv[0].as_int;
8424 mbmi->mv[1].as_int = cur_mv[1].as_int;
8425 *out_rate_mv = rate_mv;
David Barker426a9972017-01-27 11:03:11 +00008426 av1_build_wedge_inter_predictor_from_buf(xd, bsize, 0, 0,
8427#if CONFIG_SUPERTX
8428 0, 0,
8429#endif // CONFIG_SUPERTX
8430 preds0, strides, preds1,
8431 strides);
Sarah Parker6fdc8532016-11-16 17:47:13 -08008432 }
8433 av1_subtract_plane(x, bsize, 0);
8434 rd = estimate_yrd_for_sb(cpi, bsize, x, &rate_sum, &dist_sum,
8435 &tmp_skip_txfm_sb, &tmp_skip_sse_sb, INT64_MAX);
8436 if (rd != INT64_MAX)
Urvang Joshi70006e42017-06-14 16:08:55 -07008437 rd = RDCOST(x->rdmult, rs2 + *out_rate_mv + rate_sum, dist_sum);
Sarah Parker6fdc8532016-11-16 17:47:13 -08008438 best_rd_cur = rd;
8439
8440 } else {
David Barker426a9972017-01-27 11:03:11 +00008441 av1_build_wedge_inter_predictor_from_buf(xd, bsize, 0, 0,
8442#if CONFIG_SUPERTX
8443 0, 0,
8444#endif // CONFIG_SUPERTX
8445 preds0, strides, preds1, strides);
Sarah Parker6fdc8532016-11-16 17:47:13 -08008446 av1_subtract_plane(x, bsize, 0);
8447 rd = estimate_yrd_for_sb(cpi, bsize, x, &rate_sum, &dist_sum,
8448 &tmp_skip_txfm_sb, &tmp_skip_sse_sb, INT64_MAX);
8449 if (rd != INT64_MAX)
Urvang Joshi70006e42017-06-14 16:08:55 -07008450 rd = RDCOST(x->rdmult, rs2 + rate_mv + rate_sum, dist_sum);
Sarah Parker6fdc8532016-11-16 17:47:13 -08008451 best_rd_cur = rd;
8452 }
8453 return best_rd_cur;
8454}
Sarah Parkerddcea392017-04-25 15:57:22 -07008455#endif // CONFIG_COMPOUND_SEGMENT || CONFIG_WEDGE
Yaowu Xuc27fc142016-08-22 16:08:15 -07008456
Fergus Simpson073c6f32017-02-17 12:13:48 -08008457typedef struct {
8458#if CONFIG_MOTION_VAR
8459 // Inter prediction buffers and respective strides
8460 uint8_t *above_pred_buf[MAX_MB_PLANE];
8461 int above_pred_stride[MAX_MB_PLANE];
8462 uint8_t *left_pred_buf[MAX_MB_PLANE];
8463 int left_pred_stride[MAX_MB_PLANE];
8464#endif // CONFIG_MOTION_VAR
Zoe Liu7f24e1b2017-03-17 17:42:05 -07008465 int_mv *single_newmv;
Fergus Simpson073c6f32017-02-17 12:13:48 -08008466 // Pointer to array of motion vectors to use for each ref and their rates
8467 // Should point to first of 2 arrays in 2D array
Zoe Liu7f24e1b2017-03-17 17:42:05 -07008468 int *single_newmv_rate;
Fergus Simpson073c6f32017-02-17 12:13:48 -08008469 // Pointer to array of predicted rate-distortion
8470 // Should point to first of 2 arrays in 2D array
8471 int64_t (*modelled_rd)[TOTAL_REFS_PER_FRAME];
Fergus Simpson3424c2d2017-03-09 11:48:15 -08008472 InterpFilter single_filter[MB_MODE_COUNT][TOTAL_REFS_PER_FRAME];
Fergus Simpson073c6f32017-02-17 12:13:48 -08008473} HandleInterModeArgs;
8474
Fergus Simpson45509632017-02-22 15:30:50 -08008475static int64_t handle_newmv(const AV1_COMP *const cpi, MACROBLOCK *const x,
8476 const BLOCK_SIZE bsize,
8477 int_mv (*const mode_mv)[TOTAL_REFS_PER_FRAME],
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008478#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07008479 int_mv (*const mode_comp_mv)[TOTAL_REFS_PER_FRAME],
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008480#endif // CONFIG_COMPOUND_SINGLEREF
Fergus Simpson45509632017-02-22 15:30:50 -08008481 const int mi_row, const int mi_col,
8482 int *const rate_mv, int_mv *const single_newmv,
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -08008483 HandleInterModeArgs *const args) {
Fergus Simpson45509632017-02-22 15:30:50 -08008484 const MACROBLOCKD *const xd = &x->e_mbd;
8485 const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
8486 const MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
8487 const int is_comp_pred = has_second_ref(mbmi);
8488 const PREDICTION_MODE this_mode = mbmi->mode;
Fergus Simpson45509632017-02-22 15:30:50 -08008489 const int is_comp_interintra_pred = (mbmi->ref_frame[1] == INTRA_FRAME);
Fergus Simpson45509632017-02-22 15:30:50 -08008490 int_mv *const frame_mv = mode_mv[this_mode];
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008491#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07008492 int_mv *const frame_comp_mv = mode_comp_mv[this_mode];
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008493#endif // CONFIG_COMPOUND_SINGLEREF
Fergus Simpson45509632017-02-22 15:30:50 -08008494 const int refs[2] = { mbmi->ref_frame[0],
8495 mbmi->ref_frame[1] < 0 ? 0 : mbmi->ref_frame[1] };
8496 int i;
8497
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -08008498 (void)args;
Fergus Simpson45509632017-02-22 15:30:50 -08008499
8500 if (is_comp_pred) {
Fergus Simpson45509632017-02-22 15:30:50 -08008501 for (i = 0; i < 2; ++i) {
Zoe Liu7f24e1b2017-03-17 17:42:05 -07008502 single_newmv[refs[i]].as_int = args->single_newmv[refs[i]].as_int;
Fergus Simpson45509632017-02-22 15:30:50 -08008503 }
8504
8505 if (this_mode == NEW_NEWMV) {
8506 frame_mv[refs[0]].as_int = single_newmv[refs[0]].as_int;
8507 frame_mv[refs[1]].as_int = single_newmv[refs[1]].as_int;
8508
8509 if (cpi->sf.comp_inter_joint_search_thresh <= bsize) {
Zoe Liu85b66462017-04-20 14:28:19 -07008510 joint_motion_search(cpi, x, bsize, frame_mv,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008511#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07008512 NULL, // int_mv *frame_comp_mv
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008513#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07008514 mi_row, mi_col, NULL, NULL, 0, rate_mv, 0);
Fergus Simpson45509632017-02-22 15:30:50 -08008515 } else {
8516 *rate_mv = 0;
8517 for (i = 0; i < 2; ++i) {
Zoe Liu122f3942017-04-25 11:18:38 -07008518 av1_set_mvcost(x, refs[i], i, mbmi->ref_mv_idx);
Fergus Simpson45509632017-02-22 15:30:50 -08008519 *rate_mv += av1_mv_bit_cost(
8520 &frame_mv[refs[i]].as_mv, &mbmi_ext->ref_mvs[refs[i]][0].as_mv,
8521 x->nmvjointcost, x->mvcost, MV_COST_WEIGHT);
8522 }
8523 }
8524 } else if (this_mode == NEAREST_NEWMV || this_mode == NEAR_NEWMV) {
8525 frame_mv[refs[1]].as_int = single_newmv[refs[1]].as_int;
David Barker8dd9b572017-05-12 16:31:38 +01008526 if (cpi->sf.comp_inter_joint_search_thresh <= bsize) {
8527 frame_mv[refs[0]].as_int =
8528 mode_mv[compound_ref0_mode(this_mode)][refs[0]].as_int;
Zoe Liu85b66462017-04-20 14:28:19 -07008529 compound_single_motion_search_interinter(cpi, x, bsize, frame_mv,
8530#if CONFIG_COMPOUND_SINGLEREF
8531 NULL,
8532#endif // CONFIG_COMPOUND_SINGLEREF
8533 mi_row, mi_col, NULL, 0,
8534 rate_mv, 0, 1);
David Barker8dd9b572017-05-12 16:31:38 +01008535 } else {
8536 av1_set_mvcost(x, refs[1], 1, mbmi->ref_mv_idx);
8537 *rate_mv = av1_mv_bit_cost(&frame_mv[refs[1]].as_mv,
8538 &mbmi_ext->ref_mvs[refs[1]][0].as_mv,
8539 x->nmvjointcost, x->mvcost, MV_COST_WEIGHT);
8540 }
Fergus Simpson45509632017-02-22 15:30:50 -08008541 } else {
David Barkercb03dc32017-04-07 13:05:09 +01008542 assert(this_mode == NEW_NEARESTMV || this_mode == NEW_NEARMV);
Fergus Simpson45509632017-02-22 15:30:50 -08008543 frame_mv[refs[0]].as_int = single_newmv[refs[0]].as_int;
David Barker8dd9b572017-05-12 16:31:38 +01008544 if (cpi->sf.comp_inter_joint_search_thresh <= bsize) {
8545 frame_mv[refs[1]].as_int =
8546 mode_mv[compound_ref1_mode(this_mode)][refs[1]].as_int;
Zoe Liu85b66462017-04-20 14:28:19 -07008547 compound_single_motion_search_interinter(cpi, x, bsize, frame_mv,
8548#if CONFIG_COMPOUND_SINGLEREF
8549 NULL,
8550#endif // CONFIG_COMPOUND_SINGLEREF
8551 mi_row, mi_col, NULL, 0,
8552 rate_mv, 0, 0);
David Barker8dd9b572017-05-12 16:31:38 +01008553 } else {
8554 av1_set_mvcost(x, refs[0], 0, mbmi->ref_mv_idx);
8555 *rate_mv = av1_mv_bit_cost(&frame_mv[refs[0]].as_mv,
8556 &mbmi_ext->ref_mvs[refs[0]][0].as_mv,
8557 x->nmvjointcost, x->mvcost, MV_COST_WEIGHT);
8558 }
Fergus Simpson45509632017-02-22 15:30:50 -08008559 }
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008560#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07008561 } else if (is_inter_singleref_comp_mode(this_mode)) {
8562 // Single ref comp mode
8563 const int mode0 = compound_ref0_mode(this_mode);
8564
8565 single_newmv[refs[0]].as_int = args->single_newmv[refs[0]].as_int;
8566 frame_mv[refs[0]].as_int = (mode0 == NEWMV)
8567 ? single_newmv[refs[0]].as_int
8568 : mode_mv[mode0][refs[0]].as_int;
8569 assert(compound_ref1_mode(this_mode) == NEWMV);
8570 frame_comp_mv[refs[0]].as_int = single_newmv[refs[0]].as_int;
8571
8572 if (cpi->sf.comp_inter_joint_search_thresh <= bsize) {
8573 if (this_mode == SR_NEW_NEWMV) {
8574 joint_motion_search(cpi, x, bsize, frame_mv, frame_comp_mv, mi_row,
8575 mi_col, NULL, NULL, 0, rate_mv, 0);
8576 } else {
8577 assert( // this_mode == SR_NEAREST_NEWMV ||
8578 this_mode == SR_NEAR_NEWMV || this_mode == SR_ZERO_NEWMV);
8579 compound_single_motion_search_interinter(cpi, x, bsize, frame_mv,
8580 frame_comp_mv, mi_row, mi_col,
8581 NULL, 0, rate_mv, 0, 1);
8582 }
8583 } else {
8584 *rate_mv = 0;
8585 av1_set_mvcost(x, refs[0], 0, mbmi->ref_mv_idx);
8586 if (mode0 == NEWMV)
8587 *rate_mv += av1_mv_bit_cost(&frame_mv[refs[0]].as_mv,
8588 &mbmi_ext->ref_mvs[refs[0]][0].as_mv,
8589 x->nmvjointcost, x->mvcost, MV_COST_WEIGHT);
8590 *rate_mv += av1_mv_bit_cost(&frame_comp_mv[refs[0]].as_mv,
8591 &mbmi_ext->ref_mvs[refs[0]][0].as_mv,
8592 x->nmvjointcost, x->mvcost, MV_COST_WEIGHT);
8593 }
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008594#endif // CONFIG_COMPOUND_SINGLEREF
Fergus Simpson45509632017-02-22 15:30:50 -08008595 } else {
Fergus Simpson45509632017-02-22 15:30:50 -08008596 if (is_comp_interintra_pred) {
Zoe Liu7f24e1b2017-03-17 17:42:05 -07008597 x->best_mv = args->single_newmv[refs[0]];
8598 *rate_mv = args->single_newmv_rate[refs[0]];
Fergus Simpson45509632017-02-22 15:30:50 -08008599 } else {
Zoe Liu7f24e1b2017-03-17 17:42:05 -07008600 single_motion_search(cpi, x, bsize, mi_row, mi_col, 0, rate_mv);
8601 args->single_newmv[refs[0]] = x->best_mv;
8602 args->single_newmv_rate[refs[0]] = *rate_mv;
Fergus Simpson45509632017-02-22 15:30:50 -08008603 }
Fergus Simpson45509632017-02-22 15:30:50 -08008604
8605 if (x->best_mv.as_int == INVALID_MV) return INT64_MAX;
8606
8607 frame_mv[refs[0]] = x->best_mv;
8608 xd->mi[0]->bmi[0].as_mv[0] = x->best_mv;
8609
8610 // Estimate the rate implications of a new mv but discount this
8611 // under certain circumstances where we want to help initiate a weak
8612 // motion field, where the distortion gain for a single block may not
8613 // be enough to overcome the cost of a new mv.
8614 if (discount_newmv_test(cpi, this_mode, x->best_mv, mode_mv, refs[0])) {
8615 *rate_mv = AOMMAX(*rate_mv / NEW_MV_DISCOUNT_FACTOR, 1);
8616 }
8617 }
8618
8619 return 0;
8620}
8621
Fergus Simpsonde18e2b2017-03-01 20:12:34 -08008622int64_t interpolation_filter_search(
8623 MACROBLOCK *const x, const AV1_COMP *const cpi, BLOCK_SIZE bsize,
8624 int mi_row, int mi_col, const BUFFER_SET *const tmp_dst,
8625 BUFFER_SET *const orig_dst,
8626 InterpFilter (*const single_filter)[TOTAL_REFS_PER_FRAME],
8627 int64_t *const rd, int *const switchable_rate, int *const skip_txfm_sb,
8628 int64_t *const skip_sse_sb) {
8629 const AV1_COMMON *cm = &cpi->common;
8630 MACROBLOCKD *const xd = &x->e_mbd;
8631 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
8632 int i;
8633 int tmp_rate;
8634 int64_t tmp_dist;
8635
8636 (void)single_filter;
8637
8638 InterpFilter assign_filter = SWITCHABLE;
8639
8640 if (cm->interp_filter == SWITCHABLE) {
8641#if !CONFIG_DUAL_FILTER
Debargha Mukherjee0df711f2017-05-02 16:00:20 -07008642 assign_filter = av1_is_interp_needed(xd)
8643 ? predict_interp_filter(cpi, x, bsize, mi_row, mi_col,
8644 single_filter)
8645 : cm->interp_filter;
Fergus Simpsonde18e2b2017-03-01 20:12:34 -08008646#endif // !CONFIG_DUAL_FILTER
8647 } else {
8648 assign_filter = cm->interp_filter;
8649 }
8650
Debargha Mukherjee0df711f2017-05-02 16:00:20 -07008651 set_default_interp_filters(mbmi, assign_filter);
8652
Yue Chenb23d00a2017-07-28 17:01:21 -07008653 *switchable_rate = av1_get_switchable_rate(cm, x, xd);
Jingning Hanc44009c2017-05-06 11:36:49 -07008654 av1_build_inter_predictors_sb(cm, xd, mi_row, mi_col, orig_dst, bsize);
Fergus Simpsonde18e2b2017-03-01 20:12:34 -08008655 model_rd_for_sb(cpi, bsize, x, xd, 0, MAX_MB_PLANE - 1, &tmp_rate, &tmp_dist,
8656 skip_txfm_sb, skip_sse_sb);
Urvang Joshi70006e42017-06-14 16:08:55 -07008657 *rd = RDCOST(x->rdmult, *switchable_rate + tmp_rate, tmp_dist);
Fergus Simpsonde18e2b2017-03-01 20:12:34 -08008658
8659 if (assign_filter == SWITCHABLE) {
8660 // do interp_filter search
Debargha Mukherjee0df711f2017-05-02 16:00:20 -07008661 if (av1_is_interp_needed(xd) && av1_is_interp_search_needed(xd)) {
Fergus Simpsonde18e2b2017-03-01 20:12:34 -08008662#if CONFIG_DUAL_FILTER
8663 const int filter_set_size = DUAL_FILTER_SET_SIZE;
8664#else
8665 const int filter_set_size = SWITCHABLE_FILTERS;
8666#endif // CONFIG_DUAL_FILTER
8667 int best_in_temp = 0;
Rupert Swarbrick27e90292017-09-28 17:46:50 +01008668 InterpFilters best_filters = mbmi->interp_filters;
Fergus Simpsonde18e2b2017-03-01 20:12:34 -08008669 restore_dst_buf(xd, *tmp_dst);
8670 // EIGHTTAP_REGULAR mode is calculated beforehand
8671 for (i = 1; i < filter_set_size; ++i) {
8672 int tmp_skip_sb = 0;
8673 int64_t tmp_skip_sse = INT64_MAX;
8674 int tmp_rs;
8675 int64_t tmp_rd;
8676#if CONFIG_DUAL_FILTER
Rupert Swarbrick27e90292017-09-28 17:46:50 +01008677 mbmi->interp_filters =
8678 av1_make_interp_filters(filter_sets[i][0], filter_sets[i][1]);
Fergus Simpsonde18e2b2017-03-01 20:12:34 -08008679#else
Rupert Swarbrick27e90292017-09-28 17:46:50 +01008680 mbmi->interp_filters = av1_broadcast_interp_filter((InterpFilter)i);
Fergus Simpsonde18e2b2017-03-01 20:12:34 -08008681#endif // CONFIG_DUAL_FILTER
Yue Chenb23d00a2017-07-28 17:01:21 -07008682 tmp_rs = av1_get_switchable_rate(cm, x, xd);
Jingning Hanc44009c2017-05-06 11:36:49 -07008683 av1_build_inter_predictors_sb(cm, xd, mi_row, mi_col, orig_dst, bsize);
Fergus Simpsonde18e2b2017-03-01 20:12:34 -08008684 model_rd_for_sb(cpi, bsize, x, xd, 0, MAX_MB_PLANE - 1, &tmp_rate,
8685 &tmp_dist, &tmp_skip_sb, &tmp_skip_sse);
Urvang Joshi70006e42017-06-14 16:08:55 -07008686 tmp_rd = RDCOST(x->rdmult, tmp_rs + tmp_rate, tmp_dist);
Fergus Simpsonde18e2b2017-03-01 20:12:34 -08008687
8688 if (tmp_rd < *rd) {
8689 *rd = tmp_rd;
Yue Chenb23d00a2017-07-28 17:01:21 -07008690 *switchable_rate = av1_get_switchable_rate(cm, x, xd);
Rupert Swarbrick27e90292017-09-28 17:46:50 +01008691 best_filters = mbmi->interp_filters;
Fergus Simpsonde18e2b2017-03-01 20:12:34 -08008692 *skip_txfm_sb = tmp_skip_sb;
8693 *skip_sse_sb = tmp_skip_sse;
8694 best_in_temp = !best_in_temp;
8695 if (best_in_temp) {
8696 restore_dst_buf(xd, *orig_dst);
8697 } else {
8698 restore_dst_buf(xd, *tmp_dst);
8699 }
8700 }
8701 }
8702 if (best_in_temp) {
8703 restore_dst_buf(xd, *tmp_dst);
8704 } else {
8705 restore_dst_buf(xd, *orig_dst);
8706 }
Rupert Swarbrick27e90292017-09-28 17:46:50 +01008707 mbmi->interp_filters = best_filters;
Fergus Simpsonde18e2b2017-03-01 20:12:34 -08008708 } else {
Rupert Swarbrick27e90292017-09-28 17:46:50 +01008709 assert(mbmi->interp_filters ==
8710 av1_broadcast_interp_filter(EIGHTTAP_REGULAR));
Fergus Simpsonde18e2b2017-03-01 20:12:34 -08008711 }
8712 }
8713
8714 return 0;
8715}
8716
Rupert Swarbrick27e90292017-09-28 17:46:50 +01008717#if CONFIG_DUAL_FILTER
8718static InterpFilters condition_interp_filters_on_mv(
8719 InterpFilters interp_filters, const MACROBLOCKD *xd) {
8720 InterpFilter filters[2];
8721 for (int i = 0; i < 2; ++i)
8722 filters[i] = (has_subpel_mv_component(xd->mi[0], xd, i))
8723 ? av1_extract_interp_filter(interp_filters, i)
8724 : EIGHTTAP_REGULAR;
8725
8726 return av1_make_interp_filters(filters[0], filters[1]);
8727}
8728#endif
8729
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008730// TODO(afergs): Refactor the MBMI references in here - there's four
8731// TODO(afergs): Refactor optional args - add them to a struct or remove
8732static int64_t motion_mode_rd(
8733 const AV1_COMP *const cpi, MACROBLOCK *const x, BLOCK_SIZE bsize,
8734 RD_STATS *rd_stats, RD_STATS *rd_stats_y, RD_STATS *rd_stats_uv,
8735 int *disable_skip, int_mv (*mode_mv)[TOTAL_REFS_PER_FRAME], int mi_row,
8736 int mi_col, HandleInterModeArgs *const args, const int64_t ref_best_rd,
8737 const int *refs, int rate_mv,
8738#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
Wei-Ting Lin85a8f702017-06-22 13:55:15 -07008739 // only used when WARPED_MOTION is on?
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008740 int_mv *const single_newmv, int rate2_bmc_nocoeff,
8741 MB_MODE_INFO *best_bmc_mbmi, int rate_mv_bmc,
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008742#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
8743 int rs, int *skip_txfm_sb, int64_t *skip_sse_sb, BUFFER_SET *orig_dst) {
8744 const AV1_COMMON *const cm = &cpi->common;
8745 MACROBLOCKD *xd = &x->e_mbd;
8746 MODE_INFO *mi = xd->mi[0];
8747 MB_MODE_INFO *mbmi = &mi->mbmi;
8748 const int is_comp_pred = has_second_ref(mbmi);
8749 const PREDICTION_MODE this_mode = mbmi->mode;
8750
8751 (void)mode_mv;
8752 (void)mi_row;
8753 (void)mi_col;
8754 (void)args;
8755 (void)refs;
8756 (void)rate_mv;
8757 (void)is_comp_pred;
8758 (void)this_mode;
Angie Chiangcf85d5c2017-08-20 12:56:19 -07008759#if !CONFIG_WARPED_MOTION && CONFIG_MOTION_VAR
Cheng Chen811bba72017-08-21 17:39:31 -07008760 (void)single_newmv;
8761#endif
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008762
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008763#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
8764 MOTION_MODE motion_mode, last_motion_mode_allowed;
8765 int rate2_nocoeff = 0, best_xskip, best_disable_skip = 0;
8766 RD_STATS best_rd_stats, best_rd_stats_y, best_rd_stats_uv;
8767 MB_MODE_INFO base_mbmi, best_mbmi;
8768#if CONFIG_VAR_TX
8769 uint8_t best_blk_skip[MAX_MB_PLANE][MAX_MIB_SIZE * MAX_MIB_SIZE * 4];
8770#endif // CONFIG_VAR_TX
8771#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
8772
8773#if CONFIG_WARPED_MOTION
Yunqing Wang1bc82862017-06-28 15:49:48 -07008774#if WARPED_MOTION_SORT_SAMPLES
8775 int pts0[SAMPLES_ARRAY_SIZE], pts_inref0[SAMPLES_ARRAY_SIZE];
8776 int pts_mv0[SAMPLES_ARRAY_SIZE];
8777 int total_samples;
8778#else
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008779 int pts[SAMPLES_ARRAY_SIZE], pts_inref[SAMPLES_ARRAY_SIZE];
Yunqing Wang1bc82862017-06-28 15:49:48 -07008780#endif // WARPED_MOTION_SORT_SAMPLES
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008781#endif // CONFIG_WARPED_MOTION
8782
8783#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
8784 av1_invalid_rd_stats(&best_rd_stats);
8785#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
8786
8787 if (cm->interp_filter == SWITCHABLE) rd_stats->rate += rs;
8788#if CONFIG_WARPED_MOTION
8789 aom_clear_system_state();
Yunqing Wang1bc82862017-06-28 15:49:48 -07008790#if WARPED_MOTION_SORT_SAMPLES
8791 mbmi->num_proj_ref[0] =
8792 findSamples(cm, xd, mi_row, mi_col, pts0, pts_inref0, pts_mv0);
8793 total_samples = mbmi->num_proj_ref[0];
8794#else
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008795 mbmi->num_proj_ref[0] = findSamples(cm, xd, mi_row, mi_col, pts, pts_inref);
Yunqing Wang1bc82862017-06-28 15:49:48 -07008796#endif // WARPED_MOTION_SORT_SAMPLES
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008797 best_bmc_mbmi->num_proj_ref[0] = mbmi->num_proj_ref[0];
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008798#endif // CONFIG_WARPED_MOTION
8799#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
8800 rate2_nocoeff = rd_stats->rate;
8801 last_motion_mode_allowed = motion_mode_allowed(
Sarah Parker0eea89f2017-07-11 11:56:36 -07008802#if CONFIG_GLOBAL_MOTION
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008803 0, xd->global_motion,
Sarah Parker0eea89f2017-07-11 11:56:36 -07008804#endif // CONFIG_GLOBAL_MOTION
Yue Chen52c51732017-07-11 15:08:30 -07008805#if CONFIG_WARPED_MOTION
8806 xd,
8807#endif
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008808 mi);
8809 base_mbmi = *mbmi;
8810#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
8811
8812#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
8813 int64_t best_rd = INT64_MAX;
8814 for (motion_mode = SIMPLE_TRANSLATION;
8815 motion_mode <= last_motion_mode_allowed; motion_mode++) {
8816 int64_t tmp_rd = INT64_MAX;
8817 int tmp_rate;
8818 int64_t tmp_dist;
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008819 int tmp_rate2 =
8820 motion_mode != SIMPLE_TRANSLATION ? rate2_bmc_nocoeff : rate2_nocoeff;
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008821
Wei-Ting Lin20885282017-08-28 17:18:18 -07008822#if CONFIG_NCOBMC_ADAPT_WEIGHT
8823 // We cannot estimate the rd cost for the motion mode NCOBMC_ADAPT_WEIGHT
8824 // right now since it requires mvs from all neighboring blocks. We will
8825 // check if this mode is beneficial after all the mv's in the current
8826 // superblock are selected.
8827 if (motion_mode == NCOBMC_ADAPT_WEIGHT) continue;
8828#endif
8829
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008830 *mbmi = base_mbmi;
8831 mbmi->motion_mode = motion_mode;
8832#if CONFIG_MOTION_VAR
8833 if (mbmi->motion_mode == OBMC_CAUSAL) {
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008834 *mbmi = *best_bmc_mbmi;
8835 mbmi->motion_mode = OBMC_CAUSAL;
Zoe Liu85b66462017-04-20 14:28:19 -07008836 if (!is_comp_pred &&
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008837#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07008838 !is_inter_singleref_comp_mode(this_mode) &&
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008839#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07008840 have_newmv_in_inter_mode(this_mode)) {
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008841 int tmp_rate_mv = 0;
8842
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02008843 single_motion_search(cpi, x, bsize, mi_row, mi_col, 0, &tmp_rate_mv);
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008844 mbmi->mv[0].as_int = x->best_mv.as_int;
8845 if (discount_newmv_test(cpi, this_mode, mbmi->mv[0], mode_mv,
8846 refs[0])) {
8847 tmp_rate_mv = AOMMAX((tmp_rate_mv / NEW_MV_DISCOUNT_FACTOR), 1);
8848 }
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008849 tmp_rate2 = rate2_bmc_nocoeff - rate_mv_bmc + tmp_rate_mv;
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008850#if CONFIG_DUAL_FILTER
Rupert Swarbrick27e90292017-09-28 17:46:50 +01008851 mbmi->interp_filters =
8852 condition_interp_filters_on_mv(mbmi->interp_filters, xd);
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008853#endif // CONFIG_DUAL_FILTER
Jingning Hanc44009c2017-05-06 11:36:49 -07008854 av1_build_inter_predictors_sb(cm, xd, mi_row, mi_col, orig_dst, bsize);
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008855 } else {
Jingning Hanc44009c2017-05-06 11:36:49 -07008856 av1_build_inter_predictors_sb(cm, xd, mi_row, mi_col, orig_dst, bsize);
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008857 }
8858 av1_build_obmc_inter_prediction(
8859 cm, xd, mi_row, mi_col, args->above_pred_buf, args->above_pred_stride,
8860 args->left_pred_buf, args->left_pred_stride);
8861 model_rd_for_sb(cpi, bsize, x, xd, 0, MAX_MB_PLANE - 1, &tmp_rate,
8862 &tmp_dist, skip_txfm_sb, skip_sse_sb);
8863 }
8864#endif // CONFIG_MOTION_VAR
8865
8866#if CONFIG_WARPED_MOTION
8867 if (mbmi->motion_mode == WARPED_CAUSAL) {
Yunqing Wang1bc82862017-06-28 15:49:48 -07008868#if WARPED_MOTION_SORT_SAMPLES
8869 int pts[SAMPLES_ARRAY_SIZE], pts_inref[SAMPLES_ARRAY_SIZE];
8870#endif // WARPED_MOTION_SORT_SAMPLES
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008871 *mbmi = *best_bmc_mbmi;
8872 mbmi->motion_mode = WARPED_CAUSAL;
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008873 mbmi->wm_params[0].wmtype = DEFAULT_WMTYPE;
Rupert Swarbrick27e90292017-09-28 17:46:50 +01008874 mbmi->interp_filters = av1_broadcast_interp_filter(
8875 av1_unswitchable_filter(cm->interp_filter));
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008876
Yunqing Wang1bc82862017-06-28 15:49:48 -07008877#if WARPED_MOTION_SORT_SAMPLES
8878 memcpy(pts, pts0, total_samples * 2 * sizeof(*pts0));
8879 memcpy(pts_inref, pts_inref0, total_samples * 2 * sizeof(*pts_inref0));
8880 // Rank the samples by motion vector difference
8881 if (mbmi->num_proj_ref[0] > 1) {
8882 mbmi->num_proj_ref[0] = sortSamples(pts_mv0, &mbmi->mv[0].as_mv, pts,
8883 pts_inref, mbmi->num_proj_ref[0]);
Yunqing Wang1bc82862017-06-28 15:49:48 -07008884 best_bmc_mbmi->num_proj_ref[0] = mbmi->num_proj_ref[0];
Yunqing Wang1bc82862017-06-28 15:49:48 -07008885 }
8886#endif // WARPED_MOTION_SORT_SAMPLES
8887
Yunqing Wang68f3ccd2017-05-23 14:43:54 -07008888 if (!find_projection(mbmi->num_proj_ref[0], pts, pts_inref, bsize,
8889 mbmi->mv[0].as_mv.row, mbmi->mv[0].as_mv.col,
8890 &mbmi->wm_params[0], mi_row, mi_col)) {
8891 // Refine MV for NEWMV mode
8892 if (!is_comp_pred && have_newmv_in_inter_mode(this_mode)) {
8893 int tmp_rate_mv = 0;
8894 const int_mv mv0 = mbmi->mv[0];
8895 WarpedMotionParams wm_params0 = mbmi->wm_params[0];
Yunqing Wang1bc82862017-06-28 15:49:48 -07008896#if WARPED_MOTION_SORT_SAMPLES
8897 int num_proj_ref0 = mbmi->num_proj_ref[0];
Yunqing Wang68f3ccd2017-05-23 14:43:54 -07008898
8899 // Refine MV in a small range.
Yunqing Wang1bc82862017-06-28 15:49:48 -07008900 av1_refine_warped_mv(cpi, x, bsize, mi_row, mi_col, pts0, pts_inref0,
8901 pts_mv0, total_samples);
8902#else
8903 // Refine MV in a small range.
Yunqing Wang68f3ccd2017-05-23 14:43:54 -07008904 av1_refine_warped_mv(cpi, x, bsize, mi_row, mi_col, pts, pts_inref);
Yunqing Wang1bc82862017-06-28 15:49:48 -07008905#endif // WARPED_MOTION_SORT_SAMPLES
Yunqing Wang68f3ccd2017-05-23 14:43:54 -07008906
8907 // Keep the refined MV and WM parameters.
8908 if (mv0.as_int != mbmi->mv[0].as_int) {
8909 const int ref = refs[0];
8910 const MV ref_mv = x->mbmi_ext->ref_mvs[ref][0].as_mv;
8911
8912 tmp_rate_mv =
8913 av1_mv_bit_cost(&mbmi->mv[0].as_mv, &ref_mv, x->nmvjointcost,
8914 x->mvcost, MV_COST_WEIGHT);
8915
8916 if (cpi->sf.adaptive_motion_search)
8917 x->pred_mv[ref] = mbmi->mv[0].as_mv;
8918
8919 single_newmv[ref] = mbmi->mv[0];
8920
8921 if (discount_newmv_test(cpi, this_mode, mbmi->mv[0], mode_mv,
8922 refs[0])) {
8923 tmp_rate_mv = AOMMAX((tmp_rate_mv / NEW_MV_DISCOUNT_FACTOR), 1);
8924 }
Yunqing Wang1bc82862017-06-28 15:49:48 -07008925#if WARPED_MOTION_SORT_SAMPLES
8926 best_bmc_mbmi->num_proj_ref[0] = mbmi->num_proj_ref[0];
8927#endif // WARPED_MOTION_SORT_SAMPLES
Yunqing Wang68f3ccd2017-05-23 14:43:54 -07008928 tmp_rate2 = rate2_bmc_nocoeff - rate_mv_bmc + tmp_rate_mv;
Yunqing Wang68f3ccd2017-05-23 14:43:54 -07008929#if CONFIG_DUAL_FILTER
Rupert Swarbrick27e90292017-09-28 17:46:50 +01008930 mbmi->interp_filters =
8931 condition_interp_filters_on_mv(mbmi->interp_filters, xd);
Yunqing Wang68f3ccd2017-05-23 14:43:54 -07008932#endif // CONFIG_DUAL_FILTER
8933 } else {
8934 // Restore the old MV and WM parameters.
8935 mbmi->mv[0] = mv0;
8936 mbmi->wm_params[0] = wm_params0;
Yunqing Wang1bc82862017-06-28 15:49:48 -07008937#if WARPED_MOTION_SORT_SAMPLES
8938 mbmi->num_proj_ref[0] = num_proj_ref0;
8939#endif // WARPED_MOTION_SORT_SAMPLES
Yunqing Wang68f3ccd2017-05-23 14:43:54 -07008940 }
8941 }
8942
Jingning Hanc44009c2017-05-06 11:36:49 -07008943 av1_build_inter_predictors_sb(cm, xd, mi_row, mi_col, NULL, bsize);
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008944 model_rd_for_sb(cpi, bsize, x, xd, 0, MAX_MB_PLANE - 1, &tmp_rate,
8945 &tmp_dist, skip_txfm_sb, skip_sse_sb);
8946 } else {
8947 continue;
8948 }
8949 }
8950#endif // CONFIG_WARPED_MOTION
8951 x->skip = 0;
8952
8953 rd_stats->dist = 0;
8954 rd_stats->sse = 0;
8955 rd_stats->skip = 1;
8956 rd_stats->rate = tmp_rate2;
8957 if (last_motion_mode_allowed > SIMPLE_TRANSLATION) {
8958#if CONFIG_WARPED_MOTION && CONFIG_MOTION_VAR
8959 if (last_motion_mode_allowed == WARPED_CAUSAL)
8960#endif // CONFIG_WARPED_MOTION && CONFIG_MOTION_VAR
Yue Chenbdc8dab2017-07-26 12:05:47 -07008961 rd_stats->rate += x->motion_mode_cost[bsize][mbmi->motion_mode];
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008962#if CONFIG_WARPED_MOTION && CONFIG_MOTION_VAR
8963 else
Yue Chenb23d00a2017-07-28 17:01:21 -07008964 rd_stats->rate += x->motion_mode_cost1[bsize][mbmi->motion_mode];
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08008965#endif // CONFIG_WARPED_MOTION && CONFIG_MOTION_VAR
8966 }
8967#if CONFIG_WARPED_MOTION
8968 if (mbmi->motion_mode == WARPED_CAUSAL) {
8969 rd_stats->rate -= rs;
8970 }
8971#endif // CONFIG_WARPED_MOTION
8972#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
8973 if (!*skip_txfm_sb) {
8974 int64_t rdcosty = INT64_MAX;
8975 int is_cost_valid_uv = 0;
8976
8977 // cost and distortion
8978 av1_subtract_plane(x, bsize, 0);
8979#if CONFIG_VAR_TX
8980 if (cm->tx_mode == TX_MODE_SELECT && !xd->lossless[mbmi->segment_id]) {
8981 select_tx_type_yrd(cpi, x, rd_stats_y, bsize, ref_best_rd);
8982 } else {
8983 int idx, idy;
8984 super_block_yrd(cpi, x, rd_stats_y, bsize, ref_best_rd);
8985 for (idy = 0; idy < xd->n8_h; ++idy)
8986 for (idx = 0; idx < xd->n8_w; ++idx)
8987 mbmi->inter_tx_size[idy][idx] = mbmi->tx_size;
8988 memset(x->blk_skip[0], rd_stats_y->skip,
8989 sizeof(uint8_t) * xd->n8_h * xd->n8_w * 4);
8990 }
8991#else
8992 /* clang-format off */
8993 super_block_yrd(cpi, x, rd_stats_y, bsize, ref_best_rd);
8994/* clang-format on */
8995#endif // CONFIG_VAR_TX
8996
8997 if (rd_stats_y->rate == INT_MAX) {
8998 av1_invalid_rd_stats(rd_stats);
8999#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
9000 if (mbmi->motion_mode != SIMPLE_TRANSLATION) {
9001 continue;
9002 } else {
9003#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
9004 restore_dst_buf(xd, *orig_dst);
9005 return INT64_MAX;
9006#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
9007 }
9008#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
9009 }
9010
9011 av1_merge_rd_stats(rd_stats, rd_stats_y);
9012
Urvang Joshi70006e42017-06-14 16:08:55 -07009013 rdcosty = RDCOST(x->rdmult, rd_stats->rate, rd_stats->dist);
9014 rdcosty = AOMMIN(rdcosty, RDCOST(x->rdmult, 0, rd_stats->sse));
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08009015/* clang-format off */
9016#if CONFIG_VAR_TX
9017 is_cost_valid_uv =
9018 inter_block_uvrd(cpi, x, rd_stats_uv, bsize, ref_best_rd - rdcosty);
9019#else
9020 is_cost_valid_uv =
9021 super_block_uvrd(cpi, x, rd_stats_uv, bsize, ref_best_rd - rdcosty);
9022#endif // CONFIG_VAR_TX
9023 if (!is_cost_valid_uv) {
9024#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
9025 continue;
9026#else
9027 restore_dst_buf(xd, *orig_dst);
9028 return INT64_MAX;
9029#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
9030 }
9031 /* clang-format on */
9032 av1_merge_rd_stats(rd_stats, rd_stats_uv);
9033#if CONFIG_RD_DEBUG
9034 // record transform block coefficient cost
9035 // TODO(angiebird): So far rd_debug tool only detects discrepancy of
9036 // coefficient cost. Therefore, it is fine to copy rd_stats into mbmi
9037 // here because we already collect the coefficient cost. Move this part to
9038 // other place when we need to compare non-coefficient cost.
9039 mbmi->rd_stats = *rd_stats;
9040#endif // CONFIG_RD_DEBUG
9041#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
9042 if (rd_stats->skip) {
9043 rd_stats->rate -= rd_stats_uv->rate + rd_stats_y->rate;
9044 rd_stats_y->rate = 0;
9045 rd_stats_uv->rate = 0;
9046 rd_stats->rate += av1_cost_bit(av1_get_skip_prob(cm, xd), 1);
9047 mbmi->skip = 0;
9048 // here mbmi->skip temporarily plays a role as what this_skip2 does
9049 } else if (!xd->lossless[mbmi->segment_id] &&
Urvang Joshi70006e42017-06-14 16:08:55 -07009050 (RDCOST(x->rdmult,
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08009051 rd_stats_y->rate + rd_stats_uv->rate +
9052 av1_cost_bit(av1_get_skip_prob(cm, xd), 0),
9053 rd_stats->dist) >=
Urvang Joshi70006e42017-06-14 16:08:55 -07009054 RDCOST(x->rdmult, av1_cost_bit(av1_get_skip_prob(cm, xd), 1),
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08009055 rd_stats->sse))) {
9056 rd_stats->rate -= rd_stats_uv->rate + rd_stats_y->rate;
9057 rd_stats->rate += av1_cost_bit(av1_get_skip_prob(cm, xd), 1);
9058 rd_stats->dist = rd_stats->sse;
9059 rd_stats_y->rate = 0;
9060 rd_stats_uv->rate = 0;
9061 mbmi->skip = 1;
9062 } else {
9063 rd_stats->rate += av1_cost_bit(av1_get_skip_prob(cm, xd), 0);
9064 mbmi->skip = 0;
9065 }
9066 *disable_skip = 0;
9067#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
9068 } else {
9069 x->skip = 1;
9070 *disable_skip = 1;
9071 mbmi->tx_size = tx_size_from_tx_mode(bsize, cm->tx_mode, 1);
9072
9073// The cost of skip bit needs to be added.
9074#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
9075 mbmi->skip = 0;
9076#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
9077 rd_stats->rate += av1_cost_bit(av1_get_skip_prob(cm, xd), 1);
9078
9079 rd_stats->dist = *skip_sse_sb;
9080 rd_stats->sse = *skip_sse_sb;
9081 rd_stats_y->rate = 0;
9082 rd_stats_uv->rate = 0;
9083 rd_stats->skip = 1;
9084 }
9085
9086#if CONFIG_GLOBAL_MOTION
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02009087 if (this_mode == ZEROMV || this_mode == ZERO_ZEROMV) {
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08009088 if (is_nontrans_global_motion(xd)) {
9089 rd_stats->rate -= rs;
Rupert Swarbrick27e90292017-09-28 17:46:50 +01009090 mbmi->interp_filters = av1_broadcast_interp_filter(
9091 av1_unswitchable_filter(cm->interp_filter));
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08009092 }
9093 }
9094#endif // CONFIG_GLOBAL_MOTION
9095
9096#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
Urvang Joshi70006e42017-06-14 16:08:55 -07009097 tmp_rd = RDCOST(x->rdmult, rd_stats->rate, rd_stats->dist);
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08009098 if (mbmi->motion_mode == SIMPLE_TRANSLATION || (tmp_rd < best_rd)) {
9099 best_mbmi = *mbmi;
9100 best_rd = tmp_rd;
9101 best_rd_stats = *rd_stats;
9102 best_rd_stats_y = *rd_stats_y;
9103 best_rd_stats_uv = *rd_stats_uv;
9104#if CONFIG_VAR_TX
9105 for (int i = 0; i < MAX_MB_PLANE; ++i)
9106 memcpy(best_blk_skip[i], x->blk_skip[i],
9107 sizeof(uint8_t) * xd->n8_h * xd->n8_w * 4);
9108#endif // CONFIG_VAR_TX
9109 best_xskip = x->skip;
9110 best_disable_skip = *disable_skip;
9111 }
9112 }
9113
9114 if (best_rd == INT64_MAX) {
9115 av1_invalid_rd_stats(rd_stats);
9116 restore_dst_buf(xd, *orig_dst);
9117 return INT64_MAX;
9118 }
9119 *mbmi = best_mbmi;
9120 *rd_stats = best_rd_stats;
9121 *rd_stats_y = best_rd_stats_y;
9122 *rd_stats_uv = best_rd_stats_uv;
9123#if CONFIG_VAR_TX
9124 for (int i = 0; i < MAX_MB_PLANE; ++i)
9125 memcpy(x->blk_skip[i], best_blk_skip[i],
9126 sizeof(uint8_t) * xd->n8_h * xd->n8_w * 4);
9127#endif // CONFIG_VAR_TX
9128 x->skip = best_xskip;
9129 *disable_skip = best_disable_skip;
9130#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
9131
9132 restore_dst_buf(xd, *orig_dst);
9133 return 0;
9134}
9135
Zoe Liu85b66462017-04-20 14:28:19 -07009136static int64_t handle_inter_mode(const AV1_COMP *const cpi, MACROBLOCK *x,
9137 BLOCK_SIZE bsize, RD_STATS *rd_stats,
9138 RD_STATS *rd_stats_y, RD_STATS *rd_stats_uv,
9139 int *disable_skip,
9140 int_mv (*mode_mv)[TOTAL_REFS_PER_FRAME],
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02009141#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07009142 int_mv (*mode_comp_mv)[TOTAL_REFS_PER_FRAME],
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02009143#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07009144 int mi_row, int mi_col,
9145 HandleInterModeArgs *args,
9146 const int64_t ref_best_rd) {
Urvang Joshi52648442016-10-13 17:27:51 -07009147 const AV1_COMMON *cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009148 MACROBLOCKD *xd = &x->e_mbd;
Sarah Parker19234cc2017-03-10 16:43:25 -08009149 MODE_INFO *mi = xd->mi[0];
9150 MB_MODE_INFO *mbmi = &mi->mbmi;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009151 MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
9152 const int is_comp_pred = has_second_ref(mbmi);
9153 const int this_mode = mbmi->mode;
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02009154#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07009155 const int is_singleref_comp_mode = is_inter_singleref_comp_mode(this_mode);
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02009156#endif // CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -07009157 int_mv *frame_mv = mode_mv[this_mode];
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02009158#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07009159 // The comp mv for the compound mode in single ref
9160 int_mv *frame_comp_mv = mode_comp_mv[this_mode];
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02009161#endif // CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -07009162 int i;
9163 int refs[2] = { mbmi->ref_frame[0],
9164 (mbmi->ref_frame[1] < 0 ? 0 : mbmi->ref_frame[1]) };
9165 int_mv cur_mv[2];
9166 int rate_mv = 0;
Angie Chiang75c22092016-10-25 12:19:16 -07009167 int pred_exists = 1;
Angie Chiang64a2fb82017-07-06 10:15:16 -07009168#if CONFIG_WEDGE || CONFIG_COMPOUND_SEGMENT || CONFIG_INTERINTRA
Jingning Hanae5cfde2016-11-30 12:01:44 -08009169 const int bw = block_size_wide[bsize];
James Zern89a015b2017-08-08 12:39:00 -04009170#endif // CONFIG_WEDGE || CONFIG_COMPOUND_SEGMENT
Yaowu Xuc27fc142016-08-22 16:08:15 -07009171 int_mv single_newmv[TOTAL_REFS_PER_FRAME];
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00009172#if CONFIG_INTERINTRA
Yue Chenb23d00a2017-07-28 17:01:21 -07009173 const int *const interintra_mode_cost =
9174 x->interintra_mode_cost[size_group_lookup[bsize]];
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00009175#endif // CONFIG_INTERINTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07009176 const int is_comp_interintra_pred = (mbmi->ref_frame[1] == INTRA_FRAME);
Yaowu Xuf883b422016-08-30 14:01:10 -07009177 uint8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02009178#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07009179 DECLARE_ALIGNED(16, uint8_t, tmp_buf_[2 * MAX_MB_PLANE * MAX_SB_SQUARE]);
9180#else
9181 DECLARE_ALIGNED(16, uint8_t, tmp_buf_[MAX_MB_PLANE * MAX_SB_SQUARE]);
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02009182#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07009183 uint8_t *tmp_buf;
9184
Yue Chencb60b182016-10-13 15:18:22 -07009185#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -07009186 int rate2_bmc_nocoeff;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009187 MB_MODE_INFO best_bmc_mbmi;
Yue Chen69f18e12016-09-08 14:48:15 -07009188 int rate_mv_bmc;
Yue Chencb60b182016-10-13 15:18:22 -07009189#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
Angie Chiang75c22092016-10-25 12:19:16 -07009190 int64_t rd = INT64_MAX;
David Barkerac37fa32016-12-02 12:30:21 +00009191 BUFFER_SET orig_dst, tmp_dst;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009192 int rs = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009193
9194 int skip_txfm_sb = 0;
9195 int64_t skip_sse_sb = INT64_MAX;
Yaowu Xub0d0d002016-11-22 09:26:43 -08009196 int16_t mode_ctx;
Wei-Ting Lin85a8f702017-06-22 13:55:15 -07009197#if CONFIG_NCOBMC_ADAPT_WEIGHT && CONFIG_MOTION_VAR
9198 // dummy fillers
9199 mbmi->ncobmc_mode[0] = NO_OVERLAP;
9200 mbmi->ncobmc_mode[1] = NO_OVERLAP;
9201#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07009202
Yue Chen5e606542017-05-24 17:03:17 -07009203#if CONFIG_INTERINTRA
9204 int compmode_interintra_cost = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009205 mbmi->use_wedge_interintra = 0;
Yue Chen5e606542017-05-24 17:03:17 -07009206#endif
9207#if CONFIG_WEDGE || CONFIG_COMPOUND_SEGMENT
9208 int compmode_interinter_cost = 0;
Sarah Parker2d0e9b72017-05-04 01:34:16 +00009209 mbmi->interinter_compound_type = COMPOUND_AVERAGE;
Yue Chen5e606542017-05-24 17:03:17 -07009210#endif
Lester Lu432012f2017-08-17 14:39:29 -07009211#if CONFIG_LGT_FROM_PRED
9212 mbmi->use_lgt = 0;
9213#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07009214
Debargha Mukherjee9e2c7a62017-05-23 21:18:42 -07009215#if CONFIG_INTERINTRA
9216 if (!cm->allow_interintra_compound && is_comp_interintra_pred)
9217 return INT64_MAX;
9218#endif // CONFIG_INTERINTRA
9219
Yaowu Xuc27fc142016-08-22 16:08:15 -07009220 // is_comp_interintra_pred implies !is_comp_pred
9221 assert(!is_comp_interintra_pred || (!is_comp_pred));
9222 // is_comp_interintra_pred implies is_interintra_allowed(mbmi->sb_type)
9223 assert(!is_comp_interintra_pred || is_interintra_allowed(mbmi));
Yaowu Xuc27fc142016-08-22 16:08:15 -07009224
Zoe Liu85b66462017-04-20 14:28:19 -07009225#if CONFIG_COMPOUND_SINGLEREF
9226 if (is_comp_pred || is_singleref_comp_mode)
9227#else // !CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -07009228 if (is_comp_pred)
Zoe Liu85b66462017-04-20 14:28:19 -07009229#endif // CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -07009230 mode_ctx = mbmi_ext->compound_mode_context[refs[0]];
9231 else
Yaowu Xuf883b422016-08-30 14:01:10 -07009232 mode_ctx = av1_mode_context_analyzer(mbmi_ext->mode_context,
9233 mbmi->ref_frame, bsize, -1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009234
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02009235#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07009236 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
9237 tmp_buf = CONVERT_TO_BYTEPTR(tmp_buf_);
9238 else
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02009239#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07009240 tmp_buf = tmp_buf_;
David Barkerb8069f92016-11-18 14:49:56 +00009241 // Make sure that we didn't leave the plane destination buffers set
9242 // to tmp_buf at the end of the last iteration
9243 assert(xd->plane[0].dst.buf != tmp_buf);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009244
Yue Chen69f18e12016-09-08 14:48:15 -07009245#if CONFIG_WARPED_MOTION
9246 mbmi->num_proj_ref[0] = 0;
9247 mbmi->num_proj_ref[1] = 0;
9248#endif // CONFIG_WARPED_MOTION
9249
Yaowu Xuc27fc142016-08-22 16:08:15 -07009250 if (is_comp_pred) {
9251 if (frame_mv[refs[0]].as_int == INVALID_MV ||
9252 frame_mv[refs[1]].as_int == INVALID_MV)
9253 return INT64_MAX;
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02009254#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07009255 } else if (is_singleref_comp_mode) {
9256 if (frame_mv[refs[0]].as_int == INVALID_MV ||
9257 frame_comp_mv[refs[0]].as_int == INVALID_MV)
9258 return INT64_MAX;
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02009259#endif // CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -07009260 }
9261
Yue Chene9638cc2016-10-10 12:37:54 -07009262 mbmi->motion_mode = SIMPLE_TRANSLATION;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009263 if (have_newmv_in_inter_mode(this_mode)) {
Zoe Liu85b66462017-04-20 14:28:19 -07009264 const int64_t ret_val =
9265 handle_newmv(cpi, x, bsize, mode_mv,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02009266#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07009267 mode_comp_mv,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02009268#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07009269 mi_row, mi_col, &rate_mv, single_newmv, args);
Fergus Simpson45509632017-02-22 15:30:50 -08009270 if (ret_val != 0)
9271 return ret_val;
9272 else
9273 rd_stats->rate += rate_mv;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009274 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07009275 for (i = 0; i < is_comp_pred + 1; ++i) {
9276 cur_mv[i] = frame_mv[refs[i]];
Zoe Liued29ea22017-04-20 16:48:15 -07009277 // Clip "next_nearest" so that it does not extend to far out of image
9278 if (this_mode != NEWMV) clamp_mv2(&cur_mv[i].as_mv, xd);
Alex Converse0fa0f422017-04-24 12:51:14 -07009279 if (mv_check_bounds(&x->mv_limits, &cur_mv[i].as_mv)) return INT64_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009280 mbmi->mv[i].as_int = cur_mv[i].as_int;
9281 }
9282
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02009283#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07009284 if (!is_comp_pred && is_singleref_comp_mode) {
9285 cur_mv[1] = frame_comp_mv[refs[0]];
9286 // Clip "next_nearest" so that it does not extend to far out of image
9287 if (this_mode != NEWMV) clamp_mv2(&cur_mv[1].as_mv, xd);
9288 if (mv_check_bounds(&x->mv_limits, &cur_mv[1].as_mv)) return INT64_MAX;
9289 mbmi->mv[1].as_int = cur_mv[1].as_int;
9290 }
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02009291#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07009292
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02009293 if (this_mode == NEAREST_NEARESTMV) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07009294 if (mbmi_ext->ref_mv_count[ref_frame_type] > 0) {
9295 cur_mv[0] = mbmi_ext->ref_mv_stack[ref_frame_type][0].this_mv;
9296 cur_mv[1] = mbmi_ext->ref_mv_stack[ref_frame_type][0].comp_mv;
9297
9298 for (i = 0; i < 2; ++i) {
9299 clamp_mv2(&cur_mv[i].as_mv, xd);
Alex Converse0fa0f422017-04-24 12:51:14 -07009300 if (mv_check_bounds(&x->mv_limits, &cur_mv[i].as_mv)) return INT64_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009301 mbmi->mv[i].as_int = cur_mv[i].as_int;
9302 }
9303 }
9304 }
9305
Yaowu Xuc27fc142016-08-22 16:08:15 -07009306 if (mbmi_ext->ref_mv_count[ref_frame_type] > 0) {
Zoe Liu85b66462017-04-20 14:28:19 -07009307#if CONFIG_COMPOUND_SINGLEREF
9308 if (this_mode == NEAREST_NEWMV || // this_mode == SR_NEAREST_NEWMV ||
Yushin Cho67dda512017-07-25 14:58:22 -07009309 this_mode == SR_NEAREST_NEARMV)
Zoe Liu85b66462017-04-20 14:28:19 -07009310#else // !CONFIG_COMPOUND_SINGLEREF
Yushin Cho67dda512017-07-25 14:58:22 -07009311 if (this_mode == NEAREST_NEWMV)
Zoe Liu85b66462017-04-20 14:28:19 -07009312#endif // CONFIG_COMPOUND_SINGLEREF
Yushin Cho67dda512017-07-25 14:58:22 -07009313 {
Yaowu Xuc27fc142016-08-22 16:08:15 -07009314 cur_mv[0] = mbmi_ext->ref_mv_stack[ref_frame_type][0].this_mv;
9315
RogerZhou3b635242017-09-19 10:06:46 -07009316#if CONFIG_AMVR
9317 lower_mv_precision(&cur_mv[0].as_mv, cm->allow_high_precision_mv,
9318 cm->cur_frame_mv_precision_level);
9319#else
Yaowu Xuc27fc142016-08-22 16:08:15 -07009320 lower_mv_precision(&cur_mv[0].as_mv, cm->allow_high_precision_mv);
RogerZhou3b635242017-09-19 10:06:46 -07009321#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07009322 clamp_mv2(&cur_mv[0].as_mv, xd);
Alex Converse0fa0f422017-04-24 12:51:14 -07009323 if (mv_check_bounds(&x->mv_limits, &cur_mv[0].as_mv)) return INT64_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009324 mbmi->mv[0].as_int = cur_mv[0].as_int;
9325 }
9326
Debargha Mukherjeebb6e1342017-04-17 16:05:04 -07009327 if (this_mode == NEW_NEARESTMV) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07009328 cur_mv[1] = mbmi_ext->ref_mv_stack[ref_frame_type][0].comp_mv;
9329
RogerZhou3b635242017-09-19 10:06:46 -07009330#if CONFIG_AMVR
9331 lower_mv_precision(&cur_mv[1].as_mv, cm->allow_high_precision_mv,
9332 cm->cur_frame_mv_precision_level);
9333#else
Yaowu Xuc27fc142016-08-22 16:08:15 -07009334 lower_mv_precision(&cur_mv[1].as_mv, cm->allow_high_precision_mv);
RogerZhou3b635242017-09-19 10:06:46 -07009335#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07009336 clamp_mv2(&cur_mv[1].as_mv, xd);
Alex Converse0fa0f422017-04-24 12:51:14 -07009337 if (mv_check_bounds(&x->mv_limits, &cur_mv[1].as_mv)) return INT64_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009338 mbmi->mv[1].as_int = cur_mv[1].as_int;
9339 }
9340 }
9341
9342 if (mbmi_ext->ref_mv_count[ref_frame_type] > 1) {
David Barker404b2e82017-03-27 13:07:47 +01009343 int ref_mv_idx = mbmi->ref_mv_idx + 1;
Zoe Liu85b66462017-04-20 14:28:19 -07009344 if (this_mode == NEAR_NEWMV ||
9345#if CONFIG_COMPOUND_SINGLEREF
9346 this_mode == SR_NEAR_NEWMV ||
9347#endif // CONFIG_COMPOUND_SINGLEREF
9348 this_mode == NEAR_NEARMV) {
David Barker404b2e82017-03-27 13:07:47 +01009349 cur_mv[0] = mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_idx].this_mv;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009350
RogerZhou3b635242017-09-19 10:06:46 -07009351#if CONFIG_AMVR
9352 lower_mv_precision(&cur_mv[0].as_mv, cm->allow_high_precision_mv,
9353 cm->cur_frame_mv_precision_level);
9354#else
Yaowu Xuc27fc142016-08-22 16:08:15 -07009355 lower_mv_precision(&cur_mv[0].as_mv, cm->allow_high_precision_mv);
RogerZhou3b635242017-09-19 10:06:46 -07009356#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07009357 clamp_mv2(&cur_mv[0].as_mv, xd);
Alex Converse0fa0f422017-04-24 12:51:14 -07009358 if (mv_check_bounds(&x->mv_limits, &cur_mv[0].as_mv)) return INT64_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009359 mbmi->mv[0].as_int = cur_mv[0].as_int;
9360 }
9361
Zoe Liu85b66462017-04-20 14:28:19 -07009362 if (this_mode == NEW_NEARMV ||
9363#if CONFIG_COMPOUND_SINGLEREF
9364 this_mode == SR_NEAREST_NEARMV ||
9365#endif // CONFIG_COMPOUND_SINGLEREF
9366 this_mode == NEAR_NEARMV) {
9367#if CONFIG_COMPOUND_SINGLEREF
9368 if (this_mode == SR_NEAREST_NEARMV)
9369 cur_mv[1] = mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_idx].this_mv;
9370 else
9371#endif // CONFIG_COMPOUND_SINGLEREF
9372 cur_mv[1] = mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_idx].comp_mv;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009373
RogerZhou3b635242017-09-19 10:06:46 -07009374#if CONFIG_AMVR
9375 lower_mv_precision(&cur_mv[1].as_mv, cm->allow_high_precision_mv,
9376 cm->cur_frame_mv_precision_level);
9377#else
Yaowu Xuc27fc142016-08-22 16:08:15 -07009378 lower_mv_precision(&cur_mv[1].as_mv, cm->allow_high_precision_mv);
RogerZhou3b635242017-09-19 10:06:46 -07009379#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -07009380 clamp_mv2(&cur_mv[1].as_mv, xd);
Alex Converse0fa0f422017-04-24 12:51:14 -07009381 if (mv_check_bounds(&x->mv_limits, &cur_mv[1].as_mv)) return INT64_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009382 mbmi->mv[1].as_int = cur_mv[1].as_int;
9383 }
9384 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07009385
9386 // do first prediction into the destination buffer. Do the next
9387 // prediction into a temporary buffer. Then keep track of which one
9388 // of these currently holds the best predictor, and use the other
9389 // one for future predictions. In the end, copy from tmp_buf to
9390 // dst if necessary.
9391 for (i = 0; i < MAX_MB_PLANE; i++) {
David Barkerac37fa32016-12-02 12:30:21 +00009392 tmp_dst.plane[i] = tmp_buf + i * MAX_SB_SQUARE;
9393 tmp_dst.stride[i] = MAX_SB_SIZE;
Angie Chiang75c22092016-10-25 12:19:16 -07009394 }
9395 for (i = 0; i < MAX_MB_PLANE; i++) {
David Barkerac37fa32016-12-02 12:30:21 +00009396 orig_dst.plane[i] = xd->plane[i].dst.buf;
9397 orig_dst.stride[i] = xd->plane[i].dst.stride;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009398 }
9399
9400 // We don't include the cost of the second reference here, because there
9401 // are only three options: Last/Golden, ARF/Last or Golden/ARF, or in other
9402 // words if you present them in that order, the second one is always known
9403 // if the first is known.
9404 //
9405 // Under some circumstances we discount the cost of new mv mode to encourage
9406 // initiation of a motion field.
9407 if (discount_newmv_test(cpi, this_mode, frame_mv[refs[0]], mode_mv,
9408 refs[0])) {
Yue Chenb23d00a2017-07-28 17:01:21 -07009409 rd_stats->rate += AOMMIN(
9410 cost_mv_ref(x, this_mode, mode_ctx),
9411 cost_mv_ref(x, is_comp_pred ? NEAREST_NEARESTMV : NEARESTMV, mode_ctx));
Yaowu Xuc27fc142016-08-22 16:08:15 -07009412 } else {
Yue Chenb23d00a2017-07-28 17:01:21 -07009413 rd_stats->rate += cost_mv_ref(x, this_mode, mode_ctx);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009414 }
9415
Urvang Joshi70006e42017-06-14 16:08:55 -07009416 if (RDCOST(x->rdmult, rd_stats->rate, 0) > ref_best_rd &&
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02009417 mbmi->mode != NEARESTMV && mbmi->mode != NEAREST_NEARESTMV)
Yaowu Xuc27fc142016-08-22 16:08:15 -07009418 return INT64_MAX;
9419
Fergus Simpsonde18e2b2017-03-01 20:12:34 -08009420 int64_t ret_val = interpolation_filter_search(
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -08009421 x, cpi, bsize, mi_row, mi_col, &tmp_dst, &orig_dst, args->single_filter,
9422 &rd, &rs, &skip_txfm_sb, &skip_sse_sb);
Fergus Simpsonde18e2b2017-03-01 20:12:34 -08009423 if (ret_val != 0) return ret_val;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009424
Yue Chen69f18e12016-09-08 14:48:15 -07009425#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -07009426 best_bmc_mbmi = *mbmi;
Angie Chiang76159122016-11-09 12:13:22 -08009427 rate2_bmc_nocoeff = rd_stats->rate;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009428 if (cm->interp_filter == SWITCHABLE) rate2_bmc_nocoeff += rs;
Yue Chen69f18e12016-09-08 14:48:15 -07009429 rate_mv_bmc = rate_mv;
Yue Chen69f18e12016-09-08 14:48:15 -07009430#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -07009431
Yue Chen5e606542017-05-24 17:03:17 -07009432#if CONFIG_WEDGE || CONFIG_COMPOUND_SEGMENT
Zoe Liu85b66462017-04-20 14:28:19 -07009433#if CONFIG_COMPOUND_SINGLEREF
Yushin Cho67dda512017-07-25 14:58:22 -07009434 if (is_comp_pred || is_singleref_comp_mode)
Zoe Liu85b66462017-04-20 14:28:19 -07009435#else
Yushin Cho67dda512017-07-25 14:58:22 -07009436 if (is_comp_pred)
Zoe Liu85b66462017-04-20 14:28:19 -07009437#endif // CONFIG_COMPOUND_SINGLEREF
Yushin Cho67dda512017-07-25 14:58:22 -07009438 {
Urvang Joshi368fbc92016-10-17 16:31:34 -07009439 int rate_sum, rs2;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009440 int64_t dist_sum;
Sarah Parker6fdc8532016-11-16 17:47:13 -08009441 int64_t best_rd_compound = INT64_MAX, best_rd_cur = INT64_MAX;
9442 INTERINTER_COMPOUND_DATA best_compound_data;
9443 int_mv best_mv[2];
9444 int best_tmp_rate_mv = rate_mv;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009445 int tmp_skip_txfm_sb;
9446 int64_t tmp_skip_sse_sb;
Yaowu Xu5e8007f2017-06-28 12:39:18 -07009447 DECLARE_ALIGNED(16, uint8_t, pred0[2 * MAX_SB_SQUARE]);
9448 DECLARE_ALIGNED(16, uint8_t, pred1[2 * MAX_SB_SQUARE]);
Sarah Parker6fdc8532016-11-16 17:47:13 -08009449 uint8_t *preds0[1] = { pred0 };
9450 uint8_t *preds1[1] = { pred1 };
9451 int strides[1] = { bw };
Sarah Parker2e604882017-01-17 17:31:25 -08009452 int tmp_rate_mv;
Sarah Parker42d96102017-01-31 21:05:27 -08009453 int masked_compound_used = is_any_masked_compound_used(bsize);
Debargha Mukherjee9e2c7a62017-05-23 21:18:42 -07009454#if CONFIG_COMPOUND_SEGMENT || CONFIG_WEDGE
9455 masked_compound_used = masked_compound_used && cm->allow_masked_compound;
9456#endif // CONFIG_COMPOUND_SEGMENT || CONFIG_WEDGE
Sarah Parker6fdc8532016-11-16 17:47:13 -08009457 COMPOUND_TYPE cur_type;
Yue Chena4245512017-08-31 11:58:08 -07009458 int best_compmode_interinter_cost = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009459
Sarah Parker6fdc8532016-11-16 17:47:13 -08009460 best_mv[0].as_int = cur_mv[0].as_int;
9461 best_mv[1].as_int = cur_mv[1].as_int;
Sarah Parker2d0e9b72017-05-04 01:34:16 +00009462 memset(&best_compound_data, 0, sizeof(best_compound_data));
9463#if CONFIG_COMPOUND_SEGMENT
9464 uint8_t tmp_mask_buf[2 * MAX_SB_SQUARE];
9465 best_compound_data.seg_mask = tmp_mask_buf;
9466#endif // CONFIG_COMPOUND_SEGMENT
Yaowu Xuc27fc142016-08-22 16:08:15 -07009467
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02009468#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07009469 // TODO(zoeliu): To further check whether the following setups are needed.
9470 // Single ref compound mode: Prepare the 2nd ref frame predictor the same as
9471 // the 1st one.
9472 if (!is_comp_pred && is_singleref_comp_mode) {
9473 xd->block_refs[1] = xd->block_refs[0];
9474 for (i = 0; i < MAX_MB_PLANE; i++)
9475 xd->plane[i].pre[1] = xd->plane[i].pre[0];
9476 }
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02009477#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -07009478
Sarah Parker42d96102017-01-31 21:05:27 -08009479 if (masked_compound_used) {
Sarah Parker6fdc8532016-11-16 17:47:13 -08009480 // get inter predictors to use for masked compound modes
Yaowu Xuf883b422016-08-30 14:01:10 -07009481 av1_build_inter_predictors_for_planes_single_buf(
Yaowu Xuc27fc142016-08-22 16:08:15 -07009482 xd, bsize, 0, 0, mi_row, mi_col, 0, preds0, strides);
Yaowu Xuf883b422016-08-30 14:01:10 -07009483 av1_build_inter_predictors_for_planes_single_buf(
Yaowu Xuc27fc142016-08-22 16:08:15 -07009484 xd, bsize, 0, 0, mi_row, mi_col, 1, preds1, strides);
Sarah Parker6fdc8532016-11-16 17:47:13 -08009485 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07009486
Sarah Parker6fdc8532016-11-16 17:47:13 -08009487 for (cur_type = COMPOUND_AVERAGE; cur_type < COMPOUND_TYPES; cur_type++) {
Debargha Mukherjee9e2c7a62017-05-23 21:18:42 -07009488 if (cur_type != COMPOUND_AVERAGE && !masked_compound_used) break;
Yue Chene2518252017-06-05 12:36:46 -07009489 if (!is_interinter_compound_used(cur_type, bsize)) continue;
Sarah Parker2e604882017-01-17 17:31:25 -08009490 tmp_rate_mv = rate_mv;
Sarah Parker6fdc8532016-11-16 17:47:13 -08009491 best_rd_cur = INT64_MAX;
Sarah Parker2d0e9b72017-05-04 01:34:16 +00009492 mbmi->interinter_compound_type = cur_type;
Sarah Parker680b9b12017-08-16 18:55:34 -07009493 int masked_type_cost = 0;
9494 if (masked_compound_used) {
9495#if CONFIG_WEDGE && CONFIG_COMPOUND_SEGMENT
9496 if (!is_interinter_compound_used(COMPOUND_WEDGE, bsize))
9497 masked_type_cost += av1_cost_literal(1);
9498 else
9499#endif // CONFIG_WEDGE && CONFIG_COMPOUND_SEGMENT
9500 masked_type_cost +=
Yue Chena4245512017-08-31 11:58:08 -07009501 x->compound_type_cost[bsize][mbmi->interinter_compound_type];
Sarah Parker680b9b12017-08-16 18:55:34 -07009502 }
Sarah Parker6fdc8532016-11-16 17:47:13 -08009503 rs2 = av1_cost_literal(get_interinter_compound_type_bits(
Sarah Parker2d0e9b72017-05-04 01:34:16 +00009504 bsize, mbmi->interinter_compound_type)) +
Sarah Parker680b9b12017-08-16 18:55:34 -07009505 masked_type_cost;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009506
Sarah Parker6fdc8532016-11-16 17:47:13 -08009507 switch (cur_type) {
9508 case COMPOUND_AVERAGE:
Jingning Hanc44009c2017-05-06 11:36:49 -07009509 av1_build_inter_predictors_sby(cm, xd, mi_row, mi_col, &orig_dst,
9510 bsize);
Sarah Parker6fdc8532016-11-16 17:47:13 -08009511 av1_subtract_plane(x, bsize, 0);
9512 rd = estimate_yrd_for_sb(cpi, bsize, x, &rate_sum, &dist_sum,
9513 &tmp_skip_txfm_sb, &tmp_skip_sse_sb,
9514 INT64_MAX);
9515 if (rd != INT64_MAX)
Urvang Joshi70006e42017-06-14 16:08:55 -07009516 best_rd_cur = RDCOST(x->rdmult, rs2 + rate_mv + rate_sum, dist_sum);
Sarah Parker2e604882017-01-17 17:31:25 -08009517 best_rd_compound = best_rd_cur;
Sarah Parker6fdc8532016-11-16 17:47:13 -08009518 break;
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00009519#if CONFIG_WEDGE
Sarah Parker6fdc8532016-11-16 17:47:13 -08009520 case COMPOUND_WEDGE:
Sarah Parker6fdc8532016-11-16 17:47:13 -08009521 if (x->source_variance > cpi->sf.disable_wedge_search_var_thresh &&
9522 best_rd_compound / 3 < ref_best_rd) {
Sarah Parkerddcea392017-04-25 15:57:22 -07009523 best_rd_cur = build_and_cost_compound_type(
David Barkerac37fa32016-12-02 12:30:21 +00009524 cpi, x, cur_mv, bsize, this_mode, rs2, rate_mv, &orig_dst,
9525 &tmp_rate_mv, preds0, preds1, strides, mi_row, mi_col);
Sarah Parker6fdc8532016-11-16 17:47:13 -08009526 }
9527 break;
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00009528#endif // CONFIG_WEDGE
Sarah Parker2f6ce752016-12-08 15:26:46 -08009529#if CONFIG_COMPOUND_SEGMENT
Sarah Parker569edda2016-12-14 14:57:38 -08009530 case COMPOUND_SEG:
Sarah Parker569edda2016-12-14 14:57:38 -08009531 if (x->source_variance > cpi->sf.disable_wedge_search_var_thresh &&
9532 best_rd_compound / 3 < ref_best_rd) {
Sarah Parkerddcea392017-04-25 15:57:22 -07009533 best_rd_cur = build_and_cost_compound_type(
Sarah Parker569edda2016-12-14 14:57:38 -08009534 cpi, x, cur_mv, bsize, this_mode, rs2, rate_mv, &orig_dst,
9535 &tmp_rate_mv, preds0, preds1, strides, mi_row, mi_col);
Sarah Parker569edda2016-12-14 14:57:38 -08009536 }
9537 break;
Sarah Parker2f6ce752016-12-08 15:26:46 -08009538#endif // CONFIG_COMPOUND_SEGMENT
Sarah Parker6fdc8532016-11-16 17:47:13 -08009539 default: assert(0); return 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009540 }
Sarah Parker2e604882017-01-17 17:31:25 -08009541
9542 if (best_rd_cur < best_rd_compound) {
9543 best_rd_compound = best_rd_cur;
Sarah Parker2d0e9b72017-05-04 01:34:16 +00009544#if CONFIG_WEDGE
9545 best_compound_data.wedge_index = mbmi->wedge_index;
9546 best_compound_data.wedge_sign = mbmi->wedge_sign;
9547#endif // CONFIG_WEDGE
9548#if CONFIG_COMPOUND_SEGMENT
9549 best_compound_data.mask_type = mbmi->mask_type;
9550 memcpy(best_compound_data.seg_mask, xd->seg_mask,
9551 2 * MAX_SB_SQUARE * sizeof(uint8_t));
9552#endif // CONFIG_COMPOUND_SEGMENT
9553 best_compound_data.interinter_compound_type =
9554 mbmi->interinter_compound_type;
Yue Chena4245512017-08-31 11:58:08 -07009555 best_compmode_interinter_cost = rs2;
Sarah Parker2e604882017-01-17 17:31:25 -08009556 if (have_newmv_in_inter_mode(this_mode)) {
9557 if (use_masked_motion_search(cur_type)) {
9558 best_tmp_rate_mv = tmp_rate_mv;
9559 best_mv[0].as_int = mbmi->mv[0].as_int;
9560 best_mv[1].as_int = mbmi->mv[1].as_int;
9561 } else {
9562 best_mv[0].as_int = cur_mv[0].as_int;
9563 best_mv[1].as_int = cur_mv[1].as_int;
9564 }
9565 }
9566 }
9567 // reset to original mvs for next iteration
9568 mbmi->mv[0].as_int = cur_mv[0].as_int;
9569 mbmi->mv[1].as_int = cur_mv[1].as_int;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009570 }
Sarah Parker2d0e9b72017-05-04 01:34:16 +00009571#if CONFIG_WEDGE
9572 mbmi->wedge_index = best_compound_data.wedge_index;
9573 mbmi->wedge_sign = best_compound_data.wedge_sign;
9574#endif // CONFIG_WEDGE
9575#if CONFIG_COMPOUND_SEGMENT
9576 mbmi->mask_type = best_compound_data.mask_type;
9577 memcpy(xd->seg_mask, best_compound_data.seg_mask,
9578 2 * MAX_SB_SQUARE * sizeof(uint8_t));
9579#endif // CONFIG_COMPOUND_SEGMENT
9580 mbmi->interinter_compound_type =
9581 best_compound_data.interinter_compound_type;
Sarah Parker6fdc8532016-11-16 17:47:13 -08009582 if (have_newmv_in_inter_mode(this_mode)) {
9583 mbmi->mv[0].as_int = best_mv[0].as_int;
9584 mbmi->mv[1].as_int = best_mv[1].as_int;
9585 xd->mi[0]->bmi[0].as_mv[0].as_int = mbmi->mv[0].as_int;
9586 xd->mi[0]->bmi[0].as_mv[1].as_int = mbmi->mv[1].as_int;
Sarah Parker2d0e9b72017-05-04 01:34:16 +00009587 if (use_masked_motion_search(mbmi->interinter_compound_type)) {
Sarah Parker6fdc8532016-11-16 17:47:13 -08009588 rd_stats->rate += best_tmp_rate_mv - rate_mv;
9589 rate_mv = best_tmp_rate_mv;
9590 }
9591 }
9592
9593 if (ref_best_rd < INT64_MAX && best_rd_compound / 3 > ref_best_rd) {
David Barkerac37fa32016-12-02 12:30:21 +00009594 restore_dst_buf(xd, orig_dst);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009595 return INT64_MAX;
David Barkerb8069f92016-11-18 14:49:56 +00009596 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07009597
9598 pred_exists = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009599
Yue Chena4245512017-08-31 11:58:08 -07009600 compmode_interinter_cost = best_compmode_interinter_cost;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009601 }
Yue Chen5e606542017-05-24 17:03:17 -07009602#endif // CONFIG_WEDGE || CONFIG_COMPOUND_SEGMENT
Yaowu Xuc27fc142016-08-22 16:08:15 -07009603
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00009604#if CONFIG_INTERINTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07009605 if (is_comp_interintra_pred) {
9606 INTERINTRA_MODE best_interintra_mode = II_DC_PRED;
9607 int64_t best_interintra_rd = INT64_MAX;
9608 int rmode, rate_sum;
9609 int64_t dist_sum;
9610 int j;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009611 int tmp_rate_mv = 0;
9612 int tmp_skip_txfm_sb;
9613 int64_t tmp_skip_sse_sb;
9614 DECLARE_ALIGNED(16, uint8_t, intrapred_[2 * MAX_SB_SQUARE]);
9615 uint8_t *intrapred;
9616
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02009617#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07009618 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
9619 intrapred = CONVERT_TO_BYTEPTR(intrapred_);
9620 else
Sebastien Alaiwan71e87842017-04-12 16:03:28 +02009621#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -07009622 intrapred = intrapred_;
9623
Emil Keyder01770b32017-01-20 18:03:11 -05009624 mbmi->ref_frame[1] = NONE_FRAME;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009625 for (j = 0; j < MAX_MB_PLANE; j++) {
9626 xd->plane[j].dst.buf = tmp_buf + j * MAX_SB_SQUARE;
9627 xd->plane[j].dst.stride = bw;
9628 }
Debargha Mukherjeead8be032017-05-09 15:28:45 -07009629 av1_build_inter_predictors_sby(cm, xd, mi_row, mi_col, &orig_dst, bsize);
David Barkerac37fa32016-12-02 12:30:21 +00009630 restore_dst_buf(xd, orig_dst);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009631 mbmi->ref_frame[1] = INTRA_FRAME;
9632 mbmi->use_wedge_interintra = 0;
9633
9634 for (j = 0; j < INTERINTRA_MODES; ++j) {
9635 mbmi->interintra_mode = (INTERINTRA_MODE)j;
9636 rmode = interintra_mode_cost[mbmi->interintra_mode];
David Barker761b1ac2017-09-25 11:23:03 +01009637 av1_build_intra_predictors_for_interintra(cm, xd, bsize, 0, &orig_dst,
David Barkerac37fa32016-12-02 12:30:21 +00009638 intrapred, bw);
Yaowu Xuf883b422016-08-30 14:01:10 -07009639 av1_combine_interintra(xd, bsize, 0, tmp_buf, bw, intrapred, bw);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009640 model_rd_for_sb(cpi, bsize, x, xd, 0, 0, &rate_sum, &dist_sum,
9641 &tmp_skip_txfm_sb, &tmp_skip_sse_sb);
Urvang Joshi70006e42017-06-14 16:08:55 -07009642 rd = RDCOST(x->rdmult, tmp_rate_mv + rate_sum + rmode, dist_sum);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009643 if (rd < best_interintra_rd) {
9644 best_interintra_rd = rd;
9645 best_interintra_mode = mbmi->interintra_mode;
9646 }
9647 }
9648 mbmi->interintra_mode = best_interintra_mode;
9649 rmode = interintra_mode_cost[mbmi->interintra_mode];
David Barker761b1ac2017-09-25 11:23:03 +01009650 av1_build_intra_predictors_for_interintra(cm, xd, bsize, 0, &orig_dst,
David Barkerac37fa32016-12-02 12:30:21 +00009651 intrapred, bw);
Yaowu Xuf883b422016-08-30 14:01:10 -07009652 av1_combine_interintra(xd, bsize, 0, tmp_buf, bw, intrapred, bw);
9653 av1_subtract_plane(x, bsize, 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009654 rd = estimate_yrd_for_sb(cpi, bsize, x, &rate_sum, &dist_sum,
9655 &tmp_skip_txfm_sb, &tmp_skip_sse_sb, INT64_MAX);
9656 if (rd != INT64_MAX)
Urvang Joshi70006e42017-06-14 16:08:55 -07009657 rd = RDCOST(x->rdmult, rate_mv + rmode + rate_sum, dist_sum);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009658 best_interintra_rd = rd;
9659
9660 if (ref_best_rd < INT64_MAX && best_interintra_rd > 2 * ref_best_rd) {
David Barkerb8069f92016-11-18 14:49:56 +00009661 // Don't need to call restore_dst_buf here
Yaowu Xuc27fc142016-08-22 16:08:15 -07009662 return INT64_MAX;
9663 }
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00009664#if CONFIG_WEDGE
Yaowu Xuc27fc142016-08-22 16:08:15 -07009665 if (is_interintra_wedge_used(bsize)) {
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00009666 int64_t best_interintra_rd_nowedge = INT64_MAX;
9667 int64_t best_interintra_rd_wedge = INT64_MAX;
9668 int_mv tmp_mv;
9669 int rwedge = av1_cost_bit(cm->fc->wedge_interintra_prob[bsize], 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009670 if (rd != INT64_MAX)
Urvang Joshi70006e42017-06-14 16:08:55 -07009671 rd = RDCOST(x->rdmult, rmode + rate_mv + rwedge + rate_sum, dist_sum);
Yue Chenf03907a2017-05-31 12:04:04 -07009672 best_interintra_rd_nowedge = best_interintra_rd;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009673
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08009674 // Disable wedge search if source variance is small
Yaowu Xuc27fc142016-08-22 16:08:15 -07009675 if (x->source_variance > cpi->sf.disable_wedge_search_var_thresh) {
9676 mbmi->use_wedge_interintra = 1;
9677
Yaowu Xuf883b422016-08-30 14:01:10 -07009678 rwedge = av1_cost_literal(get_interintra_wedge_bits(bsize)) +
9679 av1_cost_bit(cm->fc->wedge_interintra_prob[bsize], 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009680
9681 best_interintra_rd_wedge =
9682 pick_interintra_wedge(cpi, x, bsize, intrapred_, tmp_buf_);
9683
9684 best_interintra_rd_wedge +=
Urvang Joshi70006e42017-06-14 16:08:55 -07009685 RDCOST(x->rdmult, rmode + rate_mv + rwedge, 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009686 // Refine motion vector.
9687 if (have_newmv_in_inter_mode(this_mode)) {
9688 // get negative of mask
Yaowu Xuf883b422016-08-30 14:01:10 -07009689 const uint8_t *mask = av1_get_contiguous_soft_mask(
Yaowu Xuc27fc142016-08-22 16:08:15 -07009690 mbmi->interintra_wedge_index, 1, bsize);
David Barkerf19f35f2017-05-22 16:33:22 +01009691 tmp_mv.as_int = x->mbmi_ext->ref_mvs[refs[0]][0].as_int;
9692 compound_single_motion_search(cpi, x, bsize, &tmp_mv.as_mv, mi_row,
9693 mi_col, intrapred, mask, bw,
Timothy B. Terriberry5d24b6f2017-06-15 13:39:35 -07009694 &tmp_rate_mv, 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009695 mbmi->mv[0].as_int = tmp_mv.as_int;
Debargha Mukherjeead8be032017-05-09 15:28:45 -07009696 av1_build_inter_predictors_sby(cm, xd, mi_row, mi_col, &orig_dst,
9697 bsize);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009698 model_rd_for_sb(cpi, bsize, x, xd, 0, 0, &rate_sum, &dist_sum,
9699 &tmp_skip_txfm_sb, &tmp_skip_sse_sb);
Urvang Joshi70006e42017-06-14 16:08:55 -07009700 rd = RDCOST(x->rdmult, rmode + tmp_rate_mv + rwedge + rate_sum,
9701 dist_sum);
Yue Chenf03907a2017-05-31 12:04:04 -07009702 if (rd >= best_interintra_rd_wedge) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07009703 tmp_mv.as_int = cur_mv[0].as_int;
9704 tmp_rate_mv = rate_mv;
9705 }
9706 } else {
9707 tmp_mv.as_int = cur_mv[0].as_int;
9708 tmp_rate_mv = rate_mv;
Yaowu Xuf883b422016-08-30 14:01:10 -07009709 av1_combine_interintra(xd, bsize, 0, tmp_buf, bw, intrapred, bw);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009710 }
9711 // Evaluate closer to true rd
Yaowu Xuf883b422016-08-30 14:01:10 -07009712 av1_subtract_plane(x, bsize, 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009713 rd =
9714 estimate_yrd_for_sb(cpi, bsize, x, &rate_sum, &dist_sum,
9715 &tmp_skip_txfm_sb, &tmp_skip_sse_sb, INT64_MAX);
9716 if (rd != INT64_MAX)
Urvang Joshi70006e42017-06-14 16:08:55 -07009717 rd = RDCOST(x->rdmult, rmode + tmp_rate_mv + rwedge + rate_sum,
9718 dist_sum);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009719 best_interintra_rd_wedge = rd;
9720 if (best_interintra_rd_wedge < best_interintra_rd_nowedge) {
9721 mbmi->use_wedge_interintra = 1;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009722 mbmi->mv[0].as_int = tmp_mv.as_int;
Angie Chiang76159122016-11-09 12:13:22 -08009723 rd_stats->rate += tmp_rate_mv - rate_mv;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009724 rate_mv = tmp_rate_mv;
9725 } else {
9726 mbmi->use_wedge_interintra = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009727 mbmi->mv[0].as_int = cur_mv[0].as_int;
9728 }
9729 } else {
9730 mbmi->use_wedge_interintra = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009731 }
9732 }
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00009733#endif // CONFIG_WEDGE
Yaowu Xuc27fc142016-08-22 16:08:15 -07009734
9735 pred_exists = 0;
Yue Chen5e606542017-05-24 17:03:17 -07009736 compmode_interintra_cost =
9737 av1_cost_bit(cm->fc->interintra_prob[size_group_lookup[bsize]], 1) +
Fergus Simpson073c6f32017-02-17 12:13:48 -08009738 interintra_mode_cost[mbmi->interintra_mode];
Yaowu Xuc27fc142016-08-22 16:08:15 -07009739 if (is_interintra_wedge_used(bsize)) {
Yue Chen5e606542017-05-24 17:03:17 -07009740 compmode_interintra_cost += av1_cost_bit(
Yaowu Xuc27fc142016-08-22 16:08:15 -07009741 cm->fc->wedge_interintra_prob[bsize], mbmi->use_wedge_interintra);
9742 if (mbmi->use_wedge_interintra) {
Yue Chen5e606542017-05-24 17:03:17 -07009743 compmode_interintra_cost +=
Yaowu Xuf883b422016-08-30 14:01:10 -07009744 av1_cost_literal(get_interintra_wedge_bits(bsize));
Yaowu Xuc27fc142016-08-22 16:08:15 -07009745 }
9746 }
9747 } else if (is_interintra_allowed(mbmi)) {
Yue Chen5e606542017-05-24 17:03:17 -07009748 compmode_interintra_cost =
Yaowu Xuf883b422016-08-30 14:01:10 -07009749 av1_cost_bit(cm->fc->interintra_prob[size_group_lookup[bsize]], 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009750 }
Debargha Mukherjeec5f735f2017-04-26 03:25:28 +00009751#endif // CONFIG_INTERINTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -07009752
Angie Chiang75c22092016-10-25 12:19:16 -07009753 if (pred_exists == 0) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07009754 int tmp_rate;
9755 int64_t tmp_dist;
Jingning Hanc44009c2017-05-06 11:36:49 -07009756 av1_build_inter_predictors_sb(cm, xd, mi_row, mi_col, &orig_dst, bsize);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009757 model_rd_for_sb(cpi, bsize, x, xd, 0, MAX_MB_PLANE - 1, &tmp_rate,
9758 &tmp_dist, &skip_txfm_sb, &skip_sse_sb);
Urvang Joshi70006e42017-06-14 16:08:55 -07009759 rd = RDCOST(x->rdmult, rs + tmp_rate, tmp_dist);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009760 }
9761
Fergus Simpson3424c2d2017-03-09 11:48:15 -08009762 if (!is_comp_pred)
Rupert Swarbrick27e90292017-09-28 17:46:50 +01009763 args->single_filter[this_mode][refs[0]] =
9764 av1_extract_interp_filter(mbmi->interp_filters, 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009765
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -08009766 if (args->modelled_rd != NULL) {
Yaowu Xuc27fc142016-08-22 16:08:15 -07009767 if (is_comp_pred) {
9768 const int mode0 = compound_ref0_mode(this_mode);
9769 const int mode1 = compound_ref1_mode(this_mode);
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -08009770 const int64_t mrd = AOMMIN(args->modelled_rd[mode0][refs[0]],
9771 args->modelled_rd[mode1][refs[1]]);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009772 if (rd / 4 * 3 > mrd && ref_best_rd < INT64_MAX) {
David Barkerac37fa32016-12-02 12:30:21 +00009773 restore_dst_buf(xd, orig_dst);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009774 return INT64_MAX;
9775 }
9776 } else if (!is_comp_interintra_pred) {
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -08009777 args->modelled_rd[this_mode][refs[0]] = rd;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009778 }
9779 }
Yaowu Xuc27fc142016-08-22 16:08:15 -07009780
9781 if (cpi->sf.use_rd_breakout && ref_best_rd < INT64_MAX) {
9782 // if current pred_error modeled rd is substantially more than the best
9783 // so far, do not bother doing full rd
9784 if (rd / 2 > ref_best_rd) {
David Barkerac37fa32016-12-02 12:30:21 +00009785 restore_dst_buf(xd, orig_dst);
Yaowu Xuc27fc142016-08-22 16:08:15 -07009786 return INT64_MAX;
9787 }
9788 }
9789
Yue Chen5e606542017-05-24 17:03:17 -07009790#if CONFIG_INTERINTRA
9791 rd_stats->rate += compmode_interintra_cost;
9792#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
9793 rate2_bmc_nocoeff += compmode_interintra_cost;
9794#endif
9795#endif
9796#if CONFIG_WEDGE || CONFIG_COMPOUND_SEGMENT
9797 rd_stats->rate += compmode_interinter_cost;
9798#endif
Yue Chen5e606542017-05-24 17:03:17 -07009799
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02009800 ret_val = motion_mode_rd(
9801 cpi, x, bsize, rd_stats, rd_stats_y, rd_stats_uv, disable_skip, mode_mv,
9802 mi_row, mi_col, args, ref_best_rd, refs, rate_mv,
Yue Chen69f18e12016-09-08 14:48:15 -07009803#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02009804 single_newmv, rate2_bmc_nocoeff, &best_bmc_mbmi, rate_mv_bmc,
Yue Chencb60b182016-10-13 15:18:22 -07009805#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02009806 rs, &skip_txfm_sb, &skip_sse_sb, &orig_dst);
Fergus Simpson10fb9fb2017-03-09 16:48:02 -08009807 if (ret_val != 0) return ret_val;
Angie Chiang76159122016-11-09 12:13:22 -08009808
Yaowu Xuc27fc142016-08-22 16:08:15 -07009809 return 0; // The rate-distortion cost will be re-calculated by caller.
9810}
9811
Alex Converse28744302017-04-13 14:46:22 -07009812#if CONFIG_INTRABC
Alex Converse28744302017-04-13 14:46:22 -07009813static int64_t rd_pick_intrabc_mode_sb(const AV1_COMP *cpi, MACROBLOCK *x,
Angie Chiang2a2a7dd2017-04-25 16:08:47 -07009814 RD_STATS *rd_cost, BLOCK_SIZE bsize,
Alex Converse28744302017-04-13 14:46:22 -07009815 int64_t best_rd) {
Alex Converse3d8adf32017-04-24 12:35:42 -07009816 const AV1_COMMON *const cm = &cpi->common;
RogerZhouca865462017-10-05 15:06:27 -07009817 if (!av1_allow_intrabc(bsize, cm)) return INT64_MAX;
Alex Converse3d8adf32017-04-24 12:35:42 -07009818
Alex Converse28744302017-04-13 14:46:22 -07009819 MACROBLOCKD *const xd = &x->e_mbd;
Alex Converse3d8adf32017-04-24 12:35:42 -07009820 const TileInfo *tile = &xd->tile;
9821 MODE_INFO *const mi = xd->mi[0];
9822 const int mi_row = -xd->mb_to_top_edge / (8 * MI_SIZE);
9823 const int mi_col = -xd->mb_to_left_edge / (8 * MI_SIZE);
9824 const int w = block_size_wide[bsize];
9825 const int h = block_size_high[bsize];
9826 const int sb_row = mi_row / MAX_MIB_SIZE;
Alex Converse861d7072017-05-15 14:19:53 -07009827 const int sb_col = mi_col / MAX_MIB_SIZE;
Alex Converse3d8adf32017-04-24 12:35:42 -07009828
Alex Converse44c2bad2017-05-11 09:36:10 -07009829 MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
9830 MV_REFERENCE_FRAME ref_frame = INTRA_FRAME;
9831 int_mv *const candidates = x->mbmi_ext->ref_mvs[ref_frame];
9832 av1_find_mv_refs(cm, xd, mi, ref_frame, &mbmi_ext->ref_mv_count[ref_frame],
9833 mbmi_ext->ref_mv_stack[ref_frame],
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +02009834 mbmi_ext->compound_mode_context, candidates, mi_row, mi_col,
9835 NULL, NULL, mbmi_ext->mode_context);
Alex Converse44c2bad2017-05-11 09:36:10 -07009836
9837 int_mv nearestmv, nearmv;
9838 av1_find_best_ref_mvs(0, candidates, &nearestmv, &nearmv);
9839
9840 int_mv dv_ref = nearestmv.as_int == 0 ? nearmv : nearestmv;
9841 if (dv_ref.as_int == 0) av1_find_ref_dv(&dv_ref, mi_row, mi_col);
9842 mbmi_ext->ref_mvs[INTRA_FRAME][0] = dv_ref;
Alex Converse3d8adf32017-04-24 12:35:42 -07009843
Alex Converse3d8adf32017-04-24 12:35:42 -07009844 struct buf_2d yv12_mb[MAX_MB_PLANE];
9845 av1_setup_pred_block(xd, yv12_mb, xd->cur_buf, mi_row, mi_col, NULL, NULL);
9846 for (int i = 0; i < MAX_MB_PLANE; ++i) {
9847 xd->plane[i].pre[0] = yv12_mb[i];
9848 }
9849
Alex Converse861d7072017-05-15 14:19:53 -07009850 enum IntrabcMotionDirection {
9851 IBC_MOTION_ABOVE,
9852 IBC_MOTION_LEFT,
9853 IBC_MOTION_DIRECTIONS
9854 };
Alex Converse3d8adf32017-04-24 12:35:42 -07009855
Alex Converse3d8adf32017-04-24 12:35:42 -07009856 MB_MODE_INFO *mbmi = &mi->mbmi;
9857 MB_MODE_INFO best_mbmi = *mbmi;
9858 RD_STATS best_rdcost = *rd_cost;
9859 int best_skip = x->skip;
Alex Converse861d7072017-05-15 14:19:53 -07009860
9861 for (enum IntrabcMotionDirection dir = IBC_MOTION_ABOVE;
9862 dir < IBC_MOTION_DIRECTIONS; ++dir) {
9863 const MvLimits tmp_mv_limits = x->mv_limits;
9864 switch (dir) {
9865 case IBC_MOTION_ABOVE:
9866 x->mv_limits.col_min = (tile->mi_col_start - mi_col) * MI_SIZE;
9867 x->mv_limits.col_max = (tile->mi_col_end - mi_col) * MI_SIZE - w;
9868 x->mv_limits.row_min = (tile->mi_row_start - mi_row) * MI_SIZE;
9869 x->mv_limits.row_max = (sb_row * MAX_MIB_SIZE - mi_row) * MI_SIZE - h;
9870 break;
9871 case IBC_MOTION_LEFT:
9872 x->mv_limits.col_min = (tile->mi_col_start - mi_col) * MI_SIZE;
9873 x->mv_limits.col_max = (sb_col * MAX_MIB_SIZE - mi_col) * MI_SIZE - w;
9874 // TODO(aconverse@google.com): Minimize the overlap between above and
9875 // left areas.
9876 x->mv_limits.row_min = (tile->mi_row_start - mi_row) * MI_SIZE;
9877 int bottom_coded_mi_edge =
9878 AOMMIN((sb_row + 1) * MAX_MIB_SIZE, tile->mi_row_end);
9879 x->mv_limits.row_max = (bottom_coded_mi_edge - mi_row) * MI_SIZE - h;
9880 break;
9881 default: assert(0);
9882 }
9883 assert(x->mv_limits.col_min >= tmp_mv_limits.col_min);
9884 assert(x->mv_limits.col_max <= tmp_mv_limits.col_max);
9885 assert(x->mv_limits.row_min >= tmp_mv_limits.row_min);
9886 assert(x->mv_limits.row_max <= tmp_mv_limits.row_max);
9887 av1_set_mv_search_range(&x->mv_limits, &dv_ref.as_mv);
9888
9889 if (x->mv_limits.col_max < x->mv_limits.col_min ||
9890 x->mv_limits.row_max < x->mv_limits.row_min) {
9891 x->mv_limits = tmp_mv_limits;
9892 continue;
9893 }
9894
9895 int step_param = cpi->mv_step_param;
9896 MV mvp_full = dv_ref.as_mv;
9897 mvp_full.col >>= 3;
9898 mvp_full.row >>= 3;
9899 int sadpb = x->sadperbit16;
9900 int cost_list[5];
RogerZhoucc5d35d2017-08-07 22:20:15 -07009901#if CONFIG_HASH_ME
RogerZhoud15e7c12017-09-26 08:49:28 -07009902 int bestsme = av1_full_pixel_search(
9903 cpi, x, bsize, &mvp_full, step_param, sadpb,
9904 cond_cost_list(cpi, cost_list), &dv_ref.as_mv, INT_MAX, 1,
9905 (MI_SIZE * mi_col), (MI_SIZE * mi_row), 1);
RogerZhoucc5d35d2017-08-07 22:20:15 -07009906#else
Alex Converse861d7072017-05-15 14:19:53 -07009907 int bestsme = av1_full_pixel_search(cpi, x, bsize, &mvp_full, step_param,
9908 sadpb, cond_cost_list(cpi, cost_list),
9909 &dv_ref.as_mv, INT_MAX, 1);
RogerZhoucc5d35d2017-08-07 22:20:15 -07009910#endif
Alex Converse861d7072017-05-15 14:19:53 -07009911
9912 x->mv_limits = tmp_mv_limits;
9913 if (bestsme == INT_MAX) continue;
9914 mvp_full = x->best_mv.as_mv;
9915 MV dv = {.row = mvp_full.row * 8, .col = mvp_full.col * 8 };
9916 if (mv_check_bounds(&x->mv_limits, &dv)) continue;
9917 if (!is_dv_valid(dv, tile, mi_row, mi_col, bsize)) continue;
9918
Alex Converse861d7072017-05-15 14:19:53 -07009919 memset(&mbmi->palette_mode_info, 0, sizeof(mbmi->palette_mode_info));
Alex Converse861d7072017-05-15 14:19:53 -07009920 mbmi->use_intrabc = 1;
9921 mbmi->mode = DC_PRED;
Luc Trudeaud6d9eee2017-07-12 12:36:50 -04009922 mbmi->uv_mode = UV_DC_PRED;
Alex Converse861d7072017-05-15 14:19:53 -07009923 mbmi->mv[0].as_mv = dv;
Rupert Swarbrick27e90292017-09-28 17:46:50 +01009924 mbmi->interp_filters = av1_broadcast_interp_filter(BILINEAR);
Alex Converse861d7072017-05-15 14:19:53 -07009925 mbmi->skip = 0;
9926 x->skip = 0;
9927 av1_build_inter_predictors_sb(cm, xd, mi_row, mi_col, NULL, bsize);
Alex Converse3d8adf32017-04-24 12:35:42 -07009928
Alex Conversed5d9b6c2017-05-23 15:23:45 -07009929 assert(x->mvcost == x->mv_cost_stack[0]);
9930 // TODO(aconverse@google.com): The full motion field defining discount
9931 // in MV_COST_WEIGHT is too large. Explore other values.
Alex Converse861d7072017-05-15 14:19:53 -07009932 int rate_mv = av1_mv_bit_cost(&dv, &dv_ref.as_mv, x->nmvjointcost,
Alex Conversed5d9b6c2017-05-23 15:23:45 -07009933 x->mvcost, MV_COST_WEIGHT_SUB);
Hui Su6c8584f2017-09-14 15:37:02 -07009934 const int rate_mode = x->intrabc_cost[1];
Alex Converse861d7072017-05-15 14:19:53 -07009935 RD_STATS rd_stats, rd_stats_uv;
9936 av1_subtract_plane(x, bsize, 0);
9937 super_block_yrd(cpi, x, &rd_stats, bsize, INT64_MAX);
9938 super_block_uvrd(cpi, x, &rd_stats_uv, bsize, INT64_MAX);
9939 av1_merge_rd_stats(&rd_stats, &rd_stats_uv);
Alex Converse3d8adf32017-04-24 12:35:42 -07009940#if CONFIG_RD_DEBUG
Alex Converse861d7072017-05-15 14:19:53 -07009941 mbmi->rd_stats = rd_stats;
Alex Converse3d8adf32017-04-24 12:35:42 -07009942#endif
9943
Alex Conversee16b2662017-05-24 14:00:00 -07009944#if CONFIG_VAR_TX
9945 // TODO(aconverse@google.com): Evaluate allowing VAR TX on intrabc blocks
9946 const int width = block_size_wide[bsize] >> tx_size_wide_log2[0];
9947 const int height = block_size_high[bsize] >> tx_size_high_log2[0];
9948 int idx, idy;
9949 for (idy = 0; idy < height; ++idy)
9950 for (idx = 0; idx < width; ++idx)
9951 mbmi->inter_tx_size[idy >> 1][idx >> 1] = mbmi->tx_size;
9952 mbmi->min_tx_size = get_min_tx_size(mbmi->tx_size);
9953#endif // CONFIG_VAR_TX
9954
Alex Converse861d7072017-05-15 14:19:53 -07009955 const aom_prob skip_prob = av1_get_skip_prob(cm, xd);
Alex Converse3d8adf32017-04-24 12:35:42 -07009956
Alex Converse861d7072017-05-15 14:19:53 -07009957 RD_STATS rdc_noskip;
9958 av1_init_rd_stats(&rdc_noskip);
9959 rdc_noskip.rate =
9960 rate_mode + rate_mv + rd_stats.rate + av1_cost_bit(skip_prob, 0);
9961 rdc_noskip.dist = rd_stats.dist;
Urvang Joshi70006e42017-06-14 16:08:55 -07009962 rdc_noskip.rdcost = RDCOST(x->rdmult, rdc_noskip.rate, rdc_noskip.dist);
Alex Converse861d7072017-05-15 14:19:53 -07009963 if (rdc_noskip.rdcost < best_rd) {
9964 best_rd = rdc_noskip.rdcost;
9965 best_mbmi = *mbmi;
9966 best_skip = x->skip;
9967 best_rdcost = rdc_noskip;
9968 }
Alex Converse3d8adf32017-04-24 12:35:42 -07009969
Alex Converse861d7072017-05-15 14:19:53 -07009970 x->skip = 1;
9971 mbmi->skip = 1;
9972 RD_STATS rdc_skip;
9973 av1_init_rd_stats(&rdc_skip);
9974 rdc_skip.rate = rate_mode + rate_mv + av1_cost_bit(skip_prob, 1);
9975 rdc_skip.dist = rd_stats.sse;
Urvang Joshi70006e42017-06-14 16:08:55 -07009976 rdc_skip.rdcost = RDCOST(x->rdmult, rdc_skip.rate, rdc_skip.dist);
Alex Converse861d7072017-05-15 14:19:53 -07009977 if (rdc_skip.rdcost < best_rd) {
9978 best_rd = rdc_skip.rdcost;
9979 best_mbmi = *mbmi;
9980 best_skip = x->skip;
9981 best_rdcost = rdc_skip;
9982 }
Alex Converse3d8adf32017-04-24 12:35:42 -07009983 }
9984 *mbmi = best_mbmi;
9985 *rd_cost = best_rdcost;
9986 x->skip = best_skip;
9987 return best_rd;
Alex Converse28744302017-04-13 14:46:22 -07009988}
9989#endif // CONFIG_INTRABC
9990
Urvang Joshi52648442016-10-13 17:27:51 -07009991void av1_rd_pick_intra_mode_sb(const AV1_COMP *cpi, MACROBLOCK *x,
Angie Chiang2a2a7dd2017-04-25 16:08:47 -07009992 RD_STATS *rd_cost, BLOCK_SIZE bsize,
Urvang Joshi52648442016-10-13 17:27:51 -07009993 PICK_MODE_CONTEXT *ctx, int64_t best_rd) {
9994 const AV1_COMMON *const cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009995 MACROBLOCKD *const xd = &x->e_mbd;
Luc Trudeau14fc5042017-06-16 12:40:29 -04009996 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Yaowu Xuc27fc142016-08-22 16:08:15 -07009997 struct macroblockd_plane *const pd = xd->plane;
9998 int rate_y = 0, rate_uv = 0, rate_y_tokenonly = 0, rate_uv_tokenonly = 0;
9999 int y_skip = 0, uv_skip = 0;
10000 int64_t dist_y = 0, dist_uv = 0;
10001 TX_SIZE max_uv_tx_size;
Jingning Han271bb2c2016-12-14 12:34:46 -080010002 const int unify_bsize = CONFIG_CB4X4;
10003
Yaowu Xuc27fc142016-08-22 16:08:15 -070010004 ctx->skip = 0;
Luc Trudeau14fc5042017-06-16 12:40:29 -040010005 mbmi->ref_frame[0] = INTRA_FRAME;
10006 mbmi->ref_frame[1] = NONE_FRAME;
Alex Converse28744302017-04-13 14:46:22 -070010007#if CONFIG_INTRABC
Luc Trudeau14fc5042017-06-16 12:40:29 -040010008 mbmi->use_intrabc = 0;
10009 mbmi->mv[0].as_int = 0;
Alex Converse28744302017-04-13 14:46:22 -070010010#endif // CONFIG_INTRABC
Lester Lu432012f2017-08-17 14:39:29 -070010011#if CONFIG_LGT_FROM_PRED
10012 mbmi->use_lgt = 0;
10013#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -070010014
Alex Conversed1b6fad2017-04-26 15:39:37 -070010015 const int64_t intra_yrd =
10016 (bsize >= BLOCK_8X8 || unify_bsize)
10017 ? rd_pick_intra_sby_mode(cpi, x, &rate_y, &rate_y_tokenonly, &dist_y,
10018 &y_skip, bsize, best_rd)
10019 : rd_pick_intra_sub_8x8_y_mode(cpi, x, &rate_y, &rate_y_tokenonly,
10020 &dist_y, &y_skip, best_rd);
10021
10022 if (intra_yrd < best_rd) {
Luc Trudeau14fc5042017-06-16 12:40:29 -040010023#if CONFIG_CFL
Luc Trudeau780d2492017-06-15 22:26:41 -040010024#if CONFIG_CB4X4
Luc Trudeaub05eeae2017-08-18 15:14:30 -040010025 // Only store reconstructed luma when there's chroma RDO. When there's no
10026 // chroma RDO, the reconstructed luma will be stored in encode_superblock().
10027 xd->cfl->store_y = !x->skip_chroma_rd;
Luc Trudeau780d2492017-06-15 22:26:41 -040010028#else
Luc Trudeaub05eeae2017-08-18 15:14:30 -040010029 xd->cfl->store_y = 1;
Luc Trudeau6e1cd782017-06-21 13:52:36 -040010030#endif // CONFIG_CB4X4
Luc Trudeaufcca37a2017-08-14 15:05:07 -040010031 if (xd->cfl->store_y) {
Luc Trudeaub05eeae2017-08-18 15:14:30 -040010032 // Perform one extra call to txfm_rd_in_plane(), with the values chosen
10033 // during luma RDO, so we can store reconstructed luma values
10034 RD_STATS this_rd_stats;
Luc Trudeau32306c22017-08-14 14:44:26 -040010035 txfm_rd_in_plane(x, cpi, &this_rd_stats, INT64_MAX, AOM_PLANE_Y,
10036 mbmi->sb_type, mbmi->tx_size,
10037 cpi->sf.use_fast_coef_costing);
Luc Trudeaufcca37a2017-08-14 15:05:07 -040010038 xd->cfl->store_y = 0;
Luc Trudeau32306c22017-08-14 14:44:26 -040010039 }
Luc Trudeau6e1cd782017-06-21 13:52:36 -040010040#endif // CONFIG_CFL
Luc Trudeau14fc5042017-06-16 12:40:29 -040010041 max_uv_tx_size = uv_txsize_lookup[bsize][mbmi->tx_size][pd[1].subsampling_x]
10042 [pd[1].subsampling_y];
10043 init_sbuv_mode(mbmi);
Jingning Han271bb2c2016-12-14 12:34:46 -080010044#if CONFIG_CB4X4
Alex Conversed1b6fad2017-04-26 15:39:37 -070010045 if (!x->skip_chroma_rd)
10046 rd_pick_intra_sbuv_mode(cpi, x, &rate_uv, &rate_uv_tokenonly, &dist_uv,
10047 &uv_skip, bsize, max_uv_tx_size);
Jingning Han271bb2c2016-12-14 12:34:46 -080010048#else
Alex Conversed1b6fad2017-04-26 15:39:37 -070010049 rd_pick_intra_sbuv_mode(cpi, x, &rate_uv, &rate_uv_tokenonly, &dist_uv,
10050 &uv_skip, AOMMAX(BLOCK_8X8, bsize), max_uv_tx_size);
Fergus Simpson4063a682017-02-28 16:52:22 -080010051#endif // CONFIG_CB4X4
Yaowu Xuc27fc142016-08-22 16:08:15 -070010052
Rupert Swarbrickc6cc1f52017-10-04 11:52:12 +010010053 if (y_skip && (uv_skip || x->skip_chroma_rd)) {
Alex Conversed1b6fad2017-04-26 15:39:37 -070010054 rd_cost->rate = rate_y + rate_uv - rate_y_tokenonly - rate_uv_tokenonly +
10055 av1_cost_bit(av1_get_skip_prob(cm, xd), 1);
10056 rd_cost->dist = dist_y + dist_uv;
10057 } else {
10058 rd_cost->rate =
10059 rate_y + rate_uv + av1_cost_bit(av1_get_skip_prob(cm, xd), 0);
10060 rd_cost->dist = dist_y + dist_uv;
10061 }
Urvang Joshi70006e42017-06-14 16:08:55 -070010062 rd_cost->rdcost = RDCOST(x->rdmult, rd_cost->rate, rd_cost->dist);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010063 } else {
Alex Conversed1b6fad2017-04-26 15:39:37 -070010064 rd_cost->rate = INT_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010065 }
10066
Alex Converse28744302017-04-13 14:46:22 -070010067#if CONFIG_INTRABC
Alex Conversed1b6fad2017-04-26 15:39:37 -070010068 if (rd_cost->rate != INT_MAX && rd_cost->rdcost < best_rd)
10069 best_rd = rd_cost->rdcost;
Alex Converse28744302017-04-13 14:46:22 -070010070 if (rd_pick_intrabc_mode_sb(cpi, x, rd_cost, bsize, best_rd) < best_rd) {
10071 ctx->skip = x->skip; // FIXME where is the proper place to set this?!
Alex Conversed1b6fad2017-04-26 15:39:37 -070010072 assert(rd_cost->rate != INT_MAX);
Urvang Joshi70006e42017-06-14 16:08:55 -070010073 rd_cost->rdcost = RDCOST(x->rdmult, rd_cost->rate, rd_cost->dist);
Alex Converse28744302017-04-13 14:46:22 -070010074 }
10075#endif
Alex Conversed1b6fad2017-04-26 15:39:37 -070010076 if (rd_cost->rate == INT_MAX) return;
Alex Converse28744302017-04-13 14:46:22 -070010077
Yaowu Xuc27fc142016-08-22 16:08:15 -070010078 ctx->mic = *xd->mi[0];
10079 ctx->mbmi_ext = *x->mbmi_ext;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010080}
10081
Yaowu Xuc27fc142016-08-22 16:08:15 -070010082// Do we have an internal image edge (e.g. formatting bars).
Urvang Joshi52648442016-10-13 17:27:51 -070010083int av1_internal_image_edge(const AV1_COMP *cpi) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070010084 return (cpi->oxcf.pass == 2) &&
10085 ((cpi->twopass.this_frame_stats.inactive_zone_rows > 0) ||
10086 (cpi->twopass.this_frame_stats.inactive_zone_cols > 0));
10087}
10088
10089// Checks to see if a super block is on a horizontal image edge.
10090// In most cases this is the "real" edge unless there are formatting
10091// bars embedded in the stream.
Urvang Joshi52648442016-10-13 17:27:51 -070010092int av1_active_h_edge(const AV1_COMP *cpi, int mi_row, int mi_step) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070010093 int top_edge = 0;
10094 int bottom_edge = cpi->common.mi_rows;
10095 int is_active_h_edge = 0;
10096
10097 // For two pass account for any formatting bars detected.
10098 if (cpi->oxcf.pass == 2) {
Urvang Joshi52648442016-10-13 17:27:51 -070010099 const TWO_PASS *const twopass = &cpi->twopass;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010100
10101 // The inactive region is specified in MBs not mi units.
10102 // The image edge is in the following MB row.
10103 top_edge += (int)(twopass->this_frame_stats.inactive_zone_rows * 2);
10104
10105 bottom_edge -= (int)(twopass->this_frame_stats.inactive_zone_rows * 2);
Yaowu Xuf883b422016-08-30 14:01:10 -070010106 bottom_edge = AOMMAX(top_edge, bottom_edge);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010107 }
10108
10109 if (((top_edge >= mi_row) && (top_edge < (mi_row + mi_step))) ||
10110 ((bottom_edge >= mi_row) && (bottom_edge < (mi_row + mi_step)))) {
10111 is_active_h_edge = 1;
10112 }
10113 return is_active_h_edge;
10114}
10115
10116// Checks to see if a super block is on a vertical image edge.
10117// In most cases this is the "real" edge unless there are formatting
10118// bars embedded in the stream.
Urvang Joshi52648442016-10-13 17:27:51 -070010119int av1_active_v_edge(const AV1_COMP *cpi, int mi_col, int mi_step) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070010120 int left_edge = 0;
10121 int right_edge = cpi->common.mi_cols;
10122 int is_active_v_edge = 0;
10123
10124 // For two pass account for any formatting bars detected.
10125 if (cpi->oxcf.pass == 2) {
Urvang Joshi52648442016-10-13 17:27:51 -070010126 const TWO_PASS *const twopass = &cpi->twopass;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010127
10128 // The inactive region is specified in MBs not mi units.
10129 // The image edge is in the following MB row.
10130 left_edge += (int)(twopass->this_frame_stats.inactive_zone_cols * 2);
10131
10132 right_edge -= (int)(twopass->this_frame_stats.inactive_zone_cols * 2);
Yaowu Xuf883b422016-08-30 14:01:10 -070010133 right_edge = AOMMAX(left_edge, right_edge);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010134 }
10135
10136 if (((left_edge >= mi_col) && (left_edge < (mi_col + mi_step))) ||
10137 ((right_edge >= mi_col) && (right_edge < (mi_col + mi_step)))) {
10138 is_active_v_edge = 1;
10139 }
10140 return is_active_v_edge;
10141}
10142
10143// Checks to see if a super block is at the edge of the active image.
10144// In most cases this is the "real" edge unless there are formatting
10145// bars embedded in the stream.
Urvang Joshi52648442016-10-13 17:27:51 -070010146int av1_active_edge_sb(const AV1_COMP *cpi, int mi_row, int mi_col) {
Yaowu Xuf883b422016-08-30 14:01:10 -070010147 return av1_active_h_edge(cpi, mi_row, cpi->common.mib_size) ||
10148 av1_active_v_edge(cpi, mi_col, cpi->common.mib_size);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010149}
10150
Urvang Joshi52648442016-10-13 17:27:51 -070010151static void restore_uv_color_map(const AV1_COMP *const cpi, MACROBLOCK *x) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070010152 MACROBLOCKD *const xd = &x->e_mbd;
10153 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
10154 PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
10155 const BLOCK_SIZE bsize = mbmi->sb_type;
Urvang Joshic9e71d42017-08-09 18:58:33 -070010156 assert(bsize >= BLOCK_8X8);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010157 int src_stride = x->plane[1].src.stride;
10158 const uint8_t *const src_u = x->plane[1].src.buf;
10159 const uint8_t *const src_v = x->plane[2].src.buf;
10160 float *const data = x->palette_buffer->kmeans_data_buf;
10161 float centroids[2 * PALETTE_MAX_SIZE];
10162 uint8_t *const color_map = xd->plane[1].color_index_map;
10163 int r, c;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020010164#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -070010165 const uint16_t *const src_u16 = CONVERT_TO_SHORTPTR(src_u);
10166 const uint16_t *const src_v16 = CONVERT_TO_SHORTPTR(src_v);
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020010167#endif // CONFIG_HIGHBITDEPTH
Urvang Joshi56ba91b2017-01-10 13:22:09 -080010168 int plane_block_width, plane_block_height, rows, cols;
10169 av1_get_block_dimensions(bsize, 1, xd, &plane_block_width,
10170 &plane_block_height, &rows, &cols);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010171 (void)cpi;
10172
10173 for (r = 0; r < rows; ++r) {
10174 for (c = 0; c < cols; ++c) {
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020010175#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -070010176 if (cpi->common.use_highbitdepth) {
10177 data[(r * cols + c) * 2] = src_u16[r * src_stride + c];
10178 data[(r * cols + c) * 2 + 1] = src_v16[r * src_stride + c];
10179 } else {
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020010180#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -070010181 data[(r * cols + c) * 2] = src_u[r * src_stride + c];
10182 data[(r * cols + c) * 2 + 1] = src_v[r * src_stride + c];
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020010183#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -070010184 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020010185#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -070010186 }
10187 }
10188
10189 for (r = 1; r < 3; ++r) {
10190 for (c = 0; c < pmi->palette_size[1]; ++c) {
10191 centroids[c * 2 + r - 1] = pmi->palette_colors[r * PALETTE_MAX_SIZE + c];
10192 }
10193 }
10194
Yaowu Xuf883b422016-08-30 14:01:10 -070010195 av1_calc_indices(data, centroids, color_map, rows * cols,
10196 pmi->palette_size[1], 2);
Urvang Joshi56ba91b2017-01-10 13:22:09 -080010197 extend_palette_color_map(color_map, cols, rows, plane_block_width,
10198 plane_block_height);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010199}
10200
hui su5db97432016-10-14 16:10:14 -070010201#if CONFIG_FILTER_INTRA
10202static void pick_filter_intra_interframe(
Luc Trudeau9d4cbb82017-07-27 17:01:32 -040010203 const AV1_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bsize, int mi_row,
10204 int mi_col, int *rate_uv_intra, int *rate_uv_tokenonly, int64_t *dist_uv,
10205 int *skip_uv, UV_PREDICTION_MODE *mode_uv,
Luc Trudeaud6d9eee2017-07-12 12:36:50 -040010206 FILTER_INTRA_MODE_INFO *filter_intra_mode_info_uv,
hui su5db97432016-10-14 16:10:14 -070010207#if CONFIG_EXT_INTRA
10208 int8_t *uv_angle_delta,
10209#endif // CONFIG_EXT_INTRA
Urvang Joshic6300aa2017-06-01 14:46:23 -070010210 PALETTE_MODE_INFO *pmi_uv, int palette_ctx, int skip_mask,
10211 unsigned int *ref_costs_single, int64_t *best_rd, int64_t *best_intra_rd,
10212 PREDICTION_MODE *best_intra_mode, int *best_mode_index, int *best_skip2,
10213 int *best_mode_skippable,
Yaowu Xuc27fc142016-08-22 16:08:15 -070010214#if CONFIG_SUPERTX
10215 int *returnrate_nocoef,
10216#endif // CONFIG_SUPERTX
Angie Chiang2a2a7dd2017-04-25 16:08:47 -070010217 int64_t *best_pred_rd, MB_MODE_INFO *best_mbmode, RD_STATS *rd_cost) {
Urvang Joshi52648442016-10-13 17:27:51 -070010218 const AV1_COMMON *const cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010219 MACROBLOCKD *const xd = &x->e_mbd;
10220 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
10221 PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
Hui Sue87fb232017-10-05 15:00:15 -070010222 const int try_palette =
10223 av1_allow_palette(cm->allow_screen_content_tools, mbmi->sb_type);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010224 int rate2 = 0, rate_y = INT_MAX, skippable = 0, rate_uv, rate_dummy, i;
10225 int dc_mode_index;
Yue Chenb23d00a2017-07-28 17:01:21 -070010226 const int *const intra_mode_cost = x->mbmode_cost[size_group_lookup[bsize]];
hui su8f4cc0a2017-01-13 15:14:49 -080010227 int64_t distortion2 = 0, distortion_y = 0, this_rd = *best_rd;
10228 int64_t distortion_uv, model_rd = INT64_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010229 TX_SIZE uv_tx;
10230
10231 for (i = 0; i < MAX_MODES; ++i)
Yaowu Xuf883b422016-08-30 14:01:10 -070010232 if (av1_mode_order[i].mode == DC_PRED &&
10233 av1_mode_order[i].ref_frame[0] == INTRA_FRAME)
Yaowu Xuc27fc142016-08-22 16:08:15 -070010234 break;
10235 dc_mode_index = i;
10236 assert(i < MAX_MODES);
10237
10238 // TODO(huisu): use skip_mask for further speedup.
10239 (void)skip_mask;
10240 mbmi->mode = DC_PRED;
Luc Trudeaud6d9eee2017-07-12 12:36:50 -040010241 mbmi->uv_mode = UV_DC_PRED;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010242 mbmi->ref_frame[0] = INTRA_FRAME;
Emil Keyder01770b32017-01-20 18:03:11 -050010243 mbmi->ref_frame[1] = NONE_FRAME;
hui su5db97432016-10-14 16:10:14 -070010244 if (!rd_pick_filter_intra_sby(cpi, x, &rate_dummy, &rate_y, &distortion_y,
10245 &skippable, bsize, intra_mode_cost[mbmi->mode],
hui su8f4cc0a2017-01-13 15:14:49 -080010246 &this_rd, &model_rd, 0)) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070010247 return;
hui su5db97432016-10-14 16:10:14 -070010248 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070010249 if (rate_y == INT_MAX) return;
10250
Debargha Mukherjee2f123402016-08-30 17:43:38 -070010251 uv_tx = uv_txsize_lookup[bsize][mbmi->tx_size][xd->plane[1].subsampling_x]
10252 [xd->plane[1].subsampling_y];
Yaowu Xuc27fc142016-08-22 16:08:15 -070010253 if (rate_uv_intra[uv_tx] == INT_MAX) {
Luc Trudeau9d4cbb82017-07-27 17:01:32 -040010254 choose_intra_uv_mode(cpi, x, bsize, uv_tx, &rate_uv_intra[uv_tx],
Yaowu Xuc27fc142016-08-22 16:08:15 -070010255 &rate_uv_tokenonly[uv_tx], &dist_uv[uv_tx],
10256 &skip_uv[uv_tx], &mode_uv[uv_tx]);
10257 if (cm->allow_screen_content_tools) pmi_uv[uv_tx] = *pmi;
hui su5db97432016-10-14 16:10:14 -070010258 filter_intra_mode_info_uv[uv_tx] = mbmi->filter_intra_mode_info;
10259#if CONFIG_EXT_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070010260 uv_angle_delta[uv_tx] = mbmi->angle_delta[1];
hui su5db97432016-10-14 16:10:14 -070010261#endif // CONFIG_EXT_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070010262 }
10263
10264 rate_uv = rate_uv_tokenonly[uv_tx];
10265 distortion_uv = dist_uv[uv_tx];
10266 skippable = skippable && skip_uv[uv_tx];
10267 mbmi->uv_mode = mode_uv[uv_tx];
10268 if (cm->allow_screen_content_tools) {
10269 pmi->palette_size[1] = pmi_uv[uv_tx].palette_size[1];
10270 memcpy(pmi->palette_colors + PALETTE_MAX_SIZE,
10271 pmi_uv[uv_tx].palette_colors + PALETTE_MAX_SIZE,
10272 2 * PALETTE_MAX_SIZE * sizeof(pmi->palette_colors[0]));
10273 }
hui su5db97432016-10-14 16:10:14 -070010274#if CONFIG_EXT_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070010275 mbmi->angle_delta[1] = uv_angle_delta[uv_tx];
hui su5db97432016-10-14 16:10:14 -070010276#endif // CONFIG_EXT_INTRA
10277 mbmi->filter_intra_mode_info.use_filter_intra_mode[1] =
10278 filter_intra_mode_info_uv[uv_tx].use_filter_intra_mode[1];
10279 if (filter_intra_mode_info_uv[uv_tx].use_filter_intra_mode[1]) {
10280 mbmi->filter_intra_mode_info.filter_intra_mode[1] =
10281 filter_intra_mode_info_uv[uv_tx].filter_intra_mode[1];
Yaowu Xuc27fc142016-08-22 16:08:15 -070010282 }
10283
10284 rate2 = rate_y + intra_mode_cost[mbmi->mode] + rate_uv +
Yue Chenb23d00a2017-07-28 17:01:21 -070010285 x->intra_uv_mode_cost[mbmi->mode][mbmi->uv_mode];
Rupert Swarbrick6f9cd942017-08-02 15:57:18 +010010286 if (try_palette && mbmi->mode == DC_PRED)
Yaowu Xuf883b422016-08-30 14:01:10 -070010287 rate2 += av1_cost_bit(
10288 av1_default_palette_y_mode_prob[bsize - BLOCK_8X8][palette_ctx], 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010289
10290 if (!xd->lossless[mbmi->segment_id]) {
10291 // super_block_yrd above includes the cost of the tx_size in the
10292 // tokenonly rate, but for intra blocks, tx_size is always coded
10293 // (prediction granularity), so we account for it in the full rate,
10294 // not the tokenonly rate.
Urvang Joshifeb925f2016-12-05 10:37:29 -080010295 rate_y -= tx_size_cost(cpi, x, bsize, mbmi->tx_size);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010296 }
10297
hui su5db97432016-10-14 16:10:14 -070010298 rate2 += av1_cost_bit(cm->fc->filter_intra_probs[0],
10299 mbmi->filter_intra_mode_info.use_filter_intra_mode[0]);
10300 rate2 += write_uniform_cost(
10301 FILTER_INTRA_MODES, mbmi->filter_intra_mode_info.filter_intra_mode[0]);
10302#if CONFIG_EXT_INTRA
Luc Trudeauf24a35f2017-09-11 11:56:33 -040010303 if (av1_is_directional_mode(get_uv_mode(mbmi->uv_mode), bsize) &&
Joe Young830d4ce2017-05-30 17:48:13 -070010304 av1_use_angle_delta(bsize)) {
hui su0a6731f2017-04-26 15:23:47 -070010305 rate2 += write_uniform_cost(2 * MAX_ANGLE_DELTA + 1,
10306 MAX_ANGLE_DELTA + mbmi->angle_delta[1]);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010307 }
hui su5db97432016-10-14 16:10:14 -070010308#endif // CONFIG_EXT_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070010309 if (mbmi->mode == DC_PRED) {
hui su5db97432016-10-14 16:10:14 -070010310 rate2 +=
10311 av1_cost_bit(cpi->common.fc->filter_intra_probs[1],
10312 mbmi->filter_intra_mode_info.use_filter_intra_mode[1]);
10313 if (mbmi->filter_intra_mode_info.use_filter_intra_mode[1])
10314 rate2 +=
10315 write_uniform_cost(FILTER_INTRA_MODES,
10316 mbmi->filter_intra_mode_info.filter_intra_mode[1]);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010317 }
10318 distortion2 = distortion_y + distortion_uv;
Jingning Han18c53c82017-02-17 14:49:57 -080010319 av1_encode_intra_block_plane((AV1_COMMON *)cm, x, bsize, 0, 0, mi_row,
10320 mi_col);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010321
10322 rate2 += ref_costs_single[INTRA_FRAME];
10323
10324 if (skippable) {
10325 rate2 -= (rate_y + rate_uv);
10326 rate_y = 0;
10327 rate_uv = 0;
Yaowu Xuf883b422016-08-30 14:01:10 -070010328 rate2 += av1_cost_bit(av1_get_skip_prob(cm, xd), 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010329 } else {
Yaowu Xuf883b422016-08-30 14:01:10 -070010330 rate2 += av1_cost_bit(av1_get_skip_prob(cm, xd), 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010331 }
Urvang Joshi70006e42017-06-14 16:08:55 -070010332 this_rd = RDCOST(x->rdmult, rate2, distortion2);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010333
10334 if (this_rd < *best_intra_rd) {
10335 *best_intra_rd = this_rd;
10336 *best_intra_mode = mbmi->mode;
10337 }
10338 for (i = 0; i < REFERENCE_MODES; ++i)
Yaowu Xuf883b422016-08-30 14:01:10 -070010339 best_pred_rd[i] = AOMMIN(best_pred_rd[i], this_rd);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010340
10341 if (this_rd < *best_rd) {
10342 *best_mode_index = dc_mode_index;
10343 mbmi->mv[0].as_int = 0;
10344 rd_cost->rate = rate2;
10345#if CONFIG_SUPERTX
10346 if (x->skip)
10347 *returnrate_nocoef = rate2;
10348 else
10349 *returnrate_nocoef = rate2 - rate_y - rate_uv;
Yaowu Xuf883b422016-08-30 14:01:10 -070010350 *returnrate_nocoef -= av1_cost_bit(av1_get_skip_prob(cm, xd), skippable);
10351 *returnrate_nocoef -= av1_cost_bit(av1_get_intra_inter_prob(cm, xd),
10352 mbmi->ref_frame[0] != INTRA_FRAME);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010353#endif // CONFIG_SUPERTX
10354 rd_cost->dist = distortion2;
10355 rd_cost->rdcost = this_rd;
10356 *best_rd = this_rd;
10357 *best_mbmode = *mbmi;
10358 *best_skip2 = 0;
10359 *best_mode_skippable = skippable;
10360 }
10361}
hui su5db97432016-10-14 16:10:14 -070010362#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070010363
Yue Chencb60b182016-10-13 15:18:22 -070010364#if CONFIG_MOTION_VAR
Yaowu Xuf883b422016-08-30 14:01:10 -070010365static void calc_target_weighted_pred(const AV1_COMMON *cm, const MACROBLOCK *x,
10366 const MACROBLOCKD *xd, int mi_row,
10367 int mi_col, const uint8_t *above,
10368 int above_stride, const uint8_t *left,
Yue Chene9638cc2016-10-10 12:37:54 -070010369 int left_stride);
Yue Chencb60b182016-10-13 15:18:22 -070010370#endif // CONFIG_MOTION_VAR
Yaowu Xuc27fc142016-08-22 16:08:15 -070010371
Urvang Joshi52648442016-10-13 17:27:51 -070010372void av1_rd_pick_inter_mode_sb(const AV1_COMP *cpi, TileDataEnc *tile_data,
Yaowu Xuf883b422016-08-30 14:01:10 -070010373 MACROBLOCK *x, int mi_row, int mi_col,
Angie Chiang2a2a7dd2017-04-25 16:08:47 -070010374 RD_STATS *rd_cost,
Yaowu Xuc27fc142016-08-22 16:08:15 -070010375#if CONFIG_SUPERTX
Yaowu Xuf883b422016-08-30 14:01:10 -070010376 int *returnrate_nocoef,
Yaowu Xuc27fc142016-08-22 16:08:15 -070010377#endif // CONFIG_SUPERTX
Yaowu Xuf883b422016-08-30 14:01:10 -070010378 BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx,
10379 int64_t best_rd_so_far) {
Urvang Joshi52648442016-10-13 17:27:51 -070010380 const AV1_COMMON *const cm = &cpi->common;
10381 const RD_OPT *const rd_opt = &cpi->rd;
10382 const SPEED_FEATURES *const sf = &cpi->sf;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010383 MACROBLOCKD *const xd = &x->e_mbd;
10384 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Hui Sue87fb232017-10-05 15:00:15 -070010385 const int try_palette =
10386 av1_allow_palette(cm->allow_screen_content_tools, mbmi->sb_type);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010387 PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
10388 MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
10389 const struct segmentation *const seg = &cm->seg;
10390 PREDICTION_MODE this_mode;
10391 MV_REFERENCE_FRAME ref_frame, second_ref_frame;
10392 unsigned char segment_id = mbmi->segment_id;
10393 int comp_pred, i, k;
10394 int_mv frame_mv[MB_MODE_COUNT][TOTAL_REFS_PER_FRAME];
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020010395#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -070010396 int_mv frame_comp_mv[MB_MODE_COUNT][TOTAL_REFS_PER_FRAME];
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020010397#endif // CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -070010398 struct buf_2d yv12_mb[TOTAL_REFS_PER_FRAME][MAX_MB_PLANE];
Yaowu Xuc27fc142016-08-22 16:08:15 -070010399 int_mv single_newmv[TOTAL_REFS_PER_FRAME] = { { 0 } };
Zoe Liu7f24e1b2017-03-17 17:42:05 -070010400 int single_newmv_rate[TOTAL_REFS_PER_FRAME] = { 0 };
10401 int64_t modelled_rd[MB_MODE_COUNT][TOTAL_REFS_PER_FRAME];
Yaowu Xuc27fc142016-08-22 16:08:15 -070010402 static const int flag_list[TOTAL_REFS_PER_FRAME] = {
10403 0,
Yaowu Xuf883b422016-08-30 14:01:10 -070010404 AOM_LAST_FLAG,
Yaowu Xuc27fc142016-08-22 16:08:15 -070010405#if CONFIG_EXT_REFS
Yaowu Xuf883b422016-08-30 14:01:10 -070010406 AOM_LAST2_FLAG,
10407 AOM_LAST3_FLAG,
Yaowu Xuc27fc142016-08-22 16:08:15 -070010408#endif // CONFIG_EXT_REFS
Yaowu Xuf883b422016-08-30 14:01:10 -070010409 AOM_GOLD_FLAG,
Yaowu Xuc27fc142016-08-22 16:08:15 -070010410#if CONFIG_EXT_REFS
Yaowu Xuf883b422016-08-30 14:01:10 -070010411 AOM_BWD_FLAG,
Zoe Liue9b15e22017-07-19 15:53:01 -070010412 AOM_ALT2_FLAG,
Yaowu Xuc27fc142016-08-22 16:08:15 -070010413#endif // CONFIG_EXT_REFS
Yaowu Xuf883b422016-08-30 14:01:10 -070010414 AOM_ALT_FLAG
Yaowu Xuc27fc142016-08-22 16:08:15 -070010415 };
10416 int64_t best_rd = best_rd_so_far;
10417 int best_rate_y = INT_MAX, best_rate_uv = INT_MAX;
10418 int64_t best_pred_diff[REFERENCE_MODES];
10419 int64_t best_pred_rd[REFERENCE_MODES];
10420 MB_MODE_INFO best_mbmode;
Yaowu Xu4306b6e2016-09-27 12:55:32 -070010421 int rate_skip0 = av1_cost_bit(av1_get_skip_prob(cm, xd), 0);
10422 int rate_skip1 = av1_cost_bit(av1_get_skip_prob(cm, xd), 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010423 int best_mode_skippable = 0;
10424 int midx, best_mode_index = -1;
10425 unsigned int ref_costs_single[TOTAL_REFS_PER_FRAME];
Zoe Liuc082bbc2017-05-17 13:31:37 -070010426#if CONFIG_EXT_COMP_REFS
10427 unsigned int ref_costs_comp[TOTAL_REFS_PER_FRAME][TOTAL_REFS_PER_FRAME];
10428#else
Yaowu Xuc27fc142016-08-22 16:08:15 -070010429 unsigned int ref_costs_comp[TOTAL_REFS_PER_FRAME];
Zoe Liuc082bbc2017-05-17 13:31:37 -070010430#endif // CONFIG_EXT_COMP_REFS
Yaowu Xuf883b422016-08-30 14:01:10 -070010431 aom_prob comp_mode_p;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010432 int64_t best_intra_rd = INT64_MAX;
10433 unsigned int best_pred_sse = UINT_MAX;
10434 PREDICTION_MODE best_intra_mode = DC_PRED;
Urvang Joshifeb925f2016-12-05 10:37:29 -080010435 int rate_uv_intra[TX_SIZES_ALL], rate_uv_tokenonly[TX_SIZES_ALL];
10436 int64_t dist_uvs[TX_SIZES_ALL];
10437 int skip_uvs[TX_SIZES_ALL];
Luc Trudeaud6d9eee2017-07-12 12:36:50 -040010438 UV_PREDICTION_MODE mode_uv[TX_SIZES_ALL];
Urvang Joshifeb925f2016-12-05 10:37:29 -080010439 PALETTE_MODE_INFO pmi_uv[TX_SIZES_ALL];
Yaowu Xuc27fc142016-08-22 16:08:15 -070010440#if CONFIG_EXT_INTRA
Urvang Joshifeb925f2016-12-05 10:37:29 -080010441 int8_t uv_angle_delta[TX_SIZES_ALL];
Yaowu Xuc27fc142016-08-22 16:08:15 -070010442 int is_directional_mode, angle_stats_ready = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010443 uint8_t directional_mode_skip_mask[INTRA_MODES];
10444#endif // CONFIG_EXT_INTRA
hui su5db97432016-10-14 16:10:14 -070010445#if CONFIG_FILTER_INTRA
10446 int8_t dc_skipped = 1;
Urvang Joshifeb925f2016-12-05 10:37:29 -080010447 FILTER_INTRA_MODE_INFO filter_intra_mode_info_uv[TX_SIZES_ALL];
hui su5db97432016-10-14 16:10:14 -070010448#endif // CONFIG_FILTER_INTRA
Yaowu Xuf883b422016-08-30 14:01:10 -070010449 const int intra_cost_penalty = av1_get_intra_cost_penalty(
Yaowu Xuc27fc142016-08-22 16:08:15 -070010450 cm->base_qindex, cm->y_dc_delta_q, cm->bit_depth);
Yue Chenb23d00a2017-07-28 17:01:21 -070010451 const int *const intra_mode_cost = x->mbmode_cost[size_group_lookup[bsize]];
Yaowu Xuc27fc142016-08-22 16:08:15 -070010452 int best_skip2 = 0;
Zoe Liu97ad0582017-02-09 10:51:00 -080010453 uint16_t ref_frame_skip_mask[2] = { 0 };
Yaowu Xuc27fc142016-08-22 16:08:15 -070010454 uint32_t mode_skip_mask[TOTAL_REFS_PER_FRAME] = { 0 };
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020010455#if CONFIG_INTERINTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070010456 MV_REFERENCE_FRAME best_single_inter_ref = LAST_FRAME;
10457 int64_t best_single_inter_rd = INT64_MAX;
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020010458#endif // CONFIG_INTERINTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070010459 int mode_skip_start = sf->mode_skip_start + 1;
10460 const int *const rd_threshes = rd_opt->threshes[segment_id][bsize];
10461 const int *const rd_thresh_freq_fact = tile_data->thresh_freq_fact[bsize];
10462 int64_t mode_threshold[MAX_MODES];
10463 int *mode_map = tile_data->mode_map[bsize];
10464 const int mode_search_skip_flags = sf->mode_search_skip_flags;
Yushin Cho77bba8d2016-11-04 16:36:56 -070010465#if CONFIG_PVQ
10466 od_rollback_buffer pre_buf;
Fergus Simpson4063a682017-02-28 16:52:22 -080010467#endif // CONFIG_PVQ
Yushin Cho77bba8d2016-11-04 16:36:56 -070010468
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -080010469 HandleInterModeArgs args = {
Fergus Simpson073c6f32017-02-17 12:13:48 -080010470#if CONFIG_MOTION_VAR
10471 { NULL },
10472 { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE },
10473 { NULL },
10474 { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE },
10475#endif // CONFIG_MOTION_VAR
Fergus Simpson073c6f32017-02-17 12:13:48 -080010476 NULL,
10477 NULL,
10478 NULL,
Fergus Simpson3424c2d2017-03-09 11:48:15 -080010479 { { 0 } },
Fergus Simpson073c6f32017-02-17 12:13:48 -080010480 };
10481
Jingning Hanae5cfde2016-11-30 12:01:44 -080010482 const int rows = block_size_high[bsize];
10483 const int cols = block_size_wide[bsize];
Urvang Joshib100db72016-10-12 16:28:56 -070010484 int palette_ctx = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010485 const MODE_INFO *above_mi = xd->above_mi;
10486 const MODE_INFO *left_mi = xd->left_mi;
Yue Chencb60b182016-10-13 15:18:22 -070010487#if CONFIG_MOTION_VAR
Yaowu Xuc27fc142016-08-22 16:08:15 -070010488 int dst_width1[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE };
10489 int dst_width2[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE };
10490 int dst_height1[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE };
10491 int dst_height2[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE };
Yaowu Xuc27fc142016-08-22 16:08:15 -070010492
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020010493#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -070010494 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
10495 int len = sizeof(uint16_t);
Jingning Hand064cf02017-06-01 10:00:39 -070010496 args.above_pred_buf[0] = CONVERT_TO_BYTEPTR(x->above_pred_buf);
10497 args.above_pred_buf[1] =
10498 CONVERT_TO_BYTEPTR(x->above_pred_buf + MAX_SB_SQUARE * len);
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -080010499 args.above_pred_buf[2] =
Jingning Hand064cf02017-06-01 10:00:39 -070010500 CONVERT_TO_BYTEPTR(x->above_pred_buf + 2 * MAX_SB_SQUARE * len);
10501 args.left_pred_buf[0] = CONVERT_TO_BYTEPTR(x->left_pred_buf);
10502 args.left_pred_buf[1] =
10503 CONVERT_TO_BYTEPTR(x->left_pred_buf + MAX_SB_SQUARE * len);
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -080010504 args.left_pred_buf[2] =
Jingning Hand064cf02017-06-01 10:00:39 -070010505 CONVERT_TO_BYTEPTR(x->left_pred_buf + 2 * MAX_SB_SQUARE * len);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010506 } else {
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020010507#endif // CONFIG_HIGHBITDEPTH
Jingning Hand064cf02017-06-01 10:00:39 -070010508 args.above_pred_buf[0] = x->above_pred_buf;
10509 args.above_pred_buf[1] = x->above_pred_buf + MAX_SB_SQUARE;
10510 args.above_pred_buf[2] = x->above_pred_buf + 2 * MAX_SB_SQUARE;
10511 args.left_pred_buf[0] = x->left_pred_buf;
10512 args.left_pred_buf[1] = x->left_pred_buf + MAX_SB_SQUARE;
10513 args.left_pred_buf[2] = x->left_pred_buf + 2 * MAX_SB_SQUARE;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020010514#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -070010515 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020010516#endif // CONFIG_HIGHBITDEPTH
Yue Chencb60b182016-10-13 15:18:22 -070010517#endif // CONFIG_MOTION_VAR
Yaowu Xuc27fc142016-08-22 16:08:15 -070010518
Yaowu Xuf883b422016-08-30 14:01:10 -070010519 av1_zero(best_mbmode);
Yaowu Xuc27fc142016-08-22 16:08:15 -070010520
Urvang Joshib100db72016-10-12 16:28:56 -070010521 av1_zero(pmi_uv);
hui su9bc1d8d2017-03-24 12:36:03 -070010522 if (try_palette) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070010523 if (above_mi)
10524 palette_ctx += (above_mi->mbmi.palette_mode_info.palette_size[0] > 0);
10525 if (left_mi)
10526 palette_ctx += (left_mi->mbmi.palette_mode_info.palette_size[0] > 0);
10527 }
10528
Yaowu Xuc27fc142016-08-22 16:08:15 -070010529 estimate_ref_frame_costs(cm, xd, segment_id, ref_costs_single, ref_costs_comp,
10530 &comp_mode_p);
10531
10532 for (i = 0; i < REFERENCE_MODES; ++i) best_pred_rd[i] = INT64_MAX;
Urvang Joshifeb925f2016-12-05 10:37:29 -080010533 for (i = 0; i < TX_SIZES_ALL; i++) rate_uv_intra[i] = INT_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010534 for (i = 0; i < TOTAL_REFS_PER_FRAME; ++i) x->pred_sse[i] = INT_MAX;
10535 for (i = 0; i < MB_MODE_COUNT; ++i) {
10536 for (k = 0; k < TOTAL_REFS_PER_FRAME; ++k) {
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -080010537 args.single_filter[i][k] = SWITCHABLE;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010538 }
10539 }
10540
10541 rd_cost->rate = INT_MAX;
10542#if CONFIG_SUPERTX
10543 *returnrate_nocoef = INT_MAX;
10544#endif // CONFIG_SUPERTX
10545
10546 for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
10547 x->pred_mv_sad[ref_frame] = INT_MAX;
10548 x->mbmi_ext->mode_context[ref_frame] = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010549 x->mbmi_ext->compound_mode_context[ref_frame] = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010550 if (cpi->ref_frame_flags & flag_list[ref_frame]) {
10551 assert(get_ref_frame_buffer(cpi, ref_frame) != NULL);
10552 setup_buffer_inter(cpi, x, ref_frame, bsize, mi_row, mi_col,
10553 frame_mv[NEARESTMV], frame_mv[NEARMV], yv12_mb);
10554 }
10555 frame_mv[NEWMV][ref_frame].as_int = INVALID_MV;
Sarah Parkere5299862016-08-16 14:57:37 -070010556#if CONFIG_GLOBAL_MOTION
10557 frame_mv[ZEROMV][ref_frame].as_int =
Sarah Parkerae7c4582017-02-28 16:30:30 -080010558 gm_get_motion_vector(&cm->global_motion[ref_frame],
Debargha Mukherjeefebb59c2017-03-02 12:23:45 -080010559 cm->allow_high_precision_mv, bsize, mi_col, mi_row,
RogerZhou3b635242017-09-19 10:06:46 -070010560 0
10561#if CONFIG_AMVR
10562 ,
10563 cm->cur_frame_mv_precision_level
10564#endif
10565 )
David Barkercdcac6d2016-12-01 17:04:16 +000010566 .as_int;
Sarah Parkere5299862016-08-16 14:57:37 -070010567#else // CONFIG_GLOBAL_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -070010568 frame_mv[ZEROMV][ref_frame].as_int = 0;
Sarah Parkere5299862016-08-16 14:57:37 -070010569#endif // CONFIG_GLOBAL_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -070010570 frame_mv[NEW_NEWMV][ref_frame].as_int = INVALID_MV;
Zoe Liu85b66462017-04-20 14:28:19 -070010571#if CONFIG_COMPOUND_SINGLEREF
10572 frame_mv[SR_NEW_NEWMV][ref_frame].as_int = INVALID_MV;
10573 frame_comp_mv[SR_NEW_NEWMV][ref_frame].as_int = INVALID_MV;
10574#endif // CONFIG_COMPOUND_SINGLEREF
Sarah Parkerc2d38712017-01-24 15:15:41 -080010575#if CONFIG_GLOBAL_MOTION
10576 frame_mv[ZERO_ZEROMV][ref_frame].as_int =
Sarah Parkerae7c4582017-02-28 16:30:30 -080010577 gm_get_motion_vector(&cm->global_motion[ref_frame],
Debargha Mukherjeefebb59c2017-03-02 12:23:45 -080010578 cm->allow_high_precision_mv, bsize, mi_col, mi_row,
RogerZhou3b635242017-09-19 10:06:46 -070010579 0
10580#if CONFIG_AMVR
10581 ,
10582 cm->cur_frame_mv_precision_level
10583#endif
10584 )
Sarah Parkerc2d38712017-01-24 15:15:41 -080010585 .as_int;
10586#else // CONFIG_GLOBAL_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -070010587 frame_mv[ZERO_ZEROMV][ref_frame].as_int = 0;
Sarah Parkerc2d38712017-01-24 15:15:41 -080010588#endif // CONFIG_GLOBAL_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -070010589 }
10590
Yaowu Xuc27fc142016-08-22 16:08:15 -070010591 for (; ref_frame < MODE_CTX_REF_FRAMES; ++ref_frame) {
10592 MODE_INFO *const mi = xd->mi[0];
10593 int_mv *const candidates = x->mbmi_ext->ref_mvs[ref_frame];
10594 x->mbmi_ext->mode_context[ref_frame] = 0;
Yaowu Xuf883b422016-08-30 14:01:10 -070010595 av1_find_mv_refs(cm, xd, mi, ref_frame, &mbmi_ext->ref_mv_count[ref_frame],
10596 mbmi_ext->ref_mv_stack[ref_frame],
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020010597 mbmi_ext->compound_mode_context, candidates, mi_row,
10598 mi_col, NULL, NULL, mbmi_ext->mode_context);
Jingning Han731af492016-11-17 11:53:23 -080010599 if (mbmi_ext->ref_mv_count[ref_frame] < 2) {
10600 MV_REFERENCE_FRAME rf[2];
10601 av1_set_ref_frame(rf, ref_frame);
David Barkercdcac6d2016-12-01 17:04:16 +000010602 if (mbmi_ext->ref_mvs[rf[0]][0].as_int !=
10603 frame_mv[ZEROMV][rf[0]].as_int ||
10604 mbmi_ext->ref_mvs[rf[0]][1].as_int !=
10605 frame_mv[ZEROMV][rf[0]].as_int ||
10606 mbmi_ext->ref_mvs[rf[1]][0].as_int !=
10607 frame_mv[ZEROMV][rf[1]].as_int ||
10608 mbmi_ext->ref_mvs[rf[1]][1].as_int != frame_mv[ZEROMV][rf[1]].as_int)
Jingning Han731af492016-11-17 11:53:23 -080010609 mbmi_ext->mode_context[ref_frame] &= ~(1 << ALL_ZERO_FLAG_OFFSET);
10610 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070010611 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070010612
Yue Chencb60b182016-10-13 15:18:22 -070010613#if CONFIG_MOTION_VAR
Yue Chen5329a2b2017-02-28 17:33:00 +080010614 av1_count_overlappable_neighbors(cm, xd, mi_row, mi_col);
Jingning Hanad586b92017-05-23 10:24:57 -070010615
Yue Chenf7ba6472017-04-19 11:08:58 -070010616 if (check_num_overlappable_neighbors(mbmi) &&
10617 is_motion_variation_allowed_bsize(bsize)) {
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -080010618 av1_build_prediction_by_above_preds(cm, xd, mi_row, mi_col,
10619 args.above_pred_buf, dst_width1,
10620 dst_height1, args.above_pred_stride);
Yue Chen5329a2b2017-02-28 17:33:00 +080010621 av1_build_prediction_by_left_preds(cm, xd, mi_row, mi_col,
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -080010622 args.left_pred_buf, dst_width2,
10623 dst_height2, args.left_pred_stride);
Jingning Han91d9a792017-04-18 12:01:52 -070010624 av1_setup_dst_planes(xd->plane, bsize, get_frame_new_buffer(cm), mi_row,
10625 mi_col);
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -080010626 calc_target_weighted_pred(cm, x, xd, mi_row, mi_col, args.above_pred_buf[0],
10627 args.above_pred_stride[0], args.left_pred_buf[0],
10628 args.left_pred_stride[0]);
Yue Chen5329a2b2017-02-28 17:33:00 +080010629 }
Yue Chencb60b182016-10-13 15:18:22 -070010630#endif // CONFIG_MOTION_VAR
Yaowu Xuc27fc142016-08-22 16:08:15 -070010631
10632 for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
10633 if (!(cpi->ref_frame_flags & flag_list[ref_frame])) {
Zoe Liue9b15e22017-07-19 15:53:01 -070010634 // Skip checking missing references in both single and compound reference
10635 // modes. Note that a mode will be skipped iff both reference frames
10636 // are masked out.
Zoe Liuc082bbc2017-05-17 13:31:37 -070010637 ref_frame_skip_mask[0] |= (1 << ref_frame);
10638 ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010639 } else {
10640 for (i = LAST_FRAME; i <= ALTREF_FRAME; ++i) {
10641 // Skip fixed mv modes for poor references
10642 if ((x->pred_mv_sad[ref_frame] >> 2) > x->pred_mv_sad[i]) {
10643 mode_skip_mask[ref_frame] |= INTER_NEAREST_NEAR_ZERO;
10644 break;
10645 }
10646 }
10647 }
10648 // If the segment reference frame feature is enabled....
10649 // then do nothing if the current ref frame is not allowed..
10650 if (segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME) &&
10651 get_segdata(seg, segment_id, SEG_LVL_REF_FRAME) != (int)ref_frame) {
10652 ref_frame_skip_mask[0] |= (1 << ref_frame);
10653 ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
10654 }
10655 }
10656
10657 // Disable this drop out case if the ref frame
10658 // segment level feature is enabled for this segment. This is to
10659 // prevent the possibility that we end up unable to pick any mode.
10660 if (!segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME)) {
10661 // Only consider ZEROMV/ALTREF_FRAME for alt ref frame,
10662 // unless ARNR filtering is enabled in which case we want
10663 // an unfiltered alternative. We allow near/nearest as well
10664 // because they may result in zero-zero MVs but be cheaper.
10665 if (cpi->rc.is_src_frame_alt_ref && (cpi->oxcf.arnr_max_frames == 0)) {
Sarah Parkere5299862016-08-16 14:57:37 -070010666 int_mv zeromv;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010667 ref_frame_skip_mask[0] = (1 << LAST_FRAME) |
10668#if CONFIG_EXT_REFS
10669 (1 << LAST2_FRAME) | (1 << LAST3_FRAME) |
Zoe Liu3ac20932017-08-30 16:35:55 -070010670 (1 << BWDREF_FRAME) | (1 << ALTREF2_FRAME) |
Yaowu Xuc27fc142016-08-22 16:08:15 -070010671#endif // CONFIG_EXT_REFS
10672 (1 << GOLDEN_FRAME);
10673 ref_frame_skip_mask[1] = SECOND_REF_FRAME_MASK;
10674 // TODO(zoeliu): To further explore whether following needs to be done for
10675 // BWDREF_FRAME as well.
10676 mode_skip_mask[ALTREF_FRAME] = ~INTER_NEAREST_NEAR_ZERO;
Sarah Parkere5299862016-08-16 14:57:37 -070010677#if CONFIG_GLOBAL_MOTION
David Barkercdcac6d2016-12-01 17:04:16 +000010678 zeromv.as_int = gm_get_motion_vector(&cm->global_motion[ALTREF_FRAME],
Sarah Parkerae7c4582017-02-28 16:30:30 -080010679 cm->allow_high_precision_mv, bsize,
RogerZhou3b635242017-09-19 10:06:46 -070010680 mi_col, mi_row, 0
10681#if CONFIG_AMVR
10682 ,
10683 cm->cur_frame_mv_precision_level
10684#endif
10685 )
David Barkercdcac6d2016-12-01 17:04:16 +000010686 .as_int;
Sarah Parkere5299862016-08-16 14:57:37 -070010687#else
10688 zeromv.as_int = 0;
10689#endif // CONFIG_GLOBAL_MOTION
10690 if (frame_mv[NEARMV][ALTREF_FRAME].as_int != zeromv.as_int)
Yaowu Xuc27fc142016-08-22 16:08:15 -070010691 mode_skip_mask[ALTREF_FRAME] |= (1 << NEARMV);
Sarah Parkere5299862016-08-16 14:57:37 -070010692 if (frame_mv[NEARESTMV][ALTREF_FRAME].as_int != zeromv.as_int)
Yaowu Xuc27fc142016-08-22 16:08:15 -070010693 mode_skip_mask[ALTREF_FRAME] |= (1 << NEARESTMV);
Sarah Parkere5299862016-08-16 14:57:37 -070010694 if (frame_mv[NEAREST_NEARESTMV][ALTREF_FRAME].as_int != zeromv.as_int)
Yaowu Xuc27fc142016-08-22 16:08:15 -070010695 mode_skip_mask[ALTREF_FRAME] |= (1 << NEAREST_NEARESTMV);
Sarah Parkere5299862016-08-16 14:57:37 -070010696 if (frame_mv[NEAR_NEARMV][ALTREF_FRAME].as_int != zeromv.as_int)
Yaowu Xuc27fc142016-08-22 16:08:15 -070010697 mode_skip_mask[ALTREF_FRAME] |= (1 << NEAR_NEARMV);
Zoe Liu85b66462017-04-20 14:28:19 -070010698#if CONFIG_COMPOUND_SINGLEREF
10699 if (frame_mv[SR_NEAREST_NEARMV][ALTREF_FRAME].as_int != zeromv.as_int ||
10700 frame_comp_mv[SR_NEAREST_NEARMV][ALTREF_FRAME].as_int !=
10701 zeromv.as_int)
10702 mode_skip_mask[ALTREF_FRAME] |= (1 << SR_NEAREST_NEARMV);
10703#endif // CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -070010704 }
10705 }
10706
10707 if (cpi->rc.is_src_frame_alt_ref) {
10708 if (sf->alt_ref_search_fp) {
10709 assert(cpi->ref_frame_flags & flag_list[ALTREF_FRAME]);
10710 mode_skip_mask[ALTREF_FRAME] = 0;
10711 ref_frame_skip_mask[0] = ~(1 << ALTREF_FRAME);
10712 ref_frame_skip_mask[1] = SECOND_REF_FRAME_MASK;
10713 }
10714 }
10715
10716 if (sf->alt_ref_search_fp)
10717 if (!cm->show_frame && x->pred_mv_sad[GOLDEN_FRAME] < INT_MAX)
10718 if (x->pred_mv_sad[ALTREF_FRAME] > (x->pred_mv_sad[GOLDEN_FRAME] << 1))
10719 mode_skip_mask[ALTREF_FRAME] |= INTER_ALL;
10720
10721 if (sf->adaptive_mode_search) {
10722 if (cm->show_frame && !cpi->rc.is_src_frame_alt_ref &&
10723 cpi->rc.frames_since_golden >= 3)
Yaowu Xu36bad472017-05-16 18:29:53 -070010724 if ((x->pred_mv_sad[GOLDEN_FRAME] >> 1) > x->pred_mv_sad[LAST_FRAME])
Yaowu Xuc27fc142016-08-22 16:08:15 -070010725 mode_skip_mask[GOLDEN_FRAME] |= INTER_ALL;
10726 }
10727
10728 if (bsize > sf->max_intra_bsize) {
10729 ref_frame_skip_mask[0] |= (1 << INTRA_FRAME);
10730 ref_frame_skip_mask[1] |= (1 << INTRA_FRAME);
10731 }
10732
10733 mode_skip_mask[INTRA_FRAME] |=
10734 ~(sf->intra_y_mode_mask[max_txsize_lookup[bsize]]);
10735
10736 for (i = 0; i <= LAST_NEW_MV_INDEX; ++i) mode_threshold[i] = 0;
10737 for (i = LAST_NEW_MV_INDEX + 1; i < MAX_MODES; ++i)
10738 mode_threshold[i] = ((int64_t)rd_threshes[i] * rd_thresh_freq_fact[i]) >> 5;
10739
10740 midx = sf->schedule_mode_search ? mode_skip_start : 0;
10741 while (midx > 4) {
10742 uint8_t end_pos = 0;
10743 for (i = 5; i < midx; ++i) {
10744 if (mode_threshold[mode_map[i - 1]] > mode_threshold[mode_map[i]]) {
10745 uint8_t tmp = mode_map[i];
10746 mode_map[i] = mode_map[i - 1];
10747 mode_map[i - 1] = tmp;
10748 end_pos = i;
10749 }
10750 }
10751 midx = end_pos;
10752 }
10753
10754 if (cpi->sf.tx_type_search.fast_intra_tx_type_search)
10755 x->use_default_intra_tx_type = 1;
10756 else
10757 x->use_default_intra_tx_type = 0;
10758
10759 if (cpi->sf.tx_type_search.fast_inter_tx_type_search)
10760 x->use_default_inter_tx_type = 1;
10761 else
10762 x->use_default_inter_tx_type = 0;
Yushin Cho77bba8d2016-11-04 16:36:56 -070010763#if CONFIG_PVQ
10764 od_encode_checkpoint(&x->daala_enc, &pre_buf);
Fergus Simpson4063a682017-02-28 16:52:22 -080010765#endif // CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -070010766 for (i = 0; i < MB_MODE_COUNT; ++i)
10767 for (ref_frame = 0; ref_frame < TOTAL_REFS_PER_FRAME; ++ref_frame)
10768 modelled_rd[i][ref_frame] = INT64_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010769
10770 for (midx = 0; midx < MAX_MODES; ++midx) {
10771 int mode_index;
10772 int mode_excluded = 0;
10773 int64_t this_rd = INT64_MAX;
10774 int disable_skip = 0;
10775 int compmode_cost = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010776 int rate2 = 0, rate_y = 0, rate_uv = 0;
10777 int64_t distortion2 = 0, distortion_y = 0, distortion_uv = 0;
10778 int skippable = 0;
10779 int this_skip2 = 0;
10780 int64_t total_sse = INT64_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010781 uint8_t ref_frame_type;
Yushin Cho77bba8d2016-11-04 16:36:56 -070010782#if CONFIG_PVQ
10783 od_encode_rollback(&x->daala_enc, &pre_buf);
Fergus Simpson4063a682017-02-28 16:52:22 -080010784#endif // CONFIG_PVQ
Yaowu Xuc27fc142016-08-22 16:08:15 -070010785 mode_index = mode_map[midx];
Yaowu Xuf883b422016-08-30 14:01:10 -070010786 this_mode = av1_mode_order[mode_index].mode;
10787 ref_frame = av1_mode_order[mode_index].ref_frame[0];
10788 second_ref_frame = av1_mode_order[mode_index].ref_frame[1];
Yaowu Xu4306b6e2016-09-27 12:55:32 -070010789 mbmi->ref_mv_idx = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010790
Yaowu Xuc27fc142016-08-22 16:08:15 -070010791 if (ref_frame > INTRA_FRAME && second_ref_frame == INTRA_FRAME) {
10792 // Mode must by compatible
Debargha Mukherjee37f6fe62017-02-10 21:44:13 -080010793 if (!is_interintra_allowed_mode(this_mode)) continue;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010794 if (!is_interintra_allowed_bsize(bsize)) continue;
10795 }
10796
10797 if (is_inter_compound_mode(this_mode)) {
10798 frame_mv[this_mode][ref_frame].as_int =
10799 frame_mv[compound_ref0_mode(this_mode)][ref_frame].as_int;
10800 frame_mv[this_mode][second_ref_frame].as_int =
10801 frame_mv[compound_ref1_mode(this_mode)][second_ref_frame].as_int;
Zoe Liu85b66462017-04-20 14:28:19 -070010802#if CONFIG_COMPOUND_SINGLEREF
10803 } else if (is_inter_singleref_comp_mode(this_mode)) {
10804 frame_mv[this_mode][ref_frame].as_int =
10805 frame_mv[compound_ref0_mode(this_mode)][ref_frame].as_int;
10806 frame_comp_mv[this_mode][ref_frame].as_int =
10807 frame_mv[compound_ref1_mode(this_mode)][ref_frame].as_int;
10808#endif // CONFIG_COMPOUND_SINGLEREF
Yaowu Xuc27fc142016-08-22 16:08:15 -070010809 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070010810
10811 // Look at the reference frame of the best mode so far and set the
10812 // skip mask to look at a subset of the remaining modes.
10813 if (midx == mode_skip_start && best_mode_index >= 0) {
10814 switch (best_mbmode.ref_frame[0]) {
10815 case INTRA_FRAME: break;
10816 case LAST_FRAME:
10817 ref_frame_skip_mask[0] |= LAST_FRAME_MODE_MASK;
10818 ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
10819 break;
10820#if CONFIG_EXT_REFS
10821 case LAST2_FRAME:
10822 ref_frame_skip_mask[0] |= LAST2_FRAME_MODE_MASK;
10823 ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
10824 break;
10825 case LAST3_FRAME:
10826 ref_frame_skip_mask[0] |= LAST3_FRAME_MODE_MASK;
10827 ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
10828 break;
10829#endif // CONFIG_EXT_REFS
10830 case GOLDEN_FRAME:
10831 ref_frame_skip_mask[0] |= GOLDEN_FRAME_MODE_MASK;
10832 ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
10833 break;
10834#if CONFIG_EXT_REFS
10835 case BWDREF_FRAME:
10836 ref_frame_skip_mask[0] |= BWDREF_FRAME_MODE_MASK;
10837 ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
10838 break;
Zoe Liue9b15e22017-07-19 15:53:01 -070010839 case ALTREF2_FRAME:
10840 ref_frame_skip_mask[0] |= ALTREF2_FRAME_MODE_MASK;
10841 ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
10842 break;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010843#endif // CONFIG_EXT_REFS
10844 case ALTREF_FRAME: ref_frame_skip_mask[0] |= ALTREF_FRAME_MODE_MASK;
10845#if CONFIG_EXT_REFS
10846 ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
10847#endif // CONFIG_EXT_REFS
10848 break;
Emil Keyder01770b32017-01-20 18:03:11 -050010849 case NONE_FRAME:
Yaowu Xuc27fc142016-08-22 16:08:15 -070010850 case TOTAL_REFS_PER_FRAME:
10851 assert(0 && "Invalid Reference frame");
10852 break;
10853 }
10854 }
10855
10856 if ((ref_frame_skip_mask[0] & (1 << ref_frame)) &&
Yaowu Xuf883b422016-08-30 14:01:10 -070010857 (ref_frame_skip_mask[1] & (1 << AOMMAX(0, second_ref_frame))))
Yaowu Xuc27fc142016-08-22 16:08:15 -070010858 continue;
10859
Zoe Liuc082bbc2017-05-17 13:31:37 -070010860#if CONFIG_EXT_COMP_REFS
10861// TODO(zoeliu): Following toggle between #if 0/1 and the bug will manifest
10862// itself.
10863#if 0
10864 if (!(cpi->ref_frame_flags & flag_list[ref_frame]) ||
10865 (second_ref_frame > INTRA_FRAME &&
10866 (!(cpi->ref_frame_flags & flag_list[second_ref_frame]))))
10867 printf("Frame=%d, bsize=%d, (mi_row,mi_col)=(%d,%d), ref_frame=%d, "
10868 "second_ref_frame=%d\n", cm->current_video_frame, bsize, mi_row,
10869 mi_col, ref_frame, second_ref_frame);
10870
10871 if (!(cpi->ref_frame_flags & flag_list[ref_frame])) continue;
10872 if (second_ref_frame > INTRA_FRAME &&
10873 (!(cpi->ref_frame_flags & flag_list[second_ref_frame])))
10874 continue;
10875#endif // 0
10876
10877#if !USE_UNI_COMP_REFS
10878 // NOTE(zoeliu): Temporarily disable uni-directional comp refs
10879 if (second_ref_frame > INTRA_FRAME) {
10880 if (!((ref_frame < BWDREF_FRAME) ^ (second_ref_frame < BWDREF_FRAME)))
10881 continue;
10882 }
10883 assert(second_ref_frame <= INTRA_FRAME ||
10884 ((ref_frame < BWDREF_FRAME) ^ (second_ref_frame < BWDREF_FRAME)));
10885#endif // !USE_UNI_COMP_REFS
10886#endif // CONFIG_EXT_COMP_REFS
10887
Yaowu Xuc27fc142016-08-22 16:08:15 -070010888 if (mode_skip_mask[ref_frame] & (1 << this_mode)) continue;
10889
10890 // Test best rd so far against threshold for trying this mode.
10891 if (best_mode_skippable && sf->schedule_mode_search)
10892 mode_threshold[mode_index] <<= 1;
10893
10894 if (best_rd < mode_threshold[mode_index]) continue;
10895
Yunqing Wangff4fa062017-04-21 10:56:08 -070010896 // This is only used in motion vector unit test.
10897 if (cpi->oxcf.motion_vector_unit_test && ref_frame == INTRA_FRAME) continue;
10898
Zoe Liu5a978832017-08-15 16:33:34 -070010899#if CONFIG_ONE_SIDED_COMPOUND && !CONFIG_EXT_COMP_REFS // Changes LL bitstream
Arild Fuldseth (arilfuld)3f429082017-04-28 15:54:28 +020010900#if CONFIG_EXT_REFS
10901 if (cpi->oxcf.pass == 0) {
10902 // Complexity-compression trade-offs
10903 // if (ref_frame == ALTREF_FRAME) continue;
10904 // if (ref_frame == BWDREF_FRAME) continue;
10905 if (second_ref_frame == ALTREF_FRAME) continue;
10906 // if (second_ref_frame == BWDREF_FRAME) continue;
10907 }
Zoe Liu5a978832017-08-15 16:33:34 -070010908#endif // CONFIG_EXT_REFS
10909#endif // CONFIG_ONE_SIDED_COMPOUND && !CONFIG_EXT_COMP_REFS
Yaowu Xuc27fc142016-08-22 16:08:15 -070010910 comp_pred = second_ref_frame > INTRA_FRAME;
10911 if (comp_pred) {
10912 if (!cpi->allow_comp_inter_inter) continue;
10913
10914 // Skip compound inter modes if ARF is not available.
10915 if (!(cpi->ref_frame_flags & flag_list[second_ref_frame])) continue;
10916
10917 // Do not allow compound prediction if the segment level reference frame
10918 // feature is in use as in this case there can only be one reference.
10919 if (segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME)) continue;
10920
10921 if ((mode_search_skip_flags & FLAG_SKIP_COMP_BESTINTRA) &&
10922 best_mode_index >= 0 && best_mbmode.ref_frame[0] == INTRA_FRAME)
10923 continue;
10924
10925 mode_excluded = cm->reference_mode == SINGLE_REFERENCE;
10926 } else {
10927 if (ref_frame != INTRA_FRAME)
10928 mode_excluded = cm->reference_mode == COMPOUND_REFERENCE;
10929 }
10930
10931 if (ref_frame == INTRA_FRAME) {
10932 if (sf->adaptive_mode_search)
10933 if ((x->source_variance << num_pels_log2_lookup[bsize]) > best_pred_sse)
10934 continue;
10935
10936 if (this_mode != DC_PRED) {
10937 // Disable intra modes other than DC_PRED for blocks with low variance
10938 // Threshold for intra skipping based on source variance
10939 // TODO(debargha): Specialize the threshold for super block sizes
10940 const unsigned int skip_intra_var_thresh = 64;
10941 if ((mode_search_skip_flags & FLAG_SKIP_INTRA_LOWVAR) &&
10942 x->source_variance < skip_intra_var_thresh)
10943 continue;
10944 // Only search the oblique modes if the best so far is
10945 // one of the neighboring directional modes
10946 if ((mode_search_skip_flags & FLAG_SKIP_INTRA_BESTINTER) &&
Urvang Joshi96d1c0a2017-10-10 13:15:32 -070010947 (this_mode >= D45_PRED && this_mode <= PAETH_PRED)) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070010948 if (best_mode_index >= 0 && best_mbmode.ref_frame[0] > INTRA_FRAME)
10949 continue;
10950 }
10951 if (mode_search_skip_flags & FLAG_SKIP_INTRA_DIRMISMATCH) {
10952 if (conditional_skipintra(this_mode, best_intra_mode)) continue;
10953 }
10954 }
Sarah Parkere5299862016-08-16 14:57:37 -070010955#if CONFIG_GLOBAL_MOTION
David Barkercf3d0b02016-11-10 10:14:49 +000010956 } else if (cm->global_motion[ref_frame].wmtype == IDENTITY &&
Sarah Parkere5299862016-08-16 14:57:37 -070010957 (!comp_pred ||
David Barkercf3d0b02016-11-10 10:14:49 +000010958 cm->global_motion[second_ref_frame].wmtype == IDENTITY)) {
Sarah Parkere5299862016-08-16 14:57:37 -070010959#else // CONFIG_GLOBAL_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -070010960 } else {
Sarah Parkere5299862016-08-16 14:57:37 -070010961#endif // CONFIG_GLOBAL_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -070010962 const MV_REFERENCE_FRAME ref_frames[2] = { ref_frame, second_ref_frame };
Yue Chenb23d00a2017-07-28 17:01:21 -070010963 if (!check_best_zero_mv(cpi, x, mbmi_ext->mode_context,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020010964 mbmi_ext->compound_mode_context, frame_mv,
10965 this_mode, ref_frames, bsize, -1, mi_row, mi_col))
Yaowu Xuc27fc142016-08-22 16:08:15 -070010966 continue;
10967 }
10968
10969 mbmi->mode = this_mode;
Luc Trudeaud6d9eee2017-07-12 12:36:50 -040010970 mbmi->uv_mode = UV_DC_PRED;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010971 mbmi->ref_frame[0] = ref_frame;
10972 mbmi->ref_frame[1] = second_ref_frame;
10973 pmi->palette_size[0] = 0;
10974 pmi->palette_size[1] = 0;
hui su5db97432016-10-14 16:10:14 -070010975#if CONFIG_FILTER_INTRA
10976 mbmi->filter_intra_mode_info.use_filter_intra_mode[0] = 0;
10977 mbmi->filter_intra_mode_info.use_filter_intra_mode[1] = 0;
10978#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070010979 // Evaluate all sub-pel filters irrespective of whether we can use
10980 // them for this frame.
Debargha Mukherjee0df711f2017-05-02 16:00:20 -070010981
10982 set_default_interp_filters(mbmi, cm->interp_filter);
10983
Yaowu Xuc27fc142016-08-22 16:08:15 -070010984 mbmi->mv[0].as_int = mbmi->mv[1].as_int = 0;
Yue Chencb60b182016-10-13 15:18:22 -070010985 mbmi->motion_mode = SIMPLE_TRANSLATION;
Yaowu Xuc27fc142016-08-22 16:08:15 -070010986
10987 x->skip = 0;
10988 set_ref_ptrs(cm, xd, ref_frame, second_ref_frame);
10989
10990 // Select prediction reference frames.
10991 for (i = 0; i < MAX_MB_PLANE; i++) {
10992 xd->plane[i].pre[0] = yv12_mb[ref_frame][i];
10993 if (comp_pred) xd->plane[i].pre[1] = yv12_mb[second_ref_frame][i];
10994 }
10995
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020010996#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -070010997 // Single ref compound mode
10998 if (!comp_pred && is_inter_singleref_comp_mode(mbmi->mode)) {
10999 xd->block_refs[1] = xd->block_refs[0];
11000 for (i = 0; i < MAX_MB_PLANE; i++)
11001 xd->plane[i].pre[1] = xd->plane[i].pre[0];
11002 }
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020011003#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -070011004
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020011005#if CONFIG_INTERINTRA
Debargha Mukherjeecb603792016-10-04 13:10:23 -070011006 mbmi->interintra_mode = (INTERINTRA_MODE)(II_DC_PRED - 1);
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020011007#endif // CONFIG_INTERINTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070011008
11009 if (ref_frame == INTRA_FRAME) {
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011010 RD_STATS rd_stats_y;
Yaowu Xuc27fc142016-08-22 16:08:15 -070011011 TX_SIZE uv_tx;
11012 struct macroblockd_plane *const pd = &xd->plane[1];
11013#if CONFIG_EXT_INTRA
hui su45dc5972016-12-08 17:42:50 -080011014 is_directional_mode = av1_is_directional_mode(mbmi->mode, bsize);
Joe Young830d4ce2017-05-30 17:48:13 -070011015 if (is_directional_mode && av1_use_angle_delta(bsize)) {
hui su45dc5972016-12-08 17:42:50 -080011016 int rate_dummy;
hui su9a416f52017-01-13 11:37:53 -080011017 int64_t model_rd = INT64_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -070011018 if (!angle_stats_ready) {
11019 const int src_stride = x->plane[0].src.stride;
11020 const uint8_t *src = x->plane[0].src.buf;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020011021#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -070011022 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
hui su9cc10652017-04-27 17:22:07 -070011023 highbd_angle_estimation(src, src_stride, rows, cols, bsize,
Yaowu Xuc27fc142016-08-22 16:08:15 -070011024 directional_mode_skip_mask);
11025 else
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020011026#endif // CONFIG_HIGHBITDEPTH
hui su9cc10652017-04-27 17:22:07 -070011027 angle_estimation(src, src_stride, rows, cols, bsize,
Yaowu Xuc27fc142016-08-22 16:08:15 -070011028 directional_mode_skip_mask);
11029 angle_stats_ready = 1;
11030 }
11031 if (directional_mode_skip_mask[mbmi->mode]) continue;
hui su45dc5972016-12-08 17:42:50 -080011032 rd_stats_y.rate = INT_MAX;
Yue Chenb0f808b2017-04-26 11:55:14 -070011033 rd_pick_intra_angle_sby(cpi, x, &rate_dummy, &rd_stats_y, bsize,
11034 intra_mode_cost[mbmi->mode], best_rd,
11035 &model_rd);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011036 } else {
11037 mbmi->angle_delta[0] = 0;
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011038 super_block_yrd(cpi, x, &rd_stats_y, bsize, best_rd);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011039 }
11040#else
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011041 super_block_yrd(cpi, x, &rd_stats_y, bsize, best_rd);
hui su45dc5972016-12-08 17:42:50 -080011042#endif // CONFIG_EXT_INTRA
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011043 rate_y = rd_stats_y.rate;
11044 distortion_y = rd_stats_y.dist;
11045 skippable = rd_stats_y.skip;
Yaowu Xuc27fc142016-08-22 16:08:15 -070011046
11047 if (rate_y == INT_MAX) continue;
11048
hui su5db97432016-10-14 16:10:14 -070011049#if CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070011050 if (mbmi->mode == DC_PRED) dc_skipped = 0;
hui su5db97432016-10-14 16:10:14 -070011051#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070011052
Debargha Mukherjee2f123402016-08-30 17:43:38 -070011053 uv_tx = uv_txsize_lookup[bsize][mbmi->tx_size][pd->subsampling_x]
11054 [pd->subsampling_y];
Yaowu Xuc27fc142016-08-22 16:08:15 -070011055 if (rate_uv_intra[uv_tx] == INT_MAX) {
Luc Trudeau9d4cbb82017-07-27 17:01:32 -040011056 choose_intra_uv_mode(cpi, x, bsize, uv_tx, &rate_uv_intra[uv_tx],
Urvang Joshi368fbc92016-10-17 16:31:34 -070011057 &rate_uv_tokenonly[uv_tx], &dist_uvs[uv_tx],
11058 &skip_uvs[uv_tx], &mode_uv[uv_tx]);
hui su9bc1d8d2017-03-24 12:36:03 -070011059 if (try_palette) pmi_uv[uv_tx] = *pmi;
Urvang Joshib100db72016-10-12 16:28:56 -070011060
Yaowu Xuc27fc142016-08-22 16:08:15 -070011061#if CONFIG_EXT_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070011062 uv_angle_delta[uv_tx] = mbmi->angle_delta[1];
11063#endif // CONFIG_EXT_INTRA
hui su5db97432016-10-14 16:10:14 -070011064#if CONFIG_FILTER_INTRA
11065 filter_intra_mode_info_uv[uv_tx] = mbmi->filter_intra_mode_info;
11066#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070011067 }
11068
11069 rate_uv = rate_uv_tokenonly[uv_tx];
Urvang Joshi368fbc92016-10-17 16:31:34 -070011070 distortion_uv = dist_uvs[uv_tx];
11071 skippable = skippable && skip_uvs[uv_tx];
Yaowu Xuc27fc142016-08-22 16:08:15 -070011072 mbmi->uv_mode = mode_uv[uv_tx];
hui su9bc1d8d2017-03-24 12:36:03 -070011073 if (try_palette) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070011074 pmi->palette_size[1] = pmi_uv[uv_tx].palette_size[1];
11075 memcpy(pmi->palette_colors + PALETTE_MAX_SIZE,
11076 pmi_uv[uv_tx].palette_colors + PALETTE_MAX_SIZE,
11077 2 * PALETTE_MAX_SIZE * sizeof(pmi->palette_colors[0]));
11078 }
Urvang Joshib100db72016-10-12 16:28:56 -070011079
Yaowu Xuc27fc142016-08-22 16:08:15 -070011080#if CONFIG_EXT_INTRA
11081 mbmi->angle_delta[1] = uv_angle_delta[uv_tx];
Yaowu Xuc27fc142016-08-22 16:08:15 -070011082#endif // CONFIG_EXT_INTRA
hui su5db97432016-10-14 16:10:14 -070011083#if CONFIG_FILTER_INTRA
11084 mbmi->filter_intra_mode_info.use_filter_intra_mode[1] =
11085 filter_intra_mode_info_uv[uv_tx].use_filter_intra_mode[1];
11086 if (filter_intra_mode_info_uv[uv_tx].use_filter_intra_mode[1]) {
11087 mbmi->filter_intra_mode_info.filter_intra_mode[1] =
11088 filter_intra_mode_info_uv[uv_tx].filter_intra_mode[1];
11089 }
11090#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070011091
Jingning Han36fe3202017-02-20 22:31:49 -080011092#if CONFIG_CB4X4
11093 rate2 = rate_y + intra_mode_cost[mbmi->mode];
11094 if (!x->skip_chroma_rd)
Yue Chenb23d00a2017-07-28 17:01:21 -070011095 rate2 += rate_uv + x->intra_uv_mode_cost[mbmi->mode][mbmi->uv_mode];
Jingning Han36fe3202017-02-20 22:31:49 -080011096#else
Yaowu Xuc27fc142016-08-22 16:08:15 -070011097 rate2 = rate_y + intra_mode_cost[mbmi->mode] + rate_uv +
Yue Chenb23d00a2017-07-28 17:01:21 -070011098 x->intra_uv_mode_cost[mbmi->mode][mbmi->uv_mode];
Fergus Simpson4063a682017-02-28 16:52:22 -080011099#endif // CONFIG_CB4X4
Jingning Han36fe3202017-02-20 22:31:49 -080011100
hui su9bc1d8d2017-03-24 12:36:03 -070011101 if (try_palette && mbmi->mode == DC_PRED) {
Yaowu Xuf883b422016-08-30 14:01:10 -070011102 rate2 += av1_cost_bit(
11103 av1_default_palette_y_mode_prob[bsize - BLOCK_8X8][palette_ctx], 0);
hui su9bc1d8d2017-03-24 12:36:03 -070011104 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070011105
Rupert Swarbrickfcff0b22017-10-05 09:26:04 +010011106 if (!xd->lossless[mbmi->segment_id] && block_signals_txsize(bsize)) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070011107 // super_block_yrd above includes the cost of the tx_size in the
11108 // tokenonly rate, but for intra blocks, tx_size is always coded
11109 // (prediction granularity), so we account for it in the full rate,
11110 // not the tokenonly rate.
Urvang Joshifeb925f2016-12-05 10:37:29 -080011111 rate_y -= tx_size_cost(cpi, x, bsize, mbmi->tx_size);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011112 }
11113#if CONFIG_EXT_INTRA
11114 if (is_directional_mode) {
hui sueda3d762016-12-06 16:58:23 -080011115#if CONFIG_INTRA_INTERP
Yaowu Xuf883b422016-08-30 14:01:10 -070011116 const int intra_filter_ctx = av1_get_pred_context_intra_interp(xd);
hui su0a6731f2017-04-26 15:23:47 -070011117 const int p_angle =
11118 mode_to_angle_map[mbmi->mode] + mbmi->angle_delta[0] * ANGLE_STEP;
Yaowu Xuf883b422016-08-30 14:01:10 -070011119 if (av1_is_intra_filter_switchable(p_angle))
Yue Chenb23d00a2017-07-28 17:01:21 -070011120 rate2 += x->intra_filter_cost[intra_filter_ctx][mbmi->intra_filter];
hui sueda3d762016-12-06 16:58:23 -080011121#endif // CONFIG_INTRA_INTERP
Joe Young830d4ce2017-05-30 17:48:13 -070011122 if (av1_use_angle_delta(bsize)) {
11123 rate2 += write_uniform_cost(2 * MAX_ANGLE_DELTA + 1,
11124 MAX_ANGLE_DELTA + mbmi->angle_delta[0]);
11125 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070011126 }
Luc Trudeauf24a35f2017-09-11 11:56:33 -040011127 if (av1_is_directional_mode(get_uv_mode(mbmi->uv_mode), bsize) &&
Joe Young830d4ce2017-05-30 17:48:13 -070011128 av1_use_angle_delta(bsize)) {
hui su0a6731f2017-04-26 15:23:47 -070011129 rate2 += write_uniform_cost(2 * MAX_ANGLE_DELTA + 1,
11130 MAX_ANGLE_DELTA + mbmi->angle_delta[1]);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011131 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070011132#endif // CONFIG_EXT_INTRA
hui su5db97432016-10-14 16:10:14 -070011133#if CONFIG_FILTER_INTRA
11134 if (mbmi->mode == DC_PRED) {
11135 rate2 +=
11136 av1_cost_bit(cm->fc->filter_intra_probs[0],
11137 mbmi->filter_intra_mode_info.use_filter_intra_mode[0]);
11138 if (mbmi->filter_intra_mode_info.use_filter_intra_mode[0]) {
11139 rate2 += write_uniform_cost(
11140 FILTER_INTRA_MODES,
11141 mbmi->filter_intra_mode_info.filter_intra_mode[0]);
11142 }
11143 }
Luc Trudeaud6d9eee2017-07-12 12:36:50 -040011144 if (mbmi->uv_mode == UV_DC_PRED) {
hui su5db97432016-10-14 16:10:14 -070011145 rate2 +=
11146 av1_cost_bit(cpi->common.fc->filter_intra_probs[1],
11147 mbmi->filter_intra_mode_info.use_filter_intra_mode[1]);
11148 if (mbmi->filter_intra_mode_info.use_filter_intra_mode[1])
11149 rate2 += write_uniform_cost(
11150 FILTER_INTRA_MODES,
11151 mbmi->filter_intra_mode_info.filter_intra_mode[1]);
11152 }
11153#endif // CONFIG_FILTER_INTRA
Urvang Joshi96d1c0a2017-10-10 13:15:32 -070011154 if (mbmi->mode != DC_PRED && mbmi->mode != PAETH_PRED)
Yaowu Xuc27fc142016-08-22 16:08:15 -070011155 rate2 += intra_cost_penalty;
11156 distortion2 = distortion_y + distortion_uv;
Yaowu Xuc27fc142016-08-22 16:08:15 -070011157 } else {
Yaowu Xuc27fc142016-08-22 16:08:15 -070011158 int_mv backup_ref_mv[2];
11159
Debargha Mukherjee0f248c42017-09-07 12:40:18 -070011160 if (!is_comp_ref_allowed(bsize) && mbmi->ref_frame[1] > INTRA_FRAME)
11161 continue;
Jingning Hanc41a5492017-02-24 11:18:52 -080011162
Yaowu Xuc27fc142016-08-22 16:08:15 -070011163 backup_ref_mv[0] = mbmi_ext->ref_mvs[ref_frame][0];
11164 if (comp_pred) backup_ref_mv[1] = mbmi_ext->ref_mvs[second_ref_frame][0];
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020011165#if CONFIG_INTERINTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070011166 if (second_ref_frame == INTRA_FRAME) {
11167 if (best_single_inter_ref != ref_frame) continue;
Debargha Mukherjeecb603792016-10-04 13:10:23 -070011168 mbmi->interintra_mode = intra_to_interintra_mode[best_intra_mode];
hui su5db97432016-10-14 16:10:14 -070011169// TODO(debargha|geza.lore):
11170// Should we use ext_intra modes for interintra?
Yaowu Xuc27fc142016-08-22 16:08:15 -070011171#if CONFIG_EXT_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070011172 mbmi->angle_delta[0] = 0;
11173 mbmi->angle_delta[1] = 0;
hui sueda3d762016-12-06 16:58:23 -080011174#if CONFIG_INTRA_INTERP
Yaowu Xuc27fc142016-08-22 16:08:15 -070011175 mbmi->intra_filter = INTRA_FILTER_LINEAR;
hui sueda3d762016-12-06 16:58:23 -080011176#endif // CONFIG_INTRA_INTERP
Yaowu Xuc27fc142016-08-22 16:08:15 -070011177#endif // CONFIG_EXT_INTRA
hui su5db97432016-10-14 16:10:14 -070011178#if CONFIG_FILTER_INTRA
11179 mbmi->filter_intra_mode_info.use_filter_intra_mode[0] = 0;
11180 mbmi->filter_intra_mode_info.use_filter_intra_mode[1] = 0;
11181#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070011182 }
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020011183#endif // CONFIG_INTERINTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070011184 mbmi->ref_mv_idx = 0;
Yaowu Xuf883b422016-08-30 14:01:10 -070011185 ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011186
David Barker404b2e82017-03-27 13:07:47 +010011187 if (comp_pred) {
11188 if (mbmi_ext->ref_mv_count[ref_frame_type] > 1) {
David Barker3dfba992017-04-03 16:10:09 +010011189 int ref_mv_idx = 0;
11190 // Special case: NEAR_NEWMV and NEW_NEARMV modes use
11191 // 1 + mbmi->ref_mv_idx (like NEARMV) instead of
11192 // mbmi->ref_mv_idx (like NEWMV)
11193 if (mbmi->mode == NEAR_NEWMV || mbmi->mode == NEW_NEARMV)
11194 ref_mv_idx = 1;
11195
11196 if (compound_ref0_mode(mbmi->mode) == NEWMV) {
11197 int_mv this_mv =
11198 mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_idx].this_mv;
David Barker404b2e82017-03-27 13:07:47 +010011199 clamp_mv_ref(&this_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
11200 xd->n8_h << MI_SIZE_LOG2, xd);
11201 mbmi_ext->ref_mvs[mbmi->ref_frame[0]][0] = this_mv;
11202 }
David Barker3dfba992017-04-03 16:10:09 +010011203 if (compound_ref1_mode(mbmi->mode) == NEWMV) {
11204 int_mv this_mv =
11205 mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_idx].comp_mv;
David Barker404b2e82017-03-27 13:07:47 +010011206 clamp_mv_ref(&this_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
11207 xd->n8_h << MI_SIZE_LOG2, xd);
11208 mbmi_ext->ref_mvs[mbmi->ref_frame[1]][0] = this_mv;
11209 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070011210 }
Zoe Liu85b66462017-04-20 14:28:19 -070011211#if CONFIG_COMPOUND_SINGLEREF
11212 } else if (is_inter_singleref_comp_mode(mbmi->mode)) {
11213 if (mbmi_ext->ref_mv_count[ref_frame_type] > 1) {
11214 // TODO(zoeliu): To further investigate which ref_mv_idx should be
11215 // chosen for the mode of SR_NEAR_NEWMV.
11216 int ref_mv_idx = 0;
11217 // Special case: SR_NEAR_NEWMV mode use
11218 // 1 + mbmi->ref_mv_idx (like NEARMV) instead of
11219 // mbmi->ref_mv_idx (like NEWMV)
11220 if (mbmi->mode == SR_NEAR_NEWMV) ref_mv_idx = 1;
11221
11222 if (compound_ref0_mode(mbmi->mode) == NEWMV ||
11223 compound_ref1_mode(mbmi->mode) == NEWMV) {
11224 int_mv this_mv =
11225 mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_idx].this_mv;
11226 clamp_mv_ref(&this_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
11227 xd->n8_h << MI_SIZE_LOG2, xd);
11228 mbmi_ext->ref_mvs[mbmi->ref_frame[0]][0] = this_mv;
11229 }
11230 }
11231#endif // CONFIG_COMPOUND_SINGLEREF
David Barker404b2e82017-03-27 13:07:47 +010011232 } else {
Zoe Liu1157d502017-04-30 07:57:14 -070011233 if (mbmi->mode == NEWMV && mbmi_ext->ref_mv_count[ref_frame_type] > 1) {
David Barker404b2e82017-03-27 13:07:47 +010011234 int ref;
11235 for (ref = 0; ref < 1 + comp_pred; ++ref) {
11236 int_mv this_mv =
11237 (ref == 0) ? mbmi_ext->ref_mv_stack[ref_frame_type][0].this_mv
11238 : mbmi_ext->ref_mv_stack[ref_frame_type][0].comp_mv;
11239 clamp_mv_ref(&this_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
11240 xd->n8_h << MI_SIZE_LOG2, xd);
11241 mbmi_ext->ref_mvs[mbmi->ref_frame[ref]][0] = this_mv;
11242 }
11243 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070011244 }
Angie Chiang76159122016-11-09 12:13:22 -080011245 {
11246 RD_STATS rd_stats, rd_stats_y, rd_stats_uv;
11247 av1_init_rd_stats(&rd_stats);
11248 rd_stats.rate = rate2;
Fergus Simpson073c6f32017-02-17 12:13:48 -080011249
Zoe Liu7f24e1b2017-03-17 17:42:05 -070011250 // Point to variables that are maintained between loop iterations
11251 args.single_newmv = single_newmv;
Zoe Liu7f24e1b2017-03-17 17:42:05 -070011252 args.single_newmv_rate = single_newmv_rate;
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -080011253 args.modelled_rd = modelled_rd;
Fergus Simpson3424c2d2017-03-09 11:48:15 -080011254 this_rd = handle_inter_mode(cpi, x, bsize, &rd_stats, &rd_stats_y,
11255 &rd_stats_uv, &disable_skip, frame_mv,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020011256#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -070011257 frame_comp_mv,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020011258#endif // CONFIG_COMPOUND_SINGLEREF
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -080011259 mi_row, mi_col, &args, best_rd);
Angie Chiang76159122016-11-09 12:13:22 -080011260
11261 rate2 = rd_stats.rate;
11262 skippable = rd_stats.skip;
11263 distortion2 = rd_stats.dist;
11264 total_sse = rd_stats.sse;
11265 rate_y = rd_stats_y.rate;
11266 rate_uv = rd_stats_uv.rate;
11267 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070011268
David Barker404b2e82017-03-27 13:07:47 +010011269// TODO(jingning): This needs some refactoring to improve code quality
11270// and reduce redundant steps.
Zoe Liu85b66462017-04-20 14:28:19 -070011271#if CONFIG_COMPOUND_SINGLEREF
11272 if ((have_nearmv_in_inter_mode(mbmi->mode) &&
11273 mbmi_ext->ref_mv_count[ref_frame_type] > 2) ||
11274 ((mbmi->mode == NEWMV || mbmi->mode == SR_NEW_NEWMV ||
11275 mbmi->mode == NEW_NEWMV) &&
Yushin Cho67dda512017-07-25 14:58:22 -070011276 mbmi_ext->ref_mv_count[ref_frame_type] > 1))
Zoe Liu85b66462017-04-20 14:28:19 -070011277#else // !CONFIG_COMPOUND_SINGLEREF
David Barker3dfba992017-04-03 16:10:09 +010011278 if ((have_nearmv_in_inter_mode(mbmi->mode) &&
David Barker404b2e82017-03-27 13:07:47 +010011279 mbmi_ext->ref_mv_count[ref_frame_type] > 2) ||
11280 ((mbmi->mode == NEWMV || mbmi->mode == NEW_NEWMV) &&
Yushin Cho67dda512017-07-25 14:58:22 -070011281 mbmi_ext->ref_mv_count[ref_frame_type] > 1))
Zoe Liu85b66462017-04-20 14:28:19 -070011282#endif // CONFIG_COMPOUND_SINGLEREF
Yushin Cho67dda512017-07-25 14:58:22 -070011283 {
Yaowu Xuc27fc142016-08-22 16:08:15 -070011284 int_mv backup_mv = frame_mv[NEARMV][ref_frame];
11285 MB_MODE_INFO backup_mbmi = *mbmi;
11286 int backup_skip = x->skip;
11287 int64_t tmp_ref_rd = this_rd;
11288 int ref_idx;
11289
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020011290 // TODO(jingning): This should be deprecated shortly.
David Barker3dfba992017-04-03 16:10:09 +010011291 int idx_offset = have_nearmv_in_inter_mode(mbmi->mode) ? 1 : 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -070011292 int ref_set =
Yaowu Xuf883b422016-08-30 14:01:10 -070011293 AOMMIN(2, mbmi_ext->ref_mv_count[ref_frame_type] - 1 - idx_offset);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011294
11295 uint8_t drl_ctx =
Yaowu Xuf883b422016-08-30 14:01:10 -070011296 av1_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], idx_offset);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011297 // Dummy
11298 int_mv backup_fmv[2];
11299 backup_fmv[0] = frame_mv[NEWMV][ref_frame];
11300 if (comp_pred) backup_fmv[1] = frame_mv[NEWMV][second_ref_frame];
11301
Yue Chenb23d00a2017-07-28 17:01:21 -070011302 rate2 += (rate2 < INT_MAX ? x->drl_mode_cost0[drl_ctx][0] : 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011303
11304 if (this_rd < INT64_MAX) {
Urvang Joshi70006e42017-06-14 16:08:55 -070011305 if (RDCOST(x->rdmult, rate_y + rate_uv, distortion2) <
11306 RDCOST(x->rdmult, 0, total_sse))
11307 tmp_ref_rd = RDCOST(
11308 x->rdmult, rate2 + av1_cost_bit(av1_get_skip_prob(cm, xd), 0),
11309 distortion2);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011310 else
clang-format4eafefe2017-09-04 12:51:20 -070011311 tmp_ref_rd =
11312 RDCOST(x->rdmult,
11313 rate2 + av1_cost_bit(av1_get_skip_prob(cm, xd), 1) -
11314 rate_y - rate_uv,
11315 total_sse);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011316 }
11317#if CONFIG_VAR_TX
11318 for (i = 0; i < MAX_MB_PLANE; ++i)
11319 memcpy(x->blk_skip_drl[i], x->blk_skip[i],
11320 sizeof(uint8_t) * ctx->num_4x4_blk);
Fergus Simpson4063a682017-02-28 16:52:22 -080011321#endif // CONFIG_VAR_TX
Yaowu Xuc27fc142016-08-22 16:08:15 -070011322
11323 for (ref_idx = 0; ref_idx < ref_set; ++ref_idx) {
11324 int64_t tmp_alt_rd = INT64_MAX;
Yaowu Xuc27fc142016-08-22 16:08:15 -070011325 int dummy_disable_skip = 0;
11326 int ref;
11327 int_mv cur_mv;
Angie Chiang76159122016-11-09 12:13:22 -080011328 RD_STATS tmp_rd_stats, tmp_rd_stats_y, tmp_rd_stats_uv;
Yaowu Xuc27fc142016-08-22 16:08:15 -070011329
Yaowu Xu5bfbfdf2016-11-22 16:43:34 -080011330 av1_invalid_rd_stats(&tmp_rd_stats);
Yushin Choc0f6bf22017-06-09 16:08:02 -070011331
Jingning Han52617b22017-04-11 12:50:08 -070011332 x->skip = 0;
Yaowu Xu5bfbfdf2016-11-22 16:43:34 -080011333
Yaowu Xuc27fc142016-08-22 16:08:15 -070011334 mbmi->ref_mv_idx = 1 + ref_idx;
11335
David Barker3dfba992017-04-03 16:10:09 +010011336 if (comp_pred) {
11337 int ref_mv_idx = mbmi->ref_mv_idx;
11338 // Special case: NEAR_NEWMV and NEW_NEARMV modes use
11339 // 1 + mbmi->ref_mv_idx (like NEARMV) instead of
11340 // mbmi->ref_mv_idx (like NEWMV)
11341 if (mbmi->mode == NEAR_NEWMV || mbmi->mode == NEW_NEARMV)
11342 ref_mv_idx = 1 + mbmi->ref_mv_idx;
11343
11344 if (compound_ref0_mode(mbmi->mode) == NEWMV) {
11345 int_mv this_mv =
11346 mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_idx].this_mv;
11347 clamp_mv_ref(&this_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
11348 xd->n8_h << MI_SIZE_LOG2, xd);
11349 mbmi_ext->ref_mvs[mbmi->ref_frame[0]][0] = this_mv;
11350 } else if (compound_ref0_mode(mbmi->mode) == NEARESTMV) {
11351 int_mv this_mv =
11352 mbmi_ext->ref_mv_stack[ref_frame_type][0].this_mv;
11353 clamp_mv_ref(&this_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
11354 xd->n8_h << MI_SIZE_LOG2, xd);
11355 mbmi_ext->ref_mvs[mbmi->ref_frame[0]][0] = this_mv;
11356 }
11357
11358 if (compound_ref1_mode(mbmi->mode) == NEWMV) {
11359 int_mv this_mv =
11360 mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_idx].comp_mv;
11361 clamp_mv_ref(&this_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
11362 xd->n8_h << MI_SIZE_LOG2, xd);
11363 mbmi_ext->ref_mvs[mbmi->ref_frame[1]][0] = this_mv;
11364 } else if (compound_ref1_mode(mbmi->mode) == NEARESTMV) {
11365 int_mv this_mv =
11366 mbmi_ext->ref_mv_stack[ref_frame_type][0].comp_mv;
11367 clamp_mv_ref(&this_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
11368 xd->n8_h << MI_SIZE_LOG2, xd);
11369 mbmi_ext->ref_mvs[mbmi->ref_frame[1]][0] = this_mv;
11370 }
Zoe Liu85b66462017-04-20 14:28:19 -070011371#if CONFIG_COMPOUND_SINGLEREF
11372 } else if (is_inter_singleref_comp_mode(mbmi->mode)) {
11373 int ref_mv_idx = mbmi->ref_mv_idx;
11374 // Special case: SR_NEAR_NEWMV mode use
11375 // 1 + mbmi->ref_mv_idx (like NEARMV) instead of
11376 // mbmi->ref_mv_idx (like NEWMV)
11377 if (mbmi->mode == SR_NEAR_NEWMV) ref_mv_idx = 1 + mbmi->ref_mv_idx;
11378
11379 // TODO(zoeliu): For the mode of SR_NEAREST_NEWMV, as it only runs
11380 // the "if", not the "else if",
11381 // mbmi_ext->ref_mvs[mbmi->ref_frame[0]] takes the
11382 // value for "NEWMV", instead of "NEARESTMV".
11383 if (compound_ref0_mode(mbmi->mode) == NEWMV ||
11384 compound_ref1_mode(mbmi->mode) == NEWMV) {
11385 int_mv this_mv =
11386 mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_idx].this_mv;
11387 clamp_mv_ref(&this_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
11388 xd->n8_h << MI_SIZE_LOG2, xd);
11389 mbmi_ext->ref_mvs[mbmi->ref_frame[0]][0] = this_mv;
11390 } else if (compound_ref0_mode(mbmi->mode) == NEARESTMV ||
11391 compound_ref1_mode(mbmi->mode) == NEARESTMV) {
11392 int_mv this_mv =
11393 mbmi_ext->ref_mv_stack[ref_frame_type][0].this_mv;
11394 clamp_mv_ref(&this_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
11395 xd->n8_h << MI_SIZE_LOG2, xd);
11396 mbmi_ext->ref_mvs[mbmi->ref_frame[0]][0] = this_mv;
11397 }
11398#endif // CONFIG_COMPOUND_SINGLEREF
David Barker3dfba992017-04-03 16:10:09 +010011399 } else {
David Barker3dfba992017-04-03 16:10:09 +010011400 for (ref = 0; ref < 1 + comp_pred; ++ref) {
11401 int_mv this_mv =
11402 (ref == 0)
11403 ? mbmi_ext->ref_mv_stack[ref_frame_type][mbmi->ref_mv_idx]
11404 .this_mv
11405 : mbmi_ext->ref_mv_stack[ref_frame_type][mbmi->ref_mv_idx]
11406 .comp_mv;
11407 clamp_mv_ref(&this_mv.as_mv, xd->n8_w << MI_SIZE_LOG2,
11408 xd->n8_h << MI_SIZE_LOG2, xd);
11409 mbmi_ext->ref_mvs[mbmi->ref_frame[ref]][0] = this_mv;
11410 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070011411 }
11412
11413 cur_mv =
11414 mbmi_ext->ref_mv_stack[ref_frame][mbmi->ref_mv_idx + idx_offset]
11415 .this_mv;
11416 clamp_mv2(&cur_mv.as_mv, xd);
11417
Alex Converse0fa0f422017-04-24 12:51:14 -070011418 if (!mv_check_bounds(&x->mv_limits, &cur_mv.as_mv)) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070011419 int_mv dummy_single_newmv[TOTAL_REFS_PER_FRAME] = { { 0 } };
Zoe Liu7f24e1b2017-03-17 17:42:05 -070011420 int dummy_single_newmv_rate[TOTAL_REFS_PER_FRAME] = { 0 };
Yaowu Xuc27fc142016-08-22 16:08:15 -070011421
11422 frame_mv[NEARMV][ref_frame] = cur_mv;
Angie Chiang76159122016-11-09 12:13:22 -080011423 av1_init_rd_stats(&tmp_rd_stats);
Yushin Cho8e75e8b2017-09-12 16:33:28 -070011424
Zoe Liu7f24e1b2017-03-17 17:42:05 -070011425 // Point to variables that are not maintained between iterations
11426 args.single_newmv = dummy_single_newmv;
Zoe Liu7f24e1b2017-03-17 17:42:05 -070011427 args.single_newmv_rate = dummy_single_newmv_rate;
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -080011428 args.modelled_rd = NULL;
Zoe Liu85b66462017-04-20 14:28:19 -070011429 tmp_alt_rd = handle_inter_mode(cpi, x, bsize, &tmp_rd_stats,
11430 &tmp_rd_stats_y, &tmp_rd_stats_uv,
11431 &dummy_disable_skip, frame_mv,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020011432#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -070011433 frame_comp_mv,
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020011434#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -070011435 mi_row, mi_col, &args, best_rd);
Zoe Liu7f24e1b2017-03-17 17:42:05 -070011436 // Prevent pointers from escaping local scope
11437 args.single_newmv = NULL;
Zoe Liu7f24e1b2017-03-17 17:42:05 -070011438 args.single_newmv_rate = NULL;
Yaowu Xuc27fc142016-08-22 16:08:15 -070011439 }
11440
11441 for (i = 0; i < mbmi->ref_mv_idx; ++i) {
11442 uint8_t drl1_ctx = 0;
Yaowu Xuf883b422016-08-30 14:01:10 -070011443 drl1_ctx = av1_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type],
11444 i + idx_offset);
Angie Chiang76159122016-11-09 12:13:22 -080011445 tmp_rd_stats.rate +=
Yue Chenb23d00a2017-07-28 17:01:21 -070011446 (tmp_rd_stats.rate < INT_MAX ? x->drl_mode_cost0[drl1_ctx][1]
Angie Chiang76159122016-11-09 12:13:22 -080011447 : 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011448 }
11449
11450 if (mbmi_ext->ref_mv_count[ref_frame_type] >
11451 mbmi->ref_mv_idx + idx_offset + 1 &&
11452 ref_idx < ref_set - 1) {
11453 uint8_t drl1_ctx =
Yaowu Xuf883b422016-08-30 14:01:10 -070011454 av1_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type],
11455 mbmi->ref_mv_idx + idx_offset);
Yaowu Xu83ed6fe2016-11-22 11:15:29 -080011456 tmp_rd_stats.rate +=
Yue Chenb23d00a2017-07-28 17:01:21 -070011457 (tmp_rd_stats.rate < INT_MAX ? x->drl_mode_cost0[drl1_ctx][0]
Yaowu Xu83ed6fe2016-11-22 11:15:29 -080011458 : 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011459 }
11460
11461 if (tmp_alt_rd < INT64_MAX) {
Yue Chen69f18e12016-09-08 14:48:15 -070011462#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
Urvang Joshi70006e42017-06-14 16:08:55 -070011463 tmp_alt_rd =
11464 RDCOST(x->rdmult, tmp_rd_stats.rate, tmp_rd_stats.dist);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011465#else
Urvang Joshi70006e42017-06-14 16:08:55 -070011466 if (RDCOST(x->rdmult, tmp_rd_stats_y.rate + tmp_rd_stats_uv.rate,
Angie Chiang76159122016-11-09 12:13:22 -080011467 tmp_rd_stats.dist) <
Urvang Joshi70006e42017-06-14 16:08:55 -070011468 RDCOST(x->rdmult, 0, tmp_rd_stats.sse))
clang-format4eafefe2017-09-04 12:51:20 -070011469 tmp_alt_rd =
11470 RDCOST(x->rdmult,
11471 tmp_rd_stats.rate +
11472 av1_cost_bit(av1_get_skip_prob(cm, xd), 0),
11473 tmp_rd_stats.dist);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011474 else
clang-format4eafefe2017-09-04 12:51:20 -070011475 tmp_alt_rd =
11476 RDCOST(x->rdmult,
11477 tmp_rd_stats.rate +
11478 av1_cost_bit(av1_get_skip_prob(cm, xd), 1) -
11479 tmp_rd_stats_y.rate - tmp_rd_stats_uv.rate,
11480 tmp_rd_stats.sse);
Yue Chen69f18e12016-09-08 14:48:15 -070011481#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -070011482 }
11483
11484 if (tmp_ref_rd > tmp_alt_rd) {
Angie Chiang76159122016-11-09 12:13:22 -080011485 rate2 = tmp_rd_stats.rate;
Yaowu Xuc27fc142016-08-22 16:08:15 -070011486 disable_skip = dummy_disable_skip;
Angie Chiang76159122016-11-09 12:13:22 -080011487 distortion2 = tmp_rd_stats.dist;
11488 skippable = tmp_rd_stats.skip;
11489 rate_y = tmp_rd_stats_y.rate;
11490 rate_uv = tmp_rd_stats_uv.rate;
11491 total_sse = tmp_rd_stats.sse;
Yaowu Xuc27fc142016-08-22 16:08:15 -070011492 this_rd = tmp_alt_rd;
11493 tmp_ref_rd = tmp_alt_rd;
11494 backup_mbmi = *mbmi;
11495 backup_skip = x->skip;
11496#if CONFIG_VAR_TX
11497 for (i = 0; i < MAX_MB_PLANE; ++i)
11498 memcpy(x->blk_skip_drl[i], x->blk_skip[i],
11499 sizeof(uint8_t) * ctx->num_4x4_blk);
Fergus Simpson4063a682017-02-28 16:52:22 -080011500#endif // CONFIG_VAR_TX
Yaowu Xuc27fc142016-08-22 16:08:15 -070011501 } else {
11502 *mbmi = backup_mbmi;
11503 x->skip = backup_skip;
11504 }
11505 }
11506
11507 frame_mv[NEARMV][ref_frame] = backup_mv;
11508 frame_mv[NEWMV][ref_frame] = backup_fmv[0];
11509 if (comp_pred) frame_mv[NEWMV][second_ref_frame] = backup_fmv[1];
11510#if CONFIG_VAR_TX
11511 for (i = 0; i < MAX_MB_PLANE; ++i)
11512 memcpy(x->blk_skip[i], x->blk_skip_drl[i],
11513 sizeof(uint8_t) * ctx->num_4x4_blk);
Fergus Simpson4063a682017-02-28 16:52:22 -080011514#endif // CONFIG_VAR_TX
Yaowu Xuc27fc142016-08-22 16:08:15 -070011515 }
11516 mbmi_ext->ref_mvs[ref_frame][0] = backup_ref_mv[0];
11517 if (comp_pred) mbmi_ext->ref_mvs[second_ref_frame][0] = backup_ref_mv[1];
Yaowu Xuc27fc142016-08-22 16:08:15 -070011518
11519 if (this_rd == INT64_MAX) continue;
11520
Debargha Mukherjee0f248c42017-09-07 12:40:18 -070011521 if (is_comp_ref_allowed(mbmi->sb_type))
Jingning Hanc41a5492017-02-24 11:18:52 -080011522 compmode_cost = av1_cost_bit(comp_mode_p, comp_pred);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011523
11524 if (cm->reference_mode == REFERENCE_MODE_SELECT) rate2 += compmode_cost;
11525 }
11526
Yaowu Xuc27fc142016-08-22 16:08:15 -070011527 // Estimate the reference frame signaling cost and add it
11528 // to the rolling cost variable.
11529 if (comp_pred) {
Zoe Liuc082bbc2017-05-17 13:31:37 -070011530#if CONFIG_EXT_COMP_REFS
11531 rate2 += ref_costs_comp[ref_frame][second_ref_frame];
11532#else // !CONFIG_EXT_COMP_REFS
Yaowu Xuc27fc142016-08-22 16:08:15 -070011533 rate2 += ref_costs_comp[ref_frame];
11534#if CONFIG_EXT_REFS
11535 rate2 += ref_costs_comp[second_ref_frame];
11536#endif // CONFIG_EXT_REFS
Zoe Liuc082bbc2017-05-17 13:31:37 -070011537#endif // CONFIG_EXT_COMP_REFS
Yaowu Xuc27fc142016-08-22 16:08:15 -070011538 } else {
11539 rate2 += ref_costs_single[ref_frame];
11540 }
11541
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020011542#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -070011543 // Add the cost to signal single/comp mode in single ref.
11544 if (!comp_pred && cm->reference_mode != COMPOUND_REFERENCE) {
11545 aom_prob singleref_comp_mode_p = av1_get_inter_mode_prob(cm, xd);
11546 rate2 += av1_cost_bit(singleref_comp_mode_p,
11547 is_inter_singleref_comp_mode(mbmi->mode));
11548 }
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020011549#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -070011550
Yue Chen69f18e12016-09-08 14:48:15 -070011551#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
Yushin Cho67dda512017-07-25 14:58:22 -070011552 if (ref_frame == INTRA_FRAME)
Yaowu Xuc27fc142016-08-22 16:08:15 -070011553#else
Yushin Cho67dda512017-07-25 14:58:22 -070011554 if (!disable_skip)
Yue Chen69f18e12016-09-08 14:48:15 -070011555#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
Yushin Cho67dda512017-07-25 14:58:22 -070011556 {
Yaowu Xuc27fc142016-08-22 16:08:15 -070011557 if (skippable) {
11558 // Back out the coefficient coding costs
11559 rate2 -= (rate_y + rate_uv);
11560 rate_y = 0;
11561 rate_uv = 0;
11562 // Cost the skip mb case
Yaowu Xuf883b422016-08-30 14:01:10 -070011563 rate2 += av1_cost_bit(av1_get_skip_prob(cm, xd), 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011564 } else if (ref_frame != INTRA_FRAME && !xd->lossless[mbmi->segment_id]) {
Urvang Joshi70006e42017-06-14 16:08:55 -070011565 if (RDCOST(x->rdmult, rate_y + rate_uv + rate_skip0, distortion2) <
11566 RDCOST(x->rdmult, rate_skip1, total_sse)) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070011567 // Add in the cost of the no skip flag.
Yaowu Xuf883b422016-08-30 14:01:10 -070011568 rate2 += av1_cost_bit(av1_get_skip_prob(cm, xd), 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011569 } else {
11570 // FIXME(rbultje) make this work for splitmv also
Yaowu Xuf883b422016-08-30 14:01:10 -070011571 rate2 += av1_cost_bit(av1_get_skip_prob(cm, xd), 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011572 distortion2 = total_sse;
11573 assert(total_sse >= 0);
11574 rate2 -= (rate_y + rate_uv);
11575 this_skip2 = 1;
11576 rate_y = 0;
11577 rate_uv = 0;
11578 }
11579 } else {
11580 // Add in the cost of the no skip flag.
Yaowu Xuf883b422016-08-30 14:01:10 -070011581 rate2 += av1_cost_bit(av1_get_skip_prob(cm, xd), 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011582 }
11583
11584 // Calculate the final RD estimate for this mode.
Urvang Joshi70006e42017-06-14 16:08:55 -070011585 this_rd = RDCOST(x->rdmult, rate2, distortion2);
Yue Chen69f18e12016-09-08 14:48:15 -070011586#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -070011587 } else {
11588 this_skip2 = mbmi->skip;
Urvang Joshi70006e42017-06-14 16:08:55 -070011589 this_rd = RDCOST(x->rdmult, rate2, distortion2);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011590 if (this_skip2) {
11591 rate_y = 0;
11592 rate_uv = 0;
11593 }
Yue Chen69f18e12016-09-08 14:48:15 -070011594#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -070011595 }
11596
Yaowu Xuc27fc142016-08-22 16:08:15 -070011597 if (ref_frame == INTRA_FRAME) {
11598 // Keep record of best intra rd
11599 if (this_rd < best_intra_rd) {
11600 best_intra_rd = this_rd;
11601 best_intra_mode = mbmi->mode;
11602 }
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020011603#if CONFIG_INTERINTRA
Emil Keyder01770b32017-01-20 18:03:11 -050011604 } else if (second_ref_frame == NONE_FRAME) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070011605 if (this_rd < best_single_inter_rd) {
11606 best_single_inter_rd = this_rd;
11607 best_single_inter_ref = mbmi->ref_frame[0];
11608 }
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020011609#endif // CONFIG_INTERINTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070011610 }
11611
11612 if (!disable_skip && ref_frame == INTRA_FRAME) {
11613 for (i = 0; i < REFERENCE_MODES; ++i)
Yaowu Xuf883b422016-08-30 14:01:10 -070011614 best_pred_rd[i] = AOMMIN(best_pred_rd[i], this_rd);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011615 }
11616
11617 // Did this mode help.. i.e. is it the new best mode
11618 if (this_rd < best_rd || x->skip) {
11619 if (!mode_excluded) {
11620 // Note index of best mode so far
11621 best_mode_index = mode_index;
11622
11623 if (ref_frame == INTRA_FRAME) {
11624 /* required for left and above block mv */
11625 mbmi->mv[0].as_int = 0;
11626 } else {
11627 best_pred_sse = x->pred_sse[ref_frame];
11628 }
11629
11630 rd_cost->rate = rate2;
11631#if CONFIG_SUPERTX
11632 if (x->skip)
11633 *returnrate_nocoef = rate2;
11634 else
11635 *returnrate_nocoef = rate2 - rate_y - rate_uv;
Yaowu Xuf883b422016-08-30 14:01:10 -070011636 *returnrate_nocoef -= av1_cost_bit(
11637 av1_get_skip_prob(cm, xd), disable_skip || skippable || this_skip2);
11638 *returnrate_nocoef -= av1_cost_bit(av1_get_intra_inter_prob(cm, xd),
11639 mbmi->ref_frame[0] != INTRA_FRAME);
Yue Chencb60b182016-10-13 15:18:22 -070011640#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
Yue Chen52c51732017-07-11 15:08:30 -070011641#if CONFIG_WARPED_MOTION
11642 set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
11643#endif
Yaowu Xu41a36de2017-03-23 15:55:03 -070011644#if CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
11645 MODE_INFO *const mi = xd->mi[0];
Sarah Parker19234cc2017-03-10 16:43:25 -080011646 const MOTION_MODE motion_allowed = motion_mode_allowed(
Sarah Parker0eea89f2017-07-11 11:56:36 -070011647#if CONFIG_GLOBAL_MOTION
Sarah Parker19234cc2017-03-10 16:43:25 -080011648 0, xd->global_motion,
Sarah Parker0eea89f2017-07-11 11:56:36 -070011649#endif // CONFIG_GLOBAL_MOTION
Yue Chen52c51732017-07-11 15:08:30 -070011650#if CONFIG_WARPED_MOTION
11651 xd,
11652#endif
Sarah Parker19234cc2017-03-10 16:43:25 -080011653 mi);
Sarah Parker19234cc2017-03-10 16:43:25 -080011654 if (motion_allowed == WARPED_CAUSAL)
Yue Chenbdc8dab2017-07-26 12:05:47 -070011655 *returnrate_nocoef -= x->motion_mode_cost[bsize][mbmi->motion_mode];
Sarah Parker19234cc2017-03-10 16:43:25 -080011656 else if (motion_allowed == OBMC_CAUSAL)
Yue Chenb23d00a2017-07-28 17:01:21 -070011657 *returnrate_nocoef -= x->motion_mode_cost1[bsize][mbmi->motion_mode];
Yaowu Xu41a36de2017-03-23 15:55:03 -070011658#else
Yue Chenbdc8dab2017-07-26 12:05:47 -070011659 *returnrate_nocoef -= x->motion_mode_cost[bsize][mbmi->motion_mode];
Yue Chen69f18e12016-09-08 14:48:15 -070011660#endif // CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
Yue Chencb60b182016-10-13 15:18:22 -070011661#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -070011662#endif // CONFIG_SUPERTX
11663 rd_cost->dist = distortion2;
11664 rd_cost->rdcost = this_rd;
11665 best_rd = this_rd;
11666 best_mbmode = *mbmi;
11667 best_skip2 = this_skip2;
11668 best_mode_skippable = skippable;
Yaowu Xuf883b422016-08-30 14:01:10 -070011669 best_rate_y = rate_y + av1_cost_bit(av1_get_skip_prob(cm, xd),
11670 this_skip2 || skippable);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011671 best_rate_uv = rate_uv;
Yaowu Xuc27fc142016-08-22 16:08:15 -070011672#if CONFIG_VAR_TX
11673 for (i = 0; i < MAX_MB_PLANE; ++i)
11674 memcpy(ctx->blk_skip[i], x->blk_skip[i],
11675 sizeof(uint8_t) * ctx->num_4x4_blk);
Fergus Simpson4063a682017-02-28 16:52:22 -080011676#endif // CONFIG_VAR_TX
Yaowu Xuc27fc142016-08-22 16:08:15 -070011677 }
11678 }
Yushin Cho8e75e8b2017-09-12 16:33:28 -070011679
Yaowu Xuc27fc142016-08-22 16:08:15 -070011680 /* keep record of best compound/single-only prediction */
11681 if (!disable_skip && ref_frame != INTRA_FRAME) {
11682 int64_t single_rd, hybrid_rd, single_rate, hybrid_rate;
11683
11684 if (cm->reference_mode == REFERENCE_MODE_SELECT) {
11685 single_rate = rate2 - compmode_cost;
11686 hybrid_rate = rate2;
11687 } else {
11688 single_rate = rate2;
11689 hybrid_rate = rate2 + compmode_cost;
11690 }
11691
Urvang Joshi70006e42017-06-14 16:08:55 -070011692 single_rd = RDCOST(x->rdmult, single_rate, distortion2);
11693 hybrid_rd = RDCOST(x->rdmult, hybrid_rate, distortion2);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011694
11695 if (!comp_pred) {
11696 if (single_rd < best_pred_rd[SINGLE_REFERENCE])
11697 best_pred_rd[SINGLE_REFERENCE] = single_rd;
11698 } else {
11699 if (single_rd < best_pred_rd[COMPOUND_REFERENCE])
11700 best_pred_rd[COMPOUND_REFERENCE] = single_rd;
11701 }
11702 if (hybrid_rd < best_pred_rd[REFERENCE_MODE_SELECT])
11703 best_pred_rd[REFERENCE_MODE_SELECT] = hybrid_rd;
11704 }
11705
Yaowu Xuc27fc142016-08-22 16:08:15 -070011706 if (x->skip && !comp_pred) break;
11707 }
11708
11709 if (xd->lossless[mbmi->segment_id] == 0 && best_mode_index >= 0 &&
11710 ((sf->tx_type_search.fast_inter_tx_type_search == 1 &&
11711 is_inter_mode(best_mbmode.mode)) ||
11712 (sf->tx_type_search.fast_intra_tx_type_search == 1 &&
11713 !is_inter_mode(best_mbmode.mode)))) {
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011714 int skip_blk = 0;
11715 RD_STATS rd_stats_y, rd_stats_uv;
Yaowu Xuc27fc142016-08-22 16:08:15 -070011716
11717 x->use_default_inter_tx_type = 0;
11718 x->use_default_intra_tx_type = 0;
11719
11720 *mbmi = best_mbmode;
11721
11722 set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
11723
11724 // Select prediction reference frames.
11725 for (i = 0; i < MAX_MB_PLANE; i++) {
11726 xd->plane[i].pre[0] = yv12_mb[mbmi->ref_frame[0]][i];
11727 if (has_second_ref(mbmi))
11728 xd->plane[i].pre[1] = yv12_mb[mbmi->ref_frame[1]][i];
11729 }
11730
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020011731#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -070011732 // Single ref compound mode
11733 if (!has_second_ref(mbmi) && is_inter_singleref_comp_mode(mbmi->mode)) {
11734 xd->block_refs[1] = xd->block_refs[0];
11735 for (i = 0; i < MAX_MB_PLANE; i++)
11736 xd->plane[i].pre[1] = xd->plane[i].pre[0];
11737 }
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020011738#endif // CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -070011739
Yaowu Xuc27fc142016-08-22 16:08:15 -070011740 if (is_inter_mode(mbmi->mode)) {
Jingning Hanc44009c2017-05-06 11:36:49 -070011741 av1_build_inter_predictors_sb(cm, xd, mi_row, mi_col, NULL, bsize);
Yue Chencb60b182016-10-13 15:18:22 -070011742#if CONFIG_MOTION_VAR
Sarah Parker19234cc2017-03-10 16:43:25 -080011743 if (mbmi->motion_mode == OBMC_CAUSAL) {
Fergus Simpson073c6f32017-02-17 12:13:48 -080011744 av1_build_obmc_inter_prediction(
Fergus Simpson9f7ca0b2017-03-10 10:46:46 -080011745 cm, xd, mi_row, mi_col, args.above_pred_buf, args.above_pred_stride,
11746 args.left_pred_buf, args.left_pred_stride);
Sarah Parker19234cc2017-03-10 16:43:25 -080011747 }
Yue Chencb60b182016-10-13 15:18:22 -070011748#endif // CONFIG_MOTION_VAR
Yaowu Xuf883b422016-08-30 14:01:10 -070011749 av1_subtract_plane(x, bsize, 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011750#if CONFIG_VAR_TX
11751 if (cm->tx_mode == TX_MODE_SELECT || xd->lossless[mbmi->segment_id]) {
Angie Chiangb5dda482016-11-02 16:19:58 -070011752 select_tx_type_yrd(cpi, x, &rd_stats_y, bsize, INT64_MAX);
Hui Su1ddf2312017-08-19 15:21:34 -070011753 assert(rd_stats_y.rate != INT_MAX);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011754 } else {
11755 int idx, idy;
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011756 super_block_yrd(cpi, x, &rd_stats_y, bsize, INT64_MAX);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011757 for (idy = 0; idy < xd->n8_h; ++idy)
11758 for (idx = 0; idx < xd->n8_w; ++idx)
11759 mbmi->inter_tx_size[idy][idx] = mbmi->tx_size;
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011760 memset(x->blk_skip[0], rd_stats_y.skip,
Yaowu Xuc27fc142016-08-22 16:08:15 -070011761 sizeof(uint8_t) * xd->n8_h * xd->n8_w * 4);
11762 }
11763
Angie Chiangb5dda482016-11-02 16:19:58 -070011764 inter_block_uvrd(cpi, x, &rd_stats_uv, bsize, INT64_MAX);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011765#else
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011766 super_block_yrd(cpi, x, &rd_stats_y, bsize, INT64_MAX);
Angie Chiang284d7772016-11-08 11:06:45 -080011767 super_block_uvrd(cpi, x, &rd_stats_uv, bsize, INT64_MAX);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011768#endif // CONFIG_VAR_TX
11769 } else {
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011770 super_block_yrd(cpi, x, &rd_stats_y, bsize, INT64_MAX);
Angie Chiang284d7772016-11-08 11:06:45 -080011771 super_block_uvrd(cpi, x, &rd_stats_uv, bsize, INT64_MAX);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011772 }
11773
Urvang Joshi70006e42017-06-14 16:08:55 -070011774 if (RDCOST(x->rdmult, rd_stats_y.rate + rd_stats_uv.rate,
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011775 (rd_stats_y.dist + rd_stats_uv.dist)) >
Urvang Joshi70006e42017-06-14 16:08:55 -070011776 RDCOST(x->rdmult, 0, (rd_stats_y.sse + rd_stats_uv.sse))) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070011777 skip_blk = 1;
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011778 rd_stats_y.rate = av1_cost_bit(av1_get_skip_prob(cm, xd), 1);
11779 rd_stats_uv.rate = 0;
11780 rd_stats_y.dist = rd_stats_y.sse;
11781 rd_stats_uv.dist = rd_stats_uv.sse;
Yaowu Xuc27fc142016-08-22 16:08:15 -070011782 } else {
11783 skip_blk = 0;
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011784 rd_stats_y.rate += av1_cost_bit(av1_get_skip_prob(cm, xd), 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011785 }
11786
Urvang Joshi70006e42017-06-14 16:08:55 -070011787 if (RDCOST(x->rdmult, best_rate_y + best_rate_uv, rd_cost->dist) >
11788 RDCOST(x->rdmult, rd_stats_y.rate + rd_stats_uv.rate,
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011789 (rd_stats_y.dist + rd_stats_uv.dist))) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070011790#if CONFIG_VAR_TX
11791 int idx, idy;
Fergus Simpson4063a682017-02-28 16:52:22 -080011792#endif // CONFIG_VAR_TX
Yaowu Xuc27fc142016-08-22 16:08:15 -070011793 best_mbmode.tx_type = mbmi->tx_type;
11794 best_mbmode.tx_size = mbmi->tx_size;
Lester Lu432012f2017-08-17 14:39:29 -070011795#if CONFIG_LGT_FROM_PRED
11796 best_mbmode.use_lgt = mbmi->use_lgt;
11797#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -070011798#if CONFIG_VAR_TX
11799 for (idy = 0; idy < xd->n8_h; ++idy)
11800 for (idx = 0; idx < xd->n8_w; ++idx)
11801 best_mbmode.inter_tx_size[idy][idx] = mbmi->inter_tx_size[idy][idx];
11802
11803 for (i = 0; i < MAX_MB_PLANE; ++i)
11804 memcpy(ctx->blk_skip[i], x->blk_skip[i],
11805 sizeof(uint8_t) * ctx->num_4x4_blk);
Jingning Hane67b38a2016-11-04 10:30:00 -070011806
11807 best_mbmode.min_tx_size = mbmi->min_tx_size;
Fergus Simpson4063a682017-02-28 16:52:22 -080011808#endif // CONFIG_VAR_TX
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011809 rd_cost->rate +=
11810 (rd_stats_y.rate + rd_stats_uv.rate - best_rate_y - best_rate_uv);
11811 rd_cost->dist = rd_stats_y.dist + rd_stats_uv.dist;
Urvang Joshi70006e42017-06-14 16:08:55 -070011812 rd_cost->rdcost = RDCOST(x->rdmult, rd_cost->rate, rd_cost->dist);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011813 best_skip2 = skip_blk;
11814 }
11815 }
11816
11817 // Only try palette mode when the best mode so far is an intra mode.
hui su9bc1d8d2017-03-24 12:36:03 -070011818 if (try_palette && !is_inter_mode(best_mbmode.mode)) {
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011819 int rate2 = 0;
Yaowu Xuc27fc142016-08-22 16:08:15 -070011820#if CONFIG_SUPERTX
11821 int best_rate_nocoef;
Fergus Simpson4063a682017-02-28 16:52:22 -080011822#endif // CONFIG_SUPERTX
Urvang Joshi451e0f22017-01-31 11:18:31 -080011823 int64_t distortion2 = 0, best_rd_palette = best_rd, this_rd,
11824 best_model_rd_palette = INT64_MAX;
Urvang Joshi626591d2016-10-24 14:13:55 -070011825 int skippable = 0, rate_overhead_palette = 0;
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011826 RD_STATS rd_stats_y;
hui sude0c70a2017-01-09 17:12:17 -080011827 TX_SIZE uv_tx;
Yaowu Xuc27fc142016-08-22 16:08:15 -070011828 uint8_t *const best_palette_color_map =
11829 x->palette_buffer->best_palette_color_map;
11830 uint8_t *const color_map = xd->plane[0].color_index_map;
Urvang Joshi451e0f22017-01-31 11:18:31 -080011831 MB_MODE_INFO best_mbmi_palette = best_mbmode;
Yaowu Xuc27fc142016-08-22 16:08:15 -070011832
11833 mbmi->mode = DC_PRED;
Luc Trudeaud6d9eee2017-07-12 12:36:50 -040011834 mbmi->uv_mode = UV_DC_PRED;
Yaowu Xuc27fc142016-08-22 16:08:15 -070011835 mbmi->ref_frame[0] = INTRA_FRAME;
Emil Keyder01770b32017-01-20 18:03:11 -050011836 mbmi->ref_frame[1] = NONE_FRAME;
Urvang Joshi626591d2016-10-24 14:13:55 -070011837 rate_overhead_palette = rd_pick_palette_intra_sby(
Urvang Joshi451e0f22017-01-31 11:18:31 -080011838 cpi, x, bsize, palette_ctx, intra_mode_cost[DC_PRED],
11839 &best_mbmi_palette, best_palette_color_map, &best_rd_palette,
11840 &best_model_rd_palette, NULL, NULL, NULL, NULL);
hui sude0c70a2017-01-09 17:12:17 -080011841 if (pmi->palette_size[0] == 0) goto PALETTE_EXIT;
11842 memcpy(color_map, best_palette_color_map,
11843 rows * cols * sizeof(best_palette_color_map[0]));
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011844 super_block_yrd(cpi, x, &rd_stats_y, bsize, best_rd);
11845 if (rd_stats_y.rate == INT_MAX) goto PALETTE_EXIT;
Debargha Mukherjee2f123402016-08-30 17:43:38 -070011846 uv_tx = uv_txsize_lookup[bsize][mbmi->tx_size][xd->plane[1].subsampling_x]
11847 [xd->plane[1].subsampling_y];
Yaowu Xuc27fc142016-08-22 16:08:15 -070011848 if (rate_uv_intra[uv_tx] == INT_MAX) {
Luc Trudeau9d4cbb82017-07-27 17:01:32 -040011849 choose_intra_uv_mode(cpi, x, bsize, uv_tx, &rate_uv_intra[uv_tx],
Urvang Joshi368fbc92016-10-17 16:31:34 -070011850 &rate_uv_tokenonly[uv_tx], &dist_uvs[uv_tx],
11851 &skip_uvs[uv_tx], &mode_uv[uv_tx]);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011852 pmi_uv[uv_tx] = *pmi;
11853#if CONFIG_EXT_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070011854 uv_angle_delta[uv_tx] = mbmi->angle_delta[1];
11855#endif // CONFIG_EXT_INTRA
hui su5db97432016-10-14 16:10:14 -070011856#if CONFIG_FILTER_INTRA
11857 filter_intra_mode_info_uv[uv_tx] = mbmi->filter_intra_mode_info;
11858#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070011859 }
11860 mbmi->uv_mode = mode_uv[uv_tx];
11861 pmi->palette_size[1] = pmi_uv[uv_tx].palette_size[1];
hui sude0c70a2017-01-09 17:12:17 -080011862 if (pmi->palette_size[1] > 0) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070011863 memcpy(pmi->palette_colors + PALETTE_MAX_SIZE,
11864 pmi_uv[uv_tx].palette_colors + PALETTE_MAX_SIZE,
11865 2 * PALETTE_MAX_SIZE * sizeof(pmi->palette_colors[0]));
hui sude0c70a2017-01-09 17:12:17 -080011866 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070011867#if CONFIG_EXT_INTRA
11868 mbmi->angle_delta[1] = uv_angle_delta[uv_tx];
Yaowu Xuc27fc142016-08-22 16:08:15 -070011869#endif // CONFIG_EXT_INTRA
hui su5db97432016-10-14 16:10:14 -070011870#if CONFIG_FILTER_INTRA
11871 mbmi->filter_intra_mode_info.use_filter_intra_mode[1] =
11872 filter_intra_mode_info_uv[uv_tx].use_filter_intra_mode[1];
11873 if (filter_intra_mode_info_uv[uv_tx].use_filter_intra_mode[1]) {
11874 mbmi->filter_intra_mode_info.filter_intra_mode[1] =
11875 filter_intra_mode_info_uv[uv_tx].filter_intra_mode[1];
11876 }
11877#endif // CONFIG_FILTER_INTRA
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011878 skippable = rd_stats_y.skip && skip_uvs[uv_tx];
11879 distortion2 = rd_stats_y.dist + dist_uvs[uv_tx];
11880 rate2 = rd_stats_y.rate + rate_overhead_palette + rate_uv_intra[uv_tx];
Yaowu Xuc27fc142016-08-22 16:08:15 -070011881 rate2 += ref_costs_single[INTRA_FRAME];
11882
11883 if (skippable) {
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011884 rate2 -= (rd_stats_y.rate + rate_uv_tokenonly[uv_tx]);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011885#if CONFIG_SUPERTX
11886 best_rate_nocoef = rate2;
Fergus Simpson4063a682017-02-28 16:52:22 -080011887#endif // CONFIG_SUPERTX
Yaowu Xuf883b422016-08-30 14:01:10 -070011888 rate2 += av1_cost_bit(av1_get_skip_prob(cm, xd), 1);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011889 } else {
11890#if CONFIG_SUPERTX
Angie Chiang0e9a2e92016-11-08 09:45:40 -080011891 best_rate_nocoef = rate2 - (rd_stats_y.rate + rate_uv_tokenonly[uv_tx]);
Fergus Simpson4063a682017-02-28 16:52:22 -080011892#endif // CONFIG_SUPERTX
Yaowu Xuf883b422016-08-30 14:01:10 -070011893 rate2 += av1_cost_bit(av1_get_skip_prob(cm, xd), 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011894 }
Urvang Joshi70006e42017-06-14 16:08:55 -070011895 this_rd = RDCOST(x->rdmult, rate2, distortion2);
Yaowu Xuc27fc142016-08-22 16:08:15 -070011896 if (this_rd < best_rd) {
11897 best_mode_index = 3;
11898 mbmi->mv[0].as_int = 0;
11899 rd_cost->rate = rate2;
11900#if CONFIG_SUPERTX
11901 *returnrate_nocoef = best_rate_nocoef;
Fergus Simpson4063a682017-02-28 16:52:22 -080011902#endif // CONFIG_SUPERTX
Yaowu Xuc27fc142016-08-22 16:08:15 -070011903 rd_cost->dist = distortion2;
11904 rd_cost->rdcost = this_rd;
11905 best_rd = this_rd;
11906 best_mbmode = *mbmi;
11907 best_skip2 = 0;
11908 best_mode_skippable = skippable;
11909 }
11910 }
11911PALETTE_EXIT:
11912
hui su5db97432016-10-14 16:10:14 -070011913#if CONFIG_FILTER_INTRA
11914 // TODO(huisu): filter-intra is turned off in lossless mode for now to
Yaowu Xuc27fc142016-08-22 16:08:15 -070011915 // avoid a unit test failure
Urvang Joshic6300aa2017-06-01 14:46:23 -070011916 if (!xd->lossless[mbmi->segment_id] && pmi->palette_size[0] == 0 &&
Urvang Joshib100db72016-10-12 16:28:56 -070011917 !dc_skipped && best_mode_index >= 0 &&
11918 best_intra_rd < (best_rd + (best_rd >> 3))) {
hui su5db97432016-10-14 16:10:14 -070011919 pick_filter_intra_interframe(
Luc Trudeau9d4cbb82017-07-27 17:01:32 -040011920 cpi, x, bsize, mi_row, mi_col, rate_uv_intra, rate_uv_tokenonly,
Jingning Han18c53c82017-02-17 14:49:57 -080011921 dist_uvs, skip_uvs, mode_uv, filter_intra_mode_info_uv,
hui su5db97432016-10-14 16:10:14 -070011922#if CONFIG_EXT_INTRA
11923 uv_angle_delta,
11924#endif // CONFIG_EXT_INTRA
Urvang Joshic6300aa2017-06-01 14:46:23 -070011925 pmi_uv, palette_ctx, 0, ref_costs_single, &best_rd, &best_intra_rd,
11926 &best_intra_mode, &best_mode_index, &best_skip2, &best_mode_skippable,
Yaowu Xuc27fc142016-08-22 16:08:15 -070011927#if CONFIG_SUPERTX
11928 returnrate_nocoef,
11929#endif // CONFIG_SUPERTX
11930 best_pred_rd, &best_mbmode, rd_cost);
11931 }
hui su5db97432016-10-14 16:10:14 -070011932#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070011933
Zoe Liu85b66462017-04-20 14:28:19 -070011934// The inter modes' rate costs are not calculated precisely in some cases.
11935// Therefore, sometimes, NEWMV is chosen instead of NEARESTMV, NEARMV, and
11936// ZEROMV. Here, checks are added for those cases, and the mode decisions
11937// are corrected.
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020011938#if CONFIG_COMPOUND_SINGLEREF
Zoe Liu85b66462017-04-20 14:28:19 -070011939// NOTE: For SR_NEW_NEWMV, no need to check as the two mvs from the same ref
11940// are surely different from each other.
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020011941#endif // CONFIG_COMPOUND_SINGLEREF
11942 if (best_mbmode.mode == NEWMV || best_mbmode.mode == NEW_NEWMV) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070011943 const MV_REFERENCE_FRAME refs[2] = { best_mbmode.ref_frame[0],
11944 best_mbmode.ref_frame[1] };
11945 int comp_pred_mode = refs[1] > INTRA_FRAME;
Sarah Parkere5299862016-08-16 14:57:37 -070011946 int_mv zeromv[2];
Yaowu Xuf883b422016-08-30 14:01:10 -070011947 const uint8_t rf_type = av1_ref_frame_type(best_mbmode.ref_frame);
Sarah Parkere5299862016-08-16 14:57:37 -070011948#if CONFIG_GLOBAL_MOTION
Debargha Mukherjeefebb59c2017-03-02 12:23:45 -080011949 zeromv[0].as_int = gm_get_motion_vector(&cm->global_motion[refs[0]],
11950 cm->allow_high_precision_mv, bsize,
RogerZhou3b635242017-09-19 10:06:46 -070011951 mi_col, mi_row, 0
11952#if CONFIG_AMVR
11953 ,
11954 cm->cur_frame_mv_precision_level
11955#endif
11956 )
Debargha Mukherjeefebb59c2017-03-02 12:23:45 -080011957 .as_int;
RogerZhou3b635242017-09-19 10:06:46 -070011958 zeromv[1].as_int =
11959 comp_pred_mode
11960 ? gm_get_motion_vector(&cm->global_motion[refs[1]],
11961 cm->allow_high_precision_mv, bsize, mi_col,
11962 mi_row, 0
11963#if CONFIG_AMVR
11964 ,
11965 cm->cur_frame_mv_precision_level
11966#endif
11967 )
11968 .as_int
11969 : 0;
Sarah Parkere5299862016-08-16 14:57:37 -070011970#else
11971 zeromv[0].as_int = 0;
11972 zeromv[1].as_int = 0;
11973#endif // CONFIG_GLOBAL_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -070011974 if (!comp_pred_mode) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070011975 int ref_set = (mbmi_ext->ref_mv_count[rf_type] >= 2)
Yaowu Xuf883b422016-08-30 14:01:10 -070011976 ? AOMMIN(2, mbmi_ext->ref_mv_count[rf_type] - 2)
Yaowu Xuc27fc142016-08-22 16:08:15 -070011977 : INT_MAX;
11978
11979 for (i = 0; i <= ref_set && ref_set != INT_MAX; ++i) {
11980 int_mv cur_mv = mbmi_ext->ref_mv_stack[rf_type][i + 1].this_mv;
11981 if (cur_mv.as_int == best_mbmode.mv[0].as_int) {
11982 best_mbmode.mode = NEARMV;
11983 best_mbmode.ref_mv_idx = i;
11984 }
11985 }
11986
11987 if (frame_mv[NEARESTMV][refs[0]].as_int == best_mbmode.mv[0].as_int)
11988 best_mbmode.mode = NEARESTMV;
Sarah Parkere5299862016-08-16 14:57:37 -070011989 else if (best_mbmode.mv[0].as_int == zeromv[0].as_int)
Yaowu Xuc27fc142016-08-22 16:08:15 -070011990 best_mbmode.mode = ZEROMV;
11991 } else {
11992 int_mv nearestmv[2];
11993 int_mv nearmv[2];
11994
Yaowu Xuc27fc142016-08-22 16:08:15 -070011995 if (mbmi_ext->ref_mv_count[rf_type] > 1) {
11996 nearmv[0] = mbmi_ext->ref_mv_stack[rf_type][1].this_mv;
11997 nearmv[1] = mbmi_ext->ref_mv_stack[rf_type][1].comp_mv;
11998 } else {
11999 nearmv[0] = frame_mv[NEARMV][refs[0]];
12000 nearmv[1] = frame_mv[NEARMV][refs[1]];
12001 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070012002 if (mbmi_ext->ref_mv_count[rf_type] >= 1) {
12003 nearestmv[0] = mbmi_ext->ref_mv_stack[rf_type][0].this_mv;
12004 nearestmv[1] = mbmi_ext->ref_mv_stack[rf_type][0].comp_mv;
12005 } else {
12006 nearestmv[0] = frame_mv[NEARESTMV][refs[0]];
12007 nearestmv[1] = frame_mv[NEARESTMV][refs[1]];
12008 }
12009
12010 if (nearestmv[0].as_int == best_mbmode.mv[0].as_int &&
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020012011 nearestmv[1].as_int == best_mbmode.mv[1].as_int) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070012012 best_mbmode.mode = NEAREST_NEARESTMV;
David Barker404b2e82017-03-27 13:07:47 +010012013 } else {
12014 int ref_set = (mbmi_ext->ref_mv_count[rf_type] >= 2)
12015 ? AOMMIN(2, mbmi_ext->ref_mv_count[rf_type] - 2)
12016 : INT_MAX;
12017
12018 for (i = 0; i <= ref_set && ref_set != INT_MAX; ++i) {
12019 nearmv[0] = mbmi_ext->ref_mv_stack[rf_type][i + 1].this_mv;
12020 nearmv[1] = mbmi_ext->ref_mv_stack[rf_type][i + 1].comp_mv;
12021
Debargha Mukherjeebb6e1342017-04-17 16:05:04 -070012022 // Try switching to the NEAR_NEARMV mode
12023 if (nearmv[0].as_int == best_mbmode.mv[0].as_int &&
David Barker404b2e82017-03-27 13:07:47 +010012024 nearmv[1].as_int == best_mbmode.mv[1].as_int) {
12025 best_mbmode.mode = NEAR_NEARMV;
12026 best_mbmode.ref_mv_idx = i;
12027 }
12028 }
12029
David Barker3dfba992017-04-03 16:10:09 +010012030 if (best_mbmode.mode == NEW_NEWMV &&
David Barker404b2e82017-03-27 13:07:47 +010012031 best_mbmode.mv[0].as_int == zeromv[0].as_int &&
12032 best_mbmode.mv[1].as_int == zeromv[1].as_int)
12033 best_mbmode.mode = ZERO_ZEROMV;
12034 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070012035 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070012036 }
12037
David Barker9620bcd2017-03-22 14:46:42 +000012038 // Make sure that the ref_mv_idx is only nonzero when we're
12039 // using a mode which can support ref_mv_idx
12040 if (best_mbmode.ref_mv_idx != 0 &&
Zoe Liu85b66462017-04-20 14:28:19 -070012041#if CONFIG_COMPOUND_SINGLEREF
12042 !(best_mbmode.mode == NEWMV || best_mbmode.mode == SR_NEW_NEWMV ||
12043 best_mbmode.mode == NEW_NEWMV ||
Yushin Cho67dda512017-07-25 14:58:22 -070012044 have_nearmv_in_inter_mode(best_mbmode.mode)))
Zoe Liu85b66462017-04-20 14:28:19 -070012045#else // !CONFIG_COMPOUND_SINGLEREF
David Barker3dfba992017-04-03 16:10:09 +010012046 !(best_mbmode.mode == NEWMV || best_mbmode.mode == NEW_NEWMV ||
Yushin Cho67dda512017-07-25 14:58:22 -070012047 have_nearmv_in_inter_mode(best_mbmode.mode)))
Zoe Liu85b66462017-04-20 14:28:19 -070012048#endif // CONFIG_COMPOUND_SINGLEREF
Yushin Cho67dda512017-07-25 14:58:22 -070012049 {
David Barker9620bcd2017-03-22 14:46:42 +000012050 best_mbmode.ref_mv_idx = 0;
12051 }
12052
Rupert Swarbrick799ff702017-10-04 17:37:52 +010012053 if (best_mbmode.ref_frame[0] > INTRA_FRAME &&
12054 best_mbmode.ref_frame[1] <= INTRA_FRAME) {
Jingning Han731af492016-11-17 11:53:23 -080012055 int8_t ref_frame_type = av1_ref_frame_type(best_mbmode.ref_frame);
12056 int16_t mode_ctx = mbmi_ext->mode_context[ref_frame_type];
David Barker68e6e862016-11-24 15:10:15 +000012057 if (mode_ctx & (1 << ALL_ZERO_FLAG_OFFSET)) {
Rupert Swarbrick799ff702017-10-04 17:37:52 +010012058 int_mv zeromv;
David Barker68e6e862016-11-24 15:10:15 +000012059#if CONFIG_GLOBAL_MOTION
Rupert Swarbrick799ff702017-10-04 17:37:52 +010012060 const MV_REFERENCE_FRAME ref = best_mbmode.ref_frame[0];
12061 zeromv.as_int = gm_get_motion_vector(&cm->global_motion[ref],
12062 cm->allow_high_precision_mv, bsize,
12063 mi_col, mi_row, 0
RogerZhou3b635242017-09-19 10:06:46 -070012064#if CONFIG_AMVR
Rupert Swarbrick799ff702017-10-04 17:37:52 +010012065 ,
12066 cm->cur_frame_mv_precision_level
RogerZhou3b635242017-09-19 10:06:46 -070012067#endif
Rupert Swarbrick799ff702017-10-04 17:37:52 +010012068 )
12069 .as_int;
RogerZhou3b635242017-09-19 10:06:46 -070012070#else
Rupert Swarbrick799ff702017-10-04 17:37:52 +010012071 zeromv.as_int = 0;
David Barkercdcac6d2016-12-01 17:04:16 +000012072#endif // CONFIG_GLOBAL_MOTION
Rupert Swarbrick799ff702017-10-04 17:37:52 +010012073 if (best_mbmode.mv[0].as_int == zeromv.as_int) {
David Barkercdcac6d2016-12-01 17:04:16 +000012074 best_mbmode.mode = ZEROMV;
12075 }
David Barker68e6e862016-11-24 15:10:15 +000012076 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070012077 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070012078
12079 if (best_mode_index < 0 || best_rd >= best_rd_so_far) {
12080 rd_cost->rate = INT_MAX;
12081 rd_cost->rdcost = INT64_MAX;
12082 return;
12083 }
12084
Rupert Swarbrick27e90292017-09-28 17:46:50 +010012085 assert((cm->interp_filter == SWITCHABLE) ||
12086 (cm->interp_filter ==
12087 av1_extract_interp_filter(best_mbmode.interp_filters, 0)) ||
12088 !is_inter_block(&best_mbmode));
Yaowu Xuc27fc142016-08-22 16:08:15 -070012089#if CONFIG_DUAL_FILTER
12090 assert((cm->interp_filter == SWITCHABLE) ||
Rupert Swarbrick27e90292017-09-28 17:46:50 +010012091 (cm->interp_filter ==
12092 av1_extract_interp_filter(best_mbmode.interp_filters, 1)) ||
Yaowu Xuc27fc142016-08-22 16:08:15 -070012093 !is_inter_block(&best_mbmode));
Fergus Simpson4063a682017-02-28 16:52:22 -080012094#endif // CONFIG_DUAL_FILTER
Yaowu Xuc27fc142016-08-22 16:08:15 -070012095
12096 if (!cpi->rc.is_src_frame_alt_ref)
Yaowu Xuf883b422016-08-30 14:01:10 -070012097 av1_update_rd_thresh_fact(cm, tile_data->thresh_freq_fact,
12098 sf->adaptive_rd_thresh, bsize, best_mode_index);
Yaowu Xuc27fc142016-08-22 16:08:15 -070012099
12100 // macroblock modes
12101 *mbmi = best_mbmode;
12102 x->skip |= best_skip2;
12103
Yue Chen19e7aa82016-11-30 14:05:39 -080012104// Note: this section is needed since the mode may have been forced to
12105// ZEROMV by the all-zero mode handling of ref-mv.
12106#if CONFIG_GLOBAL_MOTION
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +020012107 if (mbmi->mode == ZEROMV || mbmi->mode == ZERO_ZEROMV) {
Sarah Parker19234cc2017-03-10 16:43:25 -080012108#if CONFIG_WARPED_MOTION || CONFIG_MOTION_VAR
12109 // Correct the motion mode for ZEROMV
Sarah Parker0eea89f2017-07-11 11:56:36 -070012110 const MOTION_MODE last_motion_mode_allowed =
Yue Chen52c51732017-07-11 15:08:30 -070012111 motion_mode_allowed(0, xd->global_motion,
12112#if CONFIG_WARPED_MOTION
12113 xd,
12114#endif
12115 xd->mi[0]);
Sarah Parker19234cc2017-03-10 16:43:25 -080012116 if (mbmi->motion_mode > last_motion_mode_allowed)
12117 mbmi->motion_mode = last_motion_mode_allowed;
12118#endif // CONFIG_WARPED_MOTION || CONFIG_MOTION_VAR
12119
12120 // Correct the interpolation filter for ZEROMV
Yue Chen19e7aa82016-11-30 14:05:39 -080012121 if (is_nontrans_global_motion(xd)) {
Rupert Swarbrick27e90292017-09-28 17:46:50 +010012122 mbmi->interp_filters = av1_broadcast_interp_filter(
12123 av1_unswitchable_filter(cm->interp_filter));
Yue Chen19e7aa82016-11-30 14:05:39 -080012124 }
12125 }
12126#endif // CONFIG_GLOBAL_MOTION
12127
Yaowu Xuc27fc142016-08-22 16:08:15 -070012128 for (i = 0; i < 1 + has_second_ref(mbmi); ++i) {
12129 if (mbmi->mode != NEWMV)
12130 mbmi->pred_mv[i].as_int = mbmi->mv[i].as_int;
12131 else
12132 mbmi->pred_mv[i].as_int = mbmi_ext->ref_mvs[mbmi->ref_frame[i]][0].as_int;
12133 }
Yaowu Xuc27fc142016-08-22 16:08:15 -070012134
12135 for (i = 0; i < REFERENCE_MODES; ++i) {
12136 if (best_pred_rd[i] == INT64_MAX)
12137 best_pred_diff[i] = INT_MIN;
12138 else
12139 best_pred_diff[i] = best_rd - best_pred_rd[i];
12140 }
12141
12142 x->skip |= best_mode_skippable;
12143
12144 assert(best_mode_index >= 0);
12145
12146 store_coding_context(x, ctx, best_mode_index, best_pred_diff,
12147 best_mode_skippable);
12148
Urvang Joshic9e71d42017-08-09 18:58:33 -070012149 if (pmi->palette_size[1] > 0) {
12150 assert(try_palette);
Yaowu Xuc27fc142016-08-22 16:08:15 -070012151 restore_uv_color_map(cpi, x);
12152 }
12153}
12154
Urvang Joshi52648442016-10-13 17:27:51 -070012155void av1_rd_pick_inter_mode_sb_seg_skip(const AV1_COMP *cpi,
12156 TileDataEnc *tile_data, MACROBLOCK *x,
David Barker45390c12017-02-20 14:44:40 +000012157 int mi_row, int mi_col,
Angie Chiang2a2a7dd2017-04-25 16:08:47 -070012158 RD_STATS *rd_cost, BLOCK_SIZE bsize,
Yaowu Xuf883b422016-08-30 14:01:10 -070012159 PICK_MODE_CONTEXT *ctx,
12160 int64_t best_rd_so_far) {
Urvang Joshi52648442016-10-13 17:27:51 -070012161 const AV1_COMMON *const cm = &cpi->common;
Yaowu Xuc27fc142016-08-22 16:08:15 -070012162 MACROBLOCKD *const xd = &x->e_mbd;
12163 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
12164 unsigned char segment_id = mbmi->segment_id;
12165 const int comp_pred = 0;
12166 int i;
12167 int64_t best_pred_diff[REFERENCE_MODES];
12168 unsigned int ref_costs_single[TOTAL_REFS_PER_FRAME];
Zoe Liuc082bbc2017-05-17 13:31:37 -070012169#if CONFIG_EXT_COMP_REFS
12170 unsigned int ref_costs_comp[TOTAL_REFS_PER_FRAME][TOTAL_REFS_PER_FRAME];
12171#else
Yaowu Xuc27fc142016-08-22 16:08:15 -070012172 unsigned int ref_costs_comp[TOTAL_REFS_PER_FRAME];
Zoe Liuc082bbc2017-05-17 13:31:37 -070012173#endif // CONFIG_EXT_COMP_REFS
Yaowu Xuf883b422016-08-30 14:01:10 -070012174 aom_prob comp_mode_p;
James Zern7b9407a2016-05-18 23:48:05 -070012175 InterpFilter best_filter = SWITCHABLE;
Yaowu Xuc27fc142016-08-22 16:08:15 -070012176 int64_t this_rd = INT64_MAX;
12177 int rate2 = 0;
12178 const int64_t distortion2 = 0;
David Barker45390c12017-02-20 14:44:40 +000012179 (void)mi_row;
12180 (void)mi_col;
Yaowu Xuc27fc142016-08-22 16:08:15 -070012181
12182 estimate_ref_frame_costs(cm, xd, segment_id, ref_costs_single, ref_costs_comp,
12183 &comp_mode_p);
12184
12185 for (i = 0; i < TOTAL_REFS_PER_FRAME; ++i) x->pred_sse[i] = INT_MAX;
12186 for (i = LAST_FRAME; i < TOTAL_REFS_PER_FRAME; ++i)
12187 x->pred_mv_sad[i] = INT_MAX;
12188
12189 rd_cost->rate = INT_MAX;
12190
12191 assert(segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP));
12192
12193 mbmi->palette_mode_info.palette_size[0] = 0;
12194 mbmi->palette_mode_info.palette_size[1] = 0;
Urvang Joshib100db72016-10-12 16:28:56 -070012195
hui su5db97432016-10-14 16:10:14 -070012196#if CONFIG_FILTER_INTRA
12197 mbmi->filter_intra_mode_info.use_filter_intra_mode[0] = 0;
12198 mbmi->filter_intra_mode_info.use_filter_intra_mode[1] = 0;
12199#endif // CONFIG_FILTER_INTRA
Yaowu Xuc27fc142016-08-22 16:08:15 -070012200 mbmi->mode = ZEROMV;
Yue Chencb60b182016-10-13 15:18:22 -070012201 mbmi->motion_mode = SIMPLE_TRANSLATION;
Luc Trudeaud6d9eee2017-07-12 12:36:50 -040012202 mbmi->uv_mode = UV_DC_PRED;
Yaowu Xuc27fc142016-08-22 16:08:15 -070012203 mbmi->ref_frame[0] = LAST_FRAME;
Emil Keyder01770b32017-01-20 18:03:11 -050012204 mbmi->ref_frame[1] = NONE_FRAME;
Sarah Parkere5299862016-08-16 14:57:37 -070012205#if CONFIG_GLOBAL_MOTION
12206 mbmi->mv[0].as_int =
Sarah Parkerae7c4582017-02-28 16:30:30 -080012207 gm_get_motion_vector(&cm->global_motion[mbmi->ref_frame[0]],
RogerZhou3b635242017-09-19 10:06:46 -070012208 cm->allow_high_precision_mv, bsize, mi_col, mi_row, 0
12209#if CONFIG_AMVR
12210 ,
12211 cm->cur_frame_mv_precision_level
12212#endif
12213 )
David Barkercdcac6d2016-12-01 17:04:16 +000012214 .as_int;
Sarah Parkere5299862016-08-16 14:57:37 -070012215#else // CONFIG_GLOBAL_MOTION
Yaowu Xuc27fc142016-08-22 16:08:15 -070012216 mbmi->mv[0].as_int = 0;
Sarah Parkere5299862016-08-16 14:57:37 -070012217#endif // CONFIG_GLOBAL_MOTION
Jingning Han64088952016-07-11 11:24:24 -070012218 mbmi->tx_size = max_txsize_lookup[bsize];
Yaowu Xuee775b12016-10-18 10:00:21 -070012219 x->skip = 1;
Sarah Parkere5299862016-08-16 14:57:37 -070012220
Yaowu Xuc27fc142016-08-22 16:08:15 -070012221 mbmi->ref_mv_idx = 0;
12222 mbmi->pred_mv[0].as_int = 0;
Lester Lu432012f2017-08-17 14:39:29 -070012223#if CONFIG_LGT_FROM_PRED
12224 mbmi->use_lgt = 0;
12225#endif
Yaowu Xuc27fc142016-08-22 16:08:15 -070012226
Yue Chendead17d2017-04-20 16:19:39 -070012227 mbmi->motion_mode = SIMPLE_TRANSLATION;
12228#if CONFIG_MOTION_VAR
12229 av1_count_overlappable_neighbors(cm, xd, mi_row, mi_col);
12230#endif
Yue Chenf3e1ead2017-04-21 14:05:51 -070012231#if CONFIG_WARPED_MOTION
12232 if (is_motion_variation_allowed_bsize(bsize) && !has_second_ref(mbmi)) {
12233 int pts[SAMPLES_ARRAY_SIZE], pts_inref[SAMPLES_ARRAY_SIZE];
Yunqing Wang1bc82862017-06-28 15:49:48 -070012234#if WARPED_MOTION_SORT_SAMPLES
12235 int pts_mv[SAMPLES_ARRAY_SIZE];
12236 mbmi->num_proj_ref[0] =
12237 findSamples(cm, xd, mi_row, mi_col, pts, pts_inref, pts_mv);
12238 // Rank the samples by motion vector difference
12239 if (mbmi->num_proj_ref[0] > 1)
12240 mbmi->num_proj_ref[0] = sortSamples(pts_mv, &mbmi->mv[0].as_mv, pts,
12241 pts_inref, mbmi->num_proj_ref[0]);
12242#else
Yue Chenf3e1ead2017-04-21 14:05:51 -070012243 mbmi->num_proj_ref[0] = findSamples(cm, xd, mi_row, mi_col, pts, pts_inref);
Yunqing Wang1bc82862017-06-28 15:49:48 -070012244#endif // WARPED_MOTION_SORT_SAMPLES
Yue Chenf3e1ead2017-04-21 14:05:51 -070012245 }
12246#endif
Yue Chendead17d2017-04-20 16:19:39 -070012247
Debargha Mukherjee0df711f2017-05-02 16:00:20 -070012248 set_default_interp_filters(mbmi, cm->interp_filter);
12249
12250 if (cm->interp_filter != SWITCHABLE) {
12251 best_filter = cm->interp_filter;
12252 } else {
Yaowu Xuc27fc142016-08-22 16:08:15 -070012253 best_filter = EIGHTTAP_REGULAR;
Debargha Mukherjee0df711f2017-05-02 16:00:20 -070012254 if (av1_is_interp_needed(xd) && av1_is_interp_search_needed(xd) &&
Yaowu Xuc27fc142016-08-22 16:08:15 -070012255 x->source_variance >= cpi->sf.disable_filter_search_var_thresh) {
12256 int rs;
12257 int best_rs = INT_MAX;
12258 for (i = 0; i < SWITCHABLE_FILTERS; ++i) {
Rupert Swarbrick27e90292017-09-28 17:46:50 +010012259 mbmi->interp_filters = av1_broadcast_interp_filter(i);
Yue Chenb23d00a2017-07-28 17:01:21 -070012260 rs = av1_get_switchable_rate(cm, x, xd);
Yaowu Xuc27fc142016-08-22 16:08:15 -070012261 if (rs < best_rs) {
12262 best_rs = rs;
Rupert Swarbrick27e90292017-09-28 17:46:50 +010012263 best_filter = av1_extract_interp_filter(mbmi->interp_filters, 0);
Yaowu Xuc27fc142016-08-22 16:08:15 -070012264 }
12265 }
12266 }
12267 }
Rupert Swarbrick27e90292017-09-28 17:46:50 +010012268 // Set the appropriate filter
12269 mbmi->interp_filters = av1_broadcast_interp_filter(best_filter);
Yue Chenb23d00a2017-07-28 17:01:21 -070012270 rate2 += av1_get_switchable_rate(cm, x, xd);
Yaowu Xuc27fc142016-08-22 16:08:15 -070012271
12272 if (cm->reference_mode == REFERENCE_MODE_SELECT)
Yaowu Xuf883b422016-08-30 14:01:10 -070012273 rate2 += av1_cost_bit(comp_mode_p, comp_pred);
Yaowu Xuc27fc142016-08-22 16:08:15 -070012274
12275 // Estimate the reference frame signaling cost and add it
12276 // to the rolling cost variable.
12277 rate2 += ref_costs_single[LAST_FRAME];
Urvang Joshi70006e42017-06-14 16:08:55 -070012278 this_rd = RDCOST(x->rdmult, rate2, distortion2);
Yaowu Xuc27fc142016-08-22 16:08:15 -070012279
12280 rd_cost->rate = rate2;
12281 rd_cost->dist = distortion2;
12282 rd_cost->rdcost = this_rd;
Yushin Cho8e75e8b2017-09-12 16:33:28 -070012283
Yaowu Xuc27fc142016-08-22 16:08:15 -070012284 if (this_rd >= best_rd_so_far) {
12285 rd_cost->rate = INT_MAX;
12286 rd_cost->rdcost = INT64_MAX;
12287 return;
12288 }
12289
Yaowu Xuc27fc142016-08-22 16:08:15 -070012290 assert((cm->interp_filter == SWITCHABLE) ||
Rupert Swarbrick27e90292017-09-28 17:46:50 +010012291 (cm->interp_filter ==
12292 av1_extract_interp_filter(mbmi->interp_filters, 0)));
Yaowu Xuc27fc142016-08-22 16:08:15 -070012293
Yaowu Xuf883b422016-08-30 14:01:10 -070012294 av1_update_rd_thresh_fact(cm, tile_data->thresh_freq_fact,
12295 cpi->sf.adaptive_rd_thresh, bsize, THR_ZEROMV);
Yaowu Xuc27fc142016-08-22 16:08:15 -070012296
Yaowu Xuf883b422016-08-30 14:01:10 -070012297 av1_zero(best_pred_diff);
Yaowu Xuc27fc142016-08-22 16:08:15 -070012298
12299 store_coding_context(x, ctx, THR_ZEROMV, best_pred_diff, 0);
12300}
12301
Yue Chencb60b182016-10-13 15:18:22 -070012302#if CONFIG_MOTION_VAR
Rupert Swarbrickc0cea7f2017-08-22 14:06:56 +010012303
12304struct calc_target_weighted_pred_ctxt {
12305 const MACROBLOCK *x;
12306 const uint8_t *tmp;
12307 int tmp_stride;
12308 int overlap;
12309};
12310
12311static INLINE void calc_target_weighted_pred_above(MACROBLOCKD *xd,
12312 int rel_mi_col,
12313 uint8_t nb_mi_width,
12314 MODE_INFO *nb_mi,
12315 void *fun_ctxt) {
12316 (void)nb_mi;
12317
12318 struct calc_target_weighted_pred_ctxt *ctxt =
12319 (struct calc_target_weighted_pred_ctxt *)fun_ctxt;
12320
12321#if CONFIG_HIGHBITDEPTH
12322 const int is_hbd = (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) ? 1 : 0;
12323#else
12324 const int is_hbd = 0;
12325#endif // CONFIG_HIGHBITDEPTH
12326
12327 const int bw = xd->n8_w << MI_SIZE_LOG2;
12328 const uint8_t *const mask1d = av1_get_obmc_mask(ctxt->overlap);
12329
12330 int32_t *wsrc = ctxt->x->wsrc_buf + (rel_mi_col * MI_SIZE);
12331 int32_t *mask = ctxt->x->mask_buf + (rel_mi_col * MI_SIZE);
12332 const uint8_t *tmp = ctxt->tmp + rel_mi_col * MI_SIZE;
12333
12334 if (!is_hbd) {
12335 for (int row = 0; row < ctxt->overlap; ++row) {
12336 const uint8_t m0 = mask1d[row];
12337 const uint8_t m1 = AOM_BLEND_A64_MAX_ALPHA - m0;
12338 for (int col = 0; col < nb_mi_width * MI_SIZE; ++col) {
12339 wsrc[col] = m1 * tmp[col];
12340 mask[col] = m0;
12341 }
12342 wsrc += bw;
12343 mask += bw;
12344 tmp += ctxt->tmp_stride;
12345 }
12346#if CONFIG_HIGHBITDEPTH
12347 } else {
12348 const uint16_t *tmp16 = CONVERT_TO_SHORTPTR(tmp);
12349
12350 for (int row = 0; row < ctxt->overlap; ++row) {
12351 const uint8_t m0 = mask1d[row];
12352 const uint8_t m1 = AOM_BLEND_A64_MAX_ALPHA - m0;
12353 for (int col = 0; col < nb_mi_width * MI_SIZE; ++col) {
12354 wsrc[col] = m1 * tmp16[col];
12355 mask[col] = m0;
12356 }
12357 wsrc += bw;
12358 mask += bw;
12359 tmp16 += ctxt->tmp_stride;
12360 }
12361#endif // CONFIG_HIGHBITDEPTH
12362 }
12363}
12364
12365static INLINE void calc_target_weighted_pred_left(MACROBLOCKD *xd,
12366 int rel_mi_row,
12367 uint8_t nb_mi_height,
12368 MODE_INFO *nb_mi,
12369 void *fun_ctxt) {
12370 (void)nb_mi;
12371
12372 struct calc_target_weighted_pred_ctxt *ctxt =
12373 (struct calc_target_weighted_pred_ctxt *)fun_ctxt;
12374
12375#if CONFIG_HIGHBITDEPTH
12376 const int is_hbd = (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) ? 1 : 0;
12377#else
12378 const int is_hbd = 0;
12379#endif // CONFIG_HIGHBITDEPTH
12380
12381 const int bw = xd->n8_w << MI_SIZE_LOG2;
12382 const uint8_t *const mask1d = av1_get_obmc_mask(ctxt->overlap);
12383
12384 int32_t *wsrc = ctxt->x->wsrc_buf + (rel_mi_row * MI_SIZE * bw);
12385 int32_t *mask = ctxt->x->mask_buf + (rel_mi_row * MI_SIZE * bw);
12386 const uint8_t *tmp = ctxt->tmp + (rel_mi_row * MI_SIZE * ctxt->tmp_stride);
12387
12388 if (!is_hbd) {
12389 for (int row = 0; row < nb_mi_height * MI_SIZE; ++row) {
12390 for (int col = 0; col < ctxt->overlap; ++col) {
12391 const uint8_t m0 = mask1d[col];
12392 const uint8_t m1 = AOM_BLEND_A64_MAX_ALPHA - m0;
12393 wsrc[col] = (wsrc[col] >> AOM_BLEND_A64_ROUND_BITS) * m0 +
12394 (tmp[col] << AOM_BLEND_A64_ROUND_BITS) * m1;
12395 mask[col] = (mask[col] >> AOM_BLEND_A64_ROUND_BITS) * m0;
12396 }
12397 wsrc += bw;
12398 mask += bw;
12399 tmp += ctxt->tmp_stride;
12400 }
12401#if CONFIG_HIGHBITDEPTH
12402 } else {
12403 const uint16_t *tmp16 = CONVERT_TO_SHORTPTR(tmp);
12404
12405 for (int row = 0; row < nb_mi_height * MI_SIZE; ++row) {
12406 for (int col = 0; col < ctxt->overlap; ++col) {
12407 const uint8_t m0 = mask1d[col];
12408 const uint8_t m1 = AOM_BLEND_A64_MAX_ALPHA - m0;
12409 wsrc[col] = (wsrc[col] >> AOM_BLEND_A64_ROUND_BITS) * m0 +
12410 (tmp16[col] << AOM_BLEND_A64_ROUND_BITS) * m1;
12411 mask[col] = (mask[col] >> AOM_BLEND_A64_ROUND_BITS) * m0;
12412 }
12413 wsrc += bw;
12414 mask += bw;
12415 tmp16 += ctxt->tmp_stride;
12416 }
12417#endif // CONFIG_HIGHBITDEPTH
12418 }
12419}
12420
Yaowu Xuf883b422016-08-30 14:01:10 -070012421// This function has a structure similar to av1_build_obmc_inter_prediction
Yaowu Xuc27fc142016-08-22 16:08:15 -070012422//
12423// The OBMC predictor is computed as:
12424//
12425// PObmc(x,y) =
Yaowu Xuf883b422016-08-30 14:01:10 -070012426// AOM_BLEND_A64(Mh(x),
12427// AOM_BLEND_A64(Mv(y), P(x,y), PAbove(x,y)),
Yaowu Xuc27fc142016-08-22 16:08:15 -070012428// PLeft(x, y))
12429//
Yaowu Xuf883b422016-08-30 14:01:10 -070012430// Scaling up by AOM_BLEND_A64_MAX_ALPHA ** 2 and omitting the intermediate
Yaowu Xuc27fc142016-08-22 16:08:15 -070012431// rounding, this can be written as:
12432//
Yaowu Xuf883b422016-08-30 14:01:10 -070012433// AOM_BLEND_A64_MAX_ALPHA * AOM_BLEND_A64_MAX_ALPHA * Pobmc(x,y) =
Yaowu Xuc27fc142016-08-22 16:08:15 -070012434// Mh(x) * Mv(y) * P(x,y) +
12435// Mh(x) * Cv(y) * Pabove(x,y) +
Yaowu Xuf883b422016-08-30 14:01:10 -070012436// AOM_BLEND_A64_MAX_ALPHA * Ch(x) * PLeft(x, y)
Yaowu Xuc27fc142016-08-22 16:08:15 -070012437//
12438// Where :
12439//
Yaowu Xuf883b422016-08-30 14:01:10 -070012440// Cv(y) = AOM_BLEND_A64_MAX_ALPHA - Mv(y)
12441// Ch(y) = AOM_BLEND_A64_MAX_ALPHA - Mh(y)
Yaowu Xuc27fc142016-08-22 16:08:15 -070012442//
12443// This function computes 'wsrc' and 'mask' as:
12444//
12445// wsrc(x, y) =
Yaowu Xuf883b422016-08-30 14:01:10 -070012446// AOM_BLEND_A64_MAX_ALPHA * AOM_BLEND_A64_MAX_ALPHA * src(x, y) -
Yaowu Xuc27fc142016-08-22 16:08:15 -070012447// Mh(x) * Cv(y) * Pabove(x,y) +
Yaowu Xuf883b422016-08-30 14:01:10 -070012448// AOM_BLEND_A64_MAX_ALPHA * Ch(x) * PLeft(x, y)
Yaowu Xuc27fc142016-08-22 16:08:15 -070012449//
12450// mask(x, y) = Mh(x) * Mv(y)
12451//
12452// These can then be used to efficiently approximate the error for any
12453// predictor P in the context of the provided neighbouring predictors by
12454// computing:
12455//
12456// error(x, y) =
Yaowu Xuf883b422016-08-30 14:01:10 -070012457// wsrc(x, y) - mask(x, y) * P(x, y) / (AOM_BLEND_A64_MAX_ALPHA ** 2)
Yaowu Xuc27fc142016-08-22 16:08:15 -070012458//
Yaowu Xuf883b422016-08-30 14:01:10 -070012459static void calc_target_weighted_pred(const AV1_COMMON *cm, const MACROBLOCK *x,
Yaowu Xuc27fc142016-08-22 16:08:15 -070012460 const MACROBLOCKD *xd, int mi_row,
12461 int mi_col, const uint8_t *above,
12462 int above_stride, const uint8_t *left,
Yue Chene9638cc2016-10-10 12:37:54 -070012463 int left_stride) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070012464 const BLOCK_SIZE bsize = xd->mi[0]->mbmi.sb_type;
Jingning Hanff6ee6a2016-12-07 09:55:21 -080012465 const int bw = xd->n8_w << MI_SIZE_LOG2;
12466 const int bh = xd->n8_h << MI_SIZE_LOG2;
Yue Chene9638cc2016-10-10 12:37:54 -070012467 int32_t *mask_buf = x->mask_buf;
12468 int32_t *wsrc_buf = x->wsrc_buf;
Rupert Swarbrickc0cea7f2017-08-22 14:06:56 +010012469
Yaowu Xuf883b422016-08-30 14:01:10 -070012470 const int src_scale = AOM_BLEND_A64_MAX_ALPHA * AOM_BLEND_A64_MAX_ALPHA;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020012471#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -070012472 const int is_hbd = (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) ? 1 : 0;
12473#else
12474 const int is_hbd = 0;
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020012475#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -070012476
12477 // plane 0 should not be subsampled
12478 assert(xd->plane[0].subsampling_x == 0);
12479 assert(xd->plane[0].subsampling_y == 0);
12480
Yaowu Xuf883b422016-08-30 14:01:10 -070012481 av1_zero_array(wsrc_buf, bw * bh);
Rupert Swarbrickc0cea7f2017-08-22 14:06:56 +010012482 for (int i = 0; i < bw * bh; ++i) mask_buf[i] = AOM_BLEND_A64_MAX_ALPHA;
Yaowu Xuc27fc142016-08-22 16:08:15 -070012483
12484 // handle above row
12485 if (xd->up_available) {
Jingning Han440d4252017-07-24 14:07:34 -070012486 const int overlap =
Rupert Swarbrickc0cea7f2017-08-22 14:06:56 +010012487 AOMMIN(block_size_high[bsize], block_size_high[BLOCK_64X64]) >> 1;
12488 struct calc_target_weighted_pred_ctxt ctxt = { x, above, above_stride,
12489 overlap };
12490 foreach_overlappable_nb_above(cm, (MACROBLOCKD *)xd, mi_col,
12491 max_neighbor_obmc[b_width_log2_lookup[bsize]],
12492 calc_target_weighted_pred_above, &ctxt);
Yaowu Xuc27fc142016-08-22 16:08:15 -070012493 }
12494
Rupert Swarbrickc0cea7f2017-08-22 14:06:56 +010012495 for (int i = 0; i < bw * bh; ++i) {
Yaowu Xuf883b422016-08-30 14:01:10 -070012496 wsrc_buf[i] *= AOM_BLEND_A64_MAX_ALPHA;
12497 mask_buf[i] *= AOM_BLEND_A64_MAX_ALPHA;
Yaowu Xuc27fc142016-08-22 16:08:15 -070012498 }
12499
12500 // handle left column
12501 if (xd->left_available) {
Jingning Han440d4252017-07-24 14:07:34 -070012502 const int overlap =
Rupert Swarbrickc0cea7f2017-08-22 14:06:56 +010012503 AOMMIN(block_size_wide[bsize], block_size_wide[BLOCK_64X64]) >> 1;
12504 struct calc_target_weighted_pred_ctxt ctxt = { x, left, left_stride,
12505 overlap };
12506 foreach_overlappable_nb_left(cm, (MACROBLOCKD *)xd, mi_row,
12507 max_neighbor_obmc[b_height_log2_lookup[bsize]],
12508 calc_target_weighted_pred_left, &ctxt);
Yaowu Xuc27fc142016-08-22 16:08:15 -070012509 }
12510
12511 if (!is_hbd) {
12512 const uint8_t *src = x->plane[0].src.buf;
12513
Rupert Swarbrickc0cea7f2017-08-22 14:06:56 +010012514 for (int row = 0; row < bh; ++row) {
12515 for (int col = 0; col < bw; ++col) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070012516 wsrc_buf[col] = src[col] * src_scale - wsrc_buf[col];
12517 }
Rupert Swarbrickc0cea7f2017-08-22 14:06:56 +010012518 wsrc_buf += bw;
Yaowu Xuc27fc142016-08-22 16:08:15 -070012519 src += x->plane[0].src.stride;
12520 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020012521#if CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -070012522 } else {
12523 const uint16_t *src = CONVERT_TO_SHORTPTR(x->plane[0].src.buf);
12524
Rupert Swarbrickc0cea7f2017-08-22 14:06:56 +010012525 for (int row = 0; row < bh; ++row) {
12526 for (int col = 0; col < bw; ++col) {
Yaowu Xuc27fc142016-08-22 16:08:15 -070012527 wsrc_buf[col] = src[col] * src_scale - wsrc_buf[col];
12528 }
Rupert Swarbrickc0cea7f2017-08-22 14:06:56 +010012529 wsrc_buf += bw;
Yaowu Xuc27fc142016-08-22 16:08:15 -070012530 src += x->plane[0].src.stride;
12531 }
Sebastien Alaiwan71e87842017-04-12 16:03:28 +020012532#endif // CONFIG_HIGHBITDEPTH
Yaowu Xuc27fc142016-08-22 16:08:15 -070012533 }
12534}
Yue Chenf27b1602017-01-13 11:11:43 -080012535
12536#if CONFIG_NCOBMC
12537void av1_check_ncobmc_rd(const struct AV1_COMP *cpi, struct macroblock *x,
12538 int mi_row, int mi_col) {
12539 const AV1_COMMON *const cm = &cpi->common;
12540 MACROBLOCKD *const xd = &x->e_mbd;
12541 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
12542 MB_MODE_INFO backup_mbmi;
12543 BLOCK_SIZE bsize = mbmi->sb_type;
12544 int ref, skip_blk, backup_skip = x->skip;
12545 int64_t rd_causal;
12546 RD_STATS rd_stats_y, rd_stats_uv;
12547 int rate_skip0 = av1_cost_bit(av1_get_skip_prob(cm, xd), 0);
12548 int rate_skip1 = av1_cost_bit(av1_get_skip_prob(cm, xd), 1);
12549
12550 // Recompute the best causal predictor and rd
12551 mbmi->motion_mode = SIMPLE_TRANSLATION;
12552 set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
12553 for (ref = 0; ref < 1 + has_second_ref(mbmi); ++ref) {
12554 YV12_BUFFER_CONFIG *cfg = get_ref_frame_buffer(cpi, mbmi->ref_frame[ref]);
12555 assert(cfg != NULL);
12556 av1_setup_pre_planes(xd, ref, cfg, mi_row, mi_col,
12557 &xd->block_refs[ref]->sf);
12558 }
Jingning Han91d9a792017-04-18 12:01:52 -070012559 av1_setup_dst_planes(x->e_mbd.plane, bsize,
12560 get_frame_new_buffer(&cpi->common), mi_row, mi_col);
Yue Chenf27b1602017-01-13 11:11:43 -080012561
Jingning Hanc44009c2017-05-06 11:36:49 -070012562 av1_build_inter_predictors_sb(cm, xd, mi_row, mi_col, NULL, bsize);
Yue Chenf27b1602017-01-13 11:11:43 -080012563
12564 av1_subtract_plane(x, bsize, 0);
Wei-Ting Linba5f1872017-07-06 12:26:09 -070012565#if CONFIG_VAR_TX
12566 if (cm->tx_mode == TX_MODE_SELECT && !xd->lossless[mbmi->segment_id]) {
12567 select_tx_type_yrd(cpi, x, &rd_stats_y, bsize, INT64_MAX);
12568 } else {
12569 int idx, idy;
12570 super_block_yrd(cpi, x, &rd_stats_y, bsize, INT64_MAX);
12571 for (idy = 0; idy < xd->n8_h; ++idy)
12572 for (idx = 0; idx < xd->n8_w; ++idx)
12573 mbmi->inter_tx_size[idy][idx] = mbmi->tx_size;
12574 memset(x->blk_skip[0], rd_stats_y.skip,
12575 sizeof(uint8_t) * xd->n8_h * xd->n8_w * 4);
12576 }
12577 inter_block_uvrd(cpi, x, &rd_stats_uv, bsize, INT64_MAX);
12578#else
Yue Chenf27b1602017-01-13 11:11:43 -080012579 super_block_yrd(cpi, x, &rd_stats_y, bsize, INT64_MAX);
12580 super_block_uvrd(cpi, x, &rd_stats_uv, bsize, INT64_MAX);
Wei-Ting Linba5f1872017-07-06 12:26:09 -070012581#endif
Yue Chenf27b1602017-01-13 11:11:43 -080012582 assert(rd_stats_y.rate != INT_MAX && rd_stats_uv.rate != INT_MAX);
12583 if (rd_stats_y.skip && rd_stats_uv.skip) {
12584 rd_stats_y.rate = rate_skip1;
12585 rd_stats_uv.rate = 0;
12586 rd_stats_y.dist = rd_stats_y.sse;
12587 rd_stats_uv.dist = rd_stats_uv.sse;
12588 skip_blk = 0;
Urvang Joshi70006e42017-06-14 16:08:55 -070012589 } else if (RDCOST(x->rdmult,
Yue Chenf27b1602017-01-13 11:11:43 -080012590 (rd_stats_y.rate + rd_stats_uv.rate + rate_skip0),
12591 (rd_stats_y.dist + rd_stats_uv.dist)) >
Urvang Joshi70006e42017-06-14 16:08:55 -070012592 RDCOST(x->rdmult, rate_skip1,
Yue Chenf27b1602017-01-13 11:11:43 -080012593 (rd_stats_y.sse + rd_stats_uv.sse))) {
12594 rd_stats_y.rate = rate_skip1;
12595 rd_stats_uv.rate = 0;
12596 rd_stats_y.dist = rd_stats_y.sse;
12597 rd_stats_uv.dist = rd_stats_uv.sse;
12598 skip_blk = 1;
12599 } else {
12600 rd_stats_y.rate += rate_skip0;
12601 skip_blk = 0;
12602 }
12603 backup_skip = skip_blk;
12604 backup_mbmi = *mbmi;
Urvang Joshi70006e42017-06-14 16:08:55 -070012605 rd_causal = RDCOST(x->rdmult, (rd_stats_y.rate + rd_stats_uv.rate),
Yue Chenf27b1602017-01-13 11:11:43 -080012606 (rd_stats_y.dist + rd_stats_uv.dist));
Urvang Joshi70006e42017-06-14 16:08:55 -070012607 rd_causal +=
12608 RDCOST(x->rdmult, av1_cost_bit(cm->fc->motion_mode_prob[bsize][0], 0), 0);
Yue Chenf27b1602017-01-13 11:11:43 -080012609
12610 // Check non-causal mode
12611 mbmi->motion_mode = OBMC_CAUSAL;
12612 av1_build_ncobmc_inter_predictors_sb(cm, xd, mi_row, mi_col);
12613
12614 av1_subtract_plane(x, bsize, 0);
Wei-Ting Linba5f1872017-07-06 12:26:09 -070012615#if CONFIG_VAR_TX
12616 if (cm->tx_mode == TX_MODE_SELECT && !xd->lossless[mbmi->segment_id]) {
12617 select_tx_type_yrd(cpi, x, &rd_stats_y, bsize, INT64_MAX);
12618 } else {
12619 int idx, idy;
12620 super_block_yrd(cpi, x, &rd_stats_y, bsize, INT64_MAX);
12621 for (idy = 0; idy < xd->n8_h; ++idy)
12622 for (idx = 0; idx < xd->n8_w; ++idx)
12623 mbmi->inter_tx_size[idy][idx] = mbmi->tx_size;
12624 memset(x->blk_skip[0], rd_stats_y.skip,
12625 sizeof(uint8_t) * xd->n8_h * xd->n8_w * 4);
12626 }
12627 inter_block_uvrd(cpi, x, &rd_stats_uv, bsize, INT64_MAX);
12628#else
Yue Chenf27b1602017-01-13 11:11:43 -080012629 super_block_yrd(cpi, x, &rd_stats_y, bsize, INT64_MAX);
12630 super_block_uvrd(cpi, x, &rd_stats_uv, bsize, INT64_MAX);
Wei-Ting Linba5f1872017-07-06 12:26:09 -070012631#endif
Yue Chenf27b1602017-01-13 11:11:43 -080012632 assert(rd_stats_y.rate != INT_MAX && rd_stats_uv.rate != INT_MAX);
12633 if (rd_stats_y.skip && rd_stats_uv.skip) {
12634 rd_stats_y.rate = rate_skip1;
12635 rd_stats_uv.rate = 0;
12636 rd_stats_y.dist = rd_stats_y.sse;
12637 rd_stats_uv.dist = rd_stats_uv.sse;
12638 skip_blk = 0;
Urvang Joshi70006e42017-06-14 16:08:55 -070012639 } else if (RDCOST(x->rdmult,
Yue Chenf27b1602017-01-13 11:11:43 -080012640 (rd_stats_y.rate + rd_stats_uv.rate + rate_skip0),
12641 (rd_stats_y.dist + rd_stats_uv.dist)) >
Urvang Joshi70006e42017-06-14 16:08:55 -070012642 RDCOST(x->rdmult, rate_skip1,
Yue Chenf27b1602017-01-13 11:11:43 -080012643 (rd_stats_y.sse + rd_stats_uv.sse))) {
12644 rd_stats_y.rate = rate_skip1;
12645 rd_stats_uv.rate = 0;
12646 rd_stats_y.dist = rd_stats_y.sse;
12647 rd_stats_uv.dist = rd_stats_uv.sse;
12648 skip_blk = 1;
12649 } else {
12650 rd_stats_y.rate += rate_skip0;
12651 skip_blk = 0;
12652 }
12653
12654 if (rd_causal >
clang-format4eafefe2017-09-04 12:51:20 -070012655 RDCOST(x->rdmult,
12656 rd_stats_y.rate + rd_stats_uv.rate +
12657 av1_cost_bit(cm->fc->motion_mode_prob[bsize][0], 1),
Yue Chenf27b1602017-01-13 11:11:43 -080012658 (rd_stats_y.dist + rd_stats_uv.dist))) {
12659 x->skip = skip_blk;
12660 } else {
12661 *mbmi = backup_mbmi;
12662 x->skip = backup_skip;
12663 }
12664}
Fergus Simpson4063a682017-02-28 16:52:22 -080012665#endif // CONFIG_NCOBMC
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012666
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012667int64_t get_prediction_rd_cost(const struct AV1_COMP *cpi, struct macroblock *x,
12668 int mi_row, int mi_col, int *skip_blk,
12669 MB_MODE_INFO *backup_mbmi) {
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012670 const AV1_COMMON *const cm = &cpi->common;
12671 MACROBLOCKD *const xd = &x->e_mbd;
12672 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
12673 BLOCK_SIZE bsize = mbmi->sb_type;
Wei-Ting Lin5f8f7a12017-08-31 14:39:52 -070012674#if CONFIG_NCOBMC_ADAPT_WEIGHT && CONFIG_WARPED_MOTION
12675 const MOTION_MODE motion_allowed = motion_mode_allowed(
12676#if CONFIG_GLOBAL_MOTION
12677 0, xd->global_motion,
12678#endif // CONFIG_GLOBAL_MOTION
12679#if CONFIG_WARPED_MOTION
12680 xd,
12681#endif
12682 xd->mi[0]);
12683#endif // CONFIG_NCOBMC_ADAPT_WEIGHT && CONFIG_WARPED_MOTION
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012684 RD_STATS rd_stats_y, rd_stats_uv;
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012685 int rate_skip0 = av1_cost_bit(av1_get_skip_prob(cm, xd), 0);
12686 int rate_skip1 = av1_cost_bit(av1_get_skip_prob(cm, xd), 1);
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012687 int64_t this_rd;
12688 int ref;
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012689
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012690#if CONFIG_CB4X4
12691 x->skip_chroma_rd =
12692 !is_chroma_reference(mi_row, mi_col, bsize, xd->plane[1].subsampling_x,
12693 xd->plane[1].subsampling_y);
12694#endif
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012695
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012696 set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
12697 for (ref = 0; ref < 1 + has_second_ref(mbmi); ++ref) {
12698 YV12_BUFFER_CONFIG *cfg = get_ref_frame_buffer(cpi, mbmi->ref_frame[ref]);
12699 assert(cfg != NULL);
12700 av1_setup_pre_planes(xd, ref, cfg, mi_row, mi_col,
12701 &xd->block_refs[ref]->sf);
12702 }
12703 av1_setup_dst_planes(x->e_mbd.plane, bsize,
12704 get_frame_new_buffer(&cpi->common), mi_row, mi_col);
12705
12706#if CONFIG_NCOBMC_ADAPT_WEIGHT
12707 if (mbmi->motion_mode != NCOBMC_ADAPT_WEIGHT)
12708#endif
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012709 av1_build_inter_predictors_sb(cm, xd, mi_row, mi_col, NULL, bsize);
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012710
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012711#if CONFIG_MOTION_VAR
12712 if (mbmi->motion_mode == OBMC_CAUSAL) {
12713#if CONFIG_NCOBMC
12714 av1_build_ncobmc_inter_predictors_sb(cm, xd, mi_row, mi_col);
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012715#else
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012716 av1_build_obmc_inter_predictors_sb(cm, xd, mi_row, mi_col);
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012717#endif
12718 }
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012719#endif // CONFIG_MOTION_VAR
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012720
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012721#if CONFIG_NCOBMC_ADAPT_WEIGHT
12722 if (mbmi->motion_mode == NCOBMC_ADAPT_WEIGHT)
12723 for (int plane = 0; plane < MAX_MB_PLANE; ++plane)
12724 get_pred_from_intrpl_buf(xd, mi_row, mi_col, bsize, plane);
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012725#endif
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012726 av1_subtract_plane(x, bsize, 0);
12727
12728#if CONFIG_VAR_TX
12729 if (cm->tx_mode == TX_MODE_SELECT && !xd->lossless[mbmi->segment_id]) {
12730 select_tx_type_yrd(cpi, x, &rd_stats_y, bsize, INT64_MAX);
12731 } else {
12732 int idx, idy;
12733 super_block_yrd(cpi, x, &rd_stats_y, bsize, INT64_MAX);
12734 for (idy = 0; idy < xd->n8_h; ++idy)
12735 for (idx = 0; idx < xd->n8_w; ++idx)
12736 mbmi->inter_tx_size[idy][idx] = mbmi->tx_size;
12737 memset(x->blk_skip[0], rd_stats_y.skip,
12738 sizeof(uint8_t) * xd->n8_h * xd->n8_w * 4);
12739 }
12740 inter_block_uvrd(cpi, x, &rd_stats_uv, bsize, INT64_MAX);
12741#else
12742 super_block_yrd(cpi, x, &rd_stats_y, bsize, INT64_MAX);
12743 super_block_uvrd(cpi, x, &rd_stats_uv, bsize, INT64_MAX);
12744#endif
12745 assert(rd_stats_y.rate != INT_MAX && rd_stats_uv.rate != INT_MAX);
12746
12747 if (rd_stats_y.skip && rd_stats_uv.skip) {
12748 rd_stats_y.rate = rate_skip1;
12749 rd_stats_uv.rate = 0;
12750 rd_stats_y.dist = rd_stats_y.sse;
12751 rd_stats_uv.dist = rd_stats_uv.sse;
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012752 *skip_blk = 1;
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012753 } else if (RDCOST(x->rdmult,
12754 (rd_stats_y.rate + rd_stats_uv.rate + rate_skip0),
12755 (rd_stats_y.dist + rd_stats_uv.dist)) >
12756 RDCOST(x->rdmult, rate_skip1,
12757 (rd_stats_y.sse + rd_stats_uv.sse))) {
12758 rd_stats_y.rate = rate_skip1;
12759 rd_stats_uv.rate = 0;
12760 rd_stats_y.dist = rd_stats_y.sse;
12761 rd_stats_uv.dist = rd_stats_uv.sse;
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012762 *skip_blk = 1;
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012763 } else {
12764 rd_stats_y.rate += rate_skip0;
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012765 *skip_blk = 0;
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012766 }
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012767
12768 if (backup_mbmi) *backup_mbmi = *mbmi;
12769
12770 this_rd = RDCOST(x->rdmult, (rd_stats_y.rate + rd_stats_uv.rate),
12771 (rd_stats_y.dist + rd_stats_uv.dist));
Wei-Ting Lin5f8f7a12017-08-31 14:39:52 -070012772#if CONFIG_NCOBMC_ADAPT_WEIGHT && CONFIG_WARPED_MOTION
12773 if (motion_allowed == NCOBMC_ADAPT_WEIGHT) {
12774 assert(mbmi->motion_mode <= NCOBMC_ADAPT_WEIGHT);
12775 this_rd +=
12776 RDCOST(x->rdmult, x->motion_mode_cost2[bsize][mbmi->motion_mode], 0);
12777 } else if (motion_allowed == OBMC_CAUSAL) {
12778 assert(mbmi->motion_mode <= OBMC_CAUSAL);
12779 this_rd +=
12780 RDCOST(x->rdmult, x->motion_mode_cost1[bsize][mbmi->motion_mode], 0);
12781 } else {
12782#endif // CONFIG_NCOBMC_ADAPT_WEIGHT && CONFIG_WARPED_MOTION
12783 this_rd +=
12784 RDCOST(x->rdmult, x->motion_mode_cost[bsize][mbmi->motion_mode], 0);
12785#if CONFIG_NCOBMC_ADAPT_WEIGHT && CONFIG_WARPED_MOTION
12786 }
12787#endif // CONFIG_NCOBMC_ADAPT_WEIGHT && CONFIG_WARPED_MOTION
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012788 return this_rd;
12789}
12790
12791#if CONFIG_NCOBMC_ADAPT_WEIGHT
12792void av1_check_ncobmc_adapt_weight_rd(const struct AV1_COMP *cpi,
12793 struct macroblock *x, int mi_row,
12794 int mi_col) {
12795 MACROBLOCKD *const xd = &x->e_mbd;
12796 MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
12797 BLOCK_SIZE bsize = mbmi->sb_type;
12798#if CONFIG_VAR_TX
12799 const int n4 = bsize_to_num_blk(bsize);
12800 uint8_t st_blk_skip[MAX_MIB_SIZE * MAX_MIB_SIZE * 8];
12801 uint8_t obmc_blk_skip[MAX_MIB_SIZE * MAX_MIB_SIZE * 8];
Wei-Ting Lin5f8f7a12017-08-31 14:39:52 -070012802 uint8_t ncobmc_blk_skip[MAX_MIB_SIZE * MAX_MIB_SIZE * 8];
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012803#endif
Wei-Ting Lin5f8f7a12017-08-31 14:39:52 -070012804 MB_MODE_INFO st_mbmi, obmc_mbmi, ncobmc_mbmi;
12805 int st_skip, obmc_skip, ncobmc_skip;
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012806 int64_t st_rd, obmc_rd, ncobmc_rd;
Wei-Ting Lin5f8f7a12017-08-31 14:39:52 -070012807#if CONFIG_WARPED_MOTION
12808 const AV1_COMMON *const cm = &cpi->common;
12809 const int is_warp_motion = mbmi->motion_mode == WARPED_CAUSAL;
12810 const int rs = RDCOST(x->rdmult, av1_get_switchable_rate(cm, x, xd), 0);
12811 MB_MODE_INFO warp_mbmi;
12812 int64_t warp_rd;
12813 int warp_skip;
12814#endif
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012815
12816 // Recompute the rd for the motion mode decided in rd loop
12817 mbmi->motion_mode = SIMPLE_TRANSLATION;
12818 st_rd = get_prediction_rd_cost(cpi, x, mi_row, mi_col, &st_skip, &st_mbmi);
Wei-Ting Lin5f8f7a12017-08-31 14:39:52 -070012819#if CONFIG_WARPED_MOTION
12820 st_rd += rs;
12821#endif
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012822#if CONFIG_VAR_TX
12823 memcpy(st_blk_skip, x->blk_skip[0], sizeof(st_blk_skip[0]) * n4);
12824#endif
12825
12826 mbmi->motion_mode = OBMC_CAUSAL;
12827 obmc_rd =
12828 get_prediction_rd_cost(cpi, x, mi_row, mi_col, &obmc_skip, &obmc_mbmi);
Wei-Ting Lin5f8f7a12017-08-31 14:39:52 -070012829#if CONFIG_WARPED_MOTION
12830 obmc_rd += rs;
12831#endif
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012832#if CONFIG_VAR_TX
12833 memcpy(obmc_blk_skip, x->blk_skip[0], sizeof(obmc_blk_skip[0]) * n4);
12834#endif
Wei-Ting Lin5f8f7a12017-08-31 14:39:52 -070012835
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012836 // Compute the rd cost for ncobmc adaptive weight
12837 mbmi->motion_mode = NCOBMC_ADAPT_WEIGHT;
Wei-Ting Lin5f8f7a12017-08-31 14:39:52 -070012838 ncobmc_rd = get_prediction_rd_cost(cpi, x, mi_row, mi_col, &ncobmc_skip,
12839 &ncobmc_mbmi);
12840#if CONFIG_WARPED_MOTION
12841 ncobmc_rd += rs;
12842#endif
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012843 // Calculate the ncobmc mode costs
12844 {
12845 ADAPT_OVERLAP_BLOCK aob = adapt_overlap_block_lookup[bsize];
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012846 ncobmc_rd +=
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012847 RDCOST(x->rdmult, x->ncobmc_mode_cost[aob][mbmi->ncobmc_mode[0]], 0);
12848 if (mi_size_wide[bsize] != mi_size_high[bsize])
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012849 ncobmc_rd +=
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012850 RDCOST(x->rdmult, x->ncobmc_mode_cost[aob][mbmi->ncobmc_mode[1]], 0);
12851 }
Wei-Ting Lin5f8f7a12017-08-31 14:39:52 -070012852#if CONFIG_VAR_TX
12853 memcpy(ncobmc_blk_skip, x->blk_skip[0], sizeof(ncobmc_blk_skip[0]) * n4);
12854#endif
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012855
Wei-Ting Lin5f8f7a12017-08-31 14:39:52 -070012856#if CONFIG_WARPED_MOTION
12857 if (is_warp_motion) {
12858 mbmi->motion_mode = WARPED_CAUSAL;
12859 warp_rd =
12860 get_prediction_rd_cost(cpi, x, mi_row, mi_col, &warp_skip, &warp_mbmi);
Wei-Ting Lin3122b7d2017-08-30 17:26:58 -070012861 } else {
Wei-Ting Lin5f8f7a12017-08-31 14:39:52 -070012862 warp_rd = INT64_MAX;
12863 }
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012864#endif
Wei-Ting Lin5f8f7a12017-08-31 14:39:52 -070012865
12866#if CONFIG_WARPED_MOTION
12867 if (AOMMIN(ncobmc_rd, warp_rd) < AOMMIN(st_rd, obmc_rd)) {
12868 if (ncobmc_rd < warp_rd) {
12869 x->skip = ncobmc_skip;
12870 *mbmi = ncobmc_mbmi;
12871#if CONFIG_VAR_TX
12872 memcpy(x->blk_skip[0], ncobmc_blk_skip, sizeof(ncobmc_blk_skip[0]) * n4);
12873#endif
12874 } else {
12875 x->skip = warp_skip;
12876 *mbmi = warp_mbmi;
12877 }
12878#else
12879 if (ncobmc_rd < AOMMIN(st_rd, obmc_rd)) {
12880 x->skip = ncobmc_skip;
12881 *mbmi = ncobmc_mbmi;
12882#if CONFIG_VAR_TX
12883 memcpy(x->blk_skip[0], ncobmc_blk_skip, sizeof(ncobmc_blk_skip[0]) * n4);
12884#endif
12885#endif // CONFIG_WARPED_MOTION
12886 } else {
12887 if (obmc_rd < st_rd) {
12888 *mbmi = obmc_mbmi;
12889 x->skip = obmc_skip;
12890#if CONFIG_VAR_TX
12891 memcpy(x->blk_skip[0], obmc_blk_skip, sizeof(obmc_blk_skip[0]) * n4);
12892#endif
12893 } else {
12894 *mbmi = st_mbmi;
12895 x->skip = st_skip;
12896#if CONFIG_VAR_TX
12897 memcpy(x->blk_skip[0], st_blk_skip, sizeof(st_blk_skip[0]) * n4);
12898#endif
12899 }
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012900 }
12901}
12902
12903int64_t get_ncobmc_error(MACROBLOCKD *xd, int pxl_row, int pxl_col,
12904 BLOCK_SIZE bsize, int plane, struct buf_2d *src) {
12905 const int wide = AOMMIN(mi_size_wide[bsize] * MI_SIZE,
12906 (xd->sb_mi_bd.mi_col_end + 1) * MI_SIZE - pxl_col);
12907 const int high = AOMMIN(mi_size_high[bsize] * MI_SIZE,
12908 (xd->sb_mi_bd.mi_row_end + 1) * MI_SIZE - pxl_row);
12909 const int ss_x = xd->plane[plane].subsampling_x;
12910 const int ss_y = xd->plane[plane].subsampling_y;
12911 int row_offset = (pxl_row - xd->sb_mi_bd.mi_row_begin * MI_SIZE) >> ss_y;
12912 int col_offset = (pxl_col - xd->sb_mi_bd.mi_col_begin * MI_SIZE) >> ss_x;
12913 int dst_stride = xd->ncobmc_pred_buf_stride[plane];
12914 int dst_offset = row_offset * dst_stride + col_offset;
12915 int src_stride = src->stride;
12916
12917 int r, c;
12918 int64_t tmp, error = 0;
12919
12920 for (r = 0; r < (high >> ss_y); ++r) {
12921 for (c = 0; c < (wide >> ss_x); ++c) {
12922 tmp = xd->ncobmc_pred_buf[plane][r * dst_stride + c + dst_offset] -
12923 src->buf[r * src_stride + c];
12924 error += tmp * tmp;
12925 }
12926 }
12927 return error;
12928}
12929
12930int get_ncobmc_mode(const AV1_COMP *const cpi, MACROBLOCK *const x,
12931 MACROBLOCKD *xd, int mi_row, int mi_col, int bsize) {
12932 const AV1_COMMON *const cm = &cpi->common;
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012933 uint8_t *pred_buf[4][MAX_MB_PLANE];
12934
12935 // TODO(weitinglin): stride size needs to be fixed for high-bit depth
12936 int pred_stride[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE };
12937
12938 // target block in pxl
12939 int pxl_row = mi_row << MI_SIZE_LOG2;
12940 int pxl_col = mi_col << MI_SIZE_LOG2;
12941 int64_t error, best_error = INT64_MAX;
12942 int plane, tmp_mode, best_mode = 0;
12943#if CONFIG_HIGHBITDEPTH
12944 if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
12945 int len = sizeof(uint16_t);
Debargha Mukherjee5d108a32017-10-05 19:47:08 -070012946 ASSIGN_ALIGNED_PTRS_HBD(pred_buf[0], cm->ncobmcaw_buf[0], MAX_SB_SQUARE,
12947 len);
12948 ASSIGN_ALIGNED_PTRS_HBD(pred_buf[1], cm->ncobmcaw_buf[1], MAX_SB_SQUARE,
12949 len);
12950 ASSIGN_ALIGNED_PTRS_HBD(pred_buf[2], cm->ncobmcaw_buf[2], MAX_SB_SQUARE,
12951 len);
12952 ASSIGN_ALIGNED_PTRS_HBD(pred_buf[3], cm->ncobmcaw_buf[3], MAX_SB_SQUARE,
12953 len);
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012954 } else {
12955#endif // CONFIG_HIGHBITDEPTH
Debargha Mukherjee5d108a32017-10-05 19:47:08 -070012956 ASSIGN_ALIGNED_PTRS(pred_buf[0], cm->ncobmcaw_buf[0], MAX_SB_SQUARE);
12957 ASSIGN_ALIGNED_PTRS(pred_buf[1], cm->ncobmcaw_buf[1], MAX_SB_SQUARE);
12958 ASSIGN_ALIGNED_PTRS(pred_buf[2], cm->ncobmcaw_buf[2], MAX_SB_SQUARE);
12959 ASSIGN_ALIGNED_PTRS(pred_buf[3], cm->ncobmcaw_buf[3], MAX_SB_SQUARE);
Wei-Ting Linc5563a42017-08-03 12:45:43 -070012960#if CONFIG_HIGHBITDEPTH
12961 }
12962#endif
12963
12964 av1_get_ext_blk_preds(cm, xd, bsize, mi_row, mi_col, pred_buf, pred_stride);
12965 av1_get_ori_blk_pred(cm, xd, bsize, mi_row, mi_col, pred_buf[3], pred_stride);
12966
12967 for (tmp_mode = 0; tmp_mode < MAX_NCOBMC_MODES; ++tmp_mode) {
12968 error = 0;
12969 for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
12970 build_ncobmc_intrpl_pred(cm, xd, plane, pxl_row, pxl_col, bsize, pred_buf,
12971 pred_stride, tmp_mode);
12972 error += get_ncobmc_error(xd, pxl_row, pxl_col, bsize, plane,
12973 &x->plane[plane].src);
12974 }
12975 if (error < best_error) {
12976 best_mode = tmp_mode;
12977 best_error = error;
12978 }
12979 }
12980
12981 for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
12982 build_ncobmc_intrpl_pred(cm, xd, plane, pxl_row, pxl_col, bsize, pred_buf,
12983 pred_stride, best_mode);
12984 }
12985
12986 return best_mode;
12987}
12988
12989#endif // CONFIG_NCOBMC_ADAPT_WEIGHT
Yue Chencb60b182016-10-13 15:18:22 -070012990#endif // CONFIG_MOTION_VAR